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 }