]> source.dussan.org Git - sonarqube.git/commitdiff
Fix crlf
authorEvgeny Mandrikov <mandrikov@gmail.com>
Tue, 19 Apr 2011 15:36:14 +0000 (19:36 +0400)
committerEvgeny Mandrikov <mandrikov@gmail.com>
Wed, 20 Apr 2011 09:32:53 +0000 (13:32 +0400)
34 files changed:
COPYING
deploy-docs.sh
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ReviewsDecorator.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/ViolationPersisterDecorator.java
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ReviewsDecoratorTest.java
plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/sensors/ReviewsDecoratorTest/fixture.xml
quick-build.bat
quick-build.sh
sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java
sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
sonar-batch/src/main/java/org/sonar/batch/index/ViolationPersister.java
sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java
sonar-batch/src/test/java/org/sonar/batch/index/ViolationPersisterTest.java
sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shared.xml
sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldCopyPermanentIdFromPastViolation-result.xml
sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldCopySwitchedOffFromPastViolation-result.xml
sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldInsertViolations-result.xml
sonar-core/src/main/java/org/sonar/jpa/session/JpaDatabaseSession.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/DecoratorContext.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java
sonar-plugin-api/src/main/java/org/sonar/api/database/DatabaseSession.java
sonar-plugin-api/src/main/java/org/sonar/api/rules/Violation.java
sonar-plugin-api/src/main/java/org/sonar/api/violations/ViolationQuery.java
sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb
sonar-server/src/main/webapp/WEB-INF/app/controllers/reviews_controller.rb
sonar-server/src/main/webapp/WEB-INF/app/models/review.rb
sonar-server/src/main/webapp/WEB-INF/app/models/rule_failure.rb
sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_form.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_form_comment.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_view.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/reviews/create_comment_result.js.rjs
sonar-server/src/main/webapp/WEB-INF/app/views/reviews/create_result.js.rjs
sonar-server/src/main/webapp/WEB-INF/db/migrate/191_create_review.rb
start-mac-derby.sh

diff --git a/COPYING b/COPYING
index fc8a5de7edf437cdc98a216370faf7c757279bcb..0e4fa8aaf2049f54b1240fdefb4c1c8b93455d4f 100644 (file)
--- a/COPYING
+++ b/COPYING
@@ -1,4 +1,4 @@
-                  GNU LESSER GENERAL PUBLIC LICENSE
+                  GNU LESSER GENERAL PUBLIC LICENSE
                        Version 3, 29 June 2007
 
  Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
index 6413b469e6af0f181644f13edc3b88902613011d..6bcd4c425427ceb9c0cbc635e8f404c2cb1cca4c 100644 (file)
@@ -6,4 +6,4 @@ tar -cf docs.tar -C target/site/ .
 
 scp -i ~/.ssh/id_rsa-sonar-keypair -C -r docs.tar root@ec2-75-101-133-159.compute-1.amazonaws.com:/tmp
 
