001 /*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2008-2012 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.rules;
021
022 import org.apache.commons.lang.StringUtils;
023 import org.apache.commons.lang.builder.EqualsBuilder;
024 import org.apache.commons.lang.builder.HashCodeBuilder;
025 import org.apache.commons.lang.builder.ToStringBuilder;
026 import org.apache.commons.lang.builder.ToStringStyle;
027 import org.sonar.api.database.DatabaseProperties;
028 import org.sonar.check.Cardinality;
029
030 import javax.persistence.*;
031
032 import java.util.ArrayList;
033 import java.util.List;
034
035 @Entity
036 @Table(name = "rules")
037 public final class Rule {
038
039 @Id
040 @Column(name = "id")
041 @GeneratedValue
042 private Integer id;
043
044 /**
045 * The default priority given to a rule if not explicitly set
046 */
047 public static final RulePriority DEFAULT_PRIORITY = RulePriority.MAJOR;
048
049 @Column(name = "name", updatable = true, nullable = true, length = 200)
050 private String name;
051
052 @Column(name = "plugin_rule_key", updatable = false, nullable = true, length = 200)
053 private String key;
054
055 @Column(name = "enabled", updatable = true, nullable = true)
056 private Boolean enabled = Boolean.TRUE;
057
058 @Column(name = "plugin_config_key", updatable = true, nullable = true, length = 500)
059 private String configKey;
060
061 // Godin: This field should be named priority, otherwise StandardRulesXmlParserTest fails
062 @Column(name = "priority", updatable = true, nullable = true)
063 @Enumerated(EnumType.ORDINAL)
064 private RulePriority priority = DEFAULT_PRIORITY;
065
066 @Column(name = "description", updatable = true, nullable = true, length = DatabaseProperties.MAX_TEXT_SIZE)
067 private String description;
068
069 @Column(name = "plugin_name", updatable = true, nullable = false)
070 private String pluginName;
071
072 @Enumerated(EnumType.STRING)
073 @Column(name = "cardinality", updatable = true, nullable = false)
074 private Cardinality cardinality = Cardinality.SINGLE;
075
076 @ManyToOne(fetch = FetchType.EAGER)
077 @JoinColumn(name = "parent_id", updatable = true, nullable = true)
078 private Rule parent = null;
079
080 @org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.ALL, org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
081 @OneToMany(mappedBy = "rule")
082 private List<RuleParam> params = new ArrayList<RuleParam>();
083
084 /**
085 * @deprecated since 2.3. Use the factory method {@link #create()}
086 */
087 @Deprecated
088 public Rule() {
089 // TODO reduce visibility to package
090 }
091
092 /**
093 * Creates rule with minimum set of info
094 *
095 * @param pluginName the plugin name indicates which plugin the rule belongs to
096 * @param key the key should be unique within a plugin, but it is even more careful for the time being that it is unique across the
097 * application
098 * @deprecated since 2.3. Use the factory method {@link #create()}
099 */
100 @Deprecated
101 public Rule(String pluginName, String key) {
102 this.pluginName = pluginName;
103 this.key = key;
104 this.configKey = key;
105 }
106
107 /**
108 * Creates a fully qualified rule
109 *
110 * @param pluginKey the plugin the rule belongs to
111 * @param key the key should be unique within a plugin, but it is even more careful for the time being that it is unique across the
112 * application
113 * @param name the name displayed in the UI
114 * @param rulesCategory the ISO category the rule belongs to
115 * @param severity this is the severity associated to the rule
116 * @deprecated since 2.3. Use the factory method {@link #create()}
117 */
118 @Deprecated
119 public Rule(String pluginKey, String key, String name, RulesCategory rulesCategory, RulePriority severity) {
120 setName(name);
121 this.key = key;
122 this.configKey = key;
123 this.priority = severity;
124 this.pluginName = pluginKey;
125 }
126
127 /**
128 * @deprecated since 2.3. Use the factory method {@link #create()}
129 */
130 @Deprecated
131 public Rule(String name, String key, RulesCategory rulesCategory, String pluginName, String description) {
132 this();
133 setName(name);
134 this.key = key;
135 this.configKey = key;
136 this.pluginName = pluginName;
137 this.description = description;
138 }
139
140 /**
141 * @deprecated since 2.3. Use the factory method {@link #create()}
142 */
143 @Deprecated
144 public Rule(String name, String key, String configKey, RulesCategory rulesCategory, String pluginName, String description) {
145 this();
146 setName(name);
147 this.key = key;
148 this.configKey = configKey;
149 this.pluginName = pluginName;
150 this.description = description;
151 }
152
153 public Integer getId() {
154 return id;
155 }
156
157 /**
158 * @deprecated since 2.3. visibility should be decreased to protected or package
159 */
160 @Deprecated
161 public void setId(Integer id) {
162 this.id = id;
163 }
164
165 public String getName() {
166 return name;
167 }
168
169 /**
170 * Sets the rule name
171 */
172 public Rule setName(String name) {
173 this.name = removeNewLineCharacters(name);
174 return this;
175 }
176
177 public String getKey() {
178 return key;
179 }
180
181 /**
182 * Sets the rule key
183 */
184 public Rule setKey(String key) {
185 this.key = key;
186 return this;
187 }
188
189 /**
190 * @deprecated since 2.5 use {@link #getRepositoryKey()} instead
191 */
192 @Deprecated
193 public String getPluginName() {
194 return pluginName;
195 }
196
197 /**
198 * @deprecated since 2.5 use {@link #setRepositoryKey(String)} instead
199 */
200 @Deprecated
201 public Rule setPluginName(String pluginName) {
202 this.pluginName = pluginName;
203 return this;
204 }
205
206 public String getConfigKey() {
207 return configKey;
208 }
209
210 /**
211 * Sets the configuration key
212 */
213 public Rule setConfigKey(String configKey) {
214 this.configKey = configKey;
215 return this;
216 }
217
218 public String getDescription() {
219 return description;
220 }
221
222 /**
223 * Sets the rule description
224 */
225 public Rule setDescription(String description) {
226 this.description = StringUtils.strip(description);
227 return this;
228 }
229
230 public Boolean isEnabled() {
231 return enabled;
232 }
233
234 /**
235 * Do not call. Used only by sonar.
236 */
237 public Rule setEnabled(Boolean b) {
238 this.enabled = b;
239 return this;
240 }
241
242 public List<RuleParam> getParams() {
243 return params;
244 }
245
246 public RuleParam getParam(String key) {
247 for (RuleParam param : params) {
248 if (StringUtils.equals(key, param.getKey())) {
249 return param;
250 }
251 }
252 return null;
253 }
254
255 /**
256 * Sets the rule parameters
257 */
258 public Rule setParams(List<RuleParam> params) {
259 this.params.clear();
260 for (RuleParam param : params) {
261 param.setRule(this);
262 this.params.add(param);
263 }
264 return this;
265 }
266
267 public RuleParam createParameter() {
268 RuleParam parameter = new RuleParam()
269 .setRule(this);
270 params.add(parameter);
271 return parameter;
272 }
273
274 public RuleParam createParameter(String key) {
275 RuleParam parameter = new RuleParam()
276 .setKey(key)
277 .setRule(this);
278 params.add(parameter);
279 return parameter;
280 }
281
282 /**
283 * @deprecated since 2.5 See http://jira.codehaus.org/browse/SONAR-2007
284 */
285 @Deprecated
286 public Integer getCategoryId() {
287 return null;
288 }
289
290 /**
291 * @since 2.5
292 */
293 public RulePriority getSeverity() {
294 return priority;
295 }
296
297 /**
298 * @param severity severity to set, if null, uses the default priority.
299 * @since 2.5
300 */
301 public Rule setSeverity(RulePriority severity) {
302 if (severity == null) {
303 this.priority = DEFAULT_PRIORITY;
304 } else {
305 this.priority = severity;
306 }
307 return this;
308 }
309
310 /**
311 * @deprecated since 2.5 use {@link #getSeverity()} instead. See http://jira.codehaus.org/browse/SONAR-1829
312 */
313 @Deprecated
314 public RulePriority getPriority() {
315 return priority;
316 }
317
318 /**
319 * Sets the rule priority. If null, uses the default priority
320 *
321 * @deprecated since 2.5 use {@link #setSeverity(RulePriority)} instead. See http://jira.codehaus.org/browse/SONAR-1829
322 */
323 @Deprecated
324 public Rule setPriority(RulePriority priority) {
325 return setSeverity(priority);
326 }
327
328 public String getRepositoryKey() {
329 return pluginName;
330 }
331
332 public Rule setRepositoryKey(String s) {
333 this.pluginName = s;
334 return this;
335 }
336
337 public Rule setUniqueKey(String repositoryKey, String key) {
338 return setRepositoryKey(repositoryKey).setKey(key).setConfigKey(key);
339 }
340
341 public Cardinality getCardinality() {
342 return cardinality;
343 }
344
345 public Rule setCardinality(Cardinality c) {
346 this.cardinality = c;
347 return this;
348 }
349
350 public Rule getParent() {
351 return parent;
352 }
353
354 public Rule setParent(Rule parent) {
355 this.parent = parent;
356 return this;
357 }
358
359 @Override
360 public boolean equals(Object obj) {
361 if (!(obj instanceof Rule)) {
362 return false;
363 }
364 if (this == obj) {
365 return true;
366 }
367 Rule other = (Rule) obj;
368 return new EqualsBuilder()
369 .append(pluginName, other.getRepositoryKey())
370 .append(key, other.getKey())
371 .isEquals();
372 }
373
374 @Override
375 public int hashCode() {
376 return new HashCodeBuilder(17, 37)
377 .append(pluginName)
378 .append(key)
379 .toHashCode();
380 }
381
382 @Override
383 public String toString() {
384 // Note that ReflectionToStringBuilder will not work here - see SONAR-3077
385 return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
386 .append("id", id)
387 .append("name", name)
388 .append("key", key)
389 .append("configKey", configKey)
390 .append("plugin", pluginName)
391 .append("enabled", enabled)
392 .append("severity", priority)
393 .append("cardinality", cardinality)
394 .toString();
395 }
396
397 private String removeNewLineCharacters(String text) {
398 String removedCRLF = StringUtils.remove(text, "\n");
399 removedCRLF = StringUtils.remove(removedCRLF, "\r");
400 removedCRLF = StringUtils.remove(removedCRLF, "\n\r");
401 removedCRLF = StringUtils.remove(removedCRLF, "\r\n");
402 return removedCRLF;
403 }
404
405 public static Rule create() {
406 return new Rule();
407 }
408
409 /**
410 * Create with all required fields
411 */
412 public static Rule create(String repositoryKey, String key, String name) {
413 return new Rule().setUniqueKey(repositoryKey, key).setName(name);
414 }
415
416 /**
417 * Create with all required fields
418 *
419 * @since 2.10
420 */
421 public static Rule create(String repositoryKey, String key) {
422 return new Rule().setUniqueKey(repositoryKey, key);
423 }
424 }