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