From 906ab01373ae378f70156243259bac77cc1ab072 Mon Sep 17 00:00:00 2001 From: Fabrice Bellingard Date: Fri, 15 Apr 2011 16:59:39 +0200 Subject: [PATCH] [SONAR-1957] Adds "switched off" attribute on Violation class and make sure this gets set by the ViolationPersister --- .../sonar/batch/index/ViolationPersister.java | 3 +- .../batch/index/ViolationPersisterTest.java | 179 ++++--- .../index/ViolationPersisterTest/shared.xml | 48 +- ...opyPermanentIdFromPastViolation-result.xml | 52 +- ...opySwitchedOffFromPastViolation-result.xml | 27 + .../shouldInsertViolations-result.xml | 50 +- .../java/org/sonar/api/rules/Violation.java | 487 +++++++++--------- 7 files changed, 453 insertions(+), 393 deletions(-) create mode 100644 sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldCopySwitchedOffFromPastViolation-result.xml diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/ViolationPersister.java b/sonar-batch/src/main/java/org/sonar/batch/index/ViolationPersister.java index 7782e961922..cc156125a5d 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/ViolationPersister.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/ViolationPersister.java @@ -50,7 +50,7 @@ public final class ViolationPersister { if (pastViolation!=null) { model.setCreatedAt(pastViolation.getCreatedAt()); model.setPermanentId(pastViolation.getPermanentId()); - + model.setSwitchedOff(pastViolation.isSwitchedOff()); } else { // avoid plugins setting date model.setCreatedAt(snapshot.getCreatedAt()); @@ -67,6 +67,7 @@ public final class ViolationPersister { // the following fields can have been changed violation.setMessage(model.getMessage());// the message can be changed in the class RuleFailure (truncate + trim) violation.setCreatedAt(model.getCreatedAt()); + violation.setSwitchedOff(model.isSwitchedOff()); } public void commit() { diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/ViolationPersisterTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/ViolationPersisterTest.java index 66a73335dd9..d1d3b775f5c 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/ViolationPersisterTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/ViolationPersisterTest.java @@ -1,83 +1,96 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2011 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.batch.index; - -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.database.model.RuleFailureModel; -import org.sonar.api.database.model.Snapshot; -import org.sonar.api.resources.JavaFile; -import org.sonar.api.resources.Project; -import org.sonar.api.rules.Rule; -import org.sonar.api.rules.RulePriority; -import org.sonar.api.rules.Violation; -import org.sonar.core.components.DefaultRuleFinder; -import org.sonar.jpa.test.AbstractDbUnitTestCase; - -import static org.mockito.Matchers.anyObject; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class ViolationPersisterTest extends AbstractDbUnitTestCase { - - private ViolationPersister violationPersister; - private Rule rule1 = Rule.create("checkstyle", "com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck", "Check Header"); - private Rule rule2 = Rule.create("checkstyle", "com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck", "Equals Avoid Null"); - private JavaFile javaFile = new JavaFile("org.foo.Bar"); - Project project = new Project("project"); - - @Before - public void before() { - setupData("shared"); - Snapshot snapshot = getSession().getSingleResult(Snapshot.class, "id", 1000); - ResourcePersister resourcePersister = mock(ResourcePersister.class); - when(resourcePersister.saveResource((Project) anyObject(), eq(javaFile))).thenReturn(snapshot); - when(resourcePersister.getSnapshot(javaFile)).thenReturn(snapshot); - violationPersister = new ViolationPersister(getSession(), resourcePersister, new DefaultRuleFinder(getSessionFactory())); - } - - @Test - public void shouldSaveViolations() { - Violation violation1a = Violation.create(rule1, javaFile) - .setSeverity(RulePriority.CRITICAL).setLineId(20).setCost(55.6) - .setMessage("the message"); - Violation violation1b = Violation.create(rule1, javaFile) - .setSeverity(RulePriority.CRITICAL).setLineId(50).setCost(80.0); - Violation violation2 = Violation.create(rule2, javaFile) - .setSeverity(RulePriority.MINOR); - - violationPersister.saveViolation(project, violation1a); - violationPersister.saveViolation(project, violation1b); - violationPersister.saveViolation(project, violation2); - - checkTables("shouldInsertViolations", "rule_failures"); - } - - @Test - public void shouldCopyPermanentIdFromPastViolation() { - RuleFailureModel pastViolation = getSession().getSingleResult(RuleFailureModel.class, "id", 1); - - Violation violation = Violation.create(rule1, javaFile).setSeverity(RulePriority.MAJOR).setMessage("new message"); - violationPersister.saveViolation(project, violation, pastViolation, "line_checksum"); - - checkTables("shouldCopyPermanentIdFromPastViolation", "rule_failures"); - } -} +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.batch.index; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.database.model.RuleFailureModel; +import org.sonar.api.database.model.Snapshot; +import org.sonar.api.resources.JavaFile; +import org.sonar.api.resources.Project; +import org.sonar.api.rules.Rule; +import org.sonar.api.rules.RulePriority; +import org.sonar.api.rules.Violation; +import org.sonar.core.components.DefaultRuleFinder; +import org.sonar.jpa.test.AbstractDbUnitTestCase; + +import static org.mockito.Matchers.anyObject; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class ViolationPersisterTest extends AbstractDbUnitTestCase { + + private ViolationPersister violationPersister; + private Rule rule1 = Rule.create("checkstyle", "com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck", "Check Header"); + private Rule rule2 = Rule.create("checkstyle", "com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck", "Equals Avoid Null"); + private JavaFile javaFile = new JavaFile("org.foo.Bar"); + Project project = new Project("project"); + + @Before + public void before() { + setupData("shared"); + Snapshot snapshot = getSession().getSingleResult(Snapshot.class, "id", 1000); + ResourcePersister resourcePersister = mock(ResourcePersister.class); + when(resourcePersister.saveResource((Project) anyObject(), eq(javaFile))).thenReturn(snapshot); + when(resourcePersister.getSnapshot(javaFile)).thenReturn(snapshot); + violationPersister = new ViolationPersister(getSession(), resourcePersister, new DefaultRuleFinder(getSessionFactory())); + } + + @Test + public void shouldSaveViolations() { + Violation violation1a = Violation.create(rule1, javaFile) + .setSeverity(RulePriority.CRITICAL).setLineId(20).setCost(55.6) + .setMessage("the message"); + Violation violation1b = Violation.create(rule1, javaFile) + .setSeverity(RulePriority.CRITICAL).setLineId(50).setCost(80.0); + Violation violation2 = Violation.create(rule2, javaFile) + .setSeverity(RulePriority.MINOR); + + violationPersister.saveViolation(project, violation1a); + violationPersister.saveViolation(project, violation1b); + violationPersister.saveViolation(project, violation2); + + checkTables("shouldInsertViolations", "rule_failures"); + } + + @Test + public void shouldCopyPermanentIdFromPastViolation() { + RuleFailureModel pastViolation = getSession().getSingleResult(RuleFailureModel.class, "id", 1); + + Violation violation = Violation.create(rule1, javaFile).setSeverity(RulePriority.MAJOR).setMessage("new message"); + violationPersister.saveViolation(project, violation, pastViolation, "line_checksum"); + + checkTables("shouldCopyPermanentIdFromPastViolation", "rule_failures"); + } + + @Test + public void shouldCopySwitchedOffFromPastViolation() { + RuleFailureModel pastViolation1 = getSession().getSingleResult(RuleFailureModel.class, "id", 1); + Violation violation1 = Violation.create(rule1, javaFile).setSeverity(RulePriority.MAJOR).setMessage("new message"); + violationPersister.saveViolation(project, violation1, pastViolation1, "line_checksum"); + + RuleFailureModel pastViolation2 = getSession().getSingleResult(RuleFailureModel.class, "id", 2); + Violation violation2 = Violation.create(rule1, javaFile).setSeverity(RulePriority.MAJOR).setMessage("new message"); + violationPersister.saveViolation(project, violation2, pastViolation2, "line_checksum"); + + checkTables("shouldCopySwitchedOffFromPastViolation", "rule_failures"); + } +} diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shared.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shared.xml index d1aab8335e3..cc50133e0bd 100644 --- a/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shared.xml +++ b/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shared.xml @@ -1,24 +1,24 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldCopyPermanentIdFromPastViolation-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldCopyPermanentIdFromPastViolation-result.xml index cb60a28cdbb..842a7e10765 100644 --- a/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldCopyPermanentIdFromPastViolation-result.xml +++ b/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldCopyPermanentIdFromPastViolation-result.xml @@ -1,26 +1,26 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldCopySwitchedOffFromPastViolation-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldCopySwitchedOffFromPastViolation-result.xml new file mode 100644 index 00000000000..f72c573676d --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldCopySwitchedOffFromPastViolation-result.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldInsertViolations-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldInsertViolations-result.xml index 21e4bcea0f3..765a84bae8c 100644 --- a/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldInsertViolations-result.xml +++ b/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldInsertViolations-result.xml @@ -1,26 +1,26 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/rules/Violation.java b/sonar-plugin-api/src/main/java/org/sonar/api/rules/Violation.java index 284dbeffceb..fd2b06ec1c2 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/rules/Violation.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/rules/Violation.java @@ -1,234 +1,253 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2011 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.api.rules; - -import org.apache.commons.lang.builder.EqualsBuilder; -import org.apache.commons.lang.builder.HashCodeBuilder; -import org.apache.commons.lang.builder.ReflectionToStringBuilder; -import org.sonar.api.resources.Resource; - -import java.util.Date; - -/** - * A class that represents a violation. A violation happens when a resource does not respect a defined rule. - */ -public class Violation { - - private Resource resource; - private Rule rule; - private String message; - private RulePriority severity; - private Integer lineId; - private Double cost; - private Date createdAt; - - /** - * Creates of a violation from a rule. Will need to define the resource later on - * - * @deprecated since 2.3. Use the factory method create() - */ - @Deprecated - public Violation(Rule rule) { - this.rule = rule; - } - - /** - * Creates a fully qualified violation - * - * @param rule the rule that has been violated - * @param resource the resource the violation should be attached to - * @deprecated since 2.3. Use the factory method create() - */ - @Deprecated - public Violation(Rule rule, Resource resource) { - this.resource = resource; - this.rule = rule; - } - - public Resource getResource() { - return resource; - } - - /** - * Sets the resource the violation applies to - * - * @return the current object - */ - public Violation setResource(Resource resource) { - this.resource = resource; - return this; - } - - public Rule getRule() { - return rule; - } - - /** - * Sets the rule violated - * - * @return the current object - */ - public Violation setRule(Rule rule) { - this.rule = rule; - return this; - } - - public String getMessage() { - return message; - } - - /** - * Sets the violation message - * - * @return the current object - */ - public Violation setMessage(String message) { - this.message = message; - return this; - } - - /** - * @see #setLineId(Integer) - */ - public Integer getLineId() { - return lineId; - } - - /** - * Sets the violation line. Note that numbering starts from 1. - * - * @return the current object - */ - public Violation setLineId(Integer lineId) { - this.lineId = lineId; - return this; - } - - /** - * @since 2.5 - */ - public RulePriority getSeverity() { - return severity; - } - - /** - * For internal use only. - * - * @since 2.5 - */ - public Violation setSeverity(RulePriority severity) { - this.severity = severity; - return this; - } - - /** - * @deprecated since 2.5 use {@link #getSeverity()} instead. See http://jira.codehaus.org/browse/SONAR-1829 - */ - @Deprecated - public RulePriority getPriority() { - return severity; - } - - /** - * For internal use only - * - * @deprecated since 2.5 use {@link #setSeverity(RulePriority)} instead. See http://jira.codehaus.org/browse/SONAR-1829 - */ - @Deprecated - public Violation setPriority(RulePriority priority) { - this.severity = priority; - return this; - } - - /** - * @see #setCost(Double) - * @since 2.4 - */ - public Double getCost() { - return cost; - } - - /** - * The cost to fix a violation can't be precisely computed without this information. Let's take the following example : a rule forbids to - * have methods whose complexity is greater than 10. Without this field "cost", the same violation is created with a method whose - * 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 - * fix the method whose complexity is 15, and 3h5mn is required to fix the method whose complexity is 100. - * - * @since 2.4 - */ - public Violation setCost(Double d) { - this.cost = d; - return this; - } - - /** - * @since 2.5 - */ - public Date getCreatedAt() { - return createdAt; - } - - /** - * For internal use only - * - * @since 2.5 - */ - public Violation setCreatedAt(Date createdAt) { - this.createdAt = createdAt; - return this; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof Violation)) { - return false; - } - if (this == obj) { - return true; - } - Violation other = (Violation) obj; - return new EqualsBuilder() - .append(rule, other.getRule()) - .append(resource, other.getResource()) - .isEquals(); - } - - @Override - public int hashCode() { - return new HashCodeBuilder(17, 37) - .append(getRule()) - .append(getResource()) - .toHashCode(); - } - - @Override - public String toString() { - return ReflectionToStringBuilder.toString(this); - } - - public static Violation create(ActiveRule activeRule, Resource resource) { - return new Violation(activeRule.getRule()).setResource(resource); - } - - public static Violation create(Rule rule, Resource resource) { - return new Violation(rule).setResource(resource); - } - -} +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.rules; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.apache.commons.lang.builder.ReflectionToStringBuilder; +import org.sonar.api.resources.Resource; + +import java.util.Date; + +/** + * A class that represents a violation. A violation happens when a resource does not respect a defined rule. + */ +public class Violation { + + private Resource resource; + private Rule rule; + private String message; + private RulePriority severity; + private Integer lineId; + private Double cost; + private Date createdAt; + private boolean switchedOff; + + /** + * Creates of a violation from a rule. Will need to define the resource later on + * + * @deprecated since 2.3. Use the factory method create() + */ + @Deprecated + public Violation(Rule rule) { + this.rule = rule; + } + + /** + * Creates a fully qualified violation + * + * @param rule + * the rule that has been violated + * @param resource + * the resource the violation should be attached to + * @deprecated since 2.3. Use the factory method create() + */ + @Deprecated + public Violation(Rule rule, Resource resource) { + this.resource = resource; + this.rule = rule; + } + + public Resource getResource() { + return resource; + } + + /** + * Sets the resource the violation applies to + * + * @return the current object + */ + public Violation setResource(Resource resource) { + this.resource = resource; + return this; + } + + public Rule getRule() { + return rule; + } + + /** + * Sets the rule violated + * + * @return the current object + */ + public Violation setRule(Rule rule) { + this.rule = rule; + return this; + } + + public String getMessage() { + return message; + } + + /** + * Sets the violation message + * + * @return the current object + */ + public Violation setMessage(String message) { + this.message = message; + return this; + } + + /** + * @see #setLineId(Integer) + */ + public Integer getLineId() { + return lineId; + } + + /** + * Sets the violation line. Note that numbering starts from 1. + * + * @return the current object + */ + public Violation setLineId(Integer lineId) { + this.lineId = lineId; + return this; + } + + /** + * @since 2.5 + */ + public RulePriority getSeverity() { + return severity; + } + + /** + * For internal use only. + * + * @since 2.5 + */ + public Violation setSeverity(RulePriority severity) { + this.severity = severity; + return this; + } + + /** + * @deprecated since 2.5 use {@link #getSeverity()} instead. See http://jira.codehaus.org/browse/SONAR-1829 + */ + @Deprecated + public RulePriority getPriority() { + return severity; + } + + /** + * For internal use only + * + * @deprecated since 2.5 use {@link #setSeverity(RulePriority)} instead. See http://jira.codehaus.org/browse/SONAR-1829 + */ + @Deprecated + public Violation setPriority(RulePriority priority) { + this.severity = priority; + return this; + } + + /** + * @see #setCost(Double) + * @since 2.4 + */ + public Double getCost() { + return cost; + } + + /** + * The cost to fix a violation can't be precisely computed without this information. Let's take the following example : a rule forbids to + * have methods whose complexity is greater than 10. Without this field "cost", the same violation is created with a method whose + * 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 + * fix the method whose complexity is 15, and 3h5mn is required to fix the method whose complexity is 100. + * + * @since 2.4 + */ + public Violation setCost(Double d) { + this.cost = d; + return this; + } + + /** + * @since 2.5 + */ + public Date getCreatedAt() { + return createdAt; + } + + /** + * For internal use only + * + * @since 2.5 + */ + public Violation setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + return this; + } + + /** + * Switches off the current violation. This is a kind of "mute", which means the violation exists but won't be counted as an active + * violation (and thus, won't be counted in the total number of violations). + * + * @since 2.8 + * @param switchedOff + * if true, the violation is considered OFF + */ + public void setSwitchedOff(boolean switchedOff) { + this.switchedOff = switchedOff; + } + + /** + * Tells wether this violation is ON or OFF. + * + * @since 2.8 + * @return true if the violation has been switched off + */ + public boolean isSwitchedOff() { + return switchedOff; + } + + @Override + public boolean equals(Object obj) { + if ( !(obj instanceof Violation)) { + return false; + } + if (this == obj) { + return true; + } + Violation other = (Violation) obj; + return new EqualsBuilder().append(rule, other.getRule()).append(resource, other.getResource()).isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37).append(getRule()).append(getResource()).toHashCode(); + } + + @Override + public String toString() { + return ReflectionToStringBuilder.toString(this); + } + + public static Violation create(ActiveRule activeRule, Resource resource) { + return new Violation(activeRule.getRule()).setResource(resource); + } + + public static Violation create(Rule rule, Resource resource) { + return new Violation(rule).setResource(resource); + } + +} -- 2.39.5