001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2009 SonarSource SA 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * Sonar is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020 package org.sonar.api.rules; 021 022 import org.apache.commons.collections.CollectionUtils; 023 import org.sonar.api.BatchExtension; 024 import org.sonar.api.Plugin; 025 import org.sonar.api.Plugins; 026 import org.sonar.api.database.daos.DaoFacade; 027 import org.sonar.api.database.daos.RulesDao; 028 import org.sonar.api.resources.Language; 029 030 import java.util.*; 031 032 /** 033 * A class to manage and access rules defined in Sonar. 034 * UGLY CLASS - WILL BE COMPLETELY REFACTORED IN SONAR 2.2 035 * 036 */ 037 public class RulesManager implements BatchExtension { 038 039 private final Set<Language> languages; 040 private final RulesRepository<?>[] repositories; 041 private final Map<Language, List<RulesRepository<?>>> rulesByLanguage; 042 private final Map<Language, List<Plugin>> pluginsByLanguage; 043 private final Map<String, Map<String, Rule>> rulesByPluginAndKey = new HashMap<String, Map<String, Rule>>(); 044 private final RulesDao rulesDao; 045 private final Plugins plugins; 046 047 /** 048 * Creates a RuleManager 049 * @param plugins the plugins dictionnary 050 * @param repositories the repositories of rules 051 * @param dao the dao object 052 */ 053 public RulesManager(Plugins plugins, RulesRepository[] repositories, DaoFacade dao) { 054 this.plugins = plugins; 055 this.rulesDao = dao.getRulesDao(); 056 057 languages = new HashSet<Language>(); 058 rulesByLanguage = new HashMap<Language, List<RulesRepository<?>>>(); 059 pluginsByLanguage = new HashMap<Language, List<Plugin>>(); 060 this.repositories = repositories; 061 062 for (RulesRepository<?> repository : repositories) { 063 languages.add(repository.getLanguage()); 064 065 List<RulesRepository<?>> list = rulesByLanguage.get(repository.getLanguage()); 066 if (list == null) { 067 list = new ArrayList<RulesRepository<?>>(); 068 rulesByLanguage.put(repository.getLanguage(), list); 069 } 070 list.add(repository); 071 072 List<Plugin> languagePlugins = pluginsByLanguage.get(repository.getLanguage()); 073 if (languagePlugins == null) { 074 languagePlugins = new ArrayList<Plugin>(); 075 pluginsByLanguage.put(repository.getLanguage(), languagePlugins); 076 } 077 languagePlugins.add(plugins.getPluginByExtension(repository)); 078 } 079 } 080 081 /** 082 * Constructor for tests only 083 * 084 * @param dao the dao 085 */ 086 protected RulesManager(DaoFacade dao, Plugins plugins) { 087 this.rulesDao = dao.getRulesDao(); 088 this.plugins = plugins; 089 languages = new HashSet<Language>(); 090 rulesByLanguage = new HashMap<Language, List<RulesRepository<?>>>(); 091 pluginsByLanguage = new HashMap<Language, List<Plugin>>(); 092 repositories = null; 093 094 } 095 096 /** 097 * Returns the list of languages for which there is a rule repository 098 * 099 * @return a Set of languages 100 */ 101 public Set<Language> getLanguages() { 102 return languages; 103 } 104 105 /** 106 * Gets the list of Rules Repositories available for a language 107 * 108 * @param language the language 109 * @return the list of rules repositories 110 */ 111 public List<RulesRepository<?>> getRulesRepositories(Language language) { 112 List<RulesRepository<?>> rulesRepositories = rulesByLanguage.get(language); 113 if (CollectionUtils.isNotEmpty(rulesRepositories)) { 114 return rulesRepositories; 115 } 116 return Collections.emptyList(); 117 } 118 119 /** 120 * Gets the complete list of Rules Repositories in the Sonar instance 121 * 122 * @return the list of rules repositories 123 */ 124 public List<RulesRepository<?>> getRulesRepositories() { 125 return Arrays.asList(repositories); 126 } 127 128 /** 129 * Gets the list of rules plugins for a given language 130 * @param language the language 131 * @return the list of plugins 132 */ 133 public List<Plugin> getPlugins(Language language) { 134 List<Plugin> result = pluginsByLanguage.get(language); 135 if (!CollectionUtils.isEmpty(result)) { 136 return result; 137 } 138 return Collections.emptyList(); 139 } 140 141 /** 142 * Gets count of rules by categories defined for a given language 143 * 144 * @param language the language 145 * @return a Map with the category as key and the count as value 146 */ 147 public Map<String, Long> countRulesByCategory(Language language) { 148 return countRulesByCategory(language, rulesDao); 149 } 150 151 protected Map<String, Long> countRulesByCategory(Language language, RulesDao rulesDao) { 152 Map<String, Long> countByCategory = new HashMap<String, Long>(); 153 List<Plugin> result = getPlugins(language); 154 if (!CollectionUtils.isEmpty(result)) { 155 List<String> keys = getPluginKeys(getPlugins(language)); 156 for (RulesCategory rulesCategory : rulesDao.getCategories()) { 157 Long rulesCount = rulesDao.countRules(keys, rulesCategory.getName()); 158 countByCategory.put(rulesCategory.getName(), rulesCount); 159 } 160 } 161 return countByCategory; 162 } 163 164 private List<String> getPluginKeys(List<Plugin> plugins) { 165 ArrayList<String> keys = new ArrayList<String>(); 166 for (Plugin plugin : plugins) { 167 keys.add(plugin.getKey()); 168 } 169 return keys; 170 } 171 172 /** 173 * Get the list of rules plugin that implement a mechanism of export for a given language 174 * 175 * @param language the language 176 * @return the list of plugins 177 */ 178 public List<Plugin> getExportablePlugins(Language language) { 179 List<Plugin> targets = new ArrayList<Plugin>(); 180 List<RulesRepository<?>> rulesRepositories = getRulesRepositories(language); 181 for (RulesRepository<?> repository : rulesRepositories) { 182 if (repository instanceof ConfigurationExportable) { 183 targets.add(plugins.getPluginByExtension(repository)); 184 } 185 } 186 return targets; 187 } 188 189 /** 190 * Get the list of rules plugin that implement a mechanism of import for a given language 191 * 192 * @param language the language 193 * @return the list of plugins 194 */ 195 public List<Plugin> getImportablePlugins(Language language) { 196 List<Plugin> targets = new ArrayList<Plugin>(); 197 for (RulesRepository<?> repository : getRulesRepositories(language)) { 198 if (repository instanceof ConfigurationImportable) { 199 targets.add(plugins.getPluginByExtension(repository)); 200 } 201 } 202 return targets; 203 } 204 205 /** 206 * Gets a list of rules indexed by their key for a given plugin 207 * @param pluginKey the plugin key 208 * @return a Map with the rule key and the rule 209 */ 210 public Map<String, Rule> getPluginRulesIndexedByKey(String pluginKey) { 211 Map<String, Rule> rulesByKey = rulesByPluginAndKey.get(pluginKey); 212 if (rulesByKey == null) { 213 rulesByKey = new HashMap<String, Rule>(); 214 List<Rule> rules = rulesDao.getRulesByPlugin(pluginKey); 215 if (rules != null) { 216 for (Rule rule : rules) { 217 rulesByKey.put(rule.getKey(), rule); 218 } 219 } 220 rulesByPluginAndKey.put(pluginKey, rulesByKey); 221 } 222 return rulesByKey; 223 } 224 225 /** 226 * Gets a collection of rules belonging to a plugin 227 * 228 * @param pluginKey the plugin key 229 * @return the collection of rules 230 */ 231 public Collection<Rule> getPluginRules(String pluginKey) { 232 Map<String, Rule> rulesByKey = getPluginRulesIndexedByKey(pluginKey); 233 return rulesByKey.values(); 234 } 235 236 /** 237 * Gets a rule belonging to a defined plugin based on its key 238 * 239 * @param pluginKey the plugin key 240 * @param ruleKey the rule key 241 * @return the rule 242 */ 243 public Rule getPluginRule(String pluginKey, String ruleKey) { 244 Map<String, Rule> rulesByKey = getPluginRulesIndexedByKey(pluginKey); 245 return rulesByKey.get(ruleKey); 246 } 247 248 }