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 java.util.ArrayList; 033 import java.util.List; 034 035 import javax.persistence.*; 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 = "language", updatable = true, nullable = false) 074 private String language; 075 076 @Column(name = "parent_name", updatable = true, nullable = true) 077 private String parentName; 078 079 @OneToMany(mappedBy = "rulesProfile", fetch = FetchType.LAZY, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }) 080 private List<ActiveRule> activeRules = new ArrayList<ActiveRule>(); 081 082 @OneToMany(mappedBy = "rulesProfile", fetch = FetchType.LAZY, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }) 083 private List<Alert> alerts = new ArrayList<Alert>(); 084 085 @OneToMany(mappedBy = "rulesProfile", fetch = FetchType.LAZY) 086 private List<ResourceModel> projects = new ArrayList<ResourceModel>(); 087 088 /** 089 * @deprecated use the factory method create() 090 */ 091 @Deprecated 092 public RulesProfile() { 093 } 094 095 /** 096 * @deprecated since 2.3. Use the factory method create() 097 */ 098 @Deprecated 099 public RulesProfile(String name, String language) { 100 this.name = name; 101 this.language = language; 102 this.activeRules = new ArrayList<ActiveRule>(); 103 this.alerts = new ArrayList<Alert>(); 104 this.projects = new ArrayList<ResourceModel>(); 105 } 106 107 /** 108 * @deprecated since 2.3. Use the factory method create() 109 */ 110 @Deprecated 111 public RulesProfile(String name, String language, boolean defaultProfile, boolean provided) { 112 this(name, language); 113 this.defaultProfile = defaultProfile; 114 this.provided = provided; 115 } 116 117 public Integer getId() { 118 return id; 119 } 120 121 /** 122 * @return the profile name, unique by language. 123 */ 124 public String getName() { 125 return name; 126 } 127 128 /** 129 * Set the profile name. 130 */ 131 public RulesProfile setName(String s) { 132 this.name = s; 133 return this; 134 } 135 136 /** 137 * @return the list of active rules 138 */ 139 public List<ActiveRule> getActiveRules() { 140 return activeRules; 141 } 142 143 /** 144 * Set the list of active rules 145 */ 146 public void setActiveRules(List<ActiveRule> activeRules) { 147 this.activeRules = activeRules; 148 } 149 150 /** 151 * @return whether this is the default profile for the language 152 */ 153 public Boolean getDefaultProfile() { 154 return defaultProfile; 155 } 156 157 /** 158 * Set whether this is the default profile for the language. The default profile is used when none is explicitly defined when auditing a 159 * project. 160 */ 161 public void setDefaultProfile(Boolean b) { 162 this.defaultProfile = b; 163 } 164 165 /** 166 * @return whether the profile is defined in a plugin. Provided profiles are automatically restored during server startup and can not be 167 * updated by end users. 168 */ 169 public Boolean getProvided() { 170 return provided; 171 } 172 173 /** 174 * Set whether the profile is provided by a plugin 175 */ 176 public void setProvided(Boolean b) { 177 this.provided = b; 178 } 179 180 /** 181 * @return the profile language 182 */ 183 public String getLanguage() { 184 return language; 185 } 186 187 /** 188 * Set the profile language 189 */ 190 public RulesProfile setLanguage(String s) { 191 this.language = s; 192 return this; 193 } 194 195 /** 196 * For internal use only. 197 * 198 * @since 2.5 199 */ 200 public String getParentName() { 201 return parentName; 202 } 203 204 /** 205 * For internal use only. 206 * 207 * @since 2.5 208 */ 209 public void setParentName(String parentName) { 210 this.parentName = parentName; 211 } 212 213 /** 214 * @return the list of alerts defined in the profile 215 */ 216 public List<Alert> getAlerts() { 217 return alerts; 218 } 219 220 /** 221 * Sets the list of alerts for the profile 222 */ 223 public void setAlerts(List<Alert> alerts) { 224 this.alerts = alerts; 225 } 226 227 /** 228 * @return the list of projects attached to the profile 229 */ 230 public List<ResourceModel> getProjects() { 231 return projects; 232 } 233 234 /** 235 * Sets the list of projects attached to the profile 236 */ 237 public void setProjects(List<ResourceModel> projects) { 238 this.projects = projects; 239 } 240 241 /** 242 * @return the list of active rules for a given priority 243 */ 244 public List<ActiveRule> getActiveRules(RulePriority priority) { 245 List<ActiveRule> result = new ArrayList<ActiveRule>(); 246 for (ActiveRule activeRule : getActiveRules()) { 247 if (activeRule.getSeverity().equals(priority)) { 248 result.add(activeRule); 249 } 250 } 251 return result; 252 } 253 254 /** 255 * @deprecated since 2.3 use {@link #getActiveRulesByRepository(String)} instead. 256 */ 257 @Deprecated 258 public List<ActiveRule> getActiveRulesByPlugin(String repositoryKey) { 259 return getActiveRulesByRepository(repositoryKey); 260 } 261 262 public List<ActiveRule> getActiveRulesByRepository(String repositoryKey) { 263 List<ActiveRule> result = new ArrayList<ActiveRule>(); 264 for (ActiveRule activeRule : getActiveRules()) { 265 if (repositoryKey.equals(activeRule.getRepositoryKey())) { 266 result.add(activeRule); 267 } 268 } 269 return result; 270 } 271 272 /** 273 * @return an active rule from a plugin key and a rule key if the rule is activated, null otherwise 274 */ 275 public ActiveRule getActiveRule(String repositoryKey, String ruleKey) { 276 for (ActiveRule activeRule : getActiveRules()) { 277 if (StringUtils.equals(activeRule.getRepositoryKey(), repositoryKey) && StringUtils.equals(activeRule.getRuleKey(), ruleKey)) { 278 return activeRule; 279 } 280 } 281 return null; 282 } 283 284 public ActiveRule getActiveRuleByConfigKey(String repositoryKey, String configKey) { 285 for (ActiveRule activeRule : getActiveRules()) { 286 if (StringUtils.equals(activeRule.getRepositoryKey(), repositoryKey) && StringUtils.equals(activeRule.getConfigKey(), configKey)) { 287 return activeRule; 288 } 289 } 290 return null; 291 } 292 293 public ActiveRule getActiveRule(Rule rule) { 294 return getActiveRule(rule.getRepositoryKey(), rule.getKey()); 295 } 296 297 /** 298 * @param optionalSeverity if null, then the default rule severity is used 299 */ 300 public ActiveRule activateRule(Rule rule, RulePriority optionalSeverity) { 301 ActiveRule activeRule = new ActiveRule(); 302 activeRule.setRule(rule); 303 activeRule.setRulesProfile(this); 304 activeRule.setSeverity(optionalSeverity == null ? rule.getSeverity() : optionalSeverity); 305 activeRules.add(activeRule); 306 return activeRule; 307 } 308 309 @Override 310 public boolean equals(Object obj) { 311 if (!(obj instanceof RulesProfile)) { 312 return false; 313 } 314 if (this == obj) { 315 return true; 316 } 317 RulesProfile other = (RulesProfile) obj; 318 return new EqualsBuilder().append(language, other.getLanguage()).append(name, other.getName()).isEquals(); 319 } 320 321 @Override 322 public int hashCode() { 323 return new HashCodeBuilder(17, 37).append(language).append(name).toHashCode(); 324 } 325 326 @Override 327 public Object clone() { 328 RulesProfile clone = RulesProfile.create(getName(), getLanguage()); 329 clone.setDefaultProfile(getDefaultProfile()); 330 clone.setProvided(getProvided()); 331 clone.setParentName(getParentName()); 332 if (CollectionUtils.isNotEmpty(getActiveRules())) { 333 clone.setActiveRules(new ArrayList<ActiveRule>(CollectionUtils.collect(getActiveRules(), new Transformer() { 334 public Object transform(Object input) { 335 return ((ActiveRule) input).clone(); 336 } 337 }))); 338 } 339 if (CollectionUtils.isNotEmpty(getAlerts())) { 340 clone.setAlerts(new ArrayList<Alert>(CollectionUtils.collect(getAlerts(), new Transformer() { 341 public Object transform(Object input) { 342 return ((Alert) input).clone(); 343 } 344 }))); 345 } 346 if (CollectionUtils.isNotEmpty(getProjects())) { 347 clone.setProjects(new ArrayList<ResourceModel>(CollectionUtils.collect(getProjects(), new Transformer() { 348 public Object transform(Object input) { 349 return ((ResourceModel) input).clone(); 350 } 351 }))); 352 } 353 return clone; 354 } 355 356 @Override 357 public String toString() { 358 return new StringBuilder().append("[name=").append(name).append(",language=").append(language).append("]").toString(); 359 } 360 361 public static RulesProfile create(String name, String language) { 362 return new RulesProfile().setName(name).setLanguage(language); 363 } 364 365 public static RulesProfile create() { 366 return new RulesProfile(); 367 } 368 }