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 }