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 *
035 */
036 public class RulesManager implements BatchExtension {
037
038 private final Set<Language> languages;
039 private final RulesRepository<?>[] repositories;
040 private final Map<Language, List<RulesRepository<?>>> rulesByLanguage;
041 private final Map<Language, List<Plugin>> pluginsByLanguage;
042 private final Map<String, Map<String, Rule>> rulesByPluginAndKey = new HashMap<String, Map<String, Rule>>();
043 private final RulesDao rulesDao;
044 private final Plugins plugins;
045
046 /**
047 * Creates a RuleManager
048 * @param plugins the plugins dictionnary
049 * @param repositories the repositories of rules
050 * @param dao the dao object
051 */
052 public RulesManager(Plugins plugins, RulesRepository[] repositories, DaoFacade dao) {
053 this.plugins = plugins;
054 this.rulesDao = dao.getRulesDao();
055
056 languages = new HashSet<Language>();
057 rulesByLanguage = new HashMap<Language, List<RulesRepository<?>>>();
058 pluginsByLanguage = new HashMap<Language, List<Plugin>>();
059 this.repositories = repositories;
060
061 for (RulesRepository<?> repository : repositories) {
062 languages.add(repository.getLanguage());
063
064 List<RulesRepository<?>> list = rulesByLanguage.get(repository.getLanguage());
065 if (list == null) {
066 list = new ArrayList<RulesRepository<?>>();
067 rulesByLanguage.put(repository.getLanguage(), list);
068 }
069 list.add(repository);
070
071 List<Plugin> languagePlugins = pluginsByLanguage.get(repository.getLanguage());
072 if (languagePlugins == null) {
073 languagePlugins = new ArrayList<Plugin>();
074 pluginsByLanguage.put(repository.getLanguage(), languagePlugins);
075 }
076 languagePlugins.add(plugins.getPluginByExtension(repository));
077 }
078 }
079
080 /**
081 * Constructor for tests only
082 *
083 * @param dao the dao
084 */
085 protected RulesManager(DaoFacade dao) {
086 this.rulesDao = dao.getRulesDao();
087 plugins = new Plugins();
088 languages = new HashSet<Language>();
089 rulesByLanguage = new HashMap<Language, List<RulesRepository<?>>>();
090 pluginsByLanguage = new HashMap<Language, List<Plugin>>();
091 repositories = null;
092
093 }
094
095 /**
096 * Returns the list of languages for which there is a rule repository
097 *
098 * @return a Set of languages
099 */
100 public Set<Language> getLanguages() {
101 return languages;
102 }
103
104 /**
105 * Gets the list of Rules Repositories available for a language
106 *
107 * @param language the language
108 * @return the list of rules repositories
109 */
110 public List<RulesRepository<?>> getRulesRepositories(Language language) {
111 List<RulesRepository<?>> rulesRepositories = rulesByLanguage.get(language);
112 if (CollectionUtils.isNotEmpty(rulesRepositories)) {
113 return rulesRepositories;
114 }
115 return Collections.emptyList();
116 }
117
118 /**
119 * Gets the complete list of Rules Repositories in the Sonar instance
120 *
121 * @return the list of rules repositories
122 */
123 public List<RulesRepository<?>> getRulesRepositories() {
124 return Arrays.asList(repositories);
125 }
126
127 /**
128 * Gets the list of rules plugins for a given language
129 * @param language the language
130 * @return the list of plugins
131 */
132 public List<Plugin> getPlugins(Language language) {
133 List<Plugin> result = pluginsByLanguage.get(language);
134 if (!CollectionUtils.isEmpty(result)) {
135 return result;
136 }
137 return Collections.emptyList();
138 }
139
140 /**
141 * Gets count of rules by categories defined for a given language
142 *
143 * @param language the language
144 * @return a Map with the category as key and the count as value
145 */
146 public Map<String, Long> countRulesByCategory(Language language) {
147 return countRulesByCategory(language, rulesDao);
148 }
149
150 protected Map<String, Long> countRulesByCategory(Language language, RulesDao rulesDao) {
151 Map<String, Long> countByCategory = new HashMap<String, Long>();
152 List<Plugin> result = getPlugins(language);
153 if (!CollectionUtils.isEmpty(result)) {
154 List<String> keys = getPluginKeys(getPlugins(language));
155 for (RulesCategory rulesCategory : rulesDao.getCategories()) {
156 Long rulesCount = rulesDao.countRules(keys, rulesCategory.getName());
157 countByCategory.put(rulesCategory.getName(), rulesCount);
158 }
159 }
160 return countByCategory;
161 }
162
163 private List<String> getPluginKeys(List<Plugin> plugins) {
164 ArrayList<String> keys = new ArrayList<String>();
165 for (Plugin plugin : plugins) {
166 keys.add(plugin.getKey());
167 }
168 return keys;
169 }
170
171 /**
172 * Get the list of rules plugin that implement a mechanism of export for a given language
173 *
174 * @param language the language
175 * @return the list of plugins
176 */
177 public List<Plugin> getExportablePlugins(Language language) {
178 List<Plugin> targets = new ArrayList<Plugin>();
179 List<RulesRepository<?>> rulesRepositories = getRulesRepositories(language);
180 for (RulesRepository<?> repository : rulesRepositories) {
181 if (repository instanceof ConfigurationExportable) {
182 targets.add(plugins.getPluginByExtension(repository));
183 }
184 }
185 return targets;
186 }
187
188 /**
189 * Get the list of rules plugin that implement a mechanism of import for a given language
190 *
191 * @param language the language
192 * @return the list of plugins
193 */
194 public List<Plugin> getImportablePlugins(Language language) {
195 List<Plugin> targets = new ArrayList<Plugin>();
196 for (RulesRepository<?> repository : getRulesRepositories(language)) {
197 if (repository instanceof ConfigurationImportable) {
198 targets.add(plugins.getPluginByExtension(repository));
199 }
200 }
201 return targets;
202 }
203
204 /**
205 * Gets a list of rules indexed by their key for a given plugin
206 * @param pluginKey the plugin key
207 * @return a Map with the rule key and the rule
208 */
209 public Map<String, Rule> getPluginRulesIndexedByKey(String pluginKey) {
210 Map<String, Rule> rulesByKey = rulesByPluginAndKey.get(pluginKey);
211 if (rulesByKey == null) {
212 rulesByKey = new HashMap<String, Rule>();
213 List<Rule> rules = rulesDao.getRulesByPlugin(pluginKey);
214 if (rules != null) {
215 for (Rule rule : rules) {
216 rulesByKey.put(rule.getKey(), rule);
217 }
218 }
219 rulesByPluginAndKey.put(pluginKey, rulesByKey);
220 }
221 return rulesByKey;
222 }
223
224 /**
225 * Gets a collection of rules belonging to a plugin
226 *
227 * @param pluginKey the plugin key
228 * @return the collection of rules
229 */
230 public Collection<Rule> getPluginRules(String pluginKey) {
231 Map<String, Rule> rulesByKey = getPluginRulesIndexedByKey(pluginKey);
232 return rulesByKey.values();
233 }
234
235 /**
236 * Gets a rule belonging to a defined plugin based on its key
237 *
238 * @param pluginKey the plugin key
239 * @param ruleKey the rule key
240 * @return the rule
241 */
242 public Rule getPluginRule(String pluginKey, String ruleKey) {
243 Map<String, Rule> rulesByKey = getPluginRulesIndexedByKey(pluginKey);
244 return rulesByKey.get(ruleKey);
245 }
246
247 }