001/*
002 * SonarQube, open source software quality management tool.
003 * Copyright (C) 2008-2013 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * SonarQube 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 * SonarQube 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 License
017 * along with this program; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
019 */
020package org.sonar.api.rules;
021
022import org.apache.commons.lang.builder.ReflectionToStringBuilder;
023import org.sonar.api.resources.Resource;
024import org.sonar.api.utils.Logs;
025
026import java.util.Date;
027
028/**
029 * A class that represents a violation. A violation happens when a resource does not respect a defined rule.
030 * @deprecated in 3.6. Replaced by {@link org.sonar.api.issue.Issue}.
031 */
032@Deprecated
033public class Violation {
034
035  private Resource resource;
036  private Rule rule;
037  private String message;
038  private RulePriority severity;
039  private Integer lineId;
040  private Double cost;
041  private Date createdAt;
042  private boolean switchedOff = false;
043  private String checksum;
044  private boolean isNew = false;
045  private boolean isManual = false;
046  private Integer permanentId;
047  private Integer personId;
048
049  /**
050   * Creates of a violation from a rule. Will need to define the resource later on
051   *
052   * @deprecated since 2.3. Use the factory method create()
053   */
054  @Deprecated
055  public Violation(Rule rule) {
056    this.rule = rule;
057  }
058
059  /**
060   * Creates a fully qualified violation
061   *
062   * @param rule     the rule that has been violated
063   * @param resource the resource the violation should be attached to
064   * @deprecated since 2.3. Use the factory method create()
065   */
066  @Deprecated
067  public Violation(Rule rule, Resource resource) {
068    this.resource = resource;
069    this.rule = rule;
070  }
071
072  public Resource getResource() {
073    return resource;
074  }
075
076  /**
077   * Sets the resource the violation applies to
078   *
079   * @return the current object
080   */
081  public Violation setResource(Resource resource) {
082    this.resource = resource;
083    return this;
084  }
085
086  public Rule getRule() {
087    return rule;
088  }
089
090  /**
091   * Sets the rule violated
092   *
093   * @return the current object
094   */
095  public Violation setRule(Rule rule) {
096    this.rule = rule;
097    return this;
098  }
099
100  public String getMessage() {
101    return message;
102  }
103
104  /**
105   * Sets the violation message
106   *
107   * @return the current object
108   */
109  public Violation setMessage(String message) {
110    this.message = message;
111    return this;
112  }
113
114  /**
115   * @return line number (numeration starts from 1), or <code>null</code> if violation doesn't belong to concrete line
116   * @see #hasLineId()
117   */
118  public Integer getLineId() {
119    return lineId;
120  }
121
122  /**
123   * Sets the violation line.
124   *
125   * @param lineId line number (numeration starts from 1), or <code>null</code> if violation doesn't belong to concrete line
126   * @return the current object
127   */
128  public Violation setLineId(Integer lineId) {
129    if (lineId != null && lineId < 1) {
130      // TODO this normalization was added in 2.8, throw exception in future versions - see http://jira.codehaus.org/browse/SONAR-2386
131      Logs.INFO.warn("line must not be less than 1 - in future versions this will cause IllegalArgumentException");
132      this.lineId = null;
133    } else {
134      this.lineId = lineId;
135    }
136    return this;
137  }
138
139  /**
140   * @return <code>true<code> if violation belongs to concrete line
141   * @since 2.8
142   */
143  public boolean hasLineId() {
144    return lineId != null;
145  }
146
147  /**
148   * @since 2.5
149   */
150  public RulePriority getSeverity() {
151    return severity;
152  }
153
154  /**
155   * For internal use only.
156   *
157   * @since 2.5
158   */
159  public Violation setSeverity(RulePriority severity) {
160    this.severity = severity;
161    return this;
162  }
163
164  /**
165   * @deprecated since 2.5 use {@link #getSeverity()} instead. See http://jira.codehaus.org/browse/SONAR-1829
166   */
167  @Deprecated
168  public RulePriority getPriority() {
169    return severity;
170  }
171
172  /**
173   * For internal use only
174   *
175   * @deprecated since 2.5 use {@link #setSeverity(RulePriority)} instead. See http://jira.codehaus.org/browse/SONAR-1829
176   */
177  @Deprecated
178  public Violation setPriority(RulePriority priority) {
179    this.severity = priority;
180    return this;
181  }
182
183  /**
184   * @see #setCost(Double)
185   * @since 2.4
186   */
187  public Double getCost() {
188    return cost;
189  }
190
191  /**
192   * The cost to fix a violation can't be precisely computed without this information. Let's take the following example : a rule forbids to
193   * have methods whose complexity is greater than 10. Without this field "cost", the same violation is created with a method whose
194   * complexity is 15 and a method whose complexity is 100. If the cost to fix one point of complexity is 0.05h, then 15mn is necessary to
195   * fix the method whose complexity is 15, and 3h5mn is required to fix the method whose complexity is 100.
196   *
197   * @since 2.4
198   */
199  public Violation setCost(Double d) {
200    if (d == null || d >= 0) {
201      this.cost = d;
202      return this;
203    } else {
204      throw new IllegalArgumentException("Cost to fix violation can't be negative or NaN");
205    }
206  }
207
208  /**
209   * @since 2.5
210   */
211  public Date getCreatedAt() {
212    return createdAt;
213  }
214
215  /**
216   * For internal use only
217   *
218   * @since 2.5
219   */
220  public Violation setCreatedAt(Date createdAt) {
221    this.createdAt = createdAt;
222    return this;
223  }
224
225  /**
226   * Switches off the current violation. This is a kind of "mute", which means the violation exists but won't be counted as an active
227   * violation (and thus, won't be counted in the total number of violations). It's usually used for false-positives.
228   * <p/>
229   * The extensions which call this method must be executed
230   *
231   * @param b if true, the violation is considered OFF
232   * @since 2.8
233   */
234  public Violation setSwitchedOff(boolean b) {
235    this.switchedOff = b;
236    return this;
237  }
238
239  /**
240   * Tells whether this violation is ON or OFF.
241   *
242   * @since 2.8
243   */
244  public boolean isSwitchedOff() {
245    return switchedOff;
246  }
247
248  /**
249   * Checksum is available in decorators executed after the barrier {@link org.sonar.api.batch.DecoratorBarriers#END_OF_VIOLATION_TRACKING}
250   */
251  public String getChecksum() {
252    return checksum;
253  }
254
255  /**
256   * For internal use only. Checksum is automatically set by Sonar. Plugins must not call this method.
257   */
258  public Violation setChecksum(String s) {
259    this.checksum = s;
260    return this;
261  }
262
263  /**
264   * A violation is considered as "new" if it has been created after the reference analysis
265   * (the "previous" analysis).
266   * This method must be used only by post-jobs and decorators depending on the barrier
267   * {@link org.sonar.api.batch.DecoratorBarriers#END_OF_VIOLATION_TRACKING}
268   *
269   * @since 2.9
270   */
271  public boolean isNew() {
272    return isNew;
273  }
274
275  /**
276   * For internal use only. MUST NOT BE SET FROM PLUGINS.
277   *
278   * @since 2.9
279   */
280  public Violation setNew(boolean b) {
281    isNew = b;
282    return this;
283  }
284
285  /**
286   * @since 2.13
287   */
288  public boolean isManual() {
289    return isManual;
290  }
291
292  /**
293   * For internal use only. MUST NOT BE SET FROM PLUGINS.
294   *
295   * @since 2.13
296   */
297  public Violation setManual(boolean b) {
298    isManual = b;
299    return this;
300  }
301
302  /**
303   * For internal use only. MUST NOT BE SET FROM PLUGINS.
304   *
305   * @since 2.13
306   */
307  public Integer getPermanentId() {
308    return permanentId;
309  }
310
311  /**
312   * For internal use only. MUST NOT BE SET FROM PLUGINS.
313   *
314   * @since 2.13
315   */
316  public Violation setPermanentId(Integer i) {
317    this.permanentId = i;
318    return this;
319  }
320
321  /**
322   * @since 2.13
323   */
324  public Integer getPersonId() {
325    return personId;
326  }
327
328  /**
329   * For internal use only.
330   * 
331   * @since 2.13
332   */
333  public Violation setPersonId(Integer i) {
334    this.personId = i;
335    return this;
336  }
337
338  @Override
339  public String toString() {
340    return ReflectionToStringBuilder.toString(this);
341  }
342
343  public static Violation create(ActiveRule activeRule, Resource resource) {
344    return new Violation(activeRule.getRule()).setResource(resource);
345  }
346
347  public static Violation create(Rule rule, Resource resource) {
348    return new Violation(rule).setResource(resource);
349  }
350
351}