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