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.profiles;
021
022 import org.apache.commons.collections.CollectionUtils;
023 import org.apache.commons.collections.Transformer;
024 import org.apache.commons.lang.StringUtils;
025 import org.apache.commons.lang.builder.EqualsBuilder;
026 import org.apache.commons.lang.builder.HashCodeBuilder;
027 import org.sonar.api.database.model.ResourceModel;
028 import org.sonar.api.rules.ActiveRule;
029 import org.sonar.api.rules.Rule;
030 import org.sonar.api.rules.RulePriority;
031
032 import javax.persistence.*;
033 import java.util.ArrayList;
034 import java.util.List;
035
036 /**
037 * This class is badly named. It should be "QualityProfile". Indeed it does not relate only to rules but to metric
038 * thresholds too.
039 */
040 @Entity
041 @Table(name = "rules_profiles")
042 public class RulesProfile implements Cloneable {
043
044 /**
045 * Name of the default profile "Sonar Way"
046 */
047 public static final String SONAR_WAY_NAME = "Sonar way";
048
049 /**
050 * Name of the default java profile "Sonar way with Findbugs"
051 */
052 public static final String SONAR_WAY_FINDBUGS_NAME = "Sonar way with Findbugs";
053
054 /**
055 * Name of the default java profile "Sun checks"
056 */
057 public static final String SUN_CONVENTIONS_NAME = "Sun checks";
058
059 @Id
060 @Column(name = "id")
061 @GeneratedValue
062 private Integer id;
063
064 @Column(name = "name", updatable = true, nullable = false)
065 private String name;
066
067 @Column(name = "default_profile", updatable = true, nullable = false)
068 private Boolean defaultProfile = Boolean.FALSE;
069
070 @Column(name = "provided", updatable = true, nullable = false)
071 private Boolean provided = Boolean.FALSE;
072
073 @Column(name = "language", updatable = true, nullable = false)
074 private String language;
075
076 @OneToMany(mappedBy = "rulesProfile", fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE})
077 private List<ActiveRule> activeRules = new ArrayList<ActiveRule>();
078
079 @OneToMany(mappedBy = "rulesProfile", fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE})
080 private List<Alert> alerts = new ArrayList<Alert>();
081
082 @OneToMany(mappedBy = "rulesProfile", fetch = FetchType.LAZY)
083 private List<ResourceModel> projects = new ArrayList<ResourceModel>();
084
085 /**
086 * @deprecated use the factory method create()
087 */
088 @Deprecated
089 public RulesProfile() {
090 }
091
092 /**
093 * @deprecated since 2.3. Use the factory method create()
094 */
095 @Deprecated
096 public RulesProfile(String name, String language) {
097 this.name = name;
098 this.language = language;
099 this.activeRules = new ArrayList<ActiveRule>();
100 this.alerts = new ArrayList<Alert>();
101 this.projects = new ArrayList<ResourceModel>();
102 }
103
104 /**
105 * @deprecated since 2.3. Use the factory method create()
106 */
107 @Deprecated
108 public RulesProfile(String name, String language, boolean defaultProfile, boolean provided) {
109 this(name, language);
110 this.defaultProfile = defaultProfile;
111 this.provided = provided;
112 }
113
114 public Integer getId() {
115 return id;
116 }
117
118 /**
119 * @return the profile name, unique by language.
120 */
121 public String getName() {
122 return name;
123 }
124
125 /**
126 * Set the profile name.
127 */
128 public RulesProfile setName(String s) {
129 this.name = s;
130 return this;
131 }
132
133 /**
134 * @return the list of active rules
135 */
136 public List<ActiveRule> getActiveRules() {
137 return activeRules;
138 }
139
140 /**
141 * Set the list of active rules
142 */
143 public void setActiveRules(List<ActiveRule> activeRules) {
144 this.activeRules = activeRules;
145 }
146
147 /**
148 * @return whether this is the default profile for the language
149 */
150 public Boolean getDefaultProfile() {
151 return defaultProfile;
152 }
153
154 /**
155 * Set whether this is the default profile for the language. The default profile is used when none is explicitly
156 * defined when auditing a project.
157 */
158 public void setDefaultProfile(Boolean b) {
159 this.defaultProfile = b;
160 }
161
162 /**
163 * @return whether the profile is defined in a plugin. Provided profiles are automatically restored during
164 * server startup and can not be updated by end users.
165 */
166 public Boolean getProvided() {
167 return provided;
168 }
169
170 /**
171 * Set whether the profile is provided by a plugin
172 */
173 public void setProvided(Boolean b) {
174 this.provided = b;
175 }
176
177 /**
178 * @return the profile language
179 */
180 public String getLanguage() {
181 return language;
182 }
183
184 /**
185 * Set the profile language
186 */
187 public RulesProfile setLanguage(String s) {
188 this.language = s;
189 return this;
190 }
191
192 /**
193 * @return the list of alerts defined in the profile
194 */
195 public List<Alert> getAlerts() {
196 return alerts;
197 }
198
199 /**
200 * Sets the list of alerts for the profile
201 */
202 public void setAlerts(List<Alert> alerts) {
203 this.alerts = alerts;
204 }
205
206 /**
207 * @return the list of projects attached to the profile
208 */
209 public List<ResourceModel> getProjects() {
210 return projects;
211 }
212
213 /**
214 * Sets the list of projects attached to the profile
215 */
216 public void setProjects(List<ResourceModel> projects) {
217 this.projects = projects;
218 }
219
220 /**
221 * @return the list of active rules for a given priority
222 */
223 public List<ActiveRule> getActiveRules(RulePriority priority) {
224 List<ActiveRule> result = new ArrayList<ActiveRule>();
225 for (ActiveRule activeRule : getActiveRules()) {
226 if (activeRule.getPriority().equals(priority)) {
227 result.add(activeRule);
228 }
229 }
230 return result;
231 }
232
233 /**
234 * @deprecated since 2.3. Use getActiveRulesByRepository().
235 */
236 @Deprecated
237 public List<ActiveRule> getActiveRulesByPlugin(String repositoryKey) {
238 return getActiveRulesByRepository(repositoryKey);
239 }
240
241 public List<ActiveRule> getActiveRulesByRepository(String repositoryKey) {
242 List<ActiveRule> result = new ArrayList<ActiveRule>();
243 for (ActiveRule activeRule : getActiveRules()) {
244 if (repositoryKey.equals(activeRule.getPluginName())) {
245 result.add(activeRule);
246 }
247 }
248 return result;
249 }
250
251 /**
252 * @return an active rule from a plugin key and a rule key if the rule is activated, null otherwise
253 */
254 public ActiveRule getActiveRule(String repositoryKey, String ruleKey) {
255 for (ActiveRule activeRule : getActiveRules()) {
256 if (StringUtils.equals(activeRule.getRepositoryKey(), repositoryKey) && StringUtils.equals(activeRule.getRuleKey(), ruleKey)) {
257 return activeRule;
258 }
259 }
260 return null;
261 }
262
263 public ActiveRule getActiveRuleByConfigKey(String repositoryKey, String configKey) {
264 for (ActiveRule activeRule : getActiveRules()) {
265 if (StringUtils.equals(activeRule.getRepositoryKey(), repositoryKey) && StringUtils.equals(activeRule.getConfigKey(), configKey)) {
266 return activeRule;
267 }
268 }
269 return null;
270 }
271
272 public ActiveRule getActiveRule(Rule rule) {
273 return getActiveRule(rule.getRepositoryKey(), rule.getKey());
274 }
275
276 /**
277 *
278 * @param rule
279 * @param optionalPriority if null, then the default rule priority is used
280 * @return
281 */
282 public ActiveRule activateRule(Rule rule, RulePriority optionalPriority) {
283 ActiveRule activeRule = new ActiveRule();
284 activeRule.setRule(rule);
285 activeRule.setRulesProfile(this);
286 activeRule.setPriority(optionalPriority==null ? rule.getPriority() : optionalPriority);
287 activeRules.add(activeRule);
288 return activeRule;
289 }
290
291 @Override
292 public boolean equals(Object obj) {
293 if (!(obj instanceof RulesProfile)) {
294 return false;
295 }
296 if (this == obj) {
297 return true;
298 }
299 RulesProfile other = (RulesProfile) obj;
300 return new EqualsBuilder().append(language, other.getLanguage()).append(name, other.getName()).isEquals();
301 }
302
303 @Override
304 public int hashCode() {
305 return new HashCodeBuilder(17, 37).append(language).append(name).toHashCode();
306 }
307
308 @Override
309 public Object clone() {
310 RulesProfile clone = RulesProfile.create(getName(), getLanguage());
311 clone.setDefaultProfile(getDefaultProfile());
312 clone.setProvided(getProvided());
313 if (CollectionUtils.isNotEmpty(getActiveRules())) {
314 clone.setActiveRules(new ArrayList<ActiveRule>(CollectionUtils.collect(getActiveRules(), new Transformer() {
315 public Object transform(Object input) {
316 return ((ActiveRule) input).clone();
317 }
318 })));
319 }
320 if (CollectionUtils.isNotEmpty(getAlerts())) {
321 clone.setAlerts(new ArrayList<Alert>(CollectionUtils.collect(getAlerts(), new Transformer() {
322 public Object transform(Object input) {
323 return ((Alert) input).clone();
324 }
325 })));
326 }
327 if (CollectionUtils.isNotEmpty(getProjects())) {
328 clone.setProjects(new ArrayList<ResourceModel>(CollectionUtils.collect(getProjects(), new Transformer() {
329 public Object transform(Object input) {
330 return ((ResourceModel) input).clone();
331 }
332 })));
333 }
334 return clone;
335 }
336
337 @Override
338 public String toString() {
339 return new StringBuilder().append("[name=").append(name).append(",language=").append(language).append("]").toString();
340 }
341
342 public static RulesProfile create(String name, String language) {
343 return new RulesProfile().setName(name).setLanguage(language);
344 }
345
346 public static RulesProfile create() {
347 return new RulesProfile();
348 }
349 }