001 /*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2008-2011 SonarSource
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 com.google.common.collect.Lists;
023 import org.apache.commons.collections.CollectionUtils;
024 import org.apache.commons.collections.Transformer;
025 import org.apache.commons.lang.StringUtils;
026 import org.apache.commons.lang.builder.EqualsBuilder;
027 import org.apache.commons.lang.builder.HashCodeBuilder;
028 import org.sonar.api.database.model.ResourceModel;
029 import org.sonar.api.rules.ActiveRule;
030 import org.sonar.api.rules.Rule;
031 import org.sonar.api.rules.RulePriority;
032
033 import javax.persistence.*;
034 import java.util.ArrayList;
035 import java.util.List;
036
037 /**
038 * This class is badly named. It should be "QualityProfile". Indeed it does not relate only to rules but to metric 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 = "enabled", updatable = true, nullable = false)
074 private Boolean enabled = Boolean.TRUE;
075
076 @Column(name = "language", updatable = true, nullable = false)
077 private String language;
078
079 @Column(name = "parent_name", updatable = true, nullable = true)
080 private String parentName;
081
082 @OneToMany(mappedBy = "rulesProfile", fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE})
083 private List<ActiveRule> activeRules = Lists.newArrayList();
084
085 @OneToMany(mappedBy = "rulesProfile", fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE})
086 private List<Alert> alerts = Lists.newArrayList();
087
088 @OneToMany(mappedBy = "rulesProfile", fetch = FetchType.LAZY)
089 private List<ResourceModel> projects = Lists.newArrayList();
090
091 /**
092 * @deprecated use the factory method create()
093 */
094 @Deprecated
095 public RulesProfile() {
096 }
097
098 /**
099 * @deprecated since 2.3. Use the factory method create()
100 */
101 @Deprecated
102 public RulesProfile(String name, String language) {
103 this.name = name;
104 this.language = language;
105 this.activeRules = Lists.newArrayList();
106 this.alerts = Lists.newArrayList();
107 this.projects = Lists.newArrayList();
108 }
109
110 /**
111 * @deprecated since 2.3. Use the factory method create()
112 */
113 @Deprecated
114 public RulesProfile(String name, String language, boolean defaultProfile, boolean provided) {
115 this(name, language);
116 this.defaultProfile = defaultProfile;
117 this.provided = provided;
118 }
119
120 public Integer getId() {
121 return id;
122 }
123
124 /**
125 * @return the profile name, unique by language.
126 */
127 public String getName() {
128 return name;
129 }
130
131 /**
132 * Set the profile name.
133 */
134 public RulesProfile setName(String s) {
135 this.name = s;
136 return this;
137 }
138
139 /**
140 * @return the list of active rules
141 */
142 public List<ActiveRule> getActiveRules() {
143 return getActiveRules(false);
144 }
145
146 /**
147 * @return the list of active rules
148 */
149 public List<ActiveRule> getActiveRules(boolean acceptDisabledRules) {
150 if (acceptDisabledRules) {
151 return activeRules;
152 }
153 List<ActiveRule> result = Lists.newArrayList();
154 for (ActiveRule activeRule : activeRules) {
155 if (activeRule.isEnabled()) {
156 result.add(activeRule);
157 }
158 }
159 return result;
160 }
161
162 public RulesProfile removeActiveRule(ActiveRule activeRule) {
163 activeRules.remove(activeRule);
164 return this;
165 }
166
167 public RulesProfile addActiveRule(ActiveRule activeRule) {
168 activeRules.add(activeRule);
169 return this;
170 }
171
172 /**
173 * Set the list of active rules
174 */
175 public void setActiveRules(List<ActiveRule> activeRules) {
176 this.activeRules = activeRules;
177 }
178
179 /**
180 * @return whether this is the default profile for the language
181 */
182 public Boolean getDefaultProfile() {
183 return defaultProfile;
184 }
185
186 /**
187 * Set whether this is the default profile for the language. The default profile is used when none is explicitly defined when auditing a
188 * project.
189 */
190 public void setDefaultProfile(Boolean b) {
191 this.defaultProfile = b;
192 }
193
194 /**
195 * @return whether the profile is defined in a plugin. Provided profiles are automatically restored during server startup and can not be
196 * updated by end users.
197 */
198 public Boolean getProvided() {
199 return provided;
200 }
201
202 /**
203 * Set whether the profile is provided by a plugin
204 */
205 public void setProvided(Boolean b) {
206 this.provided = b;
207 }
208
209 public Boolean getEnabled() {
210 return enabled;
211 }
212
213 public boolean isEnabled() {
214 return enabled == Boolean.TRUE;
215 }
216
217 public RulesProfile setEnabled(Boolean b) {
218 this.enabled = b;
219 return this;
220 }
221
222 /**
223 * @return the profile language
224 */
225 public String getLanguage() {
226 return language;
227 }
228
229 /**
230 * Set the profile language
231 */
232 public RulesProfile setLanguage(String s) {
233 this.language = s;
234 return this;
235 }
236
237 /**
238 * For internal use only.
239 *
240 * @since 2.5
241 */
242 public String getParentName() {
243 return parentName;
244 }
245
246 /**
247 * For internal use only.
248 *
249 * @since 2.5
250 */
251 public void setParentName(String parentName) {
252 this.parentName = parentName;
253 }
254
255 /**
256 * @return the list of alerts defined in the profile
257 */
258 public List<Alert> getAlerts() {
259 return alerts;
260 }
261
262 /**
263 * Sets the list of alerts for the profile
264 */
265 public void setAlerts(List<Alert> alerts) {
266 this.alerts = alerts;
267 }
268
269 /**
270 * @return the list of projects attached to the profile
271 */
272 public List<ResourceModel> getProjects() {
273 return projects;
274 }
275
276 /**
277 * Sets the list of projects attached to the profile
278 */
279 public void setProjects(List<ResourceModel> projects) {
280 this.projects = projects;
281 }
282
283 /**
284 * Note: disabled rules are excluded.
285 * @return the list of active rules for a given severity
286 */
287 public List<ActiveRule> getActiveRules(RulePriority severity) {
288 List<ActiveRule> result = Lists.newArrayList();
289 for (ActiveRule activeRule : activeRules) {
290 if (activeRule.getSeverity().equals(severity) && activeRule.isEnabled()) {
291 result.add(activeRule);
292 }
293 }
294 return result;
295 }
296
297 /**
298 * @deprecated since 2.3 use {@link #getActiveRulesByRepository(String)} instead.
299 */
300 @Deprecated
301 public List<ActiveRule> getActiveRulesByPlugin(String repositoryKey) {
302 return getActiveRulesByRepository(repositoryKey);
303 }
304
305 /**
306 * Get the active rules of a specific repository.
307 * Only enabled rules are selected. Disabled rules are excluded.
308 */
309 public List<ActiveRule> getActiveRulesByRepository(String repositoryKey) {
310 List<ActiveRule> result = Lists.newArrayList();
311 for (ActiveRule activeRule : activeRules) {
312 if (repositoryKey.equals(activeRule.getRepositoryKey()) && activeRule.isEnabled()) {
313 result.add(activeRule);
314 }
315 }
316 return result;
317 }
318
319 /**
320 * Note: disabled rules are excluded.
321 * @return an active rule from a plugin key and a rule key if the rule is activated, null otherwise
322 */
323 public ActiveRule getActiveRule(String repositoryKey, String ruleKey) {
324 for (ActiveRule activeRule : activeRules) {
325 if (StringUtils.equals(activeRule.getRepositoryKey(), repositoryKey) && StringUtils.equals(activeRule.getRuleKey(), ruleKey) && activeRule.isEnabled()) {
326 return activeRule;
327 }
328 }
329 return null;
330 }
331
332 /**
333 * Note: disabled rules are excluded.
334 */
335 public ActiveRule getActiveRuleByConfigKey(String repositoryKey, String configKey) {
336 for (ActiveRule activeRule : activeRules) {
337 if (StringUtils.equals(activeRule.getRepositoryKey(), repositoryKey) && StringUtils.equals(activeRule.getConfigKey(), configKey) && activeRule.isEnabled()) {
338 return activeRule;
339 }
340 }
341 return null;
342 }
343
344 /**
345 * Note: disabled rules are excluded.
346 */
347
348 public ActiveRule getActiveRule(Rule rule) {
349 return getActiveRule(rule.getRepositoryKey(), rule.getKey());
350 }
351
352 /**
353 * @param optionalSeverity if null, then the default rule severity is used
354 */
355 public ActiveRule activateRule(Rule rule, RulePriority optionalSeverity) {
356 ActiveRule activeRule = new ActiveRule();
357 activeRule.setRule(rule);
358 activeRule.setRulesProfile(this);
359 activeRule.setSeverity(optionalSeverity == null ? rule.getSeverity() : optionalSeverity);
360 activeRules.add(activeRule);
361 return activeRule;
362 }
363
364 @Override
365 public boolean equals(Object obj) {
366 if (!(obj instanceof RulesProfile)) {
367 return false;
368 }
369 if (this == obj) {
370 return true;
371 }
372 RulesProfile other = (RulesProfile) obj;
373 return new EqualsBuilder().append(language, other.getLanguage()).append(name, other.getName()).isEquals();
374 }
375
376 @Override
377 public int hashCode() {
378 return new HashCodeBuilder(17, 37).append(language).append(name).toHashCode();
379 }
380
381 @Override
382 public Object clone() {
383 RulesProfile clone = RulesProfile.create(getName(), getLanguage());
384 clone.setDefaultProfile(getDefaultProfile());
385 clone.setProvided(getProvided());
386 clone.setParentName(getParentName());
387 if (CollectionUtils.isNotEmpty(activeRules)) {
388 clone.setActiveRules(new ArrayList<ActiveRule>(CollectionUtils.collect(activeRules, new Transformer() {
389 public Object transform(Object input) {
390 return ((ActiveRule) input).clone();
391 }
392 })));
393 }
394 if (CollectionUtils.isNotEmpty(getAlerts())) {
395 clone.setAlerts(new ArrayList<Alert>(CollectionUtils.collect(getAlerts(), new Transformer() {
396 public Object transform(Object input) {
397 return ((Alert) input).clone();
398 }
399 })));
400 }
401 if (CollectionUtils.isNotEmpty(getProjects())) {
402 clone.setProjects(new ArrayList<ResourceModel>(CollectionUtils.collect(getProjects(), new Transformer() {
403 public Object transform(Object input) {
404 return ((ResourceModel) input).clone();
405 }
406 })));
407 }
408 return clone;
409 }
410
411 @Override
412 public String toString() {
413 return new StringBuilder().append("[name=").append(name).append(",language=").append(language).append("]").toString();
414 }
415
416 public static RulesProfile create(String name, String language) {
417 return new RulesProfile().setName(name).setLanguage(language);
418 }
419
420 public static RulesProfile create() {
421 return new RulesProfile();
422 }
423 }