-ssh -i ~/.ssh/id_rsa-sonar-keypair root@ec2-75-101-133-159.compute-1.amazonaws.com 'tar -xf /tmp/docs.tar -C /vol/www/sonar.codehaus.org/docs'
\ No newline at end of file
+ssh -i ~/.ssh/id_rsa-sonar-keypair root@ec2-75-101-133-159.compute-1.amazonaws.com 'tar -xf /tmp/docs.tar -C /vol/www/sonar.codehaus.org/docs'
index 1faef7c4f664132f427f37869bad2ff8e2763397..c0b5b7ef94c528396a0e650da92286cbdbc6a2e5 100644 (file)
@@ -1,71 +1,71 @@
-/*\r
- * Sonar, open source software quality management tool.\r
- * Copyright (C) 2008-2011 SonarSource\r
- * mailto:contact AT sonarsource DOT com\r
- *\r
- * Sonar is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 3 of the License, or (at your option) any later version.\r
- *\r
- * Sonar is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with Sonar; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02\r
- */\r
-package org.sonar.plugins.core.sensors;\r
-\r
-import javax.persistence.EntityManager;\r
-import javax.persistence.EntityTransaction;\r
-import javax.persistence.Query;\r
-\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-import org.sonar.api.batch.Decorator;\r
-import org.sonar.api.batch.DecoratorContext;\r
-import org.sonar.api.batch.DependedUpon;\r
-import org.sonar.api.batch.DependsUpon;\r
-import org.sonar.api.database.DatabaseSession;\r
-import org.sonar.api.database.model.Snapshot;\r
-import org.sonar.api.resources.Project;\r
-import org.sonar.api.resources.Resource;\r
-import org.sonar.batch.index.ResourcePersister;\r
-\r
-/**\r
- * Decorator that currently only closes a review when its corresponding violation has been fixed.\r
- */\r
-@DependsUpon("ViolationPersisterDecorator")\r
-public class ReviewsDecorator implements Decorator {\r
-\r
-  private static final Logger LOG = LoggerFactory.getLogger(ReviewsDecorator.class);\r
-\r
-  private ResourcePersister resourcePersister;\r
-  private DatabaseSession databaseSession;\r
-\r
-  public ReviewsDecorator(ResourcePersister resourcePersister, DatabaseSession databaseSession) {\r
-    this.resourcePersister = resourcePersister;\r
-    this.databaseSession = databaseSession;\r
-  }\r
-\r
-  public boolean shouldExecuteOnProject(Project project) {\r
-    return true;\r
-  }\r
-\r
-  public void decorate(Resource resource, DecoratorContext context) {\r
-    Snapshot currentSnapshot = resourcePersister.getSnapshot(resource);\r
-    if (currentSnapshot != null) {\r
-      int resourceId = currentSnapshot.getResourceId();\r
-      int snapshotId = currentSnapshot.getId();\r
-      Query query = databaseSession.createNativeQuery("UPDATE reviews SET status='closed' " + "WHERE resource_id = " + resourceId\r
-          + " AND rule_failure_permanent_id NOT IN " + "(SELECT permanent_id FROM rule_failures WHERE snapshot_id = " + snapshotId + ")");\r
-      int rowUpdated = query.executeUpdate();\r
-      LOG.debug("- {} reviews set to 'closed' on resource #{}", rowUpdated, resourceId);\r
-      databaseSession.commit();\r
-    }\r
-  }\r
-\r
-}\r
+/*
+ * 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.plugins.core.sensors;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityTransaction;
+import javax.persistence.Query;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.batch.Decorator;
+import org.sonar.api.batch.DecoratorContext;
+import org.sonar.api.batch.DependedUpon;
+import org.sonar.api.batch.DependsUpon;
+import org.sonar.api.database.DatabaseSession;
+import org.sonar.api.database.model.Snapshot;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Resource;
+import org.sonar.batch.index.ResourcePersister;
+
+/**
+ * Decorator that currently only closes a review when its corresponding violation has been fixed.
+ */
+@DependsUpon("ViolationPersisterDecorator")
+public class ReviewsDecorator implements Decorator {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ReviewsDecorator.class);
+
+  private ResourcePersister resourcePersister;
+  private DatabaseSession databaseSession;
+
+  public ReviewsDecorator(ResourcePersister resourcePersister, DatabaseSession databaseSession) {
+    this.resourcePersister = resourcePersister;
+    this.databaseSession = databaseSession;
+  }
+
+  public boolean shouldExecuteOnProject(Project project) {
+    return true;
+  }
+
+  public void decorate(Resource resource, DecoratorContext context) {
+    Snapshot currentSnapshot = resourcePersister.getSnapshot(resource);
+    if (currentSnapshot != null) {
+      int resourceId = currentSnapshot.getResourceId();
+      int snapshotId = currentSnapshot.getId();
+      Query query = databaseSession.createNativeQuery("UPDATE reviews SET status='closed' " + "WHERE resource_id = " + resourceId
+          + " AND rule_failure_permanent_id NOT IN " + "(SELECT permanent_id FROM rule_failures WHERE snapshot_id = " + snapshotId + ")");
+      int rowUpdated = query.executeUpdate();
+      LOG.debug("- {} reviews set to 'closed' on resource #{}", rowUpdated, resourceId);
+      databaseSession.commit();
+    }
+  }
+
+}
index 455ec647f942df3cc73eae216c13e5617df10ec7..59ad0a168ca1320e6a5766189b7507fa2e34d082 100644 (file)
-/*\r
- * Sonar, open source software quality management tool.\r
- * Copyright (C) 2008-2011 SonarSource\r
- * mailto:contact AT sonarsource DOT com\r
- *\r
- * Sonar is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 3 of the License, or (at your option) any later version.\r
- *\r
- * Sonar is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with Sonar; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02\r
- */\r
-package org.sonar.plugins.core.timemachine;\r
-\r
-import com.google.common.collect.LinkedHashMultimap;\r
-import com.google.common.collect.Lists;\r
-import com.google.common.collect.Multimap;\r
-import org.apache.commons.codec.digest.DigestUtils;\r
-import org.apache.commons.io.IOUtils;\r
-import org.apache.commons.lang.ObjectUtils;\r
-import org.apache.commons.lang.StringUtils;\r
-import org.codehaus.plexus.util.StringInputStream;\r
-import org.sonar.api.batch.*;\r
-import org.sonar.api.database.model.RuleFailureModel;\r
-import org.sonar.api.database.model.SnapshotSource;\r
-import org.sonar.api.resources.Project;\r
-import org.sonar.api.resources.Resource;\r
-import org.sonar.api.rules.Rule;\r
-import org.sonar.api.rules.RuleFinder;\r
-import org.sonar.api.rules.Violation;\r
-import org.sonar.api.utils.SonarException;\r
-import org.sonar.batch.components.PastViolationsLoader;\r
-import org.sonar.batch.index.ViolationPersister;\r
-\r
-import java.io.IOException;\r
-import java.util.Collection;\r
-import java.util.Collections;\r
-import java.util.List;\r
-\r
-@DependsUpon(DecoratorBarriers.END_OF_VIOLATIONS_GENERATION)\r
-@DependedUpon("ViolationPersisterDecorator") /* temporary workaround - see NewViolationsDecorator */\r
-public class ViolationPersisterDecorator implements Decorator {\r
-\r
-  /**\r
-   * Those chars would be ignored during generation of checksums.\r
-   */\r
-  private static final String SPACE_CHARS = "\t\n\r ";\r
-\r
-  private RuleFinder ruleFinder;\r
-  private PastViolationsLoader pastViolationsLoader;\r
-  private ViolationPersister violationPersister;\r
-\r
-  List<String> checksums = Lists.newArrayList();\r
-\r
-  public ViolationPersisterDecorator(RuleFinder ruleFinder, PastViolationsLoader pastViolationsLoader, ViolationPersister violationPersister) {\r
-    this.ruleFinder = ruleFinder;\r
-    this.pastViolationsLoader = pastViolationsLoader;\r
-    this.violationPersister = violationPersister;\r
-  }\r
-\r
-  public boolean shouldExecuteOnProject(Project project) {\r
-    return true;\r
-  }\r
-\r
-  public void decorate(Resource resource, DecoratorContext context) {\r
-    if (context.getViolations().isEmpty()) {\r
-      return;\r
-    }\r
-    // Load past violations\r
-    List<RuleFailureModel> pastViolations = pastViolationsLoader.getPastViolations(resource);\r
-    // Load current source and calculate checksums\r
-    checksums = getChecksums(pastViolationsLoader.getSource(resource));\r
-    // Save violations\r
-    compareWithPastViolations(context, pastViolations);\r
-    // Clear cache\r
-    checksums.clear();\r
-  }\r
-\r
-  private void compareWithPastViolations(DecoratorContext context, List<RuleFailureModel> pastViolations) {\r
-    Multimap<Rule, RuleFailureModel> pastViolationsByRule = LinkedHashMultimap.create();\r
-    for (RuleFailureModel pastViolation : pastViolations) {\r
-      Rule rule = ruleFinder.findById(pastViolation.getRuleId());\r
-      pastViolationsByRule.put(rule, pastViolation);\r
-    }\r
-    // for each violation, search equivalent past violation\r
-    for (Violation violation : context.getViolations()) {\r
-      RuleFailureModel pastViolation = selectPastViolation(violation, pastViolationsByRule);\r
-      if (pastViolation != null) {\r
-        // remove violation, since would be updated and shouldn't affect other violations anymore\r
-        pastViolationsByRule.remove(violation.getRule(), pastViolation);\r
-      }\r
-      String checksum = getChecksumForLine(checksums, violation.getLineId());\r
-      violationPersister.saveViolation(context.getProject(), violation, pastViolation, checksum);\r
-    }\r
-    violationPersister.commit();\r
-  }\r
-\r
-  /**\r
-   * @return checksums, never null\r
-   */\r
-  private List<String> getChecksums(SnapshotSource source) {\r
-    return source == null || source.getData() == null ? Collections.<String>emptyList() : getChecksums(source.getData());\r
-  }\r
-\r
-  static List<String> getChecksums(String data) {\r
-    List<String> result = Lists.newArrayList();\r
-    StringInputStream stream = new StringInputStream(data);\r
-    try {\r
-      List<String> lines = IOUtils.readLines(stream);\r
-      for (String line : lines) {\r
-        result.add(getChecksum(line));\r
-      }\r
-    } catch (IOException e) {\r
-      throw new SonarException("Unable to calculate checksums", e);\r
-      \r
-    } finally {\r
-      IOUtils.closeQuietly(stream);\r
-    }\r
-    return result;\r
-  }\r
-\r
-  static String getChecksum(String line) {\r
-    String reducedLine = StringUtils.replaceChars(line, SPACE_CHARS, "");\r
-    return DigestUtils.md5Hex(reducedLine);\r
-  }\r
-\r
-  /**\r
-   * @return checksum or null if checksum not exists for line\r
-   */\r
-  private String getChecksumForLine(List<String> checksums, Integer line) {\r
-    if (line == null || line < 1 || line > checksums.size()) {\r
-      return null;\r
-    }\r
-    return checksums.get(line - 1);\r
-  }\r
-\r
-  /**\r
-   * Search for past violation.\r
-   */\r
-  RuleFailureModel selectPastViolation(Violation violation, Multimap<Rule, RuleFailureModel> pastViolationsByRule) {\r
-    Collection<RuleFailureModel> pastViolations = pastViolationsByRule.get(violation.getRule());\r
-    if (pastViolations==null || pastViolations.isEmpty()) {\r
-      // skip violation, if there is no past violations with same rule\r
-      return null;\r
-    }\r
-    String dbFormattedMessage = RuleFailureModel.abbreviateMessage(violation.getMessage());\r
-    RuleFailureModel found = selectPastViolationUsingLine(violation, dbFormattedMessage, pastViolations);\r
-    if (found == null) {\r
-      found = selectPastViolationUsingChecksum(violation, dbFormattedMessage, pastViolations);\r
-    }\r
-    return found;\r
-  }\r
-\r
-  /**\r
-   * Search for past violation with same message and line.\r
-   */\r
-  private RuleFailureModel selectPastViolationUsingLine(Violation violation, String dbFormattedMessage, Collection<RuleFailureModel> pastViolations) {\r
-    for (RuleFailureModel pastViolation : pastViolations) {\r
-      if (ObjectUtils.equals(violation.getLineId(), pastViolation.getLine()) && StringUtils.equals(dbFormattedMessage, pastViolation.getMessage())) {\r
-        return pastViolation;\r
-      }\r
-    }\r
-    return null;\r
-  }\r
-\r
-  /**\r
-   * Search for past violation with same message and checksum.\r
-   */\r
-  private RuleFailureModel selectPastViolationUsingChecksum(Violation violation, String dbFormattedMessage, Collection<RuleFailureModel> pastViolations) {\r
-    String checksum = getChecksumForLine(checksums, violation.getLineId());\r
-    // skip violation, which not attached to line\r
-    if (checksum == null) {\r
-      return null;\r
-    }\r
-    for (RuleFailureModel pastViolation : pastViolations) {\r
-      String pastChecksum = pastViolation.getChecksum();\r
-      if (StringUtils.equals(checksum, pastChecksum) && StringUtils.equals(dbFormattedMessage, pastViolation.getMessage())) {\r
-        return pastViolation;\r
-      }\r
-    }\r
-    return null;\r
-  }\r
-\r
-  @Override\r
-  public String toString() {\r
-    return getClass().getSimpleName();\r
-  }\r
-\r
+/*
+ * 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.plugins.core.timemachine;
+
+import com.google.common.collect.LinkedHashMultimap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Multimap;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.ObjectUtils;
+import org.apache.commons.lang.StringUtils;
+import org.codehaus.plexus.util.StringInputStream;
+import org.sonar.api.batch.*;
+import org.sonar.api.database.model.RuleFailureModel;
+import org.sonar.api.database.model.SnapshotSource;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.RuleFinder;
+import org.sonar.api.rules.Violation;
+import org.sonar.api.utils.SonarException;
+import org.sonar.batch.components.PastViolationsLoader;
+import org.sonar.batch.index.ViolationPersister;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+@DependsUpon(DecoratorBarriers.END_OF_VIOLATIONS_GENERATION)
+@DependedUpon("ViolationPersisterDecorator") /* temporary workaround - see NewViolationsDecorator */
+public class ViolationPersisterDecorator implements Decorator {
+
+  /**
+   * Those chars would be ignored during generation of checksums.
+   */
+  private static final String SPACE_CHARS = "\t\n\r ";
+
+  private RuleFinder ruleFinder;
+  private PastViolationsLoader pastViolationsLoader;
+  private ViolationPersister violationPersister;
+
+  List<String> checksums = Lists.newArrayList();
+
+  public ViolationPersisterDecorator(RuleFinder ruleFinder, PastViolationsLoader pastViolationsLoader, ViolationPersister violationPersister) {
+    this.ruleFinder = ruleFinder;
+    this.pastViolationsLoader = pastViolationsLoader;
+    this.violationPersister = violationPersister;
+  }
+
+  public boolean shouldExecuteOnProject(Project project) {
+    return true;
+  }
+
+  public void decorate(Resource resource, DecoratorContext context) {
+    if (context.getViolations().isEmpty()) {
+      return;
+    }
+    // Load past violations
+    List<RuleFailureModel> pastViolations = pastViolationsLoader.getPastViolations(resource);
+    // Load current source and calculate checksums
+    checksums = getChecksums(pastViolationsLoader.getSource(resource));
+    // Save violations
+    compareWithPastViolations(context, pastViolations);
+    // Clear cache
+    checksums.clear();
+  }
+
+  private void compareWithPastViolations(DecoratorContext context, List<RuleFailureModel> pastViolations) {
+    Multimap<Rule, RuleFailureModel> pastViolationsByRule = LinkedHashMultimap.create();
+    for (RuleFailureModel pastViolation : pastViolations) {
+      Rule rule = ruleFinder.findById(pastViolation.getRuleId());
+      pastViolationsByRule.put(rule, pastViolation);
+    }
+    // for each violation, search equivalent past violation
+    for (Violation violation : context.getViolations()) {
+      RuleFailureModel pastViolation = selectPastViolation(violation, pastViolationsByRule);
+      if (pastViolation != null) {
+        // remove violation, since would be updated and shouldn't affect other violations anymore
+        pastViolationsByRule.remove(violation.getRule(), pastViolation);
+      }
+      String checksum = getChecksumForLine(checksums, violation.getLineId());
+      violationPersister.saveViolation(context.getProject(), violation, pastViolation, checksum);
+    }
+    violationPersister.commit();
+  }
+
+  /**
+   * @return checksums, never null
+   */
+  private List<String> getChecksums(SnapshotSource source) {
+    return source == null || source.getData() == null ? Collections.<String>emptyList() : getChecksums(source.getData());
+  }
+
+  static List<String> getChecksums(String data) {
+    List<String> result = Lists.newArrayList();
+    StringInputStream stream = new StringInputStream(data);
+    try {
+      List<String> lines = IOUtils.readLines(stream);
+      for (String line : lines) {
+        result.add(getChecksum(line));
+      }
+    } catch (IOException e) {
+      throw new SonarException("Unable to calculate checksums", e);
+      
+    } finally {
+      IOUtils.closeQuietly(stream);
+    }
+    return result;
+  }
+
+  static String getChecksum(String line) {
+    String reducedLine = StringUtils.replaceChars(line, SPACE_CHARS, "");
+    return DigestUtils.md5Hex(reducedLine);
+  }
+
+  /**
+   * @return checksum or null if checksum not exists for line
+   */
+  private String getChecksumForLine(List<String> checksums, Integer line) {
+    if (line == null || line < 1 || line > checksums.size()) {
+      return null;
+    }
+    return checksums.get(line - 1);
+  }
+
+  /**
+   * Search for past violation.
+   */
+  RuleFailureModel selectPastViolation(Violation violation, Multimap<Rule, RuleFailureModel> pastViolationsByRule) {
+    Collection<RuleFailureModel> pastViolations = pastViolationsByRule.get(violation.getRule());
+    if (pastViolations==null || pastViolations.isEmpty()) {
+      // skip violation, if there is no past violations with same rule
+      return null;
+    }
+    String dbFormattedMessage = RuleFailureModel.abbreviateMessage(violation.getMessage());
+    RuleFailureModel found = selectPastViolationUsingLine(violation, dbFormattedMessage, pastViolations);
+    if (found == null) {
+      found = selectPastViolationUsingChecksum(violation, dbFormattedMessage, pastViolations);
+    }
+    return found;
+  }
+
+  /**
+   * Search for past violation with same message and line.
+   */
+  private RuleFailureModel selectPastViolationUsingLine(Violation violation, String dbFormattedMessage, Collection<RuleFailureModel> pastViolations) {
+    for (RuleFailureModel pastViolation : pastViolations) {
+      if (ObjectUtils.equals(violation.getLineId(), pastViolation.getLine()) && StringUtils.equals(dbFormattedMessage, pastViolation.getMessage())) {
+        return pastViolation;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Search for past violation with same message and checksum.
+   */
+  private RuleFailureModel selectPastViolationUsingChecksum(Violation violation, String dbFormattedMessage, Collection<RuleFailureModel> pastViolations) {
+    String checksum = getChecksumForLine(checksums, violation.getLineId());
+    // skip violation, which not attached to line
+    if (checksum == null) {
+      return null;
+    }
+    for (RuleFailureModel pastViolation : pastViolations) {
+      String pastChecksum = pastViolation.getChecksum();
+      if (StringUtils.equals(checksum, pastChecksum) && StringUtils.equals(dbFormattedMessage, pastViolation.getMessage())) {
+        return pastViolation;
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public String toString() {
+    return getClass().getSimpleName();
+  }
+
 }
index 1fd4da1748a2c0df73d8a5434add88173fa34107..256cca68c04983524d5a4b328c5481dd9d8cd5e4 100644 (file)
@@ -1,58 +1,58 @@
-/*\r
- * Sonar, open source software quality management tool.\r
- * Copyright (C) 2008-2011 SonarSource\r
- * mailto:contact AT sonarsource DOT com\r
- *\r
- * Sonar is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 3 of the License, or (at your option) any later version.\r
- *\r
- * Sonar is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with Sonar; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02\r
- */\r
-package org.sonar.plugins.core.sensors;\r
-\r
-import org.junit.Ignore;\r
-import org.junit.Test;\r
-import org.sonar.api.database.model.Snapshot;\r
-import org.sonar.api.resources.File;\r
-import org.sonar.api.resources.Resource;\r
-import org.sonar.api.utils.DateUtils;\r
-import org.sonar.batch.components.PastSnapshot;\r
-import org.sonar.batch.components.TimeMachineConfiguration;\r
-import org.sonar.batch.index.ResourcePersister;\r
-import org.sonar.jpa.test.AbstractDbUnitTestCase;\r
-\r
-import java.text.ParseException;\r
-import java.util.Arrays;\r
-\r
-import static org.mockito.Mockito.mock;\r
-import static org.mockito.Mockito.when;\r
-\r
-public class ReviewsDecoratorTest extends AbstractDbUnitTestCase {\r
-\r
-  @Test\r
-  @Ignore("DBUnit needs Hibernate mapping...")\r
-  public void shouldSaveConfigurationInSnapshotsTable() throws ParseException {\r
-    setupData("fixture");\r
-    \r
-    File resource = new File("Foo");\r
-    Snapshot snapshot = new Snapshot();\r
-    snapshot.setId(666);\r
-    snapshot.setResourceId(111);\r
-    ResourcePersister persister = mock(ResourcePersister.class);\r
-    when(persister.getSnapshot(resource)).thenReturn(snapshot);\r
-\r
-    ReviewsDecorator reviewsDecorator = new ReviewsDecorator(persister, getSession());\r
-    reviewsDecorator.decorate(resource, null);\r
-\r
-    //checkTables("shouldSaveConfigurationInSnapshotsTable", "snapshots");\r
-  }\r
-}\r
+/*
+ * 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.plugins.core.sensors;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.sonar.api.database.model.Snapshot;
+import org.sonar.api.resources.File;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.batch.components.PastSnapshot;
+import org.sonar.batch.components.TimeMachineConfiguration;
+import org.sonar.batch.index.ResourcePersister;
+import org.sonar.jpa.test.AbstractDbUnitTestCase;
+
+import java.text.ParseException;
+import java.util.Arrays;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class ReviewsDecoratorTest extends AbstractDbUnitTestCase {
+
+  @Test
+  @Ignore("DBUnit needs Hibernate mapping...")
+  public void shouldSaveConfigurationInSnapshotsTable() throws ParseException {
+    setupData("fixture");
+    
+    File resource = new File("Foo");
+    Snapshot snapshot = new Snapshot();
+    snapshot.setId(666);
+    snapshot.setResourceId(111);
+    ResourcePersister persister = mock(ResourcePersister.class);
+    when(persister.getSnapshot(resource)).thenReturn(snapshot);
+
+    ReviewsDecorator reviewsDecorator = new ReviewsDecorator(persister, getSession());
+    reviewsDecorator.decorate(resource, null);
+
+    //checkTables("shouldSaveConfigurationInSnapshotsTable", "snapshots");
+  }
+}
index 24cf1cfb55dcaf4e3c7be835dc09bce93acb7daa..ea16316886c332a44125b0460d6f987de8c57795 100644 (file)
@@ -1,53 +1,53 @@
-<dataset>\r
-\r
-  <snapshots \r
-             id="11" \r
-             project_id="555"/>\r
-  <snapshots \r
-             id="111" \r
-             project_id="555"/>\r
-  <snapshots \r
-             id="22" \r
-             project_id="666"/>\r
-  <snapshots \r
-             id="222" \r
-             project_id="666"/>\r
-\r
-  <rule_failures \r
-             id="1"\r
-             permament_id="1"\r
-             snapshot_id="11"/>\r
-  <rule_failures \r
-             id="2"\r
-             permament_id="2"\r
-             snapshot_id="22"/>\r
-  <rule_failures \r
-             id="3"\r
-             permament_id="3"\r
-             snapshot_id="22"/>\r
-  <rule_failures \r
-             id="4"\r
-             permament_id="1"\r
-             snapshot_id="111"/>\r
-  <rule_failures \r
-             id="5"\r
-             permament_id="3"\r
-             snapshot_id="222"/>\r
-\r
-  <reviews\r
-                       id="1"\r
-                       status="open"\r
-                       rule_failure_permanent_id="1"\r
-                       resource_id="555"/>\r
-  <reviews\r
-                       id="2"\r
-                       status="open"\r
-                       rule_failure_permanent_id="2"\r
-                       resource_id="666"/>\r
-  <reviews\r
-                       id="3"\r
-                       status="open"\r
-                       rule_failure_permanent_id="3"\r
-                       resource_id="666"/>\r
-\r
+<dataset>
+
+  <snapshots 
+             id="11" 
+             project_id="555"/>
+  <snapshots 
+             id="111" 
+             project_id="555"/>
+  <snapshots 
+             id="22" 
+             project_id="666"/>
+  <snapshots 
+             id="222" 
+             project_id="666"/>
+
+  <rule_failures 
+             id="1"
+             permament_id="1"
+             snapshot_id="11"/>
+  <rule_failures 
+             id="2"
+             permament_id="2"
+             snapshot_id="22"/>
+  <rule_failures 
+             id="3"
+             permament_id="3"
+             snapshot_id="22"/>
+  <rule_failures 
+             id="4"
+             permament_id="1"
+             snapshot_id="111"/>
+  <rule_failures 
+             id="5"
+             permament_id="3"
+             snapshot_id="222"/>
+
+  <reviews
+                       id="1"
+                       status="open"
+                       rule_failure_permanent_id="1"
+                       resource_id="555"/>
+  <reviews
+                       id="2"
+                       status="open"
+                       rule_failure_permanent_id="2"
+                       resource_id="666"/>
+  <reviews
+                       id="3"
+                       status="open"
+                       rule_failure_permanent_id="3"
+                       resource_id="666"/>
+
 </dataset>
\ No newline at end of file
index a72fc8a4a6add289ef355b21aaad563f6bd78aae..d83b5db50311a988bf91afcc0f6102b93e152145 100644 (file)
@@ -1,2 +1,2 @@
 set MAVEN_OPTS=-Xmx768m -XX:MaxPermSize=256m
-mvn clean install -Dtest=false -DfailIfNoTests=false -Ddev
\ No newline at end of file
+mvn clean install -Dtest=false -DfailIfNoTests=false -Ddev
index 75b97b0a50490b8654f1050bf4f0e1b530e2ce6c..f0755770766cae4c028215da3b2ea3ec2a2915b6 100755 (executable)
@@ -9,4 +9,4 @@ echo ''
 echo '-------------------------------------------------'
 
 # it is recommended to use maven 3 for faster builds
-mvn clean install -Dtest=false -DfailIfNoTests=false -Ddev
\ No newline at end of file
+mvn clean install -Dtest=false -DfailIfNoTests=false -Ddev
index 4ca401c310ab4ded8a586a40dc21f8db48d8b203..3e5caae2957e788cfaed983392d05dfe273ab168 100644 (file)
-/*\r
- * Sonar, open source software quality management tool.\r
- * Copyright (C) 2008-2011 SonarSource\r
- * mailto:contact AT sonarsource DOT com\r
- *\r
- * Sonar is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 3 of the License, or (at your option) any later version.\r
- *\r
- * Sonar is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with Sonar; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02\r
- */\r
-package org.sonar.batch;\r
-\r
-import java.util.Collection;\r
-import java.util.Date;\r
-import java.util.List;\r
-import java.util.Set;\r
-\r
-import com.google.common.collect.Lists;\r
-import org.sonar.api.batch.DecoratorContext;\r
-import org.sonar.api.batch.Event;\r
-import org.sonar.api.batch.SonarIndex;\r
-import org.sonar.api.design.Dependency;\r
-import org.sonar.api.measures.Measure;\r
-import org.sonar.api.measures.MeasuresFilter;\r
-import org.sonar.api.measures.MeasuresFilters;\r
-import org.sonar.api.measures.Metric;\r
-import org.sonar.api.resources.Project;\r
-import org.sonar.api.resources.Resource;\r
-import org.sonar.api.rules.Violation;\r
-import org.sonar.api.violations.ViolationQuery;\r
-\r
-public class DefaultDecoratorContext implements DecoratorContext {\r
-\r
-  private SonarIndex index;\r
-  private Resource resource;\r
-  private boolean readOnly = false;\r
-\r
-  private List<DecoratorContext> childrenContexts;\r
-\r
-  public DefaultDecoratorContext(Resource resource,\r
-                                 SonarIndex index,\r
-                                 List<DecoratorContext> childrenContexts) {\r
-    this.index = index;\r
-    this.resource = resource;\r
-    this.childrenContexts = childrenContexts;\r
-  }\r
-\r
-  public DefaultDecoratorContext setReadOnly(boolean b) {\r
-    readOnly = b;\r
-    childrenContexts = null;\r
-    return this;\r
-  }\r
-\r
-  public Project getProject() {\r
-    return index.getProject();\r
-  }\r
-\r
-  public List<DecoratorContext> getChildren() {\r
-    checkReadOnly("getModules");\r
-    return childrenContexts;\r
-  }\r
-\r
-  private void checkReadOnly(String methodName) {\r
-    if (readOnly) {\r
-      throw new IllegalStateException("Method DecoratorContext." + methodName + "() can not be executed on children.");\r
-    }\r
-  }\r
-\r
-  public <M> M getMeasures(MeasuresFilter<M> filter) {\r
-    return index.getMeasures(resource, filter);\r
-  }\r
-\r
-  public Measure getMeasure(Metric metric) {\r
-    return index.getMeasure(resource, metric);\r
-  }\r
-\r
-  public Collection<Measure> getChildrenMeasures(MeasuresFilter filter) {\r
-    List<Measure> result = Lists.newArrayList();\r
-    for (DecoratorContext childContext : childrenContexts) {\r
-      Object childResult = childContext.getMeasures(filter);\r
-      if (childResult != null) {\r
-        if (childResult instanceof Collection) {\r
-          result.addAll((Collection) childResult);\r
-        } else {\r
-          result.add((Measure) childResult);\r
-        }\r
-      }\r
-    }\r
-    return result;\r
-  }\r
-\r
-  public Collection<Measure> getChildrenMeasures(Metric metric) {\r
-    return getChildrenMeasures(MeasuresFilters.metric(metric));\r
-  }\r
-\r
-  public Resource getResource() {\r
-    return resource;\r
-  }\r
-\r
-  public DecoratorContext saveMeasure(Measure measure) {\r
-    checkReadOnly("saveMeasure");\r
-    index.addMeasure(resource, measure);\r
-    return this;\r
-  }\r
-\r
-  public DecoratorContext saveMeasure(Metric metric, Double value) {\r
-    checkReadOnly("saveMeasure");\r
-    index.addMeasure(resource, new Measure(metric, value));\r
-    return this;\r
-  }\r
-\r
-  /**\r
-  * {@inheritDoc}\r
-  */\r
-  public List<Violation> getViolations(ViolationQuery violationQuery) {\r
-    return index.getViolations(violationQuery);\r
-  }\r
-  \r
-  /**\r
-  * {@inheritDoc}\r
-  */\r
-  public List<Violation> getViolations() {\r
-    return index.getViolations(resource);\r
-  }\r
-\r
-  public Dependency saveDependency(Dependency dependency) {\r
-    checkReadOnly("addDependency");\r
-    return index.addDependency(dependency);\r
-  }\r
-\r
-  public Set<Dependency> getDependencies() {\r
-    return index.getDependencies();\r
-  }\r
-\r
-  public Collection<Dependency> getIncomingDependencies() {\r
-    return index.getIncomingEdges(resource);\r
-  }\r
-\r
-  public Collection<Dependency> getOutgoingDependencies() {\r
-    return index.getOutgoingEdges(resource);\r
-  }\r
-\r
-  public List<Event> getEvents() {\r
-    return index.getEvents(resource);\r
-  }\r
-\r
-  public Event createEvent(String name, String description, String category, Date date) {\r
-    return index.addEvent(resource, name, description, category, date);\r
-  }\r
-\r
-  public void deleteEvent(Event event) {\r
-    index.deleteEvent(event);\r
-  }\r
-\r
-  public DefaultDecoratorContext saveViolation(Violation violation, boolean force) {\r
-    if (violation.getResource() == null) {\r
-      violation.setResource(resource);\r
-    }\r
-    index.addViolation(violation, force);\r
-    return this;\r
-  }\r
-\r
-  public DefaultDecoratorContext saveViolation(Violation violation) {\r
-    return saveViolation(violation, false);\r
-  }\r
-}\r
+/*
+ * 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;
+
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+import com.google.common.collect.Lists;
+import org.sonar.api.batch.DecoratorContext;
+import org.sonar.api.batch.Event;
+import org.sonar.api.batch.SonarIndex;
+import org.sonar.api.design.Dependency;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.measures.MeasuresFilter;
+import org.sonar.api.measures.MeasuresFilters;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.rules.Violation;
+import org.sonar.api.violations.ViolationQuery;
+
+public class DefaultDecoratorContext implements DecoratorContext {
+
+  private SonarIndex index;
+  private Resource resource;
+  private boolean readOnly = false;
+
+  private List<DecoratorContext> childrenContexts;
+
+  public DefaultDecoratorContext(Resource resource,
+                                 SonarIndex index,
+                                 List<DecoratorContext> childrenContexts) {
+    this.index = index;
+    this.resource = resource;
+    this.childrenContexts = childrenContexts;
+  }
+
+  public DefaultDecoratorContext setReadOnly(boolean b) {
+    readOnly = b;
+    childrenContexts = null;
+    return this;
+  }
+
+  public Project getProject() {
+    return index.getProject();
+  }
+
+  public List<DecoratorContext> getChildren() {
+    checkReadOnly("getModules");
+    return childrenContexts;
+  }
+
+  private void checkReadOnly(String methodName) {
+    if (readOnly) {
+      throw new IllegalStateException("Method DecoratorContext." + methodName + "() can not be executed on children.");
+    }
+  }
+
+  public <M> M getMeasures(MeasuresFilter<M> filter) {
+    return index.getMeasures(resource, filter);
+  }
+
+  public Measure getMeasure(Metric metric) {
+    return index.getMeasure(resource, metric);
+  }
+
+  public Collection<Measure> getChildrenMeasures(MeasuresFilter filter) {
+    List<Measure> result = Lists.newArrayList();
+    for (DecoratorContext childContext : childrenContexts) {
+      Object childResult = childContext.getMeasures(filter);
+      if (childResult != null) {
+        if (childResult instanceof Collection) {
+          result.addAll((Collection) childResult);
+        } else {
+          result.add((Measure) childResult);
+        }
+      }
+    }
+    return result;
+  }
+
+  public Collection<Measure> getChildrenMeasures(Metric metric) {
+    return getChildrenMeasures(MeasuresFilters.metric(metric));
+  }
+
+  public Resource getResource() {
+    return resource;
+  }
+
+  public DecoratorContext saveMeasure(Measure measure) {
+    checkReadOnly("saveMeasure");
+    index.addMeasure(resource, measure);
+    return this;
+  }
+
+  public DecoratorContext saveMeasure(Metric metric, Double value) {
+    checkReadOnly("saveMeasure");
+    index.addMeasure(resource, new Measure(metric, value));
+    return this;
+  }
+
+  /**
+  * {@inheritDoc}
+  */
+  public List<Violation> getViolations(ViolationQuery violationQuery) {
+    return index.getViolations(violationQuery);
+  }
+  
+  /**
+  * {@inheritDoc}
+  */
+  public List<Violation> getViolations() {
+    return index.getViolations(resource);
+  }
+
+  public Dependency saveDependency(Dependency dependency) {
+    checkReadOnly("addDependency");
+    return index.addDependency(dependency);
+  }
+
+  public Set<Dependency> getDependencies() {
+    return index.getDependencies();
+  }
+
+  public Collection<Dependency> getIncomingDependencies() {
+    return index.getIncomingEdges(resource);
+  }
+
+  public Collection<Dependency> getOutgoingDependencies() {
+    return index.getOutgoingEdges(resource);
+  }
+
+  public List<Event> getEvents() {
+    return index.getEvents(resource);
+  }
+
+  public Event createEvent(String name, String description, String category, Date date) {
+    return index.addEvent(resource, name, description, category, date);
+  }
+
+  public void deleteEvent(Event event) {
+    index.deleteEvent(event);
+  }
+
+  public DefaultDecoratorContext saveViolation(Violation violation, boolean force) {
+    if (violation.getResource() == null) {
+      violation.setResource(resource);
+    }
+    index.addViolation(violation, force);
+    return this;
+  }
+
+  public DefaultDecoratorContext saveViolation(Violation violation) {
+    return saveViolation(violation, false);
+  }
+}
index b8f42c96040f2f882e1e7bf7032d53803024b859..5b4dd14c5fdf68cb03f1ca5b0e712680a4c5cfde 100644 (file)
-/*\r
- * Sonar, open source software quality management tool.\r
- * Copyright (C) 2008-2011 SonarSource\r
- * mailto:contact AT sonarsource DOT com\r
- *\r
- * Sonar is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 3 of the License, or (at your option) any later version.\r
- *\r
- * Sonar is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with Sonar; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02\r
- */\r
-package org.sonar.batch.index;\r
-\r
-import com.google.common.collect.Lists;\r
-import com.google.common.collect.Maps;\r
-import com.google.common.collect.Sets;\r
-import org.apache.commons.lang.ObjectUtils;\r
-import org.apache.commons.lang.StringUtils;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-import org.sonar.api.batch.Event;\r
-import org.sonar.api.batch.SonarIndex;\r
-import org.sonar.api.database.model.ResourceModel;\r
-import org.sonar.api.design.Dependency;\r
-import org.sonar.api.measures.*;\r
-import org.sonar.api.profiles.RulesProfile;\r
-import org.sonar.api.resources.*;\r
-import org.sonar.api.rules.ActiveRule;\r
-import org.sonar.api.rules.Violation;\r
-import org.sonar.api.utils.SonarException;\r
-import org.sonar.api.violations.ViolationQuery;\r
-import org.sonar.batch.DefaultResourceCreationLock;\r
-import org.sonar.batch.ProjectTree;\r
-import org.sonar.batch.ResourceFilters;\r
-import org.sonar.batch.ViolationFilters;\r
-\r
-import java.util.*;\r
-\r
-public class DefaultIndex extends SonarIndex {\r
-\r
-  private static final Logger LOG = LoggerFactory.getLogger(DefaultIndex.class);\r
-\r
-  private RulesProfile profile;\r
-  private PersistenceManager persistence;\r
-  private DefaultResourceCreationLock lock;\r
-  private MetricFinder metricFinder;\r
-\r
-  // filters\r
-  private ViolationFilters violationFilters;\r
-  private ResourceFilters resourceFilters;\r
-\r
-  // caches\r
-  private Project currentProject;\r
-  private Map<Resource, Bucket> buckets = Maps.newHashMap();\r
-  private Set<Dependency> dependencies = Sets.newHashSet();\r
-  private Map<Resource, Map<Resource, Dependency>> outgoingDependenciesByResource = Maps.newHashMap();\r
-  private Map<Resource, Map<Resource, Dependency>> incomingDependenciesByResource = Maps.newHashMap();\r
-  private ProjectTree projectTree;\r
-\r
-  public DefaultIndex(PersistenceManager persistence, DefaultResourceCreationLock lock, ProjectTree projectTree, MetricFinder metricFinder) {\r
-    this.persistence = persistence;\r
-    this.lock = lock;\r
-    this.projectTree = projectTree;\r
-    this.metricFinder = metricFinder;\r
-  }\r
-\r
-  public void start() {\r
-    Project rootProject = projectTree.getRootProject();\r
-    doStart(rootProject);\r
-  }\r
-\r
-  void doStart(Project rootProject) {\r
-    Bucket bucket = new Bucket(rootProject);\r
-    buckets.put(rootProject, bucket);\r
-    persistence.saveProject(rootProject, null);\r
-    currentProject = rootProject;\r
-\r
-    for (Project project : rootProject.getModules()) {\r
-      addProject(project);\r
-    }\r
-  }\r
-\r
-  private void addProject(Project project) {\r
-    addResource(project);\r
-    for (Project module : project.getModules()) {\r
-      addProject(module);\r
-    }\r
-  }\r
-\r
-  public Project getProject() {\r
-    return currentProject;\r
-  }\r
-\r
-  public void setCurrentProject(Project project, ResourceFilters resourceFilters, ViolationFilters violationFilters, RulesProfile profile) {\r
-    this.currentProject = project;\r
-\r
-    // the following components depend on the current project, so they need to be reloaded.\r
-    this.resourceFilters = resourceFilters;\r
-    this.violationFilters = violationFilters;\r
-    this.profile = profile;\r
-  }\r
-\r
-  /**\r
-   * Keep only project stuff\r
-   */\r
-  public void clear() {\r
-    Iterator<Map.Entry<Resource, Bucket>> it = buckets.entrySet().iterator();\r
-    while (it.hasNext()) {\r
-      Map.Entry<Resource, Bucket> entry = it.next();\r
-      Resource resource = entry.getKey();\r
-      if (!ResourceUtils.isSet(resource)) {\r
-        entry.getValue().clear();\r
-        it.remove();\r
-      }\r
-    }\r
-\r
-    Set<Dependency> projectDependencies = getDependenciesBetweenProjects();\r
-    dependencies.clear();\r
-    incomingDependenciesByResource.clear();\r
-    outgoingDependenciesByResource.clear();\r
-    for (Dependency projectDependency : projectDependencies) {\r
-      projectDependency.setId(null);\r
-      registerDependency(projectDependency);\r
-    }\r
-\r
-    lock.unlock();\r
-  }\r
-\r
-  public Measure getMeasure(Resource resource, Metric metric) {\r
-    Bucket bucket = buckets.get(resource);\r
-    if (bucket != null) {\r
-      Measure measure = bucket.getMeasures(MeasuresFilters.metric(metric));\r
-      if (measure != null) {\r
-        return persistence.reloadMeasure(measure);\r
-      }\r
-    }\r
-    return null;\r
-  }\r
-\r
-  public <M> M getMeasures(Resource resource, MeasuresFilter<M> filter) {\r
-    Bucket bucket = buckets.get(resource);\r
-    if (bucket != null) {\r
-      // TODO the data measures which are not kept in memory are not reloaded yet. Use getMeasure().\r
-      return bucket.getMeasures(filter);\r
-    }\r
-    return null;\r
-  }\r
-\r
-  /**\r
-   * the measure is updated if it's already registered.\r
-   */\r
-  public Measure addMeasure(Resource resource, Measure measure) {\r
-    Bucket bucket = checkIndexed(resource);\r
-    if (bucket != null && !bucket.isExcluded()) {\r
-      Metric metric = metricFinder.findByKey(measure.getMetricKey());\r
-      if (metric == null) {\r
-        throw new SonarException("Unknown metric: " + measure.getMetricKey());\r
-      }\r
-      measure.setMetric(metric);\r
-      bucket.addMeasure(measure);\r
-\r
-      if (measure.getPersistenceMode().useDatabase()) {\r
-        persistence.saveMeasure(resource, measure);\r
-      }\r
-    }\r
-    return measure;\r
-  }\r
-\r
-  //\r
-  //\r
-  //\r
-  // DEPENDENCIES\r
-  //\r
-  //\r
-  //\r
-\r
-  public Dependency addDependency(Dependency dependency) {\r
-    Dependency existingDep = getEdge(dependency.getFrom(), dependency.getTo());\r
-    if (existingDep != null) {\r
-      return existingDep;\r
-    }\r
-\r
-    Dependency parentDependency = dependency.getParent();\r
-    if (parentDependency != null) {\r
-      addDependency(parentDependency);\r
-    }\r
-\r
-    if (registerDependency(dependency)) {\r
-      persistence.saveDependency(currentProject, dependency, parentDependency);\r
-    }\r
-    return dependency;\r
-  }\r
-\r
-  boolean registerDependency(Dependency dependency) {\r
-    Bucket fromBucket = doIndex(dependency.getFrom());\r
-    Bucket toBucket = doIndex(dependency.getTo());\r
-\r
-    if (fromBucket != null && !fromBucket.isExcluded() && toBucket != null && !toBucket.isExcluded()) {\r
-      dependencies.add(dependency);\r
-      registerOutgoingDependency(dependency);\r
-      registerIncomingDependency(dependency);\r
-      return true;\r
-    }\r
-    return false;\r
-  }\r
-\r
-  private void registerOutgoingDependency(Dependency dependency) {\r
-    Map<Resource, Dependency> outgoingDeps = outgoingDependenciesByResource.get(dependency.getFrom());\r
-    if (outgoingDeps == null) {\r
-      outgoingDeps = new HashMap<Resource, Dependency>();\r
-      outgoingDependenciesByResource.put(dependency.getFrom(), outgoingDeps);\r
-    }\r
-    outgoingDeps.put(dependency.getTo(), dependency);\r
-  }\r
-\r
-  private void registerIncomingDependency(Dependency dependency) {\r
-    Map<Resource, Dependency> incomingDeps = incomingDependenciesByResource.get(dependency.getTo());\r
-    if (incomingDeps == null) {\r
-      incomingDeps = new HashMap<Resource, Dependency>();\r
-      incomingDependenciesByResource.put(dependency.getTo(), incomingDeps);\r
-    }\r
-    incomingDeps.put(dependency.getFrom(), dependency);\r
-  }\r
-\r
-  public Set<Dependency> getDependencies() {\r
-    return dependencies;\r
-  }\r
-\r
-  public Dependency getEdge(Resource from, Resource to) {\r
-    Map<Resource, Dependency> map = outgoingDependenciesByResource.get(from);\r
-    if (map != null) {\r
-      return map.get(to);\r
-    }\r
-    return null;\r
-  }\r
-\r
-  public boolean hasEdge(Resource from, Resource to) {\r
-    return getEdge(from, to) != null;\r
-  }\r
-\r
-  public Set<Resource> getVertices() {\r
-    return buckets.keySet();\r
-  }\r
-\r
-  public Collection<Dependency> getOutgoingEdges(Resource from) {\r
-    Map<Resource, Dependency> deps = outgoingDependenciesByResource.get(from);\r
-    if (deps != null) {\r
-      return deps.values();\r
-    }\r
-    return Collections.emptyList();\r
-  }\r
-\r
-  public Collection<Dependency> getIncomingEdges(Resource to) {\r
-    Map<Resource, Dependency> deps = incomingDependenciesByResource.get(to);\r
-    if (deps != null) {\r
-      return deps.values();\r
-    }\r
-    return Collections.emptyList();\r
-  }\r
-\r
-  Set<Dependency> getDependenciesBetweenProjects() {\r
-    Set<Dependency> result = Sets.newLinkedHashSet();\r
-    for (Dependency dependency : dependencies) {\r
-      if (ResourceUtils.isSet(dependency.getFrom()) || ResourceUtils.isSet(dependency.getTo())) {\r
-        result.add(dependency);\r
-      }\r
-    }\r
-    return result;\r
-  }\r
-\r
-  //\r
-  //\r
-  //\r
-  // VIOLATIONS\r
-  //\r
-  //\r
-  //\r
-\r
-  /**\r
-   * {@inheritDoc}\r
-   */\r
-  public List<Violation> getViolations(ViolationQuery violationQuery) {\r
-    Resource resource = violationQuery.getResource();\r
-    if (resource == null) {\r
-      throw new IllegalArgumentException("A resource must be set on the ViolationQuery in order to search for violations.");\r
-    }\r
-    Bucket bucket = buckets.get(resource);\r
-    if (bucket == null) {\r
-      return Collections.emptyList();\r
-    }\r
-    List<Violation> filteredViolations = Lists.newArrayList();\r
-    boolean ignoreSwitchedOff = violationQuery.ignoreSwitchedOff();\r
-    for (Violation violation : bucket.getViolations()) {\r
-      if ( ignoreSwitchedOff && violation.isSwitchedOff()) {\r
-        continue;\r
-      }\r
-      filteredViolations.add(violation);\r
-    }\r
-    return filteredViolations;\r
-  }\r
-\r
-  public void addViolation(Violation violation, boolean force) {\r
-    Resource resource = violation.getResource();\r
-    if (resource == null) {\r
-      violation.setResource(currentProject);\r
-    } else if (!Scopes.isHigherThanOrEquals(resource, Scopes.FILE)) {\r
-      throw new IllegalArgumentException("Violations are only supported on files, directories and project");\r
-    }\r
-\r
-    if (violation.getRule() == null) {\r
-      LOG.warn("Rule is null, ignoring violation {}", violation);\r
-      return;\r
-    }\r
-\r
-    Bucket bucket = checkIndexed(resource);\r
-    if (bucket != null && !bucket.isExcluded()) {\r
-      boolean isIgnored = !force && violationFilters != null && violationFilters.isIgnored(violation);\r
-      if (!isIgnored) {\r
-        ActiveRule activeRule = profile.getActiveRule(violation.getRule());\r
-        if (activeRule == null) {\r
-          if (currentProject.getReuseExistingRulesConfig()) {\r
-            violation.setSeverity(violation.getRule().getSeverity());\r
-            doAddViolation(violation, bucket);\r
-\r
-          } else {\r
-            LoggerFactory.getLogger(getClass()).debug("Rule is not activated, ignoring violation {}", violation);\r
-          }\r
-\r
-        } else {\r
-          violation.setSeverity(activeRule.getSeverity());\r
-          doAddViolation(violation, bucket);\r
-        }\r
-      }\r
-    }\r
-  }\r
-\r
-  private void doAddViolation(Violation violation, Bucket bucket) {\r
-    bucket.addViolation(violation);\r
-  }\r
-\r
-  //\r
-  //\r
-  //\r
-  // LINKS\r
-  //\r
-  //\r
-  //\r
-\r
-  public void addLink(ProjectLink link) {\r
-    persistence.saveLink(currentProject, link);\r
-  }\r
-\r
-  public void deleteLink(String key) {\r
-    persistence.deleteLink(currentProject, key);\r
-  }\r
-\r
-  //\r
-  //\r
-  //\r
-  // EVENTS\r
-  //\r
-  //\r
-  //\r
-\r
-  public List<Event> getEvents(Resource resource) {\r
-    // currently events are not cached in memory\r
-    return persistence.getEvents(resource);\r
-  }\r
-\r
-  public void deleteEvent(Event event) {\r
-    persistence.deleteEvent(event);\r
-  }\r
-\r
-  public Event addEvent(Resource resource, String name, String description, String category, Date date) {\r
-    Event event = new Event(name, description, category);\r
-    event.setDate(date);\r
-    persistence.saveEvent(resource, event);\r
-    return null;\r
-  }\r
-\r
-  public void setSource(Resource reference, String source) {\r
-    Bucket bucket = checkIndexed(reference);\r
-    if (bucket != null && !bucket.isExcluded()) {\r
-      persistence.setSource(reference, source);\r
-    }\r
-  }\r
-\r
-  /**\r
-   * Does nothing if the resource is already registered.\r
-   */\r
-  public Resource addResource(Resource resource) {\r
-    Bucket bucket = doIndex(resource);\r
-    return bucket != null ? bucket.getResource() : null;\r
-  }\r
-\r
-  public <R extends Resource> R getResource(R reference) {\r
-    Bucket bucket = buckets.get(reference);\r
-    if (bucket != null) {\r
-      return (R) bucket.getResource();\r
-    }\r
-    return null;\r
-  }\r
-\r
-  static String createUID(Project project, Resource resource) {\r
-    String uid = resource.getKey();\r
-    if (!StringUtils.equals(Scopes.PROJECT, resource.getScope())) {\r
-      // not a project nor a library\r
-      uid = new StringBuilder(ResourceModel.KEY_SIZE)\r
-          .append(project.getKey())\r
-          .append(':')\r
-          .append(resource.getKey())\r
-          .toString();\r
-    }\r
-    return uid;\r
-  }\r
-\r
-  private boolean checkExclusion(Resource resource, Bucket parent) {\r
-    boolean excluded = (parent != null && parent.isExcluded()) || (resourceFilters != null && resourceFilters.isExcluded(resource));\r
-    resource.setExcluded(excluded);\r
-    return excluded;\r
-  }\r
-\r
-  public List<Resource> getChildren(Resource resource) {\r
-    return getChildren(resource, false);\r
-  }\r
-\r
-  public List<Resource> getChildren(Resource resource, boolean acceptExcluded) {\r
-    List<Resource> children = Lists.newLinkedList();\r
-    Bucket bucket = getBucket(resource, acceptExcluded);\r
-    if (bucket != null) {\r
-      for (Bucket childBucket : bucket.getChildren()) {\r
-        if (acceptExcluded || !childBucket.isExcluded()) {\r
-          children.add(childBucket.getResource());\r
-        }\r
-      }\r
-    }\r
-    return children;\r
-  }\r
-\r
-  public Resource getParent(Resource resource) {\r
-    Bucket bucket = getBucket(resource, false);\r
-    if (bucket != null && bucket.getParent() != null) {\r
-      return bucket.getParent().getResource();\r
-    }\r
-    return null;\r
-  }\r
-\r
-  public boolean index(Resource resource) {\r
-    Bucket bucket = doIndex(resource);\r
-    return bucket != null && !bucket.isExcluded();\r
-  }\r
-\r
-  private Bucket doIndex(Resource resource) {\r
-    if (resource.getParent() != null) {\r
-      doIndex(resource.getParent());\r
-    }\r
-    return doIndex(resource, resource.getParent());\r
-  }\r
-\r
-  public boolean index(Resource resource, Resource parentReference) {\r
-    Bucket bucket = doIndex(resource, parentReference);\r
-    return bucket != null && !bucket.isExcluded();\r
-  }\r
-\r
-  private Bucket doIndex(Resource resource, Resource parentReference) {\r
-    Bucket bucket = buckets.get(resource);\r
-    if (bucket != null) {\r
-      return bucket;\r
-    }\r
-\r
-    checkLock(resource);\r
-\r
-    Resource parent = null;\r
-    if (!ResourceUtils.isLibrary(resource)) {\r
-      // a library has no parent\r
-      parent = (Resource) ObjectUtils.defaultIfNull(parentReference, currentProject);\r
-    }\r
-\r
-    Bucket parentBucket = getBucket(parent, true);\r
-    if (parentBucket == null && parent != null) {\r
-      LOG.warn("Resource ignored, parent is not indexed: " + resource);\r
-      return null;\r
-    }\r
-\r
-    resource.setEffectiveKey(createUID(currentProject, resource));\r
-    bucket = new Bucket(resource).setParent(parentBucket);\r
-    buckets.put(resource, bucket);\r
-\r
-    boolean excluded = checkExclusion(resource, parentBucket);\r
-    if (!excluded) {\r
-      persistence.saveResource(currentProject, resource, (parentBucket != null ? parentBucket.getResource() : null));\r
-    }\r
-    return bucket;\r
-  }\r
-\r
-  private void checkLock(Resource resource) {\r
-    if (lock.isLocked() && !ResourceUtils.isLibrary(resource)) {\r
-      if (lock.isFailWhenLocked()) {\r
-        throw new SonarException("Index is locked, resource can not be indexed: " + resource);\r
-      }\r
-    }\r
-  }\r
-\r
-  private Bucket checkIndexed(Resource resource) {\r
-    Bucket bucket = getBucket(resource, true);\r
-    if (bucket == null) {\r
-      if (lock.isLocked()) {\r
-        if (lock.isFailWhenLocked()) {\r
-          throw new ResourceNotIndexedException(resource);\r
-        }\r
-        LOG.warn("Resource will be ignored in next Sonar versions, index is locked: " + resource);\r
-      }\r
-      if (Scopes.isDirectory(resource) || Scopes.isFile(resource)) {\r
-        bucket = doIndex(resource);\r
-      } else if (!lock.isLocked()) {\r
-        LOG.warn("Resource will be ignored in next Sonar versions, it must be indexed before adding data: " + resource);\r
-      }\r
-    }\r
-    return bucket;\r
-  }\r
-\r
-  public boolean isExcluded(Resource reference) {\r
-    Bucket bucket = getBucket(reference, true);\r
-    return bucket != null && bucket.isExcluded();\r
-  }\r
-\r
-  public boolean isIndexed(Resource reference, boolean acceptExcluded) {\r
-    return getBucket(reference, acceptExcluded) != null;\r
-  }\r
-\r
-  private Bucket getBucket(Resource resource, boolean acceptExcluded) {\r
-    Bucket bucket = null;\r
-    if (resource != null) {\r
-      bucket = buckets.get(resource);\r
-      if (!acceptExcluded && bucket != null && bucket.isExcluded()) {\r
-        bucket = null;\r
-      }\r
-    }\r
-    return bucket;\r
-  }\r
-}\r
+/*
+ * 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 com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.apache.commons.lang.ObjectUtils;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.batch.Event;
+import org.sonar.api.batch.SonarIndex;
+import org.sonar.api.database.model.ResourceModel;
+import org.sonar.api.design.Dependency;
+import org.sonar.api.measures.*;
+import org.sonar.api.profiles.RulesProfile;
+import org.sonar.api.resources.*;
+import org.sonar.api.rules.ActiveRule;
+import org.sonar.api.rules.Violation;
+import org.sonar.api.utils.SonarException;
+import org.sonar.api.violations.ViolationQuery;
+import org.sonar.batch.DefaultResourceCreationLock;
+import org.sonar.batch.ProjectTree;
+import org.sonar.batch.ResourceFilters;
+import org.sonar.batch.ViolationFilters;
+
+import java.util.*;
+
+public class DefaultIndex extends SonarIndex {
+
+  private static final Logger LOG = LoggerFactory.getLogger(DefaultIndex.class);
+
+  private RulesProfile profile;
+  private PersistenceManager persistence;
+  private DefaultResourceCreationLock lock;
+  private MetricFinder metricFinder;
+
+  // filters
+  private ViolationFilters violationFilters;
+  private ResourceFilters resourceFilters;
+
+  // caches
+  private Project currentProject;
+  private Map<Resource, Bucket> buckets = Maps.newHashMap();
+  private Set<Dependency> dependencies = Sets.newHashSet();
+  private Map<Resource, Map<Resource, Dependency>> outgoingDependenciesByResource = Maps.newHashMap();
+  private Map<Resource, Map<Resource, Dependency>> incomingDependenciesByResource = Maps.newHashMap();
+  private ProjectTree projectTree;
+
+  public DefaultIndex(PersistenceManager persistence, DefaultResourceCreationLock lock, ProjectTree projectTree, MetricFinder metricFinder) {
+    this.persistence = persistence;
+    this.lock = lock;
+    this.projectTree = projectTree;
+    this.metricFinder = metricFinder;
+  }
+
+  public void start() {
+    Project rootProject = projectTree.getRootProject();
+    doStart(rootProject);
+  }
+
+  void doStart(Project rootProject) {
+    Bucket bucket = new Bucket(rootProject);
+    buckets.put(rootProject, bucket);
+    persistence.saveProject(rootProject, null);
+    currentProject = rootProject;
+
+    for (Project project : rootProject.getModules()) {
+      addProject(project);
+    }
+  }
+
+  private void addProject(Project project) {
+    addResource(project);
+    for (Project module : project.getModules()) {
+      addProject(module);
+    }
+  }
+
+  public Project getProject() {
+    return currentProject;
+  }
+
+  public void setCurrentProject(Project project, ResourceFilters resourceFilters, ViolationFilters violationFilters, RulesProfile profile) {
+    this.currentProject = project;
+
+    // the following components depend on the current project, so they need to be reloaded.
+    this.resourceFilters = resourceFilters;
+    this.violationFilters = violationFilters;
+    this.profile = profile;
+  }
+
+  /**
+   * Keep only project stuff
+   */
+  public void clear() {
+    Iterator<Map.Entry<Resource, Bucket>> it = buckets.entrySet().iterator();
+    while (it.hasNext()) {
+      Map.Entry<Resource, Bucket> entry = it.next();
+      Resource resource = entry.getKey();
+      if (!ResourceUtils.isSet(resource)) {
+        entry.getValue().clear();
+        it.remove();
+      }
+    }
+
+    Set<Dependency> projectDependencies = getDependenciesBetweenProjects();
+    dependencies.clear();
+    incomingDependenciesByResource.clear();
+    outgoingDependenciesByResource.clear();
+    for (Dependency projectDependency : projectDependencies) {
+      projectDependency.setId(null);
+      registerDependency(projectDependency);
+    }
+
+    lock.unlock();
+  }
+
+  public Measure getMeasure(Resource resource, Metric metric) {
+    Bucket bucket = buckets.get(resource);
+    if (bucket != null) {
+      Measure measure = bucket.getMeasures(MeasuresFilters.metric(metric));
+      if (measure != null) {
+        return persistence.reloadMeasure(measure);
+      }
+    }
+    return null;
+  }
+
+  public <M> M getMeasures(Resource resource, MeasuresFilter<M> filter) {
+    Bucket bucket = buckets.get(resource);
+    if (bucket != null) {
+      // TODO the data measures which are not kept in memory are not reloaded yet. Use getMeasure().
+      return bucket.getMeasures(filter);
+    }
+    return null;
+  }
+
+  /**
+   * the measure is updated if it's already registered.
+   */
+  public Measure addMeasure(Resource resource, Measure measure) {
+    Bucket bucket = checkIndexed(resource);
+    if (bucket != null && !bucket.isExcluded()) {
+      Metric metric = metricFinder.findByKey(measure.getMetricKey());
+      if (metric == null) {
+        throw new SonarException("Unknown metric: " + measure.getMetricKey());
+      }
+      measure.setMetric(metric);
+      bucket.addMeasure(measure);
+
+      if (measure.getPersistenceMode().useDatabase()) {
+        persistence.saveMeasure(resource, measure);
+      }
+    }
+    return measure;
+  }
+
+  //
+  //
+  //
+  // DEPENDENCIES
+  //
+  //
+  //
+
+  public Dependency addDependency(Dependency dependency) {
+    Dependency existingDep = getEdge(dependency.getFrom(), dependency.getTo());
+    if (existingDep != null) {
+      return existingDep;
+    }
+
+    Dependency parentDependency = dependency.getParent();
+    if (parentDependency != null) {
+      addDependency(parentDependency);
+    }
+
+    if (registerDependency(dependency)) {
+      persistence.saveDependency(currentProject, dependency, parentDependency);
+    }
+    return dependency;
+  }
+
+  boolean registerDependency(Dependency dependency) {
+    Bucket fromBucket = doIndex(dependency.getFrom());
+    Bucket toBucket = doIndex(dependency.getTo());
+
+    if (fromBucket != null && !fromBucket.isExcluded() && toBucket != null && !toBucket.isExcluded()) {
+      dependencies.add(dependency);
+      registerOutgoingDependency(dependency);
+      registerIncomingDependency(dependency);
+      return true;
+    }
+    return false;
+  }
+
+  private void registerOutgoingDependency(Dependency dependency) {
+    Map<Resource, Dependency> outgoingDeps = outgoingDependenciesByResource.get(dependency.getFrom());
+    if (outgoingDeps == null) {
+      outgoingDeps = new HashMap<Resource, Dependency>();
+      outgoingDependenciesByResource.put(dependency.getFrom(), outgoingDeps);
+    }
+    outgoingDeps.put(dependency.getTo(), dependency);
+  }
+
+  private void registerIncomingDependency(Dependency dependency) {
+    Map<Resource, Dependency> incomingDeps = incomingDependenciesByResource.get(dependency.getTo());
+    if (incomingDeps == null) {
+      incomingDeps = new HashMap<Resource, Dependency>();
+      incomingDependenciesByResource.put(dependency.getTo(), incomingDeps);
+    }
+    incomingDeps.put(dependency.getFrom(), dependency);
+  }
+
+  public Set<Dependency> getDependencies() {
+    return dependencies;
+  }
+
+  public Dependency getEdge(Resource from, Resource to) {
+    Map<Resource, Dependency> map = outgoingDependenciesByResource.get(from);
+    if (map != null) {
+      return map.get(to);
+    }
+    return null;
+  }
+
+  public boolean hasEdge(Resource from, Resource to) {
+    return getEdge(from, to) != null;
+  }
+
+  public Set<Resource> getVertices() {
+    return buckets.keySet();
+  }
+
+  public Collection<Dependency> getOutgoingEdges(Resource from) {
+    Map<Resource, Dependency> deps = outgoingDependenciesByResource.get(from);
+    if (deps != null) {
+      return deps.values();
+    }
+    return Collections.emptyList();
+  }
+
+  public Collection<Dependency> getIncomingEdges(Resource to) {
+    Map<Resource, Dependency> deps = incomingDependenciesByResource.get(to);
+    if (deps != null) {
+      return deps.values();
+    }
+    return Collections.emptyList();
+  }
+
+  Set<Dependency> getDependenciesBetweenProjects() {
+    Set<Dependency> result = Sets.newLinkedHashSet();
+    for (Dependency dependency : dependencies) {
+      if (ResourceUtils.isSet(dependency.getFrom()) || ResourceUtils.isSet(dependency.getTo())) {
+        result.add(dependency);
+      }
+    }
+    return result;
+  }
+
+  //
+  //
+  //
+  // VIOLATIONS
+  //
+  //
+  //
+
+  /**
+   * {@inheritDoc}
+   */
+  public List<Violation> getViolations(ViolationQuery violationQuery) {
+    Resource resource = violationQuery.getResource();
+    if (resource == null) {
+      throw new IllegalArgumentException("A resource must be set on the ViolationQuery in order to search for violations.");
+    }
+    Bucket bucket = buckets.get(resource);
+    if (bucket == null) {
+      return Collections.emptyList();
+    }
+    List<Violation> filteredViolations = Lists.newArrayList();
+    boolean ignoreSwitchedOff = violationQuery.ignoreSwitchedOff();
+    for (Violation violation : bucket.getViolations()) {
+      if ( ignoreSwitchedOff && violation.isSwitchedOff()) {
+        continue;
+      }
+      filteredViolations.add(violation);
+    }
+    return filteredViolations;
+  }
+
+  public void addViolation(Violation violation, boolean force) {
+    Resource resource = violation.getResource();
+    if (resource == null) {
+      violation.setResource(currentProject);
+    } else if (!Scopes.isHigherThanOrEquals(resource, Scopes.FILE)) {
+      throw new IllegalArgumentException("Violations are only supported on files, directories and project");
+    }
+
+    if (violation.getRule() == null) {
+      LOG.warn("Rule is null, ignoring violation {}", violation);
+      return;
+    }
+
+    Bucket bucket = checkIndexed(resource);
+    if (bucket != null && !bucket.isExcluded()) {
+      boolean isIgnored = !force && violationFilters != null && violationFilters.isIgnored(violation);
+      if (!isIgnored) {
+        ActiveRule activeRule = profile.getActiveRule(violation.getRule());
+        if (activeRule == null) {
+          if (currentProject.getReuseExistingRulesConfig()) {
+            violation.setSeverity(violation.getRule().getSeverity());
+            doAddViolation(violation, bucket);
+
+          } else {
+            LoggerFactory.getLogger(getClass()).debug("Rule is not activated, ignoring violation {}", violation);
+          }
+
+        } else {
+          violation.setSeverity(activeRule.getSeverity());
+          doAddViolation(violation, bucket);
+        }
+      }
+    }
+  }
+
+  private void doAddViolation(Violation violation, Bucket bucket) {
+    bucket.addViolation(violation);
+  }
+
+  //
+  //
+  //
+  // LINKS
+  //
+  //
+  //
+
+  public void addLink(ProjectLink link) {
+    persistence.saveLink(currentProject, link);
+  }
+
+  public void deleteLink(String key) {
+    persistence.deleteLink(currentProject, key);
+  }
+
+  //
+  //
+  //
+  // EVENTS
+  //
+  //
+  //
+
+  public List<Event> getEvents(Resource resource) {
+    // currently events are not cached in memory
+    return persistence.getEvents(resource);
+  }
+
+  public void deleteEvent(Event event) {
+    persistence.deleteEvent(event);
+  }
+
+  public Event addEvent(Resource resource, String name, String description, String category, Date date) {
+    Event event = new Event(name, description, category);
+    event.setDate(date);
+    persistence.saveEvent(resource, event);
+    return null;
+  }
+
+  public void setSource(Resource reference, String source) {
+    Bucket bucket = checkIndexed(reference);
+    if (bucket != null && !bucket.isExcluded()) {
+      persistence.setSource(reference, source);
+    }
+  }
+
+  /**
+   * Does nothing if the resource is already registered.
+   */
+  public Resource addResource(Resource resource) {
+    Bucket bucket = doIndex(resource);
+    return bucket != null ? bucket.getResource() : null;
+  }
+
+  public <R extends Resource> R getResource(R reference) {
+    Bucket bucket = buckets.get(reference);
+    if (bucket != null) {
+      return (R) bucket.getResource();
+    }
+    return null;
+  }
+
+  static String createUID(Project project, Resource resource) {
+    String uid = resource.getKey();
+    if (!StringUtils.equals(Scopes.PROJECT, resource.getScope())) {
+      // not a project nor a library
+      uid = new StringBuilder(ResourceModel.KEY_SIZE)
+          .append(project.getKey())
+          .append(':')
+          .append(resource.getKey())
+          .toString();
+    }
+    return uid;
+  }
+
+  private boolean checkExclusion(Resource resource, Bucket parent) {
+    boolean excluded = (parent != null && parent.isExcluded()) || (resourceFilters != null && resourceFilters.isExcluded(resource));
+    resource.setExcluded(excluded);
+    return excluded;
+  }
+
+  public List<Resource> getChildren(Resource resource) {
+    return getChildren(resource, false);
+  }
+
+  public List<Resource> getChildren(Resource resource, boolean acceptExcluded) {
+    List<Resource> children = Lists.newLinkedList();
+    Bucket bucket = getBucket(resource, acceptExcluded);
+    if (bucket != null) {
+      for (Bucket childBucket : bucket.getChildren()) {
+        if (acceptExcluded || !childBucket.isExcluded()) {
+          children.add(childBucket.getResource());
+        }
+      }
+    }
+    return children;
+  }
+
+  public Resource getParent(Resource resource) {
+    Bucket bucket = getBucket(resource, false);
+    if (bucket != null && bucket.getParent() != null) {
+      return bucket.getParent().getResource();
+    }
+    return null;
+  }
+
+  public boolean index(Resource resource) {
+    Bucket bucket = doIndex(resource);
+    return bucket != null && !bucket.isExcluded();
+  }
+
+  private Bucket doIndex(Resource resource) {
+    if (resource.getParent() != null) {
+      doIndex(resource.getParent());
+    }
+    return doIndex(resource, resource.getParent());
+  }
+
+  public boolean index(Resource resource, Resource parentReference) {
+    Bucket bucket = doIndex(resource, parentReference);
+    return bucket != null && !bucket.isExcluded();
+  }
+
+  private Bucket doIndex(Resource resource, Resource parentReference) {
+    Bucket bucket = buckets.get(resource);
+    if (bucket != null) {
+      return bucket;
+    }
+
+    checkLock(resource);
+
+    Resource parent = null;
+    if (!ResourceUtils.isLibrary(resource)) {
+      // a library has no parent
+      parent = (Resource) ObjectUtils.defaultIfNull(parentReference, currentProject);
+    }
+
+    Bucket parentBucket = getBucket(parent, true);
+    if (parentBucket == null && parent != null) {
+      LOG.warn("Resource ignored, parent is not indexed: " + resource);
+      return null;
+    }
+
+    resource.setEffectiveKey(createUID(currentProject, resource));
+    bucket = new Bucket(resource).setParent(parentBucket);
+    buckets.put(resource, bucket);
+
+    boolean excluded = checkExclusion(resource, parentBucket);
+    if (!excluded) {
+      persistence.saveResource(currentProject, resource, (parentBucket != null ? parentBucket.getResource() : null));
+    }
+    return bucket;
+  }
+
+  private void checkLock(Resource resource) {
+    if (lock.isLocked() && !ResourceUtils.isLibrary(resource)) {
+      if (lock.isFailWhenLocked()) {
+        throw new SonarException("Index is locked, resource can not be indexed: " + resource);
+      }
+    }
+  }
+
+  private Bucket checkIndexed(Resource resource) {
+    Bucket bucket = getBucket(resource, true);
+    if (bucket == null) {
+      if (lock.isLocked()) {
+        if (lock.isFailWhenLocked()) {
+          throw new ResourceNotIndexedException(resource);
+        }
+        LOG.warn("Resource will be ignored in next Sonar versions, index is locked: " + resource);
+      }
+      if (Scopes.isDirectory(resource) || Scopes.isFile(resource)) {
+        bucket = doIndex(resource);
+      } else if (!lock.isLocked()) {
+        LOG.warn("Resource will be ignored in next Sonar versions, it must be indexed before adding data: " + resource);
+      }
+    }
+    return bucket;
+  }
+
+  public boolean isExcluded(Resource reference) {
+    Bucket bucket = getBucket(reference, true);
+    return bucket != null && bucket.isExcluded();
+  }
+
+  public boolean isIndexed(Resource reference, boolean acceptExcluded) {
+    return getBucket(reference, acceptExcluded) != null;
+  }
+
+  private Bucket getBucket(Resource resource, boolean acceptExcluded) {
+    Bucket bucket = null;
+    if (resource != null) {
+      bucket = buckets.get(resource);
+      if (!acceptExcluded && bucket != null && bucket.isExcluded()) {
+        bucket = null;
+      }
+    }
+    return bucket;
+  }
+}
index cc156125a5d125c634d5e3dbd1d7d9d805f1f6b1..2334c0f87147e647ee7820e91ad92a29132ed7dc 100644 (file)
@@ -1,88 +1,88 @@
-/*\r
- * Sonar, open source software quality management tool.\r
- * Copyright (C) 2008-2011 SonarSource\r
- * mailto:contact AT sonarsource DOT com\r
- *\r
- * Sonar is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 3 of the License, or (at your option) any later version.\r
- *\r
- * Sonar is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with Sonar; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02\r
- */\r
-package org.sonar.batch.index;\r
-\r
-import org.sonar.api.database.DatabaseSession;\r
-import org.sonar.api.database.model.RuleFailureModel;\r
-import org.sonar.api.database.model.Snapshot;\r
-import org.sonar.api.resources.Project;\r
-import org.sonar.api.rules.Rule;\r
-import org.sonar.api.rules.RuleFinder;\r
-import org.sonar.api.rules.Violation;\r
-\r
-public final class ViolationPersister {\r
-\r
-  private DatabaseSession session;\r
-  private ResourcePersister resourcePersister;\r
-  private RuleFinder ruleFinder;\r
-\r
-  public ViolationPersister(DatabaseSession session, ResourcePersister resourcePersister, RuleFinder ruleFinder) {\r
-    this.session = session;\r
-    this.resourcePersister = resourcePersister;\r
-    this.ruleFinder = ruleFinder;\r
-  }\r
-\r
-  void saveViolation(Project project, Violation violation) {\r
-    saveViolation(project, violation, null, null);\r
-  }\r
-\r
-  public void saveViolation(Project project, Violation violation, RuleFailureModel pastViolation, String checksum) {\r
-    Snapshot snapshot = resourcePersister.saveResource(project, violation.getResource());\r
-\r
-    RuleFailureModel model = createModel(violation);\r
-    if (pastViolation!=null) {\r
-      model.setCreatedAt(pastViolation.getCreatedAt());\r
-      model.setPermanentId(pastViolation.getPermanentId());\r
-      model.setSwitchedOff(pastViolation.isSwitchedOff());\r
-    } else {\r
-      // avoid plugins setting date\r
-      model.setCreatedAt(snapshot.getCreatedAt());\r
-    }\r
-    model.setSnapshotId(snapshot.getId());\r
-    model.setChecksum(checksum);\r
-    session.save(model);\r
-\r
-    if (model.getPermanentId()==null) {\r
-      model.setPermanentId(model.getId());\r
-      session.save(model);\r
-    }\r
-\r
-    // the following fields can have been changed\r
-    violation.setMessage(model.getMessage());// the message can be changed in the class RuleFailure (truncate + trim)\r
-    violation.setCreatedAt(model.getCreatedAt());\r
-    violation.setSwitchedOff(model.isSwitchedOff());\r
-  }\r
-  \r
-  public void commit() {\r
-    session.commit();\r
-  }\r
-\r
-  private RuleFailureModel createModel(Violation violation) {\r
-    RuleFailureModel model = new RuleFailureModel();\r
-    Rule rule = ruleFinder.findByKey(violation.getRule().getRepositoryKey(), violation.getRule().getKey());\r
-    model.setRuleId(rule.getId());\r
-    model.setPriority(violation.getSeverity());\r
-    model.setLine(violation.getLineId());\r
-    model.setMessage(violation.getMessage());\r
-    model.setCost(violation.getCost());\r
-    return model;\r
-  }\r
-\r
-}\r
+/*
+ * 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.sonar.api.database.DatabaseSession;
+import org.sonar.api.database.model.RuleFailureModel;
+import org.sonar.api.database.model.Snapshot;
+import org.sonar.api.resources.Project;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.RuleFinder;
+import org.sonar.api.rules.Violation;
+
+public final class ViolationPersister {
+
+  private DatabaseSession session;
+  private ResourcePersister resourcePersister;
+  private RuleFinder ruleFinder;
+
+  public ViolationPersister(DatabaseSession session, ResourcePersister resourcePersister, RuleFinder ruleFinder) {
+    this.session = session;
+    this.resourcePersister = resourcePersister;
+    this.ruleFinder = ruleFinder;
+  }
+
+  void saveViolation(Project project, Violation violation) {
+    saveViolation(project, violation, null, null);
+  }
+
+  public void saveViolation(Project project, Violation violation, RuleFailureModel pastViolation, String checksum) {
+    Snapshot snapshot = resourcePersister.saveResource(project, violation.getResource());
+
+    RuleFailureModel model = createModel(violation);
+    if (pastViolation!=null) {
+      model.setCreatedAt(pastViolation.getCreatedAt());
+      model.setPermanentId(pastViolation.getPermanentId());
+      model.setSwitchedOff(pastViolation.isSwitchedOff());
+    } else {
+      // avoid plugins setting date
+      model.setCreatedAt(snapshot.getCreatedAt());
+    }
+    model.setSnapshotId(snapshot.getId());
+    model.setChecksum(checksum);
+    session.save(model);
+
+    if (model.getPermanentId()==null) {
+      model.setPermanentId(model.getId());
+      session.save(model);
+    }
+
+    // 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() {
+    session.commit();
+  }
+
+  private RuleFailureModel createModel(Violation violation) {
+    RuleFailureModel model = new RuleFailureModel();
+    Rule rule = ruleFinder.findByKey(violation.getRule().getRepositoryKey(), violation.getRule().getKey());
+    model.setRuleId(rule.getId());
+    model.setPriority(violation.getSeverity());
+    model.setLine(violation.getLineId());
+    model.setMessage(violation.getMessage());
+    model.setCost(violation.getCost());
+    return model;
+  }
+
+}
index 6457cf2cc431b3fa5a01bbe2cd2dcc96c212f7e5..48946226df4d7fdc657472b51e32a072180b1ecc 100644 (file)
-/*\r
- * Sonar, open source software quality management tool.\r
- * Copyright (C) 2008-2011 SonarSource\r
- * mailto:contact AT sonarsource DOT com\r
- *\r
- * Sonar is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 3 of the License, or (at your option) any later version.\r
- *\r
- * Sonar is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with Sonar; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02\r
- */\r
-package org.sonar.batch.index;\r
-\r
-import static org.hamcrest.Matchers.nullValue;\r
-import static org.hamcrest.core.Is.is;\r
-import static org.junit.Assert.assertThat;\r
-import static org.mockito.Mockito.mock;\r
-import static org.mockito.Mockito.when;\r
-\r
-import org.apache.commons.lang.StringUtils;\r
-import org.junit.Before;\r
-import org.junit.Test;\r
-import org.sonar.api.batch.ResourceFilter;\r
-import org.sonar.api.measures.CoreMetrics;\r
-import org.sonar.api.measures.Measure;\r
-import org.sonar.api.measures.MeasuresFilters;\r
-import org.sonar.api.measures.MetricFinder;\r
-import org.sonar.api.profiles.RulesProfile;\r
-import org.sonar.api.resources.Directory;\r
-import org.sonar.api.resources.File;\r
-import org.sonar.api.resources.Java;\r
-import org.sonar.api.resources.JavaPackage;\r
-import org.sonar.api.resources.Language;\r
-import org.sonar.api.resources.Library;\r
-import org.sonar.api.resources.Project;\r
-import org.sonar.api.resources.Qualifiers;\r
-import org.sonar.api.resources.Resource;\r
-import org.sonar.api.rules.Rule;\r
-import org.sonar.api.rules.Violation;\r
-import org.sonar.api.utils.SonarException;\r
-import org.sonar.api.violations.ViolationQuery;\r
-import org.sonar.batch.DefaultResourceCreationLock;\r
-import org.sonar.batch.ProjectTree;\r
-import org.sonar.batch.ResourceFilters;\r
-import org.sonar.batch.ViolationFilters;\r
-\r
-public class DefaultIndexTest {\r
-\r
-  private DefaultIndex index = null;\r
-  private DefaultResourceCreationLock lock;\r
-  private Rule rule;\r
-\r
-  @Before\r
-  public void createIndex() {\r
-    lock = new DefaultResourceCreationLock();\r
-    MetricFinder metricFinder = mock(MetricFinder.class);\r
-    when(metricFinder.findByKey("ncloc")).thenReturn(CoreMetrics.NCLOC);\r
-\r
-    index = new DefaultIndex(mock(PersistenceManager.class), lock, mock(ProjectTree.class), metricFinder);\r
-    Project project = new Project("project");\r
-\r
-    ResourceFilter filter = new ResourceFilter() {\r
-\r
-      public boolean isIgnored(Resource resource) {\r
-        return StringUtils.containsIgnoreCase(resource.getKey(), "excluded");\r
-      }\r
-    };\r
-    RulesProfile rulesProfile = RulesProfile.create();\r
-    rule = Rule.create("repoKey", "ruleKey", "Rule");\r
-    rulesProfile.activateRule(rule, null);\r
-    index.setCurrentProject(project, new ResourceFilters(new ResourceFilter[] { filter }), new ViolationFilters(), rulesProfile);\r
-    index.doStart(project);\r
-  }\r
-\r
-  @Test\r
-  public void shouldCreateUID() {\r
-    Project project = new Project("my_project");\r
-    assertThat(DefaultIndex.createUID(project, project), is("my_project"));\r
-\r
-    JavaPackage javaPackage = new JavaPackage("org.foo");\r
-    assertThat(DefaultIndex.createUID(project, javaPackage), is("my_project:org.foo"));\r
-\r
-    Library library = new Library("junit:junit", "4.7");\r
-    assertThat(DefaultIndex.createUID(project, library), is("junit:junit"));\r
-  }\r
-\r
-  @Test\r
-  public void shouldIndexParentOfDeprecatedFiles() {\r
-    File file = new File("org/foo/Bar.java");\r
-    assertThat(index.index(file), is(true));\r
-\r
-    Directory reference = new Directory("org/foo");\r
-    assertThat(index.getResource(reference).getName(), is("org/foo"));\r
-    assertThat(index.isIndexed(reference, true), is(true));\r
-    assertThat(index.isExcluded(reference), is(false));\r
-    assertThat(index.getChildren(reference).size(), is(1));\r
-    assertThat(index.getParent(reference), is(Project.class));\r
-  }\r
-\r
-  @Test\r
-  public void shouldIndexTreeOfResources() {\r
-    Directory directory = new Directory("org/foo");\r
-    File file = new File("org/foo/Bar.java");\r
-    file.setLanguage(Java.INSTANCE);\r
-\r
-    assertThat(index.index(directory), is(true));\r
-    assertThat(index.index(file, directory), is(true));\r
-\r
-    File fileRef = new File("org/foo/Bar.java");\r
-    assertThat(index.getResource(fileRef).getKey(), is("org/foo/Bar.java"));\r
-    assertThat(index.getResource(fileRef).getLanguage(), is((Language) Java.INSTANCE));\r
-    assertThat(index.isIndexed(fileRef, true), is(true));\r
-    assertThat(index.isExcluded(fileRef), is(false));\r
-    assertThat(index.getChildren(fileRef).size(), is(0));\r
-    assertThat(index.getParent(fileRef), is(Directory.class));\r
-  }\r
-\r
-  @Test\r
-  public void shouldIndexLibraryOutsideProjectTree() {\r
-    Library lib = new Library("junit", "4.8");\r
-    assertThat(index.index(lib), is(true));\r
-\r
-    Library reference = new Library("junit", "4.8");\r
-    assertThat(index.getResource(reference).getQualifier(), is(Qualifiers.LIBRARY));\r
-    assertThat(index.isIndexed(reference, true), is(true));\r
-    assertThat(index.isExcluded(reference), is(false));\r
-  }\r
-\r
-  @Test\r
-  public void shouldNotIndexResourceIfParentNotIndexed() {\r
-    Directory directory = new Directory("org/other");\r
-    File file = new File("org/foo/Bar.java");\r
-\r
-    assertThat(index.index(file, directory), is(false));\r
-\r
-    File fileRef = new File("org/foo/Bar.java");\r
-    assertThat(index.isIndexed(directory, true), is(false));\r
-    assertThat(index.isIndexed(fileRef, true), is(false));\r
-    assertThat(index.isExcluded(fileRef), is(false));\r
-    assertThat(index.getChildren(fileRef).size(), is(0));\r
-    assertThat(index.getParent(fileRef), nullValue());\r
-  }\r
-\r
-  /**\r
-   * Only a warning is logged when index is locked.\r
-   */\r
-  @Test\r
-  public void shouldIndexEvenIfLocked() {\r
-    lock.lock();\r
-\r
-    Directory dir = new Directory("org/foo");\r
-    assertThat(index.index(dir), is(true));\r
-    assertThat(index.isIndexed(dir, true), is(true));\r
-  }\r
-\r
-  @Test(expected = SonarException.class)\r
-  public void shouldFailIfIndexingAndLocked() {\r
-    lock.setFailWhenLocked(true);\r
-    lock.lock();\r
-\r
-    Directory dir = new Directory("org/foo");\r
-    index.index(dir);\r
-  }\r
-\r
-  @Test\r
-  public void shouldBeExcluded() {\r
-    File file = new File("org/foo/ExcludedBar.java");\r
-    assertThat(index.index(file), is(false));\r
-    assertThat(index.isIndexed(file, true), is(true));\r
-    assertThat(index.isIndexed(file, false), is(false));\r
-    assertThat(index.isExcluded(file), is(true));\r
-  }\r
-\r
-  @Test\r
-  public void shouldIndexResourceWhenAddingMeasure() {\r
-    Resource dir = new Directory("org/foo");\r
-    index.addMeasure(dir, new Measure("ncloc").setValue(50.0));\r
-\r
-    assertThat(index.isIndexed(dir, true), is(true));\r
-    assertThat(index.getMeasures(dir, MeasuresFilters.metric("ncloc")).getIntValue(), is(50));\r
-  }\r
-\r
-  /**\r
-   * See http://jira.codehaus.org/browse/SONAR-2107\r
-   */\r
-  @Test\r
-  public void shouldNotFailWhenSavingViolationOnNullRule() {\r
-    File file = new File("org/foo/Bar.java");\r
-    Violation violation = Violation.create((Rule) null, file);\r
-    index.addViolation(violation);\r
-\r
-    assertThat(index.getViolations(file).size(), is(0));\r
-  }\r
-\r
-  @Test\r
-  public void testGetViolations() {\r
-    File file = new File("org/foo/Bar.java");\r
-    Violation violation1 = Violation.create(rule, file);\r
-    index.addViolation(violation1);\r
-    Violation violation2 = Violation.create(rule, file);\r
-    violation2.setSwitchedOff(true);\r
-    index.addViolation(violation2);\r
-    Violation violation3 = Violation.create(rule, file);\r
-    violation3.setSwitchedOff(true);\r
-    index.addViolation(violation3);\r
-\r
-    assertThat(index.getViolations(file).size(), is(1));\r
-  }\r
-\r
-  @Test\r
-  public void testGetViolationsWithQuery() {\r
-    File file = new File("org/foo/Bar.java");\r
-    Violation violation1 = Violation.create(rule, file);\r
-    index.addViolation(violation1);\r
-    Violation violation2 = Violation.create(rule, file);\r
-    violation2.setSwitchedOff(true);\r
-    index.addViolation(violation2);\r
-    Violation violation3 = Violation.create(rule, file);\r
-    violation3.setSwitchedOff(true);\r
-    index.addViolation(violation3);\r
-\r
-    assertThat(index.getViolations(ViolationQuery.create().forResource(file).ignoreSwitchedOff(false)).size(), is(3));\r
-  }\r
-\r
-  @Test(expected = IllegalArgumentException.class)\r
-  public void testGetViolationsWithQueryWithNoResource() {\r
-    index.getViolations(ViolationQuery.create());\r
-  }\r
-\r
-}\r
+/*
+ * 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 static org.hamcrest.Matchers.nullValue;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.apache.commons.lang.StringUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.batch.ResourceFilter;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.measures.MeasuresFilters;
+import org.sonar.api.measures.MetricFinder;
+import org.sonar.api.profiles.RulesProfile;
+import org.sonar.api.resources.Directory;
+import org.sonar.api.resources.File;
+import org.sonar.api.resources.Java;
+import org.sonar.api.resources.JavaPackage;
+import org.sonar.api.resources.Language;
+import org.sonar.api.resources.Library;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.Violation;
+import org.sonar.api.utils.SonarException;
+import org.sonar.api.violations.ViolationQuery;
+import org.sonar.batch.DefaultResourceCreationLock;
+import org.sonar.batch.ProjectTree;
+import org.sonar.batch.ResourceFilters;
+import org.sonar.batch.ViolationFilters;
+
+public class DefaultIndexTest {
+
+  private DefaultIndex index = null;
+  private DefaultResourceCreationLock lock;
+  private Rule rule;
+
+  @Before
+  public void createIndex() {
+    lock = new DefaultResourceCreationLock();
+    MetricFinder metricFinder = mock(MetricFinder.class);
+    when(metricFinder.findByKey("ncloc")).thenReturn(CoreMetrics.NCLOC);
+
+    index = new DefaultIndex(mock(PersistenceManager.class), lock, mock(ProjectTree.class), metricFinder);
+    Project project = new Project("project");
+
+    ResourceFilter filter = new ResourceFilter() {
+
+      public boolean isIgnored(Resource resource) {
+        return StringUtils.containsIgnoreCase(resource.getKey(), "excluded");
+      }
+    };
+    RulesProfile rulesProfile = RulesProfile.create();
+    rule = Rule.create("repoKey", "ruleKey", "Rule");
+    rulesProfile.activateRule(rule, null);
+    index.setCurrentProject(project, new ResourceFilters(new ResourceFilter[] { filter }), new ViolationFilters(), rulesProfile);
+    index.doStart(project);
+  }
+
+  @Test
+  public void shouldCreateUID() {
+    Project project = new Project("my_project");
+    assertThat(DefaultIndex.createUID(project, project), is("my_project"));
+
+    JavaPackage javaPackage = new JavaPackage("org.foo");
+    assertThat(DefaultIndex.createUID(project, javaPackage), is("my_project:org.foo"));
+
+    Library library = new Library("junit:junit", "4.7");
+    assertThat(DefaultIndex.createUID(project, library), is("junit:junit"));
+  }
+
+  @Test
+  public void shouldIndexParentOfDeprecatedFiles() {
+    File file = new File("org/foo/Bar.java");
+    assertThat(index.index(file), is(true));
+
+    Directory reference = new Directory("org/foo");
+    assertThat(index.getResource(reference).getName(), is("org/foo"));
+    assertThat(index.isIndexed(reference, true), is(true));
+    assertThat(index.isExcluded(reference), is(false));
+    assertThat(index.getChildren(reference).size(), is(1));
+    assertThat(index.getParent(reference), is(Project.class));
+  }
+
+  @Test
+  public void shouldIndexTreeOfResources() {
+    Directory directory = new Directory("org/foo");
+    File file = new File("org/foo/Bar.java");
+    file.setLanguage(Java.INSTANCE);
+
+    assertThat(index.index(directory), is(true));
+    assertThat(index.index(file, directory), is(true));
+
+    File fileRef = new File("org/foo/Bar.java");
+    assertThat(index.getResource(fileRef).getKey(), is("org/foo/Bar.java"));
+    assertThat(index.getResource(fileRef).getLanguage(), is((Language) Java.INSTANCE));
+    assertThat(index.isIndexed(fileRef, true), is(true));
+    assertThat(index.isExcluded(fileRef), is(false));
+    assertThat(index.getChildren(fileRef).size(), is(0));
+    assertThat(index.getParent(fileRef), is(Directory.class));
+  }
+
+  @Test
+  public void shouldIndexLibraryOutsideProjectTree() {
+    Library lib = new Library("junit", "4.8");
+    assertThat(index.index(lib), is(true));
+
+    Library reference = new Library("junit", "4.8");
+    assertThat(index.getResource(reference).getQualifier(), is(Qualifiers.LIBRARY));
+    assertThat(index.isIndexed(reference, true), is(true));
+    assertThat(index.isExcluded(reference), is(false));
+  }
+
+  @Test
+  public void shouldNotIndexResourceIfParentNotIndexed() {
+    Directory directory = new Directory("org/other");
+    File file = new File("org/foo/Bar.java");
+
+    assertThat(index.index(file, directory), is(false));
+
+    File fileRef = new File("org/foo/Bar.java");
+    assertThat(index.isIndexed(directory, true), is(false));
+    assertThat(index.isIndexed(fileRef, true), is(false));
+    assertThat(index.isExcluded(fileRef), is(false));
+    assertThat(index.getChildren(fileRef).size(), is(0));
+    assertThat(index.getParent(fileRef), nullValue());
+  }
+
+  /**
+   * Only a warning is logged when index is locked.
+   */
+  @Test
+  public void shouldIndexEvenIfLocked() {
+    lock.lock();
+
+    Directory dir = new Directory("org/foo");
+    assertThat(index.index(dir), is(true));
+    assertThat(index.isIndexed(dir, true), is(true));
+  }
+
+  @Test(expected = SonarException.class)
+  public void shouldFailIfIndexingAndLocked() {
+    lock.setFailWhenLocked(true);
+    lock.lock();
+
+    Directory dir = new Directory("org/foo");
+    index.index(dir);
+  }
+
+  @Test
+  public void shouldBeExcluded() {
+    File file = new File("org/foo/ExcludedBar.java");
+    assertThat(index.index(file), is(false));
+    assertThat(index.isIndexed(file, true), is(true));
+    assertThat(index.isIndexed(file, false), is(false));
+    assertThat(index.isExcluded(file), is(true));
+  }
+
+  @Test
+  public void shouldIndexResourceWhenAddingMeasure() {
+    Resource dir = new Directory("org/foo");
+    index.addMeasure(dir, new Measure("ncloc").setValue(50.0));
+
+    assertThat(index.isIndexed(dir, true), is(true));
+    assertThat(index.getMeasures(dir, MeasuresFilters.metric("ncloc")).getIntValue(), is(50));
+  }
+
+  /**
+   * See http://jira.codehaus.org/browse/SONAR-2107
+   */
+  @Test
+  public void shouldNotFailWhenSavingViolationOnNullRule() {
+    File file = new File("org/foo/Bar.java");
+    Violation violation = Violation.create((Rule) null, file);
+    index.addViolation(violation);
+
+    assertThat(index.getViolations(file).size(), is(0));
+  }
+
+  @Test
+  public void testGetViolations() {
+    File file = new File("org/foo/Bar.java");
+    Violation violation1 = Violation.create(rule, file);
+    index.addViolation(violation1);
+    Violation violation2 = Violation.create(rule, file);
+    violation2.setSwitchedOff(true);
+    index.addViolation(violation2);
+    Violation violation3 = Violation.create(rule, file);
+    violation3.setSwitchedOff(true);
+    index.addViolation(violation3);
+
+    assertThat(index.getViolations(file).size(), is(1));
+  }
+
+  @Test
+  public void testGetViolationsWithQuery() {
+    File file = new File("org/foo/Bar.java");
+    Violation violation1 = Violation.create(rule, file);
+    index.addViolation(violation1);
+    Violation violation2 = Violation.create(rule, file);
+    violation2.setSwitchedOff(true);
+    index.addViolation(violation2);
+    Violation violation3 = Violation.create(rule, file);
+    violation3.setSwitchedOff(true);
+    index.addViolation(violation3);
+
+    assertThat(index.getViolations(ViolationQuery.create().forResource(file).ignoreSwitchedOff(false)).size(), is(3));
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testGetViolationsWithQueryWithNoResource() {
+    index.getViolations(ViolationQuery.create());
+  }
+
+}
index d1d3b775f5c18fc7ded7b21da0b75fd3edd994a2..bb5bc1a34e9be6f97509a44502de70c02f78f582 100644 (file)
@@ -1,96 +1,96 @@
-/*\r
- * Sonar, open source software quality management tool.\r
- * Copyright (C) 2008-2011 SonarSource\r
- * mailto:contact AT sonarsource DOT com\r
- *\r
- * Sonar is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 3 of the License, or (at your option) any later version.\r
- *\r
- * Sonar is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with Sonar; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02\r
- */\r
-package org.sonar.batch.index;\r
-\r
-import org.junit.Before;\r
-import org.junit.Test;\r
-import org.sonar.api.database.model.RuleFailureModel;\r
-import org.sonar.api.database.model.Snapshot;\r
-import org.sonar.api.resources.JavaFile;\r
-import org.sonar.api.resources.Project;\r
-import org.sonar.api.rules.Rule;\r
-import org.sonar.api.rules.RulePriority;\r
-import org.sonar.api.rules.Violation;\r
-import org.sonar.core.components.DefaultRuleFinder;\r
-import org.sonar.jpa.test.AbstractDbUnitTestCase;\r
-\r
-import static org.mockito.Matchers.anyObject;\r
-import static org.mockito.Matchers.eq;\r
-import static org.mockito.Mockito.mock;\r
-import static org.mockito.Mockito.when;\r
-\r
-public class ViolationPersisterTest extends AbstractDbUnitTestCase {\r
-\r
-  private ViolationPersister violationPersister;\r
-  private Rule rule1 = Rule.create("checkstyle", "com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck", "Check Header");\r
-  private Rule rule2 = Rule.create("checkstyle", "com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck", "Equals Avoid Null");\r
-  private JavaFile javaFile = new JavaFile("org.foo.Bar");\r
-  Project project = new Project("project");\r
-\r
-  @Before\r
-  public void before() {\r
-    setupData("shared");\r
-    Snapshot snapshot = getSession().getSingleResult(Snapshot.class, "id", 1000);\r
-    ResourcePersister resourcePersister = mock(ResourcePersister.class);\r
-    when(resourcePersister.saveResource((Project) anyObject(), eq(javaFile))).thenReturn(snapshot);\r
-    when(resourcePersister.getSnapshot(javaFile)).thenReturn(snapshot);\r
-    violationPersister = new ViolationPersister(getSession(), resourcePersister, new DefaultRuleFinder(getSessionFactory()));\r
-  }\r
-\r
-  @Test\r
-  public void shouldSaveViolations() {\r
-    Violation violation1a = Violation.create(rule1, javaFile)\r
-        .setSeverity(RulePriority.CRITICAL).setLineId(20).setCost(55.6)\r
-        .setMessage("the message");\r
-    Violation violation1b = Violation.create(rule1, javaFile)\r
-        .setSeverity(RulePriority.CRITICAL).setLineId(50).setCost(80.0);\r
-    Violation violation2 = Violation.create(rule2, javaFile)\r
-        .setSeverity(RulePriority.MINOR);\r
-\r
-    violationPersister.saveViolation(project, violation1a);\r
-    violationPersister.saveViolation(project, violation1b);\r
-    violationPersister.saveViolation(project, violation2);\r
-\r
-    checkTables("shouldInsertViolations", "rule_failures");\r
-  }\r
-\r
-  @Test\r
-  public void shouldCopyPermanentIdFromPastViolation() {\r
-    RuleFailureModel pastViolation = getSession().getSingleResult(RuleFailureModel.class, "id", 1);\r
-\r
-    Violation violation = Violation.create(rule1, javaFile).setSeverity(RulePriority.MAJOR).setMessage("new message");\r
-    violationPersister.saveViolation(project, violation, pastViolation, "line_checksum");\r
-\r
-    checkTables("shouldCopyPermanentIdFromPastViolation", "rule_failures");\r
-  }\r
-\r
-  @Test\r
-  public void shouldCopySwitchedOffFromPastViolation() {\r
-    RuleFailureModel pastViolation1 = getSession().getSingleResult(RuleFailureModel.class, "id", 1);\r
-    Violation violation1 = Violation.create(rule1, javaFile).setSeverity(RulePriority.MAJOR).setMessage("new message");\r
-    violationPersister.saveViolation(project, violation1, pastViolation1, "line_checksum");\r
-\r
-    RuleFailureModel pastViolation2 = getSession().getSingleResult(RuleFailureModel.class, "id", 2);\r
-    Violation violation2 = Violation.create(rule1, javaFile).setSeverity(RulePriority.MAJOR).setMessage("new message");\r
-    violationPersister.saveViolation(project, violation2, pastViolation2, "line_checksum");\r
-\r
-    checkTables("shouldCopySwitchedOffFromPastViolation", "rule_failures");\r
-  }\r
-}\r
+/*
+ * 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");
+  }
+}
index cc50133e0bdb925aad0641a056e3ad5fcacb0c6c..90a3f202297a40c8c78f23476ae633413f53236c 100644 (file)
@@ -1,24 +1,24 @@
-<dataset>\r
-\r
-  <rules_categories id="1" name="Efficiency" description="[null]"/>\r
-  <rules_categories id="6" name="Usability" description="[null]"/>\r
-\r
-  <rules id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"\r
-         plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"\r
-         cardinality="SINGLE" parent_id="[null]"/>\r
-\r
-  <rules id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"\r
-         plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"\r
-         cardinality="SINGLE" parent_id="[null]"/>\r
-\r
-  <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"\r
-            name="Bar" long_name="org.foo.Bar" description="[null]"\r
-            enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>\r
-\r
-  <snapshots period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"\r
-             scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path=""\r
-             status="U" islast="false" depth="3" />\r
-\r
-  <rule_failures switched_off="false" permanent_id="1" ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>\r
-  <rule_failures switched_off="true" permanent_id="2" ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>\r
-</dataset>\r
+<dataset>
+
+  <rules_categories id="1" name="Efficiency" description="[null]"/>
+  <rules_categories id="6" name="Usability" description="[null]"/>
+
+  <rules id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
+         plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
+         cardinality="SINGLE" parent_id="[null]"/>
+
+  <rules id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
+         plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
+         cardinality="SINGLE" parent_id="[null]"/>
+
+  <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
+            name="Bar" long_name="org.foo.Bar" description="[null]"
+            enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>
+
+  <snapshots period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
+             scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
+             status="U" islast="false" depth="3" />
+
+  <rule_failures switched_off="false" permanent_id="1" ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
+  <rule_failures switched_off="true" permanent_id="2" ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
+</dataset>
index 842a7e107651807bd3e00216a4f370cc79fafe76..881a88dc3bbef8692ce21e2bdccd232c88b67c01 100644 (file)
@@ -1,26 +1,26 @@
-<dataset>\r
-\r
-  <rules_categories id="1" name="Efficiency" description="[null]"/>\r
-  <rules_categories id="6" name="Usability" description="[null]"/>\r
-\r
-  <rules id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"\r
-         plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"\r
-         cardinality="SINGLE" parent_id="[null]"/>\r
-\r
-  <rules id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"\r
-         plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"\r
-         cardinality="SINGLE" parent_id="[null]"/>\r
-\r
-  <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"\r
-            name="Bar" long_name="org.foo.Bar" description="[null]"\r
-            enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>\r
-\r
-  <snapshots period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"\r
-             scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path=""\r
-             status="U" islast="false" depth="3" />\r
-\r
-  <rule_failures switched_off="false" permanent_id="1" ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>\r
-  <rule_failures switched_off="true" permanent_id="2" ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>\r
-\r
-  <rule_failures switched_off="false" permanent_id="1" ID="3" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="2" MESSAGE="new message" LINE="[null]" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="line_checksum"/>\r
-</dataset>\r
+<dataset>
+
+  <rules_categories id="1" name="Efficiency" description="[null]"/>
+  <rules_categories id="6" name="Usability" description="[null]"/>
+
+  <rules id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
+         plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
+         cardinality="SINGLE" parent_id="[null]"/>
+
+  <rules id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
+         plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
+         cardinality="SINGLE" parent_id="[null]"/>
+
+  <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
+            name="Bar" long_name="org.foo.Bar" description="[null]"
+            enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>
+
+  <snapshots period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
+             scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
+             status="U" islast="false" depth="3" />
+
+  <rule_failures switched_off="false" permanent_id="1" ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
+  <rule_failures switched_off="true" permanent_id="2" ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
+
+  <rule_failures switched_off="false" permanent_id="1" ID="3" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="2" MESSAGE="new message" LINE="[null]" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="line_checksum"/>
+</dataset>
index f72c573676d510fe1a8d09ccb0f41ccb988828ed..bc366b16a45ac471124beb768dc5c20818d0623d 100644 (file)
@@ -1,27 +1,27 @@
-<dataset>\r
-\r
-  <rules_categories id="1" name="Efficiency" description="[null]"/>\r
-  <rules_categories id="6" name="Usability" description="[null]"/>\r
-\r
-  <rules id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"\r
-         plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"\r
-         cardinality="SINGLE" parent_id="[null]"/>\r
-\r
-  <rules id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"\r
-         plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"\r
-         cardinality="SINGLE" parent_id="[null]"/>\r
-\r
-  <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"\r
-            name="Bar" long_name="org.foo.Bar" description="[null]"\r
-            enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>\r
-\r
-  <snapshots period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"\r
-             scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path=""\r
-             status="U" islast="false" depth="3" />\r
-\r
-  <rule_failures switched_off="false" permanent_id="1" ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>\r
-  <rule_failures switched_off="true" permanent_id="2" ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>\r
-\r
-  <rule_failures switched_off="false" permanent_id="1" ID="3" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="2" MESSAGE="new message" LINE="[null]" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="line_checksum"/>\r
-  <rule_failures switched_off="true" permanent_id="2" ID="4" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="2" MESSAGE="new message" LINE="[null]" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="line_checksum"/>\r
-</dataset>\r
+<dataset>
+
+  <rules_categories id="1" name="Efficiency" description="[null]"/>
+  <rules_categories id="6" name="Usability" description="[null]"/>
+
+  <rules id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
+         plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
+         cardinality="SINGLE" parent_id="[null]"/>
+
+  <rules id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
+         plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
+         cardinality="SINGLE" parent_id="[null]"/>
+
+  <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
+            name="Bar" long_name="org.foo.Bar" description="[null]"
+            enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>
+
+  <snapshots period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
+             scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
+             status="U" islast="false" depth="3" />
+
+  <rule_failures switched_off="false" permanent_id="1" ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
+  <rule_failures switched_off="true" permanent_id="2" ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
+
+  <rule_failures switched_off="false" permanent_id="1" ID="3" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="2" MESSAGE="new message" LINE="[null]" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="line_checksum"/>
+  <rule_failures switched_off="true" permanent_id="2" ID="4" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="2" MESSAGE="new message" LINE="[null]" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="line_checksum"/>
+</dataset>
index 765a84bae8c58040296d1b8195b427095b1e0370..3b3215ffe11b5556487925dac1300e77faa57203 100644 (file)
@@ -1,26 +1,26 @@
-<dataset>\r
-  <rules_categories id="1" name="Efficiency" description="[null]"/>\r
-  <rules_categories id="6" name="Usability" description="[null]"/>\r
-\r
-  <rules id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"\r
-         plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"\r
-         cardinality="SINGLE" parent_id="[null]"/>\r
-\r
-  <rules id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"\r
-         plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"\r
-         cardinality="SINGLE" parent_id="[null]"/>\r
-\r
-  <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"\r
-            name="Bar" long_name="org.foo.Bar" description="[null]"\r
-            enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>\r
-\r
-  <snapshots period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"\r
-             scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path=""\r
-             status="U" islast="false" depth="3" />\r
-\r
-  <rule_failures switched_off="false" permanent_id="1" ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>\r
-  <rule_failures switched_off="true" permanent_id="2" ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>\r
-  <rule_failures switched_off="false" permanent_id="3" ID="3" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="the message" LINE="20" COST="55.6" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>\r
-  <rule_failures switched_off="false" permanent_id="4" ID="4" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="[null]" LINE="50" COST="80" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>\r
-  <rule_failures switched_off="false" permanent_id="5" ID="5" SNAPSHOT_ID="1000" RULE_ID="31" FAILURE_LEVEL="1" MESSAGE="[null]" LINE="[null]" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>\r
+<dataset>
+  <rules_categories id="1" name="Efficiency" description="[null]"/>
+  <rules_categories id="6" name="Usability" description="[null]"/>
+
+  <rules id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
+         plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
+         cardinality="SINGLE" parent_id="[null]"/>
+
+  <rules id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
+         plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
+         cardinality="SINGLE" parent_id="[null]"/>
+
+  <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
+            name="Bar" long_name="org.foo.Bar" description="[null]"
+            enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>
+
+  <snapshots period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
+             scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
+             status="U" islast="false" depth="3" />
+
+  <rule_failures switched_off="false" permanent_id="1" ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
+  <rule_failures switched_off="true" permanent_id="2" ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="old message" LINE="10" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
+  <rule_failures switched_off="false" permanent_id="3" ID="3" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="the message" LINE="20" COST="55.6" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
+  <rule_failures switched_off="false" permanent_id="4" ID="4" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="[null]" LINE="50" COST="80" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
+  <rule_failures switched_off="false" permanent_id="5" ID="5" SNAPSHOT_ID="1000" RULE_ID="31" FAILURE_LEVEL="1" MESSAGE="[null]" LINE="[null]" COST="[null]" created_at="2008-11-01 13:58:00.00" checksum="[null]"/>
 </dataset>
\ No newline at end of file
index 6533b5ae5cf23078e00dceb090ec92090ba083fd..ab3ee2417d0ce05af546afd3d9c4d0ed6230ac8c 100644 (file)
-/*\r
- * Sonar, open source software quality management tool.\r
- * Copyright (C) 2008-2011 SonarSource\r
- * mailto:contact AT sonarsource DOT com\r
- *\r
- * Sonar is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 3 of the License, or (at your option) any later version.\r
- *\r
- * Sonar is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with Sonar; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02\r
- */\r
-package org.sonar.jpa.session;\r
-\r
-import org.apache.commons.lang.StringUtils;\r
-import org.sonar.api.database.DatabaseSession;\r
-\r
-import java.util.*;\r
-\r
-import javax.persistence.EntityManager;\r
-import javax.persistence.NonUniqueResultException;\r
-import javax.persistence.PersistenceException;\r
-import javax.persistence.Query;\r
-\r
-public class JpaDatabaseSession extends DatabaseSession {\r
-\r
-  private final DatabaseConnector connector;\r
-  private EntityManager entityManager = null;\r
-  private int index = 0;\r
-  private boolean inTransaction = false;\r
-\r
-  public JpaDatabaseSession(DatabaseConnector connector) {\r
-    this.connector = connector;\r
-  }\r
-\r
-  /**\r
-   * Note that usage of this method is discouraged, because it allows to construct and execute queries without additional exception handling,\r
-   * which done in methods of this class.\r
-   */\r
-  public EntityManager getEntityManager() {\r
-    return entityManager;\r
-  }\r
-\r
-  public void start() {\r
-    entityManager = connector.createEntityManager();\r
-    index = 0;\r
-  }\r
-\r
-  public void stop() {\r
-    commit();\r
-    if (entityManager != null && entityManager.isOpen()) {\r
-      entityManager.close();\r
-      entityManager = null;\r
-    }\r
-  }\r
-\r
-  public void commit() {\r
-    if (entityManager != null && inTransaction) {\r
-      if (entityManager.isOpen()) {\r
-        if (entityManager.getTransaction().getRollbackOnly()) {\r
-          entityManager.getTransaction().rollback();\r
-        } else {\r
-          entityManager.getTransaction().commit();\r
-        }\r
-        entityManager.clear();\r
-        index = 0;\r
-      }\r
-      inTransaction = false;\r
-    }\r
-  }\r
-\r
-  public void rollback() {\r
-    if (entityManager != null && inTransaction) {\r
-      entityManager.getTransaction().rollback();\r
-      inTransaction = false;\r
-    }\r
-  }\r
-\r
-  public <T> T save(T model) {\r
-    startTransaction();\r
-    internalSave(model, true);\r
-    return model;\r
-  }\r
-\r
-  public Object saveWithoutFlush(Object model) {\r
-    startTransaction();\r
-    internalSave(model, false);\r
-    return model;\r
-  }\r
-\r
-  public boolean contains(Object model) {\r
-    startTransaction();\r
-    return entityManager.contains(model);\r
-  }\r
-\r
-  public void save(Object... models) {\r
-    startTransaction();\r
-    for (Object model : models) {\r
-      save(model);\r
-    }\r
-  }\r
-\r
-  private void internalSave(Object model, boolean flushIfNeeded) {\r
-    try {\r
-      entityManager.persist(model);\r
-    } catch (PersistenceException e) {\r
-      /*\r
-       * See http://jira.codehaus.org/browse/SONAR-2234\r
-       * In some cases Hibernate can throw exceptions without meaningful information about context, so we improve them here.\r
-       */\r
-      throw new PersistenceException("Unable to persist : " + model, e);\r
-    }\r
-    if (flushIfNeeded && (++index % BATCH_SIZE == 0)) {\r
-      commit();\r
-    }\r
-  }\r
-\r
-  public Object merge(Object model) {\r
-    startTransaction();\r
-    return entityManager.merge(model);\r
-  }\r
-\r
-  public void remove(Object model) {\r
-    startTransaction();\r
-    entityManager.remove(model);\r
-    if (++index % BATCH_SIZE == 0) {\r
-      commit();\r
-    }\r
-  }\r
-\r
-  public void removeWithoutFlush(Object model) {\r
-    startTransaction();\r
-    entityManager.remove(model);\r
-  }\r
-\r
-  public <T> T reattach(Class<T> entityClass, Object primaryKey) {\r
-    startTransaction();\r
-    return entityManager.getReference(entityClass, primaryKey);\r
-  }\r
-\r
-  private void startTransaction() {\r
-    if (!inTransaction) {\r
-      entityManager.getTransaction().begin();\r
-      inTransaction = true;\r
-    }\r
-  }\r
-\r
-  /**\r
-   * Note that not recommended to directly execute {@link Query#getSingleResult()}, because it will bypass exception handling,\r
-   * which done in {@link #getSingleResult(Query, Object)}.\r
-   */\r
-  public Query createQuery(String hql) {\r
-    startTransaction();\r
-    return entityManager.createQuery(hql);\r
-  }\r
-  \r
-  @Override\r
-  public Query createNativeQuery(String sql) {\r
-    startTransaction();\r
-    return entityManager.createNativeQuery(sql);\r
-  }\r
-\r
-  /**\r
-   * @return the result or <code>defaultValue</code>, if not found\r
-   * @throws NonUniqueResultException if more than one result\r
-   */\r
-  public <T> T getSingleResult(Query query, T defaultValue) {\r
-    /*\r
-     * See http://jira.codehaus.org/browse/SONAR-2225\r
-     * By default Hibernate throws NonUniqueResultException without meaningful information about context,\r
-     * so we improve it here by adding all results in error message.\r
-     * Note that in some rare situations we can receive too many results, which may lead to OOME,\r
-     * but actually it will mean that database is corrupted as we don't expect more than one result\r
-     * and in fact org.hibernate.ejb.QueryImpl#getSingleResult() anyway does loading of several results under the hood.\r
-     */\r
-    List<T> result = query.getResultList();\r
-\r
-    if (result.size() == 1) {\r
-      return result.get(0);\r
-\r
-    } else if (result.isEmpty()) {\r
-      return defaultValue;\r
-\r
-    } else {\r
-      Set<T> uniqueResult = new HashSet<T>(result);\r
-      if (uniqueResult.size() > 1) {\r
-        throw new NonUniqueResultException("Expected single result, but got : " + result.toString());\r
-      } else {\r
-        return uniqueResult.iterator().next();\r
-      }\r
-    }\r
-  }\r
-\r
-  public <T> T getEntity(Class<T> entityClass, Object id) {\r
-    startTransaction();\r
-    return getEntityManager().find(entityClass, id);\r
-  }\r
-\r
-  /**\r
-   * @return the result or <code>null</code>, if not found\r
-   * @throws NonUniqueResultException if more than one result\r
-   */\r
-  public <T> T getSingleResult(Class<T> entityClass, Object... criterias) {\r
-    try {\r
-      return getSingleResult(getQueryForCriterias(entityClass, true, criterias), (T) null);\r
-\r
-    } catch (NonUniqueResultException ex) {\r
-      NonUniqueResultException e = new NonUniqueResultException("Expected single result for entitiy " + entityClass.getSimpleName()\r
-          + " with criterias : " + StringUtils.join(criterias, ","));\r
-      e.initCause(ex);\r
-      throw e;\r
-    }\r
-  }\r
-\r
-  public <T> List<T> getResults(Class<T> entityClass, Object... criterias) {\r
-    return getQueryForCriterias(entityClass, true, criterias).getResultList();\r
-  }\r
-\r
-  public <T> List<T> getResults(Class<T> entityClass) {\r
-    return getQueryForCriterias(entityClass, false, null).getResultList();\r
-  }\r
-\r
-  private Query getQueryForCriterias(Class<?> entityClass, boolean raiseError, Object... criterias) {\r
-    if (criterias == null && raiseError) {\r
-      throw new IllegalStateException("criterias parameter must be provided");\r
-    }\r
-    startTransaction();\r
-    StringBuilder hql = new StringBuilder("SELECT o FROM ").append(entityClass.getSimpleName()).append(" o");\r
-    if (criterias != null) {\r
-      hql.append(" WHERE ");\r
-      Map<String, Object> mappedCriterias = new HashMap<String, Object>();\r
-      for (int i = 0; i < criterias.length; i += 2) {\r
-        mappedCriterias.put((String) criterias[i], criterias[i + 1]);\r
-      }\r
-      buildCriteriasHQL(hql, mappedCriterias);\r
-      Query query = getEntityManager().createQuery(hql.toString());\r
-\r
-      for (Map.Entry<String, Object> entry : mappedCriterias.entrySet()) {\r
-        query.setParameter(entry.getKey(), entry.getValue());\r
-      }\r
-      return query;\r
-    }\r
-    return getEntityManager().createQuery(hql.toString());\r
-  }\r
-\r
-  private void buildCriteriasHQL(StringBuilder hql, Map<String, Object> mappedCriterias) {\r
-    for (Iterator<String> i = mappedCriterias.keySet().iterator(); i.hasNext();) {\r
-      String criteria = i.next();\r
-      hql.append("o.").append(criteria).append("=:").append(criteria);\r
-      if (i.hasNext()) {\r
-        hql.append(" AND ");\r
-      }\r
-    }\r
-  }\r
-\r
-}\r
+/*
+ * 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.jpa.session;
+
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.database.DatabaseSession;
+
+import java.util.*;
+
+import javax.persistence.EntityManager;
+import javax.persistence.NonUniqueResultException;
+import javax.persistence.PersistenceException;
+import javax.persistence.Query;
+
+public class JpaDatabaseSession extends DatabaseSession {
+
+  private final DatabaseConnector connector;
+  private EntityManager entityManager = null;
+  private int index = 0;
+  private boolean inTransaction = false;
+
+  public JpaDatabaseSession(DatabaseConnector connector) {
+    this.connector = connector;
+  }
+
+  /**
+   * Note that usage of this method is discouraged, because it allows to construct and execute queries without additional exception handling,
+   * which done in methods of this class.
+   */
+  public EntityManager getEntityManager() {
+    return entityManager;
+  }
+
+  public void start() {
+    entityManager = connector.createEntityManager();
+    index = 0;
+  }
+
+  public void stop() {
+    commit();
+    if (entityManager != null && entityManager.isOpen()) {
+      entityManager.close();
+      entityManager = null;
+    }
+  }
+
+  public void commit() {
+    if (entityManager != null && inTransaction) {
+      if (entityManager.isOpen()) {
+        if (entityManager.getTransaction().getRollbackOnly()) {
+          entityManager.getTransaction().rollback();
+        } else {
+          entityManager.getTransaction().commit();
+        }
+        entityManager.clear();
+        index = 0;
+      }
+      inTransaction = false;
+    }
+  }
+
+  public void rollback() {
+    if (entityManager != null && inTransaction) {
+      entityManager.getTransaction().rollback();
+      inTransaction = false;
+    }
+  }
+
+  public <T> T save(T model) {
+    startTransaction();
+    internalSave(model, true);
+    return model;
+  }
+
+  public Object saveWithoutFlush(Object model) {
+    startTransaction();
+    internalSave(model, false);
+    return model;
+  }
+
+  public boolean contains(Object model) {
+    startTransaction();
+    return entityManager.contains(model);
+  }
+
+  public void save(Object... models) {
+    startTransaction();
+    for (Object model : models) {
+      save(model);
+    }
+  }
+
+  private void internalSave(Object model, boolean flushIfNeeded) {
+    try {
+      entityManager.persist(model);
+    } catch (PersistenceException e) {
+      /*
+       * See http://jira.codehaus.org/browse/SONAR-2234
+       * In some cases Hibernate can throw exceptions without meaningful information about context, so we improve them here.
+       */
+      throw new PersistenceException("Unable to persist : " + model, e);
+    }
+    if (flushIfNeeded && (++index % BATCH_SIZE == 0)) {
+      commit();
+    }
+  }
+
+  public Object merge(Object model) {
+    startTransaction();
+    return entityManager.merge(model);
+  }
+
+  public void remove(Object model) {
+    startTransaction();
+    entityManager.remove(model);
+    if (++index % BATCH_SIZE == 0) {
+      commit();
+    }
+  }
+
+  public void removeWithoutFlush(Object model) {
+    startTransaction();
+    entityManager.remove(model);
+  }
+
+  public <T> T reattach(Class<T> entityClass, Object primaryKey) {
+    startTransaction();
+    return entityManager.getReference(entityClass, primaryKey);
+  }
+
+  private void startTransaction() {
+    if (!inTransaction) {
+      entityManager.getTransaction().begin();
+      inTransaction = true;
+    }
+  }
+
+  /**
+   * Note that not recommended to directly execute {@link Query#getSingleResult()}, because it will bypass exception handling,
+   * which done in {@link #getSingleResult(Query, Object)}.
+   */
+  public Query createQuery(String hql) {
+    startTransaction();
+    return entityManager.createQuery(hql);
+  }
+  
+  @Override
+  public Query createNativeQuery(String sql) {
+    startTransaction();
+    return entityManager.createNativeQuery(sql);
+  }
+
+  /**
+   * @return the result or <code>defaultValue</code>, if not found
+   * @throws NonUniqueResultException if more than one result
+   */
+  public <T> T getSingleResult(Query query, T defaultValue) {
+    /*
+     * See http://jira.codehaus.org/browse/SONAR-2225
+     * By default Hibernate throws NonUniqueResultException without meaningful information about context,
+     * so we improve it here by adding all results in error message.
+     * Note that in some rare situations we can receive too many results, which may lead to OOME,
+     * but actually it will mean that database is corrupted as we don't expect more than one result
+     * and in fact org.hibernate.ejb.QueryImpl#getSingleResult() anyway does loading of several results under the hood.
+     */
+    List<T> result = query.getResultList();
+
+    if (result.size() == 1) {
+      return result.get(0);
+
+    } else if (result.isEmpty()) {
+      return defaultValue;
+
+    } else {
+      Set<T> uniqueResult = new HashSet<T>(result);
+      if (uniqueResult.size() > 1) {
+        throw new NonUniqueResultException("Expected single result, but got : " + result.toString());
+      } else {
+        return uniqueResult.iterator().next();
+      }
+    }
+  }
+
+  public <T> T getEntity(Class<T> entityClass, Object id) {
+    startTransaction();
+    return getEntityManager().find(entityClass, id);
+  }
+
+  /**
+   * @return the result or <code>null</code>, if not found
+   * @throws NonUniqueResultException if more than one result
+   */
+  public <T> T getSingleResult(Class<T> entityClass, Object... criterias) {
+    try {
+      return getSingleResult(getQueryForCriterias(entityClass, true, criterias), (T) null);
+
+    } catch (NonUniqueResultException ex) {
+      NonUniqueResultException e = new NonUniqueResultException("Expected single result for entitiy " + entityClass.getSimpleName()
+          + " with criterias : " + StringUtils.join(criterias, ","));
+      e.initCause(ex);
+      throw e;
+    }
+  }
+
+  public <T> List<T> getResults(Class<T> entityClass, Object... criterias) {
+    return getQueryForCriterias(entityClass, true, criterias).getResultList();
+  }
+
+  public <T> List<T> getResults(Class<T> entityClass) {
+    return getQueryForCriterias(entityClass, false, null).getResultList();
+  }
+
+  private Query getQueryForCriterias(Class<?> entityClass, boolean raiseError, Object... criterias) {
+    if (criterias == null && raiseError) {
+      throw new IllegalStateException("criterias parameter must be provided");
+    }
+    startTransaction();
+    StringBuilder hql = new StringBuilder("SELECT o FROM ").append(entityClass.getSimpleName()).append(" o");
+    if (criterias != null) {
+      hql.append(" WHERE ");
+      Map<String, Object> mappedCriterias = new HashMap<String, Object>();
+      for (int i = 0; i < criterias.length; i += 2) {
+        mappedCriterias.put((String) criterias[i], criterias[i + 1]);
+      }
+      buildCriteriasHQL(hql, mappedCriterias);
+      Query query = getEntityManager().createQuery(hql.toString());
+
+      for (Map.Entry<String, Object> entry : mappedCriterias.entrySet()) {
+        query.setParameter(entry.getKey(), entry.getValue());
+      }
+      return query;
+    }
+    return getEntityManager().createQuery(hql.toString());
+  }
+
+  private void buildCriteriasHQL(StringBuilder hql, Map<String, Object> mappedCriterias) {
+    for (Iterator<String> i = mappedCriterias.keySet().iterator(); i.hasNext();) {
+      String criteria = i.next();
+      hql.append("o.").append(criteria).append("=:").append(criteria);
+      if (i.hasNext()) {
+        hql.append(" AND ");
+      }
+    }
+  }
+
+}
index af59b924da7c8a74abe0cbfff07a488016cb3897..57103c691d0d2ec05cf27ce20e6a45104083c547 100644 (file)
-/*\r
- * Sonar, open source software quality management tool.\r
- * Copyright (C) 2008-2011 SonarSource\r
- * mailto:contact AT sonarsource DOT com\r
- *\r
- * Sonar is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 3 of the License, or (at your option) any later version.\r
- *\r
- * Sonar is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with Sonar; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02\r
- */\r
-package org.sonar.api.batch;\r
-\r
-import org.sonar.api.design.Dependency;\r
-import org.sonar.api.measures.Measure;\r
-import org.sonar.api.measures.MeasuresFilter;\r
-import org.sonar.api.measures.Metric;\r
-import org.sonar.api.resources.Project;\r
-import org.sonar.api.resources.Resource;\r
-import org.sonar.api.rules.Violation;\r
-import org.sonar.api.violations.ViolationQuery;\r
-\r
-import java.util.Collection;\r
-import java.util.Date;\r
-import java.util.List;\r
-import java.util.Set;\r
-\r
-/**\r
- * @since 1.10\r
- */\r
-public interface DecoratorContext {\r
-\r
-  /**\r
-   * @return the project in which the decorator is\r
-   */\r
-  Project getProject();\r
-\r
-  /**\r
-   * @return the resource that is currently decorated\r
-   */\r
-  Resource getResource();\r
-\r
-  /**\r
-   * Child contexts are read only\r
-   */\r
-  List<DecoratorContext> getChildren();\r
-\r
-  // MEASURES\r
-\r
-  /**\r
-   * Find a measure for the resource\r
-   */\r
-  Measure getMeasure(Metric metric);\r
-\r
-  /**\r
-   * Never return null.\r
-   */\r
-  <M> M getMeasures(MeasuresFilter<M> filter);\r
-\r
-  /**\r
-   * Never return null.\r
-   */\r
-  Collection<Measure> getChildrenMeasures(MeasuresFilter filter);\r
-\r
-  /**\r
-   * @return the resource children measures for the given metric\r
-   */\r
-  Collection<Measure> getChildrenMeasures(Metric metric);\r
-\r
-  /**\r
-   * Add a measure on the current resource. It can not be executed from children contexts.\r
-   * \r
-   * @return the same context\r
-   */\r
-  DecoratorContext saveMeasure(Measure measure);\r
-\r
-  /**\r
-   * Add a measure on the current resource. It can not be executed from children contexts.\r
-   * \r
-   * @return the current object\r
-   */\r
-  DecoratorContext saveMeasure(Metric metric, Double value);\r
-\r
-  // DEPENDENCIES\r
-\r
-  Dependency saveDependency(Dependency dependency);\r
-\r
-  Set<Dependency> getDependencies();\r
-\r
-  Collection<Dependency> getIncomingDependencies();\r
-\r
-  Collection<Dependency> getOutgoingDependencies();\r
-\r
-  // RULES\r
-\r
-  /**\r
-   * Returns the violations that match the {@link ViolationQuery} parameters.\r
-   * \r
-   * @since 2.8\r
-   * @param violationQuery\r
-   *          the request parameters specified as a {@link ViolationQuery}\r
-   * @return the list of violations that match those parameters\r
-   */\r
-  public abstract List<Violation> getViolations(ViolationQuery violationQuery);\r
-\r
-  /**\r
-   * Returns all the active (= non switched-off) violations found on the current resource.\r
-   * \r
-   * @return the list of violations\r
-   */\r
-  List<Violation> getViolations();\r
-\r
-  /**\r
-   * Save a coding rule violation. The decorator which calls this method must be depended upon BatchBarriers.END_OF_VIOLATIONS_GENERATION.\r
-   * \r
-   * @since 2.5\r
-   * @param force allows to force creation of violation even if it was suppressed by {@link org.sonar.api.rules.ViolationFilter}\r
-   */\r
-  DecoratorContext saveViolation(Violation violation, boolean force);\r
-\r
-  /**\r
-   * Save a coding rule violation. The decorator which calls this method must be depended upon BatchBarriers.END_OF_VIOLATIONS_GENERATION.\r
-   */\r
-  DecoratorContext saveViolation(Violation violation);\r
-\r
-  // EVENTS\r
-\r
-  /**\r
-   * @return the list of events associated to the current resource\r
-   */\r
-  List<Event> getEvents();\r
-\r
-  /**\r
-   * Creates an event for a given date\r
-   * \r
-   * @param name the event name\r
-   * @param description the event description\r
-   * @param category the event category\r
-   * @param date the event date\r
-   * @return the created event\r
-   */\r
-  Event createEvent(String name, String description, String category, Date date);\r
-\r
-  /**\r
-   * Deletes an event\r
-   * \r
-   * @param event the event to delete\r
-   */\r
-  void deleteEvent(Event event);\r
-\r
-}\r
+/*
+ * 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.batch;
+
+import org.sonar.api.design.Dependency;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.measures.MeasuresFilter;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.rules.Violation;
+import org.sonar.api.violations.ViolationQuery;
+
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @since 1.10
+ */
+public interface DecoratorContext {
+
+  /**
+   * @return the project in which the decorator is
+   */
+  Project getProject();
+
+  /**
+   * @return the resource that is currently decorated
+   */
+  Resource getResource();
+
+  /**
+   * Child contexts are read only
+   */
+  List<DecoratorContext> getChildren();
+
+  // MEASURES
+
+  /**
+   * Find a measure for the resource
+   */
+  Measure getMeasure(Metric metric);
+
+  /**
+   * Never return null.
+   */
+  <M> M getMeasures(MeasuresFilter<M> filter);
+
+  /**
+   * Never return null.
+   */
+  Collection<Measure> getChildrenMeasures(MeasuresFilter filter);
+
+  /**
+   * @return the resource children measures for the given metric
+   */
+  Collection<Measure> getChildrenMeasures(Metric metric);
+
+  /**
+   * Add a measure on the current resource. It can not be executed from children contexts.
+   * 
+   * @return the same context
+   */
+  DecoratorContext saveMeasure(Measure measure);
+
+  /**
+   * Add a measure on the current resource. It can not be executed from children contexts.
+   * 
+   * @return the current object
+   */
+  DecoratorContext saveMeasure(Metric metric, Double value);
+
+  // DEPENDENCIES
+
+  Dependency saveDependency(Dependency dependency);
+
+  Set<Dependency> getDependencies();
+
+  Collection<Dependency> getIncomingDependencies();
+
+  Collection<Dependency> getOutgoingDependencies();
+
+  // RULES
+
+  /**
+   * Returns the violations that match the {@link ViolationQuery} parameters.
+   * 
+   * @since 2.8
+   * @param violationQuery
+   *          the request parameters specified as a {@link ViolationQuery}
+   * @return the list of violations that match those parameters
+   */
+  public abstract List<Violation> getViolations(ViolationQuery violationQuery);
+
+  /**
+   * Returns all the active (= non switched-off) violations found on the current resource.
+   * 
+   * @return the list of violations
+   */
+  List<Violation> getViolations();
+
+  /**
+   * Save a coding rule violation. The decorator which calls this method must be depended upon BatchBarriers.END_OF_VIOLATIONS_GENERATION.
+   * 
+   * @since 2.5
+   * @param force allows to force creation of violation even if it was suppressed by {@link org.sonar.api.rules.ViolationFilter}
+   */
+  DecoratorContext saveViolation(Violation violation, boolean force);
+
+  /**
+   * Save a coding rule violation. The decorator which calls this method must be depended upon BatchBarriers.END_OF_VIOLATIONS_GENERATION.
+   */
+  DecoratorContext saveViolation(Violation violation);
+
+  // EVENTS
+
+  /**
+   * @return the list of events associated to the current resource
+   */
+  List<Event> getEvents();
+
+  /**
+   * Creates an event for a given date
+   * 
+   * @param name the event name
+   * @param description the event description
+   * @param category the event category
+   * @param date the event date
+   * @return the created event
+   */
+  Event createEvent(String name, String description, String category, Date date);
+
+  /**
+   * Deletes an event
+   * 
+   * @param event the event to delete
+   */
+  void deleteEvent(Event event);
+
+}
index f2a09f9a6ce07cdf3c916f81d45a0140bb412fb2..89133b1c6b8dccf92d0f6c084816b5174f47f84d 100644 (file)
-/*\r
- * Sonar, open source software quality management tool.\r
- * Copyright (C) 2008-2011 SonarSource\r
- * mailto:contact AT sonarsource DOT com\r
- *\r
- * Sonar is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 3 of the License, or (at your option) any later version.\r
- *\r
- * Sonar is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with Sonar; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02\r
- */\r
-package org.sonar.api.batch;\r
-\r
-import org.sonar.api.design.Dependency;\r
-import org.sonar.api.measures.Measure;\r
-import org.sonar.api.measures.MeasuresFilter;\r
-import org.sonar.api.measures.Metric;\r
-import org.sonar.api.resources.DuplicatedSourceException;\r
-import org.sonar.api.resources.Project;\r
-import org.sonar.api.resources.ProjectLink;\r
-import org.sonar.api.resources.Resource;\r
-import org.sonar.api.rules.Violation;\r
-import org.sonar.api.violations.ViolationQuery;\r
-import org.sonar.graph.DirectedGraphAccessor;\r
-\r
-import java.util.Collection;\r
-import java.util.Date;\r
-import java.util.List;\r
-import java.util.Set;\r
-\r
-public abstract class SonarIndex implements DirectedGraphAccessor<Resource, Dependency> {\r
-\r
-  /**\r
-   * Indexes a resource as a direct child of project. This method does nothing and returns true if the resource already indexed.\r
-   * If the method resource.getParent() does not return null, then this parent will be indexed too.\r
-   *\r
-   * @return false if the resource is excluded\r
-   * @since 2.6\r
-   */\r
-  public abstract boolean index(Resource resource);\r
-\r
-\r
-  /**\r
-   * Indexes a resource. This method does nothing if the resource is already indexed.\r
-   *\r
-   * @param resource        the resource to index. Not nullable\r
-   * @param parentReference a reference to the indexed parent. If null, the resource is indexed as a direct child of project.\r
-   * @return false if the parent is not indexed or if the resource is excluded\r
-   * @since 2.6\r
-   */\r
-  public abstract boolean index(Resource resource, Resource parentReference);\r
-\r
-  /**\r
-   * Returns true if the referenced resource is excluded. An excluded resource is not indexed.\r
-   * @since 2.6\r
-   */\r
-  public abstract boolean isExcluded(Resource reference);\r
-\r
-  /**\r
-   * @since 2.6\r
-   */\r
-  public abstract boolean isIndexed(Resource reference, boolean acceptExcluded);\r
-\r
-  /**\r
-   * Search for an indexed resource.\r
-   *\r
-   * @param reference the resource reference\r
-   * @return the indexed resource, null if it's not indexed\r
-   * @since 1.10. Generic types since 2.6.\r
-   */\r
-  public abstract <R extends Resource> R getResource(R reference);\r
-\r
-  /**\r
-   * @since 2.6\r
-   */\r
-  public abstract Resource getParent(Resource reference);\r
-\r
-  /**\r
-   * @since 2.6\r
-   */\r
-\r
-  public abstract Collection<Resource> getChildren(Resource reference);\r
-\r
-  /**\r
-   * Save the source code of a file. The file must be have been indexed before.\r
-   * Note: the source stream is not closed.\r
-   *\r
-   * @return false if the resource is excluded or not indexed\r
-   * @throws org.sonar.api.resources.DuplicatedSourceException\r
-   *          if the source has already been set on this resource\r
-   */\r
-  public abstract void setSource(Resource reference, String source) throws DuplicatedSourceException;\r
-\r
-  public abstract Project getProject();\r
-\r
-  public final Collection<Resource> getResources() {\r
-    return getVertices();\r
-  }\r
-\r
-  /**\r
-   * Indexes the resource.\r
-   * @return the indexed resource, even if it's excluded\r
-   * @deprecated since 2.6. Use methods index()\r
-   */\r
-  @Deprecated\r
-  public abstract Resource addResource(Resource resource);\r
-\r
-  public abstract Measure getMeasure(Resource resource, Metric metric);\r
-\r
-  public abstract <M> M getMeasures(Resource resource, MeasuresFilter<M> filter);\r
-\r
-  /**\r
-   * Returns the violations that match the {@link ViolationQuery} parameters.\r
-   * \r
-   * @since 2.8\r
-   * @param violationQuery\r
-   *          the request parameters specified as a {@link ViolationQuery}\r
-   * @return the list of violations that match those parameters\r
-   */\r
-  public abstract List<Violation> getViolations(ViolationQuery violationQuery);\r
-\r
-  /**\r
-   * Returns all the active (= non switched-off) violations found on the given resource. Equivalent to\r
-   * {@link #getViolations(ViolationQuery)} called with <code>ViolationQuery.create().forResource(resource).ignoreSwitchedOff(true)</code>\r
-   * as a parameter.\r
-   * \r
-   * @since 2.7\r
-   * @param the\r
-   *          resource on which violations are searched\r
-   * @return the list of violations\r
-   */\r
-  public final List<Violation> getViolations(Resource resource) {\r
-    return getViolations(ViolationQuery.create().forResource(resource).ignoreSwitchedOff(true));\r
-  }\r
-\r
-  /**\r
-   * @since 2.5\r
-   */\r
-  public abstract void addViolation(Violation violation, boolean force);\r
-\r
-  public final void addViolation(Violation violation) {\r
-    addViolation(violation, false);\r
-  }\r
-\r
-  /**\r
-   * Warning: the resource is automatically indexed for backward-compatibility, but it should be explictly\r
-   * indexed before. Next versions will deactivate this automatic indexation.\r
-   *\r
-   * @throws SonarException if the metric is unknown.\r
-   */\r
-  public abstract Measure addMeasure(Resource resource, Measure measure);\r
-\r
-  public abstract Dependency addDependency(Dependency dependency);\r
-\r
-  public abstract Set<Dependency> getDependencies();\r
-\r
-  public abstract void addLink(ProjectLink link);\r
-\r
-  public abstract void deleteLink(String key);\r
-\r
-  public abstract List<Event> getEvents(Resource resource);\r
-\r
-  public abstract void deleteEvent(Event event);\r
-\r
-  public abstract Event addEvent(Resource resource, String name, String description, String category, Date date);\r
-\r
-  public final Collection<Dependency> getOutgoingDependencies(Resource from) {\r
-    return getOutgoingEdges(from);\r
-  }\r
-\r
-  public final Collection<Dependency> getIncomingDependencies(Resource to) {\r
-    return getIncomingEdges(to);\r
-  }\r
-}\r
+/*
+ * 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.batch;
+
+import org.sonar.api.design.Dependency;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.measures.MeasuresFilter;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.resources.DuplicatedSourceException;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.ProjectLink;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.rules.Violation;
+import org.sonar.api.violations.ViolationQuery;
+import org.sonar.graph.DirectedGraphAccessor;
+
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+public abstract class SonarIndex implements DirectedGraphAccessor<Resource, Dependency> {
+
+  /**
+   * Indexes a resource as a direct child of project. This method does nothing and returns true if the resource already indexed.
+   * If the method resource.getParent() does not return null, then this parent will be indexed too.
+   *
+   * @return false if the resource is excluded
+   * @since 2.6
+   */
+  public abstract boolean index(Resource resource);
+
+
+  /**
+   * Indexes a resource. This method does nothing if the resource is already indexed.
+   *
+   * @param resource        the resource to index. Not nullable
+   * @param parentReference a reference to the indexed parent. If null, the resource is indexed as a direct child of project.
+   * @return false if the parent is not indexed or if the resource is excluded
+   * @since 2.6
+   */
+  public abstract boolean index(Resource resource, Resource parentReference);
+
+  /**
+   * Returns true if the referenced resource is excluded. An excluded resource is not indexed.
+   * @since 2.6
+   */
+  public abstract boolean isExcluded(Resource reference);
+
+  /**
+   * @since 2.6
+   */
+  public abstract boolean isIndexed(Resource reference, boolean acceptExcluded);
+
+  /**
+   * Search for an indexed resource.
+   *
+   * @param reference the resource reference
+   * @return the indexed resource, null if it's not indexed
+   * @since 1.10. Generic types since 2.6.
+   */
+  public abstract <R extends Resource> R getResource(R reference);
+
+  /**
+   * @since 2.6
+   */
+  public abstract Resource getParent(Resource reference);
+
+  /**
+   * @since 2.6
+   */
+
+  public abstract Collection<Resource> getChildren(Resource reference);
+
+  /**
+   * Save the source code of a file. The file must be have been indexed before.
+   * Note: the source stream is not closed.
+   *
+   * @return false if the resource is excluded or not indexed
+   * @throws org.sonar.api.resources.DuplicatedSourceException
+   *          if the source has already been set on this resource
+   */
+  public abstract void setSource(Resource reference, String source) throws DuplicatedSourceException;
+
+  public abstract Project getProject();
+
+  public final Collection<Resource> getResources() {
+    return getVertices();
+  }
+
+  /**
+   * Indexes the resource.
+   * @return the indexed resource, even if it's excluded
+   * @deprecated since 2.6. Use methods index()
+   */
+  @Deprecated
+  public abstract Resource addResource(Resource resource);
+
+  public abstract Measure getMeasure(Resource resource, Metric metric);
+
+  public abstract <M> M getMeasures(Resource resource, MeasuresFilter<M> filter);
+
+  /**
+   * Returns the violations that match the {@link ViolationQuery} parameters.
+   * 
+   * @since 2.8
+   * @param violationQuery
+   *          the request parameters specified as a {@link ViolationQuery}
+   * @return the list of violations that match those parameters
+   */
+  public abstract List<Violation> getViolations(ViolationQuery violationQuery);
+
+  /**
+   * Returns all the active (= non switched-off) violations found on the given resource. Equivalent to
+   * {@link #getViolations(ViolationQuery)} called with <code>ViolationQuery.create().forResource(resource).ignoreSwitchedOff(true)</code>
+   * as a parameter.
+   * 
+   * @since 2.7
+   * @param the
+   *          resource on which violations are searched
+   * @return the list of violations
+   */
+  public final List<Violation> getViolations(Resource resource) {
+    return getViolations(ViolationQuery.create().forResource(resource).ignoreSwitchedOff(true));
+  }
+
+  /**
+   * @since 2.5
+   */
+  public abstract void addViolation(Violation violation, boolean force);
+
+  public final void addViolation(Violation violation) {
+    addViolation(violation, false);
+  }
+
+  /**
+   * Warning: the resource is automatically indexed for backward-compatibility, but it should be explictly
+   * indexed before. Next versions will deactivate this automatic indexation.
+   *
+   * @throws SonarException if the metric is unknown.
+   */
+  public abstract Measure addMeasure(Resource resource, Measure measure);
+
+  public abstract Dependency addDependency(Dependency dependency);
+
+  public abstract Set<Dependency> getDependencies();
+
+  public abstract void addLink(ProjectLink link);
+
+  public abstract void deleteLink(String key);
+
+  public abstract List<Event> getEvents(Resource resource);
+
+  public abstract void deleteEvent(Event event);
+
+  public abstract Event addEvent(Resource resource, String name, String description, String category, Date date);
+
+  public final Collection<Dependency> getOutgoingDependencies(Resource from) {
+    return getOutgoingEdges(from);
+  }
+
+  public final Collection<Dependency> getIncomingDependencies(Resource to) {
+    return getIncomingEdges(to);
+  }
+}
index dc416bc52577917fd71c3d87c51bfa4559795413..19bf31cd5c654446d9510cc124d95326c9f0cc8d 100644 (file)
@@ -1,80 +1,80 @@
-/*\r
- * Sonar, open source software quality management tool.\r
- * Copyright (C) 2008-2011 SonarSource\r
- * mailto:contact AT sonarsource DOT com\r
- *\r
- * Sonar is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 3 of the License, or (at your option) any later version.\r
- *\r
- * Sonar is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with Sonar; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02\r
- */\r
-package org.sonar.api.database;\r
-\r
-import org.sonar.api.BatchComponent;\r
-\r
-import javax.persistence.EntityManager;\r
-import javax.persistence.Query;\r
-import java.util.List;\r
-\r
-/**\r
- * This component should not accessible from plugin API\r
- *\r
- * @since 1.10\r
- */\r
-public abstract class DatabaseSession implements BatchComponent {\r
-\r
-\r
-  // IMPORTANT : this value must be the same than the property\r
-  // hibernate.jdbc.batch_size from /META-INF/persistence.xml (module sonar-database)\r
-  public static final int BATCH_SIZE = 30;\r
-\r
-\r
-  public abstract EntityManager getEntityManager();\r
-\r
-  public abstract void start();\r
-\r
-  public abstract void stop();\r
-\r
-  public abstract void commit();\r
-\r
-  public abstract void rollback();\r
-\r
-  public abstract <T> T save(T entity);\r
-\r
-  public abstract Object saveWithoutFlush(Object entity);\r
-\r
-  public abstract boolean contains(Object entity);\r
-\r
-  public abstract void save(Object... entities);\r
-\r
-  public abstract Object merge(Object entity);\r
-\r
-  public abstract void remove(Object entity);\r
-\r
-  public abstract void removeWithoutFlush(Object entity);\r
-\r
-  public abstract <T> T reattach(Class<T> entityClass, Object primaryKey);\r
-\r
-  public abstract Query createQuery(String hql);\r
-  \r
-  public abstract Query createNativeQuery(String sql);\r
-\r
-  public abstract <T> T getSingleResult(Query query, T defaultValue);\r
-\r
-  public abstract <T> T getEntity(Class<T> entityClass, Object id);\r
-\r
-  public abstract <T> T getSingleResult(Class<T> entityClass, Object... criterias);\r
-\r
-  public abstract <T> List<T> getResults(Class<T> entityClass, Object... criterias);\r
-\r
-  public abstract <T> List<T> getResults(Class<T> entityClass);\r
-}\r
+/*
+ * 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.database;
+
+import org.sonar.api.BatchComponent;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import java.util.List;
+
+/**
+ * This component should not accessible from plugin API
+ *
+ * @since 1.10
+ */
+public abstract class DatabaseSession implements BatchComponent {
+
+
+  // IMPORTANT : this value must be the same than the property
+  // hibernate.jdbc.batch_size from /META-INF/persistence.xml (module sonar-database)
+  public static final int BATCH_SIZE = 30;
+
+
+  public abstract EntityManager getEntityManager();
+
+  public abstract void start();
+
+  public abstract void stop();
+
+  public abstract void commit();
+
+  public abstract void rollback();
+
+  public abstract <T> T save(T entity);
+
+  public abstract Object saveWithoutFlush(Object entity);
+
+  public abstract boolean contains(Object entity);
+
+  public abstract void save(Object... entities);
+
+  public abstract Object merge(Object entity);
+
+  public abstract void remove(Object entity);
+
+  public abstract void removeWithoutFlush(Object entity);
+
+  public abstract <T> T reattach(Class<T> entityClass, Object primaryKey);
+
+  public abstract Query createQuery(String hql);
+  
+  public abstract Query createNativeQuery(String sql);
+
+  public abstract <T> T getSingleResult(Query query, T defaultValue);
+
+  public abstract <T> T getEntity(Class<T> entityClass, Object id);
+
+  public abstract <T> T getSingleResult(Class<T> entityClass, Object... criterias);
+
+  public abstract <T> List<T> getResults(Class<T> entityClass, Object... criterias);
+
+  public abstract <T> List<T> getResults(Class<T> entityClass);
+}
index fd2b06ec1c26dca3518e7cea4e228a84da48076a..3e4aa063a8b15a0332cdbcac39aaf848495018c4 100644 (file)
-/*\r
- * Sonar, open source software quality management tool.\r
- * Copyright (C) 2008-2011 SonarSource\r
- * mailto:contact AT sonarsource DOT com\r
- *\r
- * Sonar is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 3 of the License, or (at your option) any later version.\r
- *\r
- * Sonar is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with Sonar; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02\r
- */\r
-package org.sonar.api.rules;\r
-\r
-import org.apache.commons.lang.builder.EqualsBuilder;\r
-import org.apache.commons.lang.builder.HashCodeBuilder;\r
-import org.apache.commons.lang.builder.ReflectionToStringBuilder;\r
-import org.sonar.api.resources.Resource;\r
-\r
-import java.util.Date;\r
-\r
-/**\r
- * A class that represents a violation. A violation happens when a resource does not respect a defined rule.\r
- */\r
-public class Violation {\r
-\r
-  private Resource resource;\r
-  private Rule rule;\r
-  private String message;\r
-  private RulePriority severity;\r
-  private Integer lineId;\r
-  private Double cost;\r
-  private Date createdAt;\r
-  private boolean switchedOff;\r
-\r
-  /**\r
-   * Creates of a violation from a rule. Will need to define the resource later on\r
-   * \r
-   * @deprecated since 2.3. Use the factory method create()\r
-   */\r
-  @Deprecated\r
-  public Violation(Rule rule) {\r
-    this.rule = rule;\r
-  }\r
-\r
-  /**\r
-   * Creates a fully qualified violation\r
-   * \r
-   * @param rule\r
-   *          the rule that has been violated\r
-   * @param resource\r
-   *          the resource the violation should be attached to\r
-   * @deprecated since 2.3. Use the factory method create()\r
-   */\r
-  @Deprecated\r
-  public Violation(Rule rule, Resource resource) {\r
-    this.resource = resource;\r
-    this.rule = rule;\r
-  }\r
-\r
-  public Resource getResource() {\r
-    return resource;\r
-  }\r
-\r
-  /**\r
-   * Sets the resource the violation applies to\r
-   * \r
-   * @return the current object\r
-   */\r
-  public Violation setResource(Resource resource) {\r
-    this.resource = resource;\r
-    return this;\r
-  }\r
-\r
-  public Rule getRule() {\r
-    return rule;\r
-  }\r
-\r
-  /**\r
-   * Sets the rule violated\r
-   * \r
-   * @return the current object\r
-   */\r
-  public Violation setRule(Rule rule) {\r
-    this.rule = rule;\r
-    return this;\r
-  }\r
-\r
-  public String getMessage() {\r
-    return message;\r
-  }\r
-\r
-  /**\r
-   * Sets the violation message\r
-   * \r
-   * @return the current object\r
-   */\r
-  public Violation setMessage(String message) {\r
-    this.message = message;\r
-    return this;\r
-  }\r
-\r
-  /**\r
-   * @see #setLineId(Integer)\r
-   */\r
-  public Integer getLineId() {\r
-    return lineId;\r
-  }\r
-\r
-  /**\r
-   * Sets the violation line. Note that numbering starts from 1.\r
-   * \r
-   * @return the current object\r
-   */\r
-  public Violation setLineId(Integer lineId) {\r
-    this.lineId = lineId;\r
-    return this;\r
-  }\r
-\r
-  /**\r
-   * @since 2.5\r
-   */\r
-  public RulePriority getSeverity() {\r
-    return severity;\r
-  }\r
-\r
-  /**\r
-   * For internal use only.\r
-   * \r
-   * @since 2.5\r
-   */\r
-  public Violation setSeverity(RulePriority severity) {\r
-    this.severity = severity;\r
-    return this;\r
-  }\r
-\r
-  /**\r
-   * @deprecated since 2.5 use {@link #getSeverity()} instead. See http://jira.codehaus.org/browse/SONAR-1829\r
-   */\r
-  @Deprecated\r
-  public RulePriority getPriority() {\r
-    return severity;\r
-  }\r
-\r
-  /**\r
-   * For internal use only\r
-   * \r
-   * @deprecated since 2.5 use {@link #setSeverity(RulePriority)} instead. See http://jira.codehaus.org/browse/SONAR-1829\r
-   */\r
-  @Deprecated\r
-  public Violation setPriority(RulePriority priority) {\r
-    this.severity = priority;\r
-    return this;\r
-  }\r
-\r
-  /**\r
-   * @see #setCost(Double)\r
-   * @since 2.4\r
-   */\r
-  public Double getCost() {\r
-    return cost;\r
-  }\r
-\r
-  /**\r
-   * The cost to fix a violation can't be precisely computed without this information. Let's take the following example : a rule forbids to\r
-   * have methods whose complexity is greater than 10. Without this field "cost", the same violation is created with a method whose\r
-   * 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\r
-   * fix the method whose complexity is 15, and 3h5mn is required to fix the method whose complexity is 100.\r
-   * \r
-   * @since 2.4\r
-   */\r
-  public Violation setCost(Double d) {\r
-    this.cost = d;\r
-    return this;\r
-  }\r
-\r
-  /**\r
-   * @since 2.5\r
-   */\r
-  public Date getCreatedAt() {\r
-    return createdAt;\r
-  }\r
-\r
-  /**\r
-   * For internal use only\r
-   * \r
-   * @since 2.5\r
-   */\r
-  public Violation setCreatedAt(Date createdAt) {\r
-    this.createdAt = createdAt;\r
-    return this;\r
-  }\r
-\r
-  /**\r
-   * Switches off the current violation. This is a kind of "mute", which means the violation exists but won't be counted as an active\r
-   * violation (and thus, won't be counted in the total number of violations).\r
-   * \r
-   * @since 2.8\r
-   * @param switchedOff\r
-   *          if true, the violation is considered OFF\r
-   */\r
-  public void setSwitchedOff(boolean switchedOff) {\r
-    this.switchedOff = switchedOff;\r
-  }\r
-\r
-  /**\r
-   * Tells wether this violation is ON or OFF.\r
-   * \r
-   * @since 2.8\r
-   * @return true if the violation has been switched off\r
-   */\r
-  public boolean isSwitchedOff() {\r
-    return switchedOff;\r
-  }\r
-\r
-  @Override\r
-  public boolean equals(Object obj) {\r
-    if ( !(obj instanceof Violation)) {\r
-      return false;\r
-    }\r
-    if (this == obj) {\r
-      return true;\r
-    }\r
-    Violation other = (Violation) obj;\r
-    return new EqualsBuilder().append(rule, other.getRule()).append(resource, other.getResource()).isEquals();\r
-  }\r
-\r
-  @Override\r
-  public int hashCode() {\r
-    return new HashCodeBuilder(17, 37).append(getRule()).append(getResource()).toHashCode();\r
-  }\r
-\r
-  @Override\r
-  public String toString() {\r
-    return ReflectionToStringBuilder.toString(this);\r
-  }\r
-\r
-  public static Violation create(ActiveRule activeRule, Resource resource) {\r
-    return new Violation(activeRule.getRule()).setResource(resource);\r
-  }\r
-\r
-  public static Violation create(Rule rule, Resource resource) {\r
-    return new Violation(rule).setResource(resource);\r
-  }\r
-\r
-}\r
+/*
+ * 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);
+  }
+
+}
index e9f5ebdbdfa51da6e9f438535485c23285fba449..10be756b640de592c99deae9fa6d82d9600fa6f7 100644 (file)
@@ -1,89 +1,89 @@
-/*\r
- * Sonar, open source software quality management tool.\r
- * Copyright (C) 2008-2011 SonarSource\r
- * mailto:contact AT sonarsource DOT com\r
- *\r
- * Sonar is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 3 of the License, or (at your option) any later version.\r
- *\r
- * Sonar is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with Sonar; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02\r
- */\r
-package org.sonar.api.violations;\r
-\r
-import org.sonar.api.resources.Resource;\r
-\r
-/**\r
- * Class that allows to query the Sonar index about violations.\r
- * \r
- * @since 2.8\r
- */\r
-public final class ViolationQuery {\r
-\r
-  private boolean ignoreSwitchedOff;\r
-  private Resource resource;\r
-\r
-  /**\r
-   * Use the factory method <code>create()</code>\r
-   */\r
-  ViolationQuery() {\r
-  }\r
-\r
-  /**\r
-   * Creates a new {@link ViolationQuery} object.\r
-   * \r
-   * @return the new query\r
-   */\r
-  public static ViolationQuery create() {\r
-    return new ViolationQuery();\r
-  }\r
-\r
-  /**\r
-   * Specifies if the query should returned switched-off violations or not.\r
-   * \r
-   * @param ignore\r
-   *          if true, the query will return only active violations.\r
-   * @return the current violation query\r
-   */\r
-  public ViolationQuery ignoreSwitchedOff(boolean ignore) {\r
-    this.ignoreSwitchedOff = ignore;\r
-    return this;\r
-  }\r
-\r
-  /**\r
-   * Tells if the query should returned switched-off violations or not.\r
-   * \r
-   * @return\r
-   */\r
-  public boolean ignoreSwitchedOff() {\r
-    return ignoreSwitchedOff;\r
-  }\r
-\r
-  /**\r
-   * Specifies the resource which violations are search from.\r
-   * \r
-   * @param resource\r
-   *          the resource\r
-   */\r
-  public ViolationQuery forResource(Resource resource) {\r
-    this.resource = resource;\r
-    return this;\r
-  }\r
-\r
-  /**\r
-   * Returns the resource which violations are search from.\r
-   * \r
-   * @return the resource\r
-   */\r
-  public Resource getResource() {\r
-    return resource;\r
-  }\r
-}\r
+/*
+ * 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.violations;
+
+import org.sonar.api.resources.Resource;
+
+/**
+ * Class that allows to query the Sonar index about violations.
+ * 
+ * @since 2.8
+ */
+public final class ViolationQuery {
+
+  private boolean ignoreSwitchedOff;
+  private Resource resource;
+
+  /**
+   * Use the factory method <code>create()</code>
+   */
+  ViolationQuery() {
+  }
+
+  /**
+   * Creates a new {@link ViolationQuery} object.
+   * 
+   * @return the new query
+   */
+  public static ViolationQuery create() {
+    return new ViolationQuery();
+  }
+
+  /**
+   * Specifies if the query should returned switched-off violations or not.
+   * 
+   * @param ignore
+   *          if true, the query will return only active violations.
+   * @return the current violation query
+   */
+  public ViolationQuery ignoreSwitchedOff(boolean ignore) {
+    this.ignoreSwitchedOff = ignore;
+    return this;
+  }
+
+  /**
+   * Tells if the query should returned switched-off violations or not.
+   * 
+   * @return
+   */
+  public boolean ignoreSwitchedOff() {
+    return ignoreSwitchedOff;
+  }
+
+  /**
+   * Specifies the resource which violations are search from.
+   * 
+   * @param resource
+   *          the resource
+   */
+  public ViolationQuery forResource(Resource resource) {
+    this.resource = resource;
+    return this;
+  }
+
+  /**
+   * Returns the resource which violations are search from.
+   * 
+   * @return the resource
+   */
+  public Resource getResource() {
+    return resource;
+  }
+}
index 12bfbb61ff6b61f75a5ec7b343c01c09bfd592a8..bc4d569dd8db64a8b820eb5320ea343c9812202a 100644 (file)
-#\r
-# Sonar, entreprise quality control tool.\r
-# Copyright (C) 2008-2011 SonarSource\r
-# mailto:contact AT sonarsource DOT com\r
-#\r
-# Sonar is free software; you can redistribute it and/or\r
-# modify it under the terms of the GNU Lesser General Public\r
-# License as published by the Free Software Foundation; either\r
-# version 3 of the License, or (at your option) any later version.\r
-#\r
-# Sonar is distributed in the hope that it will be useful,\r
-# but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-# Lesser General Public License for more details.\r
-#\r
-# You should have received a copy of the GNU Lesser General Public\r
-# License along with Sonar; if not, write to the Free Software\r
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02\r
-#\r
-class ResourceController < ApplicationController\r
-\r
-  SECTION=Navigation::SECTION_RESOURCE\r
-  helper DashboardHelper\r
-  \r
-  def index\r
-    @resource = Project.by_key(params[:id])\r
-\r
-    if (@resource && has_role?(:user, @resource))\r
-      params[:layout]='false'\r
-      @snapshot=@resource.last_snapshot\r
-\r
-      load_extensions()\r
-\r
-      if @extension\r
-        if (@extension.getId()=='violations')\r
-          render_violations()\r
-        elsif (@extension.getId()=='coverage')\r
-          render_coverage()\r
-        elsif (@extension.getId()=='source')\r
-          render_source()\r
-        else\r
-          render_extension()\r
-        end\r
-      else\r
-        render_nothing()\r
-      end\r
-    else\r
-      access_denied\r
-    end\r
-  end\r
-\r
-  private\r
-\r
-  def load_extensions\r
-    @extensions=[]\r
-    java_facade.getResourceTabs(@resource.scope, @resource.qualifier, @resource.language).each do |tab|\r
-      tab.getUserRoles().each do |role|\r
-        if has_role?(role, @resource)\r
-          @extensions<<tab\r
-          break\r
-        end\r
-      end\r
-    end\r
-\r
-    if !params[:tab].blank?\r
-      @extension=@extensions.find{|extension| extension.getId()==params[:tab]}\r
-\r
-    elsif !params[:metric].blank?\r
-      metric=Metric.by_key(params[:metric])\r
-      @extension=@extensions.find{|extension| extension.getDefaultTabForMetrics().include?(metric.key)}\r
-\r
-    end\r
-    @extension=@extensions.find{|extension| extension.isDefaultTab()} if @extension==nil\r
-  end\r
-\r
-  def load_sources\r
-    @period = params[:period].to_i unless params[:period].blank?\r
-    @expanded=(params[:expand]=='true')\r
-\r
-    if @snapshot.source\r
-      source_lines=Java::OrgSonarServerUi::JRubyFacade.new.colorizeCode(@snapshot.source.data, @snapshot.project.language).split("\n")\r
-      init_scm()\r
-\r
-      @lines=[]\r
-      source_lines.each_with_index do |source, index|\r
-        line=Line.new(source)\r
-        @lines<<line\r
-\r
-        line.revision=@revisions_by_line[index+1]\r
-        line.author=@authors_by_line[index+1]\r
-\r
-        date_string=@dates_by_line[index+1]\r
-        line.datetime=(date_string ? Java::OrgSonarApiUtils::DateUtils.parseDateTime(date_string): nil)\r
-      end\r
-    end\r
-  end\r
-\r
-  def init_scm\r
-    @scm_available=(@snapshot.measure('last_commit_datetimes_by_line')!=nil)\r
-    @authors_by_line=load_distribution('authors_by_line')\r
-    @revisions_by_line=load_distribution('revisions_by_line')\r
-    @dates_by_line=load_distribution('last_commit_datetimes_by_line')\r
-  end\r
-\r
-  def load_distribution(metric_key)\r
-    m=@snapshot.measure(metric_key)\r
-    m ? m.data_as_line_distribution() : {}\r
-  end\r
-\r
-  def render_coverage\r
-    load_sources()\r
-    @display_coverage=true\r
-    @expandable=(@lines!=nil)\r
-    if @lines\r
-      @hits_by_line=load_distribution('coverage_line_hits_data')\r
-      @conditions_by_line=load_distribution('conditions_by_line')\r
-      @covered_conditions_by_line=load_distribution('covered_conditions_by_line')\r
-\r
-      @hits_by_line.each_pair do |line_id,hits|\r
-        line=@lines[line_id-1]\r
-        if line\r
-          line.hits=hits.to_i\r
-          line.conditions=@conditions_by_line[line_id].to_i\r
-          line.covered_conditions=@covered_conditions_by_line[line_id].to_i\r
-        end\r
-      end\r
-\r
-      if @snapshot.measure('conditions_by_line').nil?\r
-        # TODO remove this code when branch_coverage_hits_data is fully removed from CoreMetrics\r
-        deprecated_branches_by_line=load_distribution('branch_coverage_hits_data')\r
-        deprecated_branches_by_line.each_pair do |line_id,label|\r
-          line=@lines[line_id-1]\r
-          if line\r
-            line.deprecated_conditions_label=label\r
-          end\r
-        end\r
-      end\r
-\r
-      to=(@period ? Java::JavaUtil::Date.new(@snapshot.period_datetime(@period).to_f * 1000) : nil)\r
-      metric=Metric.by_key(params[:coverage_filter]||params[:metric])\r
-      @coverage_filter=(metric ? metric.key : 'coverage')\r
-      @filtered=true\r
-      if ('lines_to_cover'==@coverage_filter || 'coverage'==@coverage_filter || 'line_coverage'==@coverage_filter ||\r
-          'new_lines_to_cover'==@coverage_filter || 'new_coverage'==@coverage_filter || 'new_line_coverage'==@coverage_filter)\r
-        @coverage_filter='lines_to_cover'\r
-        filter_lines{|line| line.hits && line.after(to)}\r
-\r
-      elsif 'uncovered_lines'==@coverage_filter || 'new_uncovered_lines'==@coverage_filter\r
-        @coverage_filter='uncovered_lines'\r
-        filter_lines{|line| line.hits && line.hits==0 && line.after(to)}\r
-\r
-      elsif 'conditions_to_cover'==@coverage_filter || 'branch_coverage'==@coverage_filter ||\r
-            'new_conditions_to_cover'==@coverage_filter || 'new_branch_coverage'==@coverage_filter\r
-        @coverage_filter='conditions_to_cover'\r
-        filter_lines{|line| line.conditions && line.conditions>0 && line.after(to)}\r
-\r
-      elsif 'uncovered_conditions'==@coverage_filter || 'new_uncovered_conditions'==@coverage_filter\r
-        @coverage_filter='uncovered_conditions'\r
-        filter_lines{|line| line.conditions && line.covered_conditions && line.covered_conditions<line.conditions && line.after(to)}\r
-      end\r
-    end\r
-    render :action => 'index', :layout => !request.xhr?\r
-  end\r
-\r
-  \r
-  \r
-  def render_violations\r
-    load_sources()\r
-    @display_violations=true\r
-    @global_violations=[]\r
-    @expandable=(@lines!=nil)\r
-    @filtered=!@expanded\r
-\r
-    conditions='switched_off is not true AND snapshot_id=?'\r
-    values=[@snapshot.id]\r
-    unless params[:rule].blank?\r
-      severity=Sonar::RulePriority.id(params[:rule])\r
-      if severity\r
-        conditions += ' AND failure_level=?'\r
-        values<<severity\r
-      else\r
-        rule=Rule.by_key_or_id(params[:rule])\r
-        conditions += ' AND rule_id=?'\r
-        values<<(rule ? rule.id : -1)\r
-      end\r
-    end\r
-\r
-    if @period\r
-      date=@snapshot.period_datetime(@period)\r
-      if date\r
-        conditions+=' AND created_at>?'\r
-        values<<date.advance(:minutes => 1)\r
-      else\r
-        conditions+=' AND id=-1'\r
-      end\r
-    end\r
-\r
-    RuleFailure.find(:all, :include => ['rule', 'reviews' ], :conditions => [conditions] + values, :order => 'failure_level DESC').each do |violation|\r
-      # sorted by severity => from blocker to info\r
-      if violation.line && violation.line>0 && @lines\r
-        @lines[violation.line-1].add_violation(violation)\r
-      else\r
-        @global_violations<<violation\r
-      end\r
-      # if the permanent_id does not exist, set it to the current id\r
-      unless violation.permanent_id\r
-        violation.permanent_id = violation.id\r
-        violation.save\r
-      end\r
-    end\r
-\r
-    if !@expanded && @lines\r
-      filter_lines{|line| line.violations?}\r
-    end\r
-    render :action => 'index', :layout => !request.xhr?\r
-  end\r
-  \r
-  \r
-  def render_source\r
-    load_sources()\r
-    filter_lines_by_date()\r
-    render :action => 'index', :layout => !request.xhr?\r
-  end\r
-\r
-  \r
-  def filter_lines_by_date\r
-    if @period\r
-      @filtered=true\r
-      to=Java::JavaUtil::Date.new(@snapshot.period_datetime(@period).to_f * 1000)\r
-      if to\r
-        @lines.each do |line|\r
-          line.flag_as_hidden() if !line.after(to)\r
-        end\r
-      end\r
-    end\r
-  end\r
-\r
-  def filter_lines(&block)\r
-    @lines.each_with_index do |line,index|\r
-      if yield(line)\r
-        for i in index-4...index\r
-          @lines[i].flag_as_highlight_context() if i>=0\r
-        end\r
-        line.flag_as_highlighted()\r
-        for i in index+1..index+4\r
-          @lines[i].flag_as_highlight_context() if i<@lines.size\r
-        end\r
-      else\r
-        line.flag_as_hidden()\r
-      end\r
-    end\r
-  end\r
-\r
-  class Line\r
-    attr_accessor :source, :revision, :author, :datetime, :violations, :hits, :conditions, :covered_conditions, :hidden, :highlighted, :deprecated_conditions_label\r
-\r
-    def initialize(source)\r
-      @source=source\r
-    end\r
-\r
-    def add_violation(violation)\r
-      @violations||=[]\r
-      @violations<<violation\r
-      @visible=true\r
-    end\r
-\r
-    def violations?\r
-      @violations && @violations.size>0\r
-    end\r
-\r
-    def violation_severity\r
-      if @violations && @violations.size>0\r
-        @violations[0].failure_level\r
-      else\r
-        nil\r
-      end\r
-    end\r
-\r
-    def after(date)\r
-      if date && @datetime\r
-        @datetime.after(date)\r
-      else\r
-        true\r
-      end\r
-    end\r
-\r
-    def flag_as_highlighted\r
-      @highlighted=true\r
-      @hidden=false\r
-    end\r
-\r
-    def flag_as_highlight_context\r
-      # do not force if highlighted has already been set to true\r
-      @highlighted=false if @highlighted.nil?\r
-      @hidden=false\r
-    end\r
-\r
-    def flag_as_hidden\r
-      # do not force if it has already been flagged as visible\r
-      if @hidden.nil?\r
-        @hidden=true\r
-        @highlighted=false\r
-      end\r
-    end\r
-\r
-    def hidden?\r
-      @hidden==true\r
-    end\r
-\r
-    def highlighted?\r
-      # highlighted if the @highlighted has not been set or has been set to true\r
-      !hidden? && @highlighted!=false\r
-    end\r
-\r
-    def deprecated_conditions_label=(label)\r
-      if label\r
-        @deprecated_conditions_label=label\r
-          if label=='0%'\r
-            @conditions=2\r
-            @covered_conditions=0\r
-          elsif label=='100%'\r
-            @conditions=2\r
-            @covered_conditions=2\r
-          else\r
-            @conditions=2\r
-            @covered_conditions=1\r
-        end\r
-      end\r
-    end\r
-  end\r
-\r
-  def render_extension()\r
-    render :action => 'extension', :layout => !request.xhr?\r
-  end\r
-\r
-  def render_nothing()\r
-    render :action => 'nothing', :layout => !request.xhr?\r
+#
+# Sonar, entreprise quality control 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
+#
+class ResourceController < ApplicationController
+
+  SECTION=Navigation::SECTION_RESOURCE
+  helper DashboardHelper
+  
+  def index
+    @resource = Project.by_key(params[:id])
+
+    if (@resource && has_role?(:user, @resource))
+      params[:layout]='false'
+      @snapshot=@resource.last_snapshot
+
+      load_extensions()
+
+      if @extension
+        if (@extension.getId()=='violations')
+          render_violations()
+        elsif (@extension.getId()=='coverage')
+          render_coverage()
+        elsif (@extension.getId()=='source')
+          render_source()
+        else
+          render_extension()
+        end
+      else
+        render_nothing()
+      end
+    else
+      access_denied
+    end
+  end
+
+  private
+
+  def load_extensions
+    @extensions=[]
+    java_facade.getResourceTabs(@resource.scope, @resource.qualifier, @resource.language).each do |tab|
+      tab.getUserRoles().each do |role|
+        if has_role?(role, @resource)
+          @extensions<<tab
+          break
+        end
+      end
+    end
+
+    if !params[:tab].blank?
+      @extension=@extensions.find{|extension| extension.getId()==params[:tab]}
+
+    elsif !params[:metric].blank?
+      metric=Metric.by_key(params[:metric])
+      @extension=@extensions.find{|extension| extension.getDefaultTabForMetrics().include?(metric.key)}
+
+    end
+    @extension=@extensions.find{|extension| extension.isDefaultTab()} if @extension==nil
+  end
+
+  def load_sources
+    @period = params[:period].to_i unless params[:period].blank?
+    @expanded=(params[:expand]=='true')
+
+    if @snapshot.source
+      source_lines=Java::OrgSonarServerUi::JRubyFacade.new.colorizeCode(@snapshot.source.data, @snapshot.project.language).split("\n")
+      init_scm()
+
+      @lines=[]
+      source_lines.each_with_index do |source, index|
+        line=Line.new(source)
+        @lines<<line
+
+        line.revision=@revisions_by_line[index+1]
+        line.author=@authors_by_line[index+1]
+
+        date_string=@dates_by_line[index+1]
+        line.datetime=(date_string ? Java::OrgSonarApiUtils::DateUtils.parseDateTime(date_string): nil)
+      end
+    end
+  end
+
+  def init_scm
+    @scm_available=(@snapshot.measure('last_commit_datetimes_by_line')!=nil)
+    @authors_by_line=load_distribution('authors_by_line')
+    @revisions_by_line=load_distribution('revisions_by_line')
+    @dates_by_line=load_distribution('last_commit_datetimes_by_line')
+  end
+
+  def load_distribution(metric_key)
+    m=@snapshot.measure(metric_key)
+    m ? m.data_as_line_distribution() : {}
+  end
+
+  def render_coverage
+    load_sources()
+    @display_coverage=true
+    @expandable=(@lines!=nil)
+    if @lines
+      @hits_by_line=load_distribution('coverage_line_hits_data')
+      @conditions_by_line=load_distribution('conditions_by_line')
+      @covered_conditions_by_line=load_distribution('covered_conditions_by_line')
+
+      @hits_by_line.each_pair do |line_id,hits|
+        line=@lines[line_id-1]
+        if line
+          line.hits=hits.to_i
+          line.conditions=@conditions_by_line[line_id].to_i
+          line.covered_conditions=@covered_conditions_by_line[line_id].to_i
+        end
+      end
+
+      if @snapshot.measure('conditions_by_line').nil?
+        # TODO remove this code when branch_coverage_hits_data is fully removed from CoreMetrics
+        deprecated_branches_by_line=load_distribution('branch_coverage_hits_data')
+        deprecated_branches_by_line.each_pair do |line_id,label|
+          line=@lines[line_id-1]
+          if line
+            line.deprecated_conditions_label=label
+          end
+        end
+      end
+
+      to=(@period ? Java::JavaUtil::Date.new(@snapshot.period_datetime(@period).to_f * 1000) : nil)
+      metric=Metric.by_key(params[:coverage_filter]||params[:metric])
+      @coverage_filter=(metric ? metric.key : 'coverage')
+      @filtered=true
+      if ('lines_to_cover'==@coverage_filter || 'coverage'==@coverage_filter || 'line_coverage'==@coverage_filter ||
+          'new_lines_to_cover'==@coverage_filter || 'new_coverage'==@coverage_filter || 'new_line_coverage'==@coverage_filter)
+        @coverage_filter='lines_to_cover'
+        filter_lines{|line| line.hits && line.after(to)}
+
+      elsif 'uncovered_lines'==@coverage_filter || 'new_uncovered_lines'==@coverage_filter
+        @coverage_filter='uncovered_lines'
+        filter_lines{|line| line.hits && line.hits==0 && line.after(to)}
+
+      elsif 'conditions_to_cover'==@coverage_filter || 'branch_coverage'==@coverage_filter ||
+            'new_conditions_to_cover'==@coverage_filter || 'new_branch_coverage'==@coverage_filter
+        @coverage_filter='conditions_to_cover'
+        filter_lines{|line| line.conditions && line.conditions>0 && line.after(to)}
+
+      elsif 'uncovered_conditions'==@coverage_filter || 'new_uncovered_conditions'==@coverage_filter
+        @coverage_filter='uncovered_conditions'
+        filter_lines{|line| line.conditions && line.covered_conditions && line.covered_conditions<line.conditions && line.after(to)}
+      end
+    end
+    render :action => 'index', :layout => !request.xhr?
+  end
+
+  
+  
+  def render_violations
+    load_sources()
+    @display_violations=true
+    @global_violations=[]
+    @expandable=(@lines!=nil)
+    @filtered=!@expanded
+
+    conditions='switched_off is not true AND snapshot_id=?'
+    values=[@snapshot.id]
+    unless params[:rule].blank?
+      severity=Sonar::RulePriority.id(params[:rule])
+      if severity
+        conditions += ' AND failure_level=?'
+        values<<severity
+      else
+        rule=Rule.by_key_or_id(params[:rule])
+        conditions += ' AND rule_id=?'
+        values<<(rule ? rule.id : -1)
+      end
+    end
+
+    if @period
+      date=@snapshot.period_datetime(@period)
+      if date
+        conditions+=' AND created_at>?'
+        values<<date.advance(:minutes => 1)
+      else
+        conditions+=' AND id=-1'
+      end
+    end
+
+    RuleFailure.find(:all, :include => ['rule', 'reviews' ], :conditions => [conditions] + values, :order => 'failure_level DESC').each do |violation|
+      # sorted by severity => from blocker to info
+      if violation.line && violation.line>0 && @lines
+        @lines[violation.line-1].add_violation(violation)
+      else
+        @global_violations<<violation
+      end
+      # if the permanent_id does not exist, set it to the current id
+      unless violation.permanent_id
+        violation.permanent_id = violation.id
+        violation.save
+      end
+    end
+
+    if !@expanded && @lines
+      filter_lines{|line| line.violations?}
+    end
+    render :action => 'index', :layout => !request.xhr?
+  end
+  
+  
+  def render_source
+    load_sources()
+    filter_lines_by_date()
+    render :action => 'index', :layout => !request.xhr?
+  end
+
+  
+  def filter_lines_by_date
+    if @period
+      @filtered=true
+      to=Java::JavaUtil::Date.new(@snapshot.period_datetime(@period).to_f * 1000)
+      if to
+        @lines.each do |line|
+          line.flag_as_hidden() if !line.after(to)
+        end
+      end
+    end
+  end
+
+  def filter_lines(&block)
+    @lines.each_with_index do |line,index|
+      if yield(line)
+        for i in index-4...index
+          @lines[i].flag_as_highlight_context() if i>=0
+        end
+        line.flag_as_highlighted()
+        for i in index+1..index+4
+          @lines[i].flag_as_highlight_context() if i<@lines.size
+        end
+      else
+        line.flag_as_hidden()
+      end
+    end
+  end
+
+  class Line
+    attr_accessor :source, :revision, :author, :datetime, :violations, :hits, :conditions, :covered_conditions, :hidden, :highlighted, :deprecated_conditions_label
+
+    def initialize(source)
+      @source=source
+    end
+
+    def add_violation(violation)
+      @violations||=[]
+      @violations<<violation
+      @visible=true
+    end
+
+    def violations?
+      @violations && @violations.size>0
+    end
+
+    def violation_severity
+      if @violations && @violations.size>0
+        @violations[0].failure_level
+      else
+        nil
+      end
+    end
+
+    def after(date)
+      if date && @datetime
+        @datetime.after(date)
+      else
+        true
+      end
+    end
+
+    def flag_as_highlighted
+      @highlighted=true
+      @hidden=false
+    end
+
+    def flag_as_highlight_context
+      # do not force if highlighted has already been set to true
+      @highlighted=false if @highlighted.nil?
+      @hidden=false
+    end
+
+    def flag_as_hidden
+      # do not force if it has already been flagged as visible
+      if @hidden.nil?
+        @hidden=true
+        @highlighted=false
+      end
+    end
+
+    def hidden?
+      @hidden==true
+    end
+
+    def highlighted?
+      # highlighted if the @highlighted has not been set or has been set to true
+      !hidden? && @highlighted!=false
+    end
+
+    def deprecated_conditions_label=(label)
+      if label
+        @deprecated_conditions_label=label
+          if label=='0%'
+            @conditions=2
+            @covered_conditions=0
+          elsif label=='100%'
+            @conditions=2
+            @covered_conditions=2
+          else
+            @conditions=2
+            @covered_conditions=1
+        end
+      end
+    end
+  end
+
+  def render_extension()
+    render :action => 'extension', :layout => !request.xhr?
+  end
+
+  def render_nothing()
+    render :action => 'nothing', :layout => !request.xhr?
   end
 end
\ No newline at end of file
index d5c3b7c56a0a2fb0571cb5cce4155310720f8233..ca8ef32259a1ed98e3f8dbb0942f633f3cb0ee53 100644 (file)
-#\r
-# Sonar, entreprise quality control tool.\r
-# Copyright (C) 2008-2011 SonarSource\r
-# mailto:contact AT sonarsource DOT com\r
-#\r
-# Sonar is free software; you can redistribute it and/or\r
-# modify it under the terms of the GNU Lesser General Public\r
-# License as published by the Free Software Foundation; either\r
-# version 3 of the License, or (at your option) any later version.\r
-#\r
-# Sonar is distributed in the hope that it will be useful,\r
-# but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-# Lesser General Public License for more details.\r
-#\r
-# You should have received a copy of the GNU Lesser General Public\r
-# License along with Sonar; if not, write to the Free Software\r
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02\r
-#\r
-\r
-class ReviewsController < ApplicationController\r
-\r
-  SECTION=Navigation::SECTION_HOME\r
-\r
-  verify :method => :post, :only => [  :create, :create_comment ], :redirect_to => { :action => :error_not_post }\r
-\r
-  def index\r
-    init_params\r
-\r
-    @reviews = []\r
-    unless params.blank?\r
-      find_reviews_for_user_query\r
-    end\r
-  end\r
-\r
-  def list\r
-    reviews = find_reviews_for_rule_failure params[:rule_failure_permanent_id]\r
-    render :partial => "list", :locals => { :reviews => reviews }\r
-  end\r
-\r
-  def display_violation\r
-    violation = find_last_rule_failure_with_permanent_id params[:rule_failure_permanent_id]\r
-    render :partial => "resource/violation", :locals => { :violation => violation }\r
-  end\r
-\r
-  def form\r
-    rule_failure = find_last_rule_failure_with_permanent_id params[:rule_failure_permanent_id]\r
-    @review = Review.new\r
-    @review.rule_failure_permanent_id = rule_failure.permanent_id\r
-    @review_comment = ReviewComment.new\r
-    @review_comment.review_text = ""\r
-    if params[:switch_off]\r
-      @review.review_type = "f-positive"\r
-    else\r
-      @review.review_type = Review.default_type\r
-    end\r
-    render :partial => "form"\r
-  end\r
-\r
-  def create\r
-    rule_failure = find_last_rule_failure_with_permanent_id params[:review][:rule_failure_permanent_id]\r
-    unless has_rights_to_create? rule_failure\r
-      render :text => "<b>Cannot create the review</b> : access denied."\r
-      return\r
-    end\r
-\r
-    @review = Review.new(params[:review])\r
-    @review.user = current_user\r
-    if params[:assign_to_me]\r
-      @review.assignee = current_user\r
-    end\r
-    @review.title = rule_failure.message\r
-    @review.status = Review.default_status\r
-    @review.severity = Sonar::RulePriority.to_s rule_failure.failure_level\r
-    @review.resource = RuleFailure.find( @review.rule_failure_permanent_id, :include => ['snapshot'] ).snapshot.project\r
-    @review_comment = ReviewComment.new(params[:review_comment])\r
-    @review_comment.user = current_user\r
-    @review.review_comments << @review_comment\r
-    if @review.valid?\r
-      if @review.review_type == "f-positive" \r
-        if rule_failure.get_open_review\r
-          current_open_review = rule_failure.get_open_review\r
-          current_open_review.status = "closed"\r
-          current_open_review.save\r
-        end\r
-        rule_failure.switched_off = true\r
-        rule_failure.save\r
-      end\r
-      @review.save\r
-      @violation = rule_failure\r
-    end\r
-    render "create_result"\r
-  end\r
-\r
-  def form_comment\r
-    @review_comment = ReviewComment.new\r
-    @review_comment.user = current_user\r
-    @review_comment.review_id = params[:review_id]\r
-    @review_comment.review_text = ""\r
-    @rule_failure_permanent_id = params[:rule_failure_permanent_id]\r
-    if params[:update_comment]\r
-      @update_comment = true\r
-      @review_comment.review_text = params[:review_text]\r
-    end\r
-    render :partial => "form_comment"\r
-  end\r
-\r
-  def create_comment\r
-    rule_failure = find_last_rule_failure_with_permanent_id params[:rule_failure_permanent_id]\r
-    unless has_rights_to_create? rule_failure\r
-      render :text => "<b>Cannot create the comment</b> : access denied."\r
-      return\r
-    end\r
-\r
-    @review_comment = ReviewComment.new(params[:review_comment])\r
-    @review_comment.user = current_user\r
-    @rule_failure_permanent_id = params[:rule_failure_permanent_id]\r
-    if @review_comment.valid?\r
-      @review_comment.save\r
-      # -- TODO : should create a Review#create_comment and put the following logic in it\r
-      review = @review_comment.review\r
-      review.updated_at = @review_comment.created_at\r
-      review.save\r
-      # -- End of TODO code --\r
-      @violation = rule_failure\r
-    end\r
-    render "create_comment_result"\r
-  end\r
-\r
-  def update_comment\r
-    review = Review.find params[:review_comment][:review_id]\r
-    @review_comment = review.review_comments.last\r
-    unless current_user && current_user.id == @review_comment.user_id\r
-      render :text => "<b>Cannot modify the comment</b> : access denied."\r
-      return\r
-    end\r
-\r
-    @review_comment.review_text = params[:review_comment][:review_text]\r
-    @review_comment.created_at = DateTime.now\r
-    @rule_failure_permanent_id = params[:rule_failure_permanent_id]\r
-    if @review_comment.valid?\r
-      @review_comment.save\r
-      review.updated_at = @review_comment.updated_at\r
-      review.save\r
-      @violation = find_last_rule_failure_with_permanent_id review.rule_failure_permanent_id\r
-    end\r
-    render "create_comment_result"\r
-  end\r
-  \r
-  def form_assign\r
-    @user_options = add_all_users []\r
-    @review_id = params[:review_id]\r
-    @rule_failure_permanent_id = params[:rule_failure_permanent_id]\r
-    render :partial => "form_assign"\r
-  end\r
-  \r
-  def assign\r
-    review = Review.find params[:review_id]\r
-    unless current_user\r
-      render :text => "<b>Cannot edit the review</b> : access denied."\r
-      return\r
-    end\r
-    \r
-    review.assignee = User.find params[:assignee_id]\r
-    review.save\r
-    violation = find_last_rule_failure_with_permanent_id review.rule_failure_permanent_id\r
-    render :partial => "resource/violation", :locals => { :violation => violation }\r
-  end\r
-  \r
-  def close_review\r
-    review = Review.find params[:review_id]\r
-    unless current_user\r
-      render :text => "<b>Cannot edit the review</b> : access denied."\r
-      return\r
-    end\r
-    \r
-    review.status = "closed"\r
-    review.save\r
-    violation = find_last_rule_failure_with_permanent_id review.rule_failure_permanent_id\r
-    render :partial => "resource/violation", :locals => { :violation => violation }\r
-  end\r
-\r
-  ## -------------- PRIVATE -------------- ##\r
-  private\r
-\r
-  def init_params\r
-    @user_names = [["Any", ""]]\r
-    default_user = [""]\r
-    if current_user\r
-      default_user = [current_user.id]\r
-    end\r
-    add_all_users @user_names\r
-    @review_authors = filter_any(params[:review_authors]) || default_user\r
-    @comment_authors = filter_any(params[:comment_authors]) || default_user\r
-    @severities = filter_any(params[:severities]) || [""]\r
-    @statuses = filter_any(params[:statuses]) || ["open"]\r
-  end\r
-  \r
-  def add_all_users ( user_options )\r
-    User.find( :all ).each do |user|\r
-      userName = user.name\r
-      if current_user.id == user.id\r
-        userName = "Me (" + user.name + ")"\r
-      end\r
-      user_options << [userName, user.id.to_s]\r
-    end\r
-    return user_options\r
-  end\r
-\r
-  def filter_any(array)\r
-    if array && array.size>1 && array.include?("")\r
-      array=[""]\r
-    end\r
-    array\r
-  end\r
-\r
-  def find_reviews_for_user_query\r
-    conditions=[]\r
-    values={}\r
-\r
-    unless @statuses == [""]\r
-      conditions << "reviews.status in (:statuses)"\r
-      values[:statuses]=@statuses\r
-    end\r
-    unless @severities == [""]\r
-      conditions << "reviews.severity in (:severities)"\r
-      values[:severities]=@severities\r
-    end\r
-    unless @review_authors == [""]\r
-      conditions << "reviews.user_id in (:review_authors)"\r
-      values[:review_authors]=@review_authors\r
-    end\r
-    unless @comment_authors == [""]\r
-      conditions << "review_comments.user_id in (:comment_authors)"\r
-      values[:comment_authors]=@comment_authors\r
-    end\r
-\r
-    @reviews = Review.find( :all, :order => "created_at DESC", :joins => :review_comments, :conditions => [ conditions.join(" AND "), values] ).uniq\r
-  end\r
-\r
-  def find_reviews_for_rule_failure ( rule_failure_permanent_id )\r
-    return Review.find :all, :conditions => ['rule_failure_permanent_id=?', rule_failure_permanent_id]\r
-  end\r
-\r
-  def find_last_rule_failure_with_permanent_id ( rule_failure_permanent_id )\r
-    return RuleFailure.last( :all, :conditions => [ "permanent_id = ?", rule_failure_permanent_id ], :include => ['snapshot'] )\r
-  end\r
-\r
-  def has_rights_to_create? ( rule_failure )\r
-    return false unless current_user\r
-    \r
-    project = rule_failure.snapshot.root_project\r
-    unless has_role?(:user, project)\r
-      return false\r
-    end\r
-    return true\r
-  end\r
-\r
-  def error_not_post\r
-    render :text => "Create actions must use POST method."\r
-  end\r
-\r
-end\r
+#
+# Sonar, entreprise quality control 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
+#
+
+class ReviewsController < ApplicationController
+
+  SECTION=Navigation::SECTION_HOME
+
+  verify :method => :post, :only => [  :create, :create_comment ], :redirect_to => { :action => :error_not_post }
+
+  def index
+    init_params
+
+    @reviews = []
+    unless params.blank?
+      find_reviews_for_user_query
+    end
+  end
+
+  def list
+    reviews = find_reviews_for_rule_failure params[:rule_failure_permanent_id]
+    render :partial => "list", :locals => { :reviews => reviews }
+  end
+
+  def display_violation
+    violation = find_last_rule_failure_with_permanent_id params[:rule_failure_permanent_id]
+    render :partial => "resource/violation", :locals => { :violation => violation }
+  end
+
+  def form
+    rule_failure = find_last_rule_failure_with_permanent_id params[:rule_failure_permanent_id]
+    @review = Review.new
+    @review.rule_failure_permanent_id = rule_failure.permanent_id
+    @review_comment = ReviewComment.new
+    @review_comment.review_text = ""
+    if params[:switch_off]
+      @review.review_type = "f-positive"
+    else
+      @review.review_type = Review.default_type
+    end
+    render :partial => "form"
+  end
+
+  def create
+    rule_failure = find_last_rule_failure_with_permanent_id params[:review][:rule_failure_permanent_id]
+    unless has_rights_to_create? rule_failure
+      render :text => "<b>Cannot create the review</b> : access denied."
+      return
+    end
+
+    @review = Review.new(params[:review])
+    @review.user = current_user
+    if params[:assign_to_me]
+      @review.assignee = current_user
+    end
+    @review.title = rule_failure.message
+    @review.status = Review.default_status
+    @review.severity = Sonar::RulePriority.to_s rule_failure.failure_level
+    @review.resource = RuleFailure.find( @review.rule_failure_permanent_id, :include => ['snapshot'] ).snapshot.project
+    @review_comment = ReviewComment.new(params[:review_comment])
+    @review_comment.user = current_user
+    @review.review_comments << @review_comment
+    if @review.valid?
+      if @review.review_type == "f-positive" 
+        if rule_failure.get_open_review
+          current_open_review = rule_failure.get_open_review
+          current_open_review.status = "closed"
+          current_open_review.save
+        end
+        rule_failure.switched_off = true
+        rule_failure.save
+      end
+      @review.save
+      @violation = rule_failure
+    end
+    render "create_result"
+  end
+
+  def form_comment
+    @review_comment = ReviewComment.new
+    @review_comment.user = current_user
+    @review_comment.review_id = params[:review_id]
+    @review_comment.review_text = ""
+    @rule_failure_permanent_id = params[:rule_failure_permanent_id]
+    if params[:update_comment]
+      @update_comment = true
+      @review_comment.review_text = params[:review_text]
+    end
+    render :partial => "form_comment"
+  end
+
+  def create_comment
+    rule_failure = find_last_rule_failure_with_permanent_id params[:rule_failure_permanent_id]
+    unless has_rights_to_create? rule_failure
+      render :text => "<b>Cannot create the comment</b> : access denied."
+      return
+    end
+
+    @review_comment = ReviewComment.new(params[:review_comment])
+    @review_comment.user = current_user
+    @rule_failure_permanent_id = params[:rule_failure_permanent_id]
+    if @review_comment.valid?
+      @review_comment.save
+      # -- TODO : should create a Review#create_comment and put the following logic in it
+      review = @review_comment.review
+      review.updated_at = @review_comment.created_at
+      review.save
+      # -- End of TODO code --
+      @violation = rule_failure
+    end
+    render "create_comment_result"
+  end
+
+  def update_comment
+    review = Review.find params[:review_comment][:review_id]
+    @review_comment = review.review_comments.last
+    unless current_user && current_user.id == @review_comment.user_id
+      render :text => "<b>Cannot modify the comment</b> : access denied."
+      return
+    end
+
+    @review_comment.review_text = params[:review_comment][:review_text]
+    @review_comment.created_at = DateTime.now
+    @rule_failure_permanent_id = params[:rule_failure_permanent_id]
+    if @review_comment.valid?
+      @review_comment.save
+      review.updated_at = @review_comment.updated_at
+      review.save
+      @violation = find_last_rule_failure_with_permanent_id review.rule_failure_permanent_id
+    end
+    render "create_comment_result"
+  end
+  
+  def form_assign
+    @user_options = add_all_users []
+    @review_id = params[:review_id]
+    @rule_failure_permanent_id = params[:rule_failure_permanent_id]
+    render :partial => "form_assign"
+  end
+  
+  def assign
+    review = Review.find params[:review_id]
+    unless current_user
+      render :text => "<b>Cannot edit the review</b> : access denied."
+      return
+    end
+    
+    review.assignee = User.find params[:assignee_id]
+    review.save
+    violation = find_last_rule_failure_with_permanent_id review.rule_failure_permanent_id
+    render :partial => "resource/violation", :locals => { :violation => violation }
+  end
+  
+  def close_review
+    review = Review.find params[:review_id]
+    unless current_user
+      render :text => "<b>Cannot edit the review</b> : access denied."
+      return
+    end
+    
+    review.status = "closed"
+    review.save
+    violation = find_last_rule_failure_with_permanent_id review.rule_failure_permanent_id
+    render :partial => "resource/violation", :locals => { :violation => violation }
+  end
+
+  ## -------------- PRIVATE -------------- ##
+  private
+
+  def init_params
+    @user_names = [["Any", ""]]
+    default_user = [""]
+    if current_user
+      default_user = [current_user.id]
+    end
+    add_all_users @user_names
+    @review_authors = filter_any(params[:review_authors]) || default_user
+    @comment_authors = filter_any(params[:comment_authors]) || default_user
+    @severities = filter_any(params[:severities]) || [""]
+    @statuses = filter_any(params[:statuses]) || ["open"]
+  end
+  
+  def add_all_users ( user_options )
+    User.find( :all ).each do |user|
+      userName = user.name
+      if current_user.id == user.id
+        userName = "Me (" + user.name + ")"
+      end
+      user_options << [userName, user.id.to_s]
+    end
+    return user_options
+  end
+
+  def filter_any(array)
+    if array && array.size>1 && array.include?("")
+      array=[""]
+    end
+    array
+  end
+
+  def find_reviews_for_user_query
+    conditions=[]
+    values={}
+
+    unless @statuses == [""]
+      conditions << "reviews.status in (:statuses)"
+      values[:statuses]=@statuses
+    end
+    unless @severities == [""]
+      conditions << "reviews.severity in (:severities)"
+      values[:severities]=@severities
+    end
+    unless @review_authors == [""]
+      conditions << "reviews.user_id in (:review_authors)"
+      values[:review_authors]=@review_authors
+    end
+    unless @comment_authors == [""]
+      conditions << "review_comments.user_id in (:comment_authors)"
+      values[:comment_authors]=@comment_authors
+    end
+
+    @reviews = Review.find( :all, :order => "created_at DESC", :joins => :review_comments, :conditions => [ conditions.join(" AND "), values] ).uniq
+  end
+
+  def find_reviews_for_rule_failure ( rule_failure_permanent_id )
+    return Review.find :all, :conditions => ['rule_failure_permanent_id=?', rule_failure_permanent_id]
+  end
+
+  def find_last_rule_failure_with_permanent_id ( rule_failure_permanent_id )
+    return RuleFailure.last( :all, :conditions => [ "permanent_id = ?", rule_failure_permanent_id ], :include => ['snapshot'] )
+  end
+
+  def has_rights_to_create? ( rule_failure )
+    return false unless current_user
+    
+    project = rule_failure.snapshot.root_project
+    unless has_role?(:user, project)
+      return false
+    end
+    return true
+  end
+
+  def error_not_post
+    render :text => "Create actions must use POST method."
+  end
+
+end
index df4179f309dff6611dfd2ef01981b487d158cdb0..8cd7857e7efd67bab7f99ba17a0bca24db071d10 100644 (file)
@@ -1,72 +1,72 @@
-#\r
-# Sonar, entreprise quality control tool.\r
-# Copyright (C) 2008-2011 SonarSource\r
-# mailto:contact AT sonarsource DOT com\r
-#\r
-# Sonar is free software; you can redistribute it and/or\r
-# modify it under the terms of the GNU Lesser General Public\r
-# License as published by the Free Software Foundation; either\r
-# version 3 of the License, or (at your option) any later version.\r
-#\r
-# Sonar is distributed in the hope that it will be useful,\r
-# but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-# Lesser General Public License for more details.\r
-#\r
-# You should have received a copy of the GNU Lesser General Public\r
-# License along with Sonar; if not, write to the Free Software\r
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02\r
-#\r
-class Review < ActiveRecord::Base\r
-  belongs_to :user\r
-  belongs_to :assignee, :class_name => "User", :foreign_key => "assignee_id"\r
-  belongs_to :resource, :class_name => "Project", :foreign_key => "resource_id"\r
-  has_many :review_comments, :order => "created_at", :dependent => :destroy\r
-  validates_presence_of :user, :message => "can't be empty"\r
-  validates_presence_of :title, :message => "can't be empty"\r
-  validates_presence_of :review_type, :message => "can't be empty"\r
-  validates_presence_of :status, :message => "can't be empty"\r
-\r
-  SEVERITY_INFO = "INFO"\r
-  SEVERITY_MINOR = "MINOR"\r
-  SEVERITY_MAJOR = "MAJOR"\r
-  SEVERITY_CRITICAL = "CRITICAL"\r
-  SEVERITY_BLOCKER = "BLOCKER"\r
-  \r
-  TYPE_COMMENTS = "comments"\r
-  TYPE_FALSE_POSITIVE = "f-positive"\r
-  \r
-  STATUS_OPEN = "open"\r
-  STATUS_CLOSED = "closed"\r
-\r
-\r
-  def self.default_severity\r
-    return SEVERITY_MAJOR\r
-  end\r
-  \r
-  def self.default_type\r
-    return TYPE_COMMENTS\r
-  end\r
-\r
-  def self.default_status\r
-    return STATUS_OPEN\r
-  end\r
-  \r
-  def self.severity_options\r
-    severity_ops = []\r
-    severity_ops << ["Info", SEVERITY_INFO]\r
-    severity_ops << ["Minor", SEVERITY_MINOR]\r
-    severity_ops << ["Major", SEVERITY_MAJOR]\r
-    severity_ops << ["Critical", SEVERITY_CRITICAL]\r
-    severity_ops << ["Blocker", SEVERITY_BLOCKER]\r
-    return severity_ops\r
-  end\r
-  \r
-  def self.status_options\r
-    status_ops = []\r
-    status_ops << ["Open", STATUS_OPEN]\r
-    status_ops << ["Closed", STATUS_CLOSED]\r
-    return status_ops\r
-  end\r
-\r
-end\r
+#
+# Sonar, entreprise quality control 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
+#
+class Review < ActiveRecord::Base
+  belongs_to :user
+  belongs_to :assignee, :class_name => "User", :foreign_key => "assignee_id"
+  belongs_to :resource, :class_name => "Project", :foreign_key => "resource_id"
+  has_many :review_comments, :order => "created_at", :dependent => :destroy
+  validates_presence_of :user, :message => "can't be empty"
+  validates_presence_of :title, :message => "can't be empty"
+  validates_presence_of :review_type, :message => "can't be empty"
+  validates_presence_of :status, :message => "can't be empty"
+
+  SEVERITY_INFO = "INFO"
+  SEVERITY_MINOR = "MINOR"
+  SEVERITY_MAJOR = "MAJOR"
+  SEVERITY_CRITICAL = "CRITICAL"
+  SEVERITY_BLOCKER = "BLOCKER"
+  
+  TYPE_COMMENTS = "comments"
+  TYPE_FALSE_POSITIVE = "f-positive"
+  
+  STATUS_OPEN = "open"
+  STATUS_CLOSED = "closed"
+
+
+  def self.default_severity
+    return SEVERITY_MAJOR
+  end
+  
+  def self.default_type
+    return TYPE_COMMENTS
+  end
+
+  def self.default_status
+    return STATUS_OPEN
+  end
+  
+  def self.severity_options
+    severity_ops = []
+    severity_ops << ["Info", SEVERITY_INFO]
+    severity_ops << ["Minor", SEVERITY_MINOR]
+    severity_ops << ["Major", SEVERITY_MAJOR]
+    severity_ops << ["Critical", SEVERITY_CRITICAL]
+    severity_ops << ["Blocker", SEVERITY_BLOCKER]
+    return severity_ops
+  end
+  
+  def self.status_options
+    status_ops = []
+    status_ops << ["Open", STATUS_OPEN]
+    status_ops << ["Closed", STATUS_CLOSED]
+    return status_ops
+  end
+
+end
index 45253ed2da99bb500d475413f6735e0b424404bb..bb62d4e80f20b112c28e77a624e867d3b9b725c5 100644 (file)
@@ -1,84 +1,84 @@
-#\r
-# Sonar, entreprise quality control tool.\r
-# Copyright (C) 2008-2011 SonarSource\r
-# mailto:contact AT sonarsource DOT com\r
-#\r
-# Sonar is free software; you can redistribute it and/or\r
-# modify it under the terms of the GNU Lesser General Public\r
-# License as published by the Free Software Foundation; either\r
-# version 3 of the License, or (at your option) any later version.\r
-#\r
-# Sonar is distributed in the hope that it will be useful,\r
-# but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-# Lesser General Public License for more details.\r
-#\r
-# You should have received a copy of the GNU Lesser General Public\r
-# License along with {library}; if not, write to the Free Software\r
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02\r
-#\r
-\r
-class RuleFailure < ActiveRecord::Base\r
-\r
-  belongs_to :rule\r
-  belongs_to :snapshot\r
-  has_many :reviews, :primary_key => "permanent_id", :foreign_key => "rule_failure_permanent_id", :order => "created_at"\r
-\r
-  def get_open_review\r
-    reviews.each do |review|\r
-      if review.status == "open"\r
-        return review\r
-      end\r
-    end\r
-    return nil\r
-  end\r
-  \r
-  def to_hash_json\r
-    json = {}\r
-    json['message'] = message\r
-    json['line'] = line if line\r
-    json['priority'] = Sonar::RulePriority.to_s(failure_level).upcase\r
-    if created_at\r
-      json['createdAt'] = format_datetime(created_at)\r
-    end\r
-    json['rule'] = {\r
-      :key => rule.key,\r
-      :name => rule.name\r
-    }\r
-    json['resource'] = {\r
-      :key => snapshot.project.key,\r
-      :name => snapshot.project.name,\r
-      :scope => snapshot.project.scope,\r
-      :qualifier => snapshot.project.qualifier,\r
-      :language => snapshot.project.language\r
-    }\r
-    json\r
-  end\r
-\r
-  def to_xml(xml=Builder::XmlMarkup.new(:indent => 0))\r
-    xml.violation do\r
-      xml.message(message)\r
-      xml.line(line) if line\r
-      xml.priority(Sonar::RulePriority.to_s(failure_level))\r
-      if created_at\r
-        xml.createdAt(format_datetime(created_at))\r
-      end\r
-      xml.rule do\r
-        xml.key(rule.key)\r
-        xml.name(rule.name)\r
-      end\r
-      xml.resource do\r
-        xml.key(snapshot.project.key)\r
-        xml.name(snapshot.project.name)\r
-        xml.scope(snapshot.project.scope)\r
-        xml.qualifier(snapshot.project.qualifier)\r
-        xml.language(snapshot.project.language)\r
-      end\r
-    end\r
-  end\r
-\r
-  def format_datetime(datetime)\r
-    datetime.strftime("%Y-%m-%dT%H:%M:%S%z")\r
-  end\r
-\r
-end\r
+#
+# Sonar, entreprise quality control 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 {library}; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+#
+
+class RuleFailure < ActiveRecord::Base
+
+  belongs_to :rule
+  belongs_to :snapshot
+  has_many :reviews, :primary_key => "permanent_id", :foreign_key => "rule_failure_permanent_id", :order => "created_at"
+
+  def get_open_review
+    reviews.each do |review|
+      if review.status == "open"
+        return review
+      end
+    end
+    return nil
+  end
+  
+  def to_hash_json
+    json = {}
+    json['message'] = message
+    json['line'] = line if line
+    json['priority'] = Sonar::RulePriority.to_s(failure_level).upcase
+    if created_at
+      json['createdAt'] = format_datetime(created_at)
+    end
+    json['rule'] = {
+      :key => rule.key,
+      :name => rule.name
+    }
+    json['resource'] = {
+      :key => snapshot.project.key,
+      :name => snapshot.project.name,
+      :scope => snapshot.project.scope,
+      :qualifier => snapshot.project.qualifier,
+      :language => snapshot.project.language
+    }
+    json
+  end
+
+  def to_xml(xml=Builder::XmlMarkup.new(:indent => 0))
+    xml.violation do
+      xml.message(message)
+      xml.line(line) if line
+      xml.priority(Sonar::RulePriority.to_s(failure_level))
+      if created_at
+        xml.createdAt(format_datetime(created_at))
+      end
+      xml.rule do
+        xml.key(rule.key)
+        xml.name(rule.name)
+      end
+      xml.resource do
+        xml.key(snapshot.project.key)
+        xml.name(snapshot.project.name)
+        xml.scope(snapshot.project.scope)
+        xml.qualifier(snapshot.project.qualifier)
+        xml.language(snapshot.project.language)
+      end
+    end
+  end
+
+  def format_datetime(datetime)
+    datetime.strftime("%Y-%m-%dT%H:%M:%S%z")
+  end
+
+end
index ceb5210de513098491e8c91e56e1d99d2f617904..e9ac121009354a1b7c060dcbaac19b9fcc7dd5fa 100644 (file)
@@ -1,30 +1,30 @@
-<% form_for :review, @review do |f| %>\r
-      <%= f.hidden_field :rule_failure_permanent_id -%>\r
-      <%= f.hidden_field :review_type -%>\r
-      \r
-      <% if @review.review_type == "f-positive" %>\r
-          <b>Reason for flagging this violation as a false-positive:</b>\r
-      <% end %>\r
-      <%= text_area :review_comment, :review_text, \r
-           :id => "reviewText", :rows => 8, \r
-           :style => "width:100%", :onKeyUp => "if (this.value=='') $('submit_btn').disabled='true'; else $('submit_btn').disabled='';" -%>\r
-      <br/>\r
-      \r
-      <div>\r
-        <%\r
-          if @review.review_type == "comments"\r
-            button_text = "Post review"\r
-          else\r
-            button_text = "Switch-off violation"\r
-          end\r
-        %>\r
-        <%= submit_to_remote "submit_btn", button_text, :url => { :action => 'create' }, :html => { :id => "submit_btn", :disabled => "true" } -%>\r
-        &nbsp;&nbsp;\r
-        <a onclick="$('reviewForm<%= @review.rule_failure_permanent_id.to_s -%>').style.display='none';" href="#">Cancel</a>\r
-        <% if @review.review_type == "comments" %>\r
-          &nbsp;&nbsp;\r
-          <%= check_box_tag "assign_to_me", "me", true -%> Assign to me\r
-        <% end %>\r
-      </div>\r
-      </div class="clear"></div>      \r
+<% form_for :review, @review do |f| %>
+      <%= f.hidden_field :rule_failure_permanent_id -%>
+      <%= f.hidden_field :review_type -%>
+      
+      <% if @review.review_type == "f-positive" %>
+          <b>Reason for flagging this violation as a false-positive:</b>
+      <% end %>
+      <%= text_area :review_comment, :review_text, 
+           :id => "reviewText", :rows => 8, 
+           :style => "width:100%", :onKeyUp => "if (this.value=='') $('submit_btn').disabled='true'; else $('submit_btn').disabled='';" -%>
+      <br/>
+      
+      <div>
+        <%
+          if @review.review_type == "comments"
+            button_text = "Post review"
+          else
+            button_text = "Switch-off violation"
+          end
+        %>
+        <%= submit_to_remote "submit_btn", button_text, :url => { :action => 'create' }, :html => { :id => "submit_btn", :disabled => "true" } -%>
+        &nbsp;&nbsp;
+        <a onclick="$('reviewForm<%= @review.rule_failure_permanent_id.to_s -%>').style.display='none';" href="#">Cancel</a>
+        <% if @review.review_type == "comments" %>
+          &nbsp;&nbsp;
+          <%= check_box_tag "assign_to_me", "me", true -%> Assign to me
+        <% end %>
+      </div>
+      </div class="clear"></div>      
 <% end %>
\ No newline at end of file
index 79ad5010402b21ef7b8e650783009d3b863d1e72..016e8052e991da673693dd712299a9c43f956fef 100644 (file)
@@ -1,28 +1,28 @@
-<% form_for :review_comment, @review_comment do |f| %>\r
-      <%= f.hidden_field :review_id %>\r
-      <%= f.text_area :review_text, :rows => 8, \r
-            :id => "commentText" + @rule_failure_permanent_id.to_s,\r
-            :style => "width:100%",\r
-            :onKeyUp => "if (this.value=='') $('submit_btn').disabled='true'; else $('submit_btn').disabled='';" %>\r
-      <br/>\r
-      \r
-      <% if @update_comment %>\r
-        <%= submit_to_remote 'submit_btn', 'Update comment', \r
-                     :url => { :action => 'update_comment', \r
-                               :rule_failure_permanent_id => @rule_failure_permanent_id },\r
-                     :html => { :id => "submit_btn" } %>\r
-        &nbsp;&nbsp;\r
-        <%= link_to_remote 'Cancel', \r
-                     :url => { :action => 'display_violation', \r
-                               :rule_failure_permanent_id => @rule_failure_permanent_id },\r
-                     :update => "vId" + @rule_failure_permanent_id.to_s %>     \r
-      <% else %>\r
-        <%= submit_to_remote 'submit_btn', 'Post comment', \r
-                     :url => { :action => 'create_comment', \r
-                               :rule_failure_permanent_id => @rule_failure_permanent_id },\r
-                     :html => { :id => "submit_btn", :disabled => true } %>\r
-        &nbsp;&nbsp;\r
-        <a onclick="$('reviewForm<%= @rule_failure_permanent_id.to_s -%>').style.display='none'; $('commentAction<%= @rule_failure_permanent_id.to_s -%>').style.display='';" href="#">Cancel</a>\r
-      <% end %>\r
-      \r
+<% form_for :review_comment, @review_comment do |f| %>
+      <%= f.hidden_field :review_id %>
+      <%= f.text_area :review_text, :rows => 8, 
+            :id => "commentText" + @rule_failure_permanent_id.to_s,
+            :style => "width:100%",
+            :onKeyUp => "if (this.value=='') $('submit_btn').disabled='true'; else $('submit_btn').disabled='';" %>
+      <br/>
+      
+      <% if @update_comment %>
+        <%= submit_to_remote 'submit_btn', 'Update comment', 
+                     :url => { :action => 'update_comment', 
+                               :rule_failure_permanent_id => @rule_failure_permanent_id },
+                     :html => { :id => "submit_btn" } %>
+        &nbsp;&nbsp;
+        <%= link_to_remote 'Cancel', 
+                     :url => { :action => 'display_violation', 
+                               :rule_failure_permanent_id => @rule_failure_permanent_id },
+                     :update => "vId" + @rule_failure_permanent_id.to_s %>     
+      <% else %>
+        <%= submit_to_remote 'submit_btn', 'Post comment', 
+                     :url => { :action => 'create_comment', 
+                               :rule_failure_permanent_id => @rule_failure_permanent_id },
+                     :html => { :id => "submit_btn", :disabled => true } %>
+        &nbsp;&nbsp;
+        <a onclick="$('reviewForm<%= @rule_failure_permanent_id.to_s -%>').style.display='none'; $('commentAction<%= @rule_failure_permanent_id.to_s -%>').style.display='';" href="#">Cancel</a>
+      <% end %>
+      
 <% end %>
\ No newline at end of file
index 41de20ad0f77ff0c829487de4955ac73c6cfcfd7..aa12cbc38fb0851bed53904ac6c8c68c46307134 100644 (file)
@@ -1,65 +1,65 @@
-  <div id="review<%= review.id -%>">\r
-         <div>\r
-       <b>Review #<%= review.id -%> - <%= h(review.title) -%></b>\r
-       <br/>\r
-       <% if review.assignee %>\r
-       <i>Assigned to <%= h(review.assignee.name) -%></i>\r
-       <% end %>\r
-      </div>\r
-      \r
-      <div style="margin-top: 10px; margin-left: 20px">\r
-        <% unless review.review_comments.blank?\r
-             last_comment = review.review_comments.last\r
-                    review.review_comments.each do |review_comment|\r
-               %>\r
-        <table style="width:100%; margin-bottom: 3px">\r
-                 <tr style="border: solid 1px grey; background-color: #F7F7F7">\r
-                   <td style="width:180px; vertical-align:top; padding: 2px 2px 2px 10px; font-weight: bold">\r
-                               <%= image_tag("user.png") -%> <b><%= h(review_comment.user.name) -%></b>\r
-                   </td>\r
-                   <td style="vertical-align: top; padding: 2px 10px 2px 2px; color: grey; text-align: right; font-style: italic">\r
-                       <%= l review_comment.created_at -%>\r
-                   </td>\r
-                 </tr>\r
-                 <tr style="border: solid 1px grey;">\r
-                   <td colspan="2" style="padding: 5px;">\r
-                     <% if review_comment == last_comment %>\r
-                       <div id="lastComment<%= review.id -%>">\r
-                         <%= h(review_comment.review_text) -%>\r
-                       </div>\r
-                     <% else %>\r
-                       <%= h(review_comment.review_text) -%>\r
-                     <% end %>\r
-                   </td>\r
-                 </tr>\r
-               </table>\r
-               <% \r
-                    end\r
-                  end\r
-               %>\r
-      \r
-        <% if current_user %>\r
-           <div style="text-align: right; padding: 5px">\r
-             <% if current_user.id == review.review_comments.last.user_id %>\r
-               <%= image_tag("pencil.png") -%>\r
-               <%= link_to_remote "Edit my last comment", \r
-                  :url => { :controller => "reviews", :action => "form_comment", \r
-                            :review_id => review.id, \r
-                            :rule_failure_permanent_id => review.rule_failure_permanent_id,\r
-                            :review_text => review.review_comments.last.review_text,\r
-                            :update_comment => "true" },\r
-                  :update => "lastComment" + review.id.to_s, \r
-                  :complete => "$('commentText" + review.id.to_s + "').focus()" -%>\r
-               &nbsp;\r
-             <% end %>\r
-             <%= image_tag("pencil.png") -%>\r
-             <%= link_to_remote "Add a new comment", \r
-                       :url => { :controller => "reviews", :action => "form_comment", :review_id => review.id, :rule_failure_permanent_id => review.rule_failure_permanent_id },\r
-                       :update => "createComment" + review.id.to_s, \r
-                       :complete => "$('commentText" + review.id.to_s + "').focus()" -%>\r
-           </div>\r
-           <div id="createComment<%= review.id -%>"></div>\r
-        <% end %>\r
-      </div>\r
-\r
-  </div>\r
+  <div id="review<%= review.id -%>">
+         <div>
+       <b>Review #<%= review.id -%> - <%= h(review.title) -%></b>
+       <br/>
+       <% if review.assignee %>
+       <i>Assigned to <%= h(review.assignee.name) -%></i>
+       <% end %>
+      </div>
+      
+      <div style="margin-top: 10px; margin-left: 20px">
+        <% unless review.review_comments.blank?
+             last_comment = review.review_comments.last
+                    review.review_comments.each do |review_comment|
+               %>
+        <table style="width:100%; margin-bottom: 3px">
+                 <tr style="border: solid 1px grey; background-color: #F7F7F7">
+                   <td style="width:180px; vertical-align:top; padding: 2px 2px 2px 10px; font-weight: bold">
+                               <%= image_tag("user.png") -%> <b><%= h(review_comment.user.name) -%></b>
+                   </td>
+                   <td style="vertical-align: top; padding: 2px 10px 2px 2px; color: grey; text-align: right; font-style: italic">
+                       <%= l review_comment.created_at -%>
+                   </td>
+                 </tr>
+                 <tr style="border: solid 1px grey;">
+                   <td colspan="2" style="padding: 5px;">
+                     <% if review_comment == last_comment %>
+                       <div id="lastComment<%= review.id -%>">
+                         <%= h(review_comment.review_text) -%>
+                       </div>
+                     <% else %>
+                       <%= h(review_comment.review_text) -%>
+                     <% end %>
+                   </td>
+                 </tr>
+               </table>
+               <% 
+                    end
+                  end
+               %>
+      
+        <% if current_user %>
+           <div style="text-align: right; padding: 5px">
+             <% if current_user.id == review.review_comments.last.user_id %>
+               <%= image_tag("pencil.png") -%>
+               <%= link_to_remote "Edit my last comment", 
+                  :url => { :controller => "reviews", :action => "form_comment", 
+                            :review_id => review.id, 
+                            :rule_failure_permanent_id => review.rule_failure_permanent_id,
+                            :review_text => review.review_comments.last.review_text,
+                            :update_comment => "true" },
+                  :update => "lastComment" + review.id.to_s, 
+                  :complete => "$('commentText" + review.id.to_s + "').focus()" -%>
+               &nbsp;
+             <% end %>
+             <%= image_tag("pencil.png") -%>
+             <%= link_to_remote "Add a new comment", 
+                       :url => { :controller => "reviews", :action => "form_comment", :review_id => review.id, :rule_failure_permanent_id => review.rule_failure_permanent_id },
+                       :update => "createComment" + review.id.to_s, 
+                       :complete => "$('commentText" + review.id.to_s + "').focus()" -%>
+           </div>
+           <div id="createComment<%= review.id -%>"></div>
+        <% end %>
+      </div>
+
+  </div>
index f177aae9cb22cda799daa8d14292b3f0f9657d28..3281ad51d3bd6f688ea0b1b31f9bc4dc28756986 100644 (file)
@@ -1,5 +1,5 @@
-if @violation\r
-  page.replace "vId" + @violation.permanent_id.to_s, :partial => "resource/violation", :locals => { :violation => @violation }\r
-else\r
-  page.replace_html "reviewForm" + @rule_failure_permanent_id.to_s, :partial => "form_comment"\r
+if @violation
+  page.replace "vId" + @violation.permanent_id.to_s, :partial => "resource/violation", :locals => { :violation => @violation }
+else
+  page.replace_html "reviewForm" + @rule_failure_permanent_id.to_s, :partial => "form_comment"
 end
\ No newline at end of file
index 720e00f11b3072141e7007c0e84fc392b8a6c6e6..9e735242a22db7d4466076ca153f9125e2d1d513 100644 (file)
@@ -1,5 +1,5 @@
-if @violation\r
-  page.replace "vId" + @violation.permanent_id.to_s, :partial => "resource/violation", :locals => { :violation => @violation }\r
-else \r
-  page.replace_html "reviewForm" + @review.rule_failure_permanent_id.to_s, :partial => "form"\r
+if @violation
+  page.replace "vId" + @violation.permanent_id.to_s, :partial => "resource/violation", :locals => { :violation => @violation }
+else 
+  page.replace_html "reviewForm" + @review.rule_failure_permanent_id.to_s, :partial => "form"
 end
\ No newline at end of file
index f67cadcf7152e286b4f4fea5aae4d90daf9a6c8a..937c1f60ac99a282a12d9dffc3e68a754725d914 100644 (file)
@@ -1,54 +1,54 @@
-#\r
-# Sonar, entreprise quality control tool.\r
-# Copyright (C) 2008-2011 SonarSource\r
-# mailto:contact AT sonarsource DOT com\r
-#\r
-# Sonar is free software; you can redistribute it and/or\r
-# modify it under the terms of the GNU Lesser General Public\r
-# License as published by the Free Software Foundation; either\r
-# version 3 of the License, or (at your option) any later version.\r
-#\r
-# Sonar is distributed in the hope that it will be useful,\r
-# but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-# Lesser General Public License for more details.\r
-#\r
-# You should have received a copy of the GNU Lesser General Public\r
-# License along with Sonar; if not, write to the Free Software\r
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02\r
-#\r
-\r
-#\r
-# Sonar 2.8\r
-#\r
-class CreateReview < ActiveRecord::Migration\r
-\r
-  def self.up\r
-    create_table 'reviews' do |t|\r
-      t.column 'created_at',                                   :datetime\r
-      t.column 'updated_at',                                   :datetime\r
-      t.column 'user_id',                                              :integer,       :null => true\r
-      t.column 'assignee_id',                                  :integer,       :null => true\r
-      t.column 'title',                                                        :string,        :null => true,  :limit => 500\r
-      t.column 'review_type',                                  :string,        :null => true,  :limit => 10\r
-      t.column 'status',                                               :string,        :null => true,  :limit => 10\r
-      t.column 'severity',                                             :string,        :null => true,  :limit => 10\r
-      t.column 'rule_failure_permanent_id',    :integer,       :null => true   \r
-      t.column 'resource_id',                                  :integer,       :null => true   \r
-      t.column 'resource_line',                                :integer,       :null => true      \r
-    end\r
-    \r
-    create_table 'review_comments' do |t|\r
-      t.column 'created_at',           :datetime\r
-      t.column 'updated_at',           :datetime\r
-      t.column 'review_id',            :integer\r
-      t.column 'user_id',                      :integer,       :null => true\r
-      t.column 'review_text',          :text,          :null => true\r
-    end\r
-    \r
-    alter_to_big_primary_key('reviews')\r
-    alter_to_big_primary_key('review_comments')\r
-    \r
-  end\r
-\r
-end\r
+#
+# Sonar, entreprise quality control 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
+#
+
+#
+# Sonar 2.8
+#
+class CreateReview < ActiveRecord::Migration
+
+  def self.up
+    create_table 'reviews' do |t|
+      t.column 'created_at',                                   :datetime
+      t.column 'updated_at',                                   :datetime
+      t.column 'user_id',                                              :integer,       :null => true
+      t.column 'assignee_id',                                  :integer,       :null => true
+      t.column 'title',                                                        :string,        :null => true,  :limit => 500
+      t.column 'review_type',                                  :string,        :null => true,  :limit => 10
+      t.column 'status',                                               :string,        :null => true,  :limit => 10
+      t.column 'severity',                                             :string,        :null => true,  :limit => 10
+      t.column 'rule_failure_permanent_id',    :integer,       :null => true   
+      t.column 'resource_id',                                  :integer,       :null => true   
+      t.column 'resource_line',                                :integer,       :null => true      
+    end
+    
+    create_table 'review_comments' do |t|
+      t.column 'created_at',           :datetime
+      t.column 'updated_at',           :datetime
+      t.column 'review_id',            :integer
+      t.column 'user_id',                      :integer,       :null => true
+      t.column 'review_text',          :text,          :null => true
+    end
+    
+    alter_to_big_primary_key('reviews')
+    alter_to_big_primary_key('review_comments')
+    
+  end
+
+end
index 5ed4ecb42ac0c60f115e8b22a47451be5cab4365..a26c7b10af09bf19745bbeb78fddc1074df0ef36 100755 (executable)
@@ -1,4 +1,5 @@
 #!/bin/sh
+
 #
 # NOTE: sonar must be built
 #
@@ -6,4 +7,3 @@ cd sonar-application/target/
 unzip sonar-*.zip
 cd sonar-*
 bin/macosx-universal-64/sonar.sh console
-