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