]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6736 refactor step names and descriptions
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Mon, 21 Sep 2015 20:33:29 +0000 (22:33 +0200)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Tue, 22 Sep 2015 08:54:35 +0000 (10:54 +0200)
53 files changed:
server/sonar-server/src/main/java/org/sonar/server/computation/step/ApplyPermissionsStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/BuildComponentTreeStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/CommentMeasuresStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/ComplexityMeasuresStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputeMeasureVariationsStep.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputeQProfileMeasureStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/CoverageMeasuresStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/DuplicationMeasuresStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/ExecuteVisitorsStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/ExtractReportStep.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/computation/step/FeedActiveRulesStep.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/computation/step/FeedDebtModelStep.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/computation/step/FeedMeasureComputers.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/computation/step/FeedPeriodsStep.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/computation/step/FillMeasuresWithVariationsStep.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/computation/step/LanguageDistributionMeasuresStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadDebtModelStep.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadMeasureComputersStep.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadPeriodsStep.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadQualityGateStep.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadQualityProfilesStep.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/computation/step/NewCoverageMeasuresStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistEventsStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistFileSourcesStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistProjectLinksStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/PurgeDatastoresStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityGateEventsStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityGateLoadingStep.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityGateMeasuresStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityProfileEventsStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/ReportComputationSteps.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/ReportExtractionStep.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/computation/step/SizeMeasuresStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/SwitchSnapshotStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/UnitTestMeasuresStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/ValidateProjectStep.java
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel1.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/FeedActiveRulesStepTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/computation/step/FeedDebtModelStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/FeedMeasureComputersTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/FeedPeriodsStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/LoadQualityProfilesStepTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/step/QualityGateLoadingStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/ReportComputationStepsTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/ReportComputeMeasureVariationsStepTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/step/ReportFillMeasuresWithVariationsStepTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/computation/step/ValidateProjectStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/ViewsComputeMeasureVariationsStepTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/step/ViewsFillMeasuresWithVariationsStepTest.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java
sonar-batch/src/test/java/org/sonar/batch/bootstrap/GlobalContainerTest.java
sonar-core/src/main/java/org/sonar/core/config/Logback.java
sonar-plugin-api/src/main/java/org/sonar/api/utils/DateUtils.java

index 2a3f826035cb6de6e904683935b477ccf174219f..908b491dd35f5e0994b1d5dca66179fe4716147b 100644 (file)
@@ -89,7 +89,7 @@ public class ApplyPermissionsStep implements ComputationStep {
 
   @Override
   public String getDescription() {
-    return "Apply project permissions";
+    return "Apply permissions";
   }
 
 }
index 185c3310b6bd37ced3e856900752ff2a3c9b439b..42b9a52a799a8663111b9827506b9f43ec03eca3 100644 (file)
@@ -72,6 +72,6 @@ public class BuildComponentTreeStep implements ComputationStep {
 
   @Override
   public String getDescription() {
-    return "Builds the Component tree";
+    return "Build tree of components";
   }
 }
index f097f8d5d0f4d33fe75728dc0e9a58e8378cce92..883960d4aa9dc553a7068c5b5f090880b78a9d99 100644 (file)
@@ -26,10 +26,10 @@ import org.sonar.server.computation.component.CrawlerDepthLimit;
 import org.sonar.server.computation.component.PathAwareCrawler;
 import org.sonar.server.computation.component.TreeRootHolder;
 import org.sonar.server.computation.formula.Counter;
+import org.sonar.server.computation.formula.CounterInitializationContext;
 import org.sonar.server.computation.formula.CreateMeasureContext;
 import org.sonar.server.computation.formula.Formula;
 import org.sonar.server.computation.formula.FormulaExecutorComponentVisitor;
-import org.sonar.server.computation.formula.CounterInitializationContext;
 import org.sonar.server.computation.formula.counter.IntSumCounter;
 import org.sonar.server.computation.formula.counter.SumCounter;
 import org.sonar.server.computation.measure.Measure;
@@ -200,6 +200,6 @@ public class CommentMeasuresStep implements ComputationStep {
 
   @Override
   public String getDescription() {
-    return "Aggregation of comment measures";
+    return "Compute comment measures";
   }
 }
index bd42ec28534b66cba84d08409d65f04944b0dcee..78dc338c26b1633574e8431fc47d63b2ecc3f559 100644 (file)
@@ -90,6 +90,6 @@ public class ComplexityMeasuresStep implements ComputationStep {
 
   @Override
   public String getDescription() {
-    return "Aggregation of complexity measures";
+    return "Compute complexity measures";
   }
 }
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputeMeasureVariationsStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputeMeasureVariationsStep.java
new file mode 100644 (file)
index 0000000..c7bd26f
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.computation.step;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.measure.PastMeasureDto;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.CrawlerDepthLimit;
+import org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler;
+import org.sonar.server.computation.component.TreeRootHolder;
+import org.sonar.server.computation.component.TypeAwareVisitorAdapter;
+import org.sonar.server.computation.measure.Measure;
+import org.sonar.server.computation.measure.MeasureKey;
+import org.sonar.server.computation.measure.MeasureRepository;
+import org.sonar.server.computation.measure.MeasureVariations;
+import org.sonar.server.computation.metric.Metric;
+import org.sonar.server.computation.metric.MetricRepository;
+import org.sonar.server.computation.period.Period;
+import org.sonar.server.computation.period.PeriodsHolder;
+
+import static com.google.common.collect.FluentIterable.from;
+import static org.sonar.server.computation.component.Component.Type.DIRECTORY;
+import static org.sonar.server.computation.component.Component.Type.SUBVIEW;
+import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;
+
+/**
+ * Set variations on all numeric measures found in the repository.
+ * This step MUST be executed after all steps that create some measures
+ * <p/>
+ * Note that measures on developer are not handle yet.
+ */
+public class ComputeMeasureVariationsStep implements ComputationStep {
+
+  private final DbClient dbClient;
+  private final TreeRootHolder treeRootHolder;
+  private final PeriodsHolder periodsHolder;
+  private final MetricRepository metricRepository;
+  private final MeasureRepository measureRepository;
+
+  private final Function<PastMeasureDto, MeasureKey> pastMeasureToMeasureKey = new Function<PastMeasureDto, MeasureKey>() {
+    @Nullable
+    @Override
+    public MeasureKey apply(@Nonnull PastMeasureDto input) {
+      Metric metric = metricRepository.getById(input.getMetricId());
+      return new MeasureKey(metric.getKey(), input.getCharacteristicId(), input.getRuleId());
+    }
+  };
+
+  public ComputeMeasureVariationsStep(DbClient dbClient, TreeRootHolder treeRootHolder, PeriodsHolder periodsHolder, MetricRepository metricRepository,
+    MeasureRepository measureRepository) {
+    this.dbClient = dbClient;
+    this.treeRootHolder = treeRootHolder;
+    this.periodsHolder = periodsHolder;
+    this.metricRepository = metricRepository;
+    this.measureRepository = measureRepository;
+  }
+
+  @Override
+  public void execute() {
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      List<Metric> metrics = from(metricRepository.getAll()).filter(NumericMetric.INSTANCE).toList();
+      new DepthTraversalTypeAwareCrawler(new VariationMeasuresVisitor(dbSession, metrics))
+        .visit(treeRootHolder.getRoot());
+    } finally {
+      dbClient.closeSession(dbSession);
+    }
+  }
+
+  private class VariationMeasuresVisitor extends TypeAwareVisitorAdapter {
+
+    private final DbSession session;
+    private final Set<Integer> metricIds;
+    private final Map<String, Metric> metricByKeys;
+
+    public VariationMeasuresVisitor(DbSession session, Iterable<Metric> metrics) {
+      // measures on files are currently purged, so past measures are not available on files
+      super(CrawlerDepthLimit.reportMaxDepth(DIRECTORY).withViewsMaxDepth(SUBVIEW), PRE_ORDER);
+      this.session = session;
+      this.metricIds = from(metrics).transform(MetricDtoToMetricId.INSTANCE).toSet();
+      this.metricByKeys = from(metrics).uniqueIndex(MetricToKey.INSTANCE);
+    }
+
+    @Override
+    public void visitAny(Component component) {
+      MeasuresWithVariationRepository measuresWithVariationRepository = computeMeasuresWithVariations(component);
+      processMeasuresWithVariation(component, measuresWithVariationRepository);
+    }
+
+    private MeasuresWithVariationRepository computeMeasuresWithVariations(Component component) {
+      MeasuresWithVariationRepository measuresWithVariationRepository = new MeasuresWithVariationRepository();
+      for (Period period : periodsHolder.getPeriods()) {
+        List<PastMeasureDto> pastMeasures = dbClient.measureDao()
+          .selectByComponentUuidAndProjectSnapshotIdAndMetricIds(session, component.getUuid(), period.getSnapshotId(), metricIds);
+        setVariationMeasures(component, pastMeasures, period.getIndex(), measuresWithVariationRepository);
+      }
+      return measuresWithVariationRepository;
+    }
+
+    private void processMeasuresWithVariation(Component component, MeasuresWithVariationRepository measuresWithVariationRepository) {
+      for (MeasureWithVariations measureWithVariations : measuresWithVariationRepository.measures()) {
+        Metric metric = measureWithVariations.getMetric();
+        Measure measure = Measure.updatedMeasureBuilder(measureWithVariations.getMeasure())
+          .setVariations(new MeasureVariations(
+            measureWithVariations.getVariation(1),
+            measureWithVariations.getVariation(2),
+            measureWithVariations.getVariation(3),
+            measureWithVariations.getVariation(4),
+            measureWithVariations.getVariation(5)))
+          .create();
+        measureRepository.update(component, metric, measure);
+      }
+    }
+
+    private void setVariationMeasures(Component component, List<PastMeasureDto> pastMeasures, int period, MeasuresWithVariationRepository measuresWithVariationRepository) {
+      Map<MeasureKey, PastMeasureDto> pastMeasuresByMeasureKey = from(pastMeasures).uniqueIndex(pastMeasureToMeasureKey);
+      for (Map.Entry<String, Measure> entry : measureRepository.getRawMeasures(component).entries()) {
+        String metricKey = entry.getKey();
+        Measure measure = entry.getValue();
+        PastMeasureDto pastMeasure = pastMeasuresByMeasureKey.get(new MeasureKey(metricKey, measure.getCharacteristicId(), measure.getRuleId()));
+        if (pastMeasure != null && pastMeasure.hasValue()) {
+          Metric metric = metricByKeys.get(metricKey);
+          measuresWithVariationRepository.add(metric, measure, period, computeVariation(measure, pastMeasure.getValue()));
+        }
+      }
+    }
+  }
+
+  private static double computeVariation(Measure measure, Double pastValue) {
+    switch (measure.getValueType()) {
+      case INT:
+        return measure.getIntValue() - pastValue;
+      case LONG:
+        return measure.getLongValue() - pastValue;
+      case DOUBLE:
+        return measure.getDoubleValue() - pastValue;
+      case BOOLEAN:
+        return (measure.getBooleanValue() ? 1d : 0d) - pastValue;
+      default:
+        throw new IllegalArgumentException("Unsupported Measure.ValueType " + measure.getValueType());
+    }
+  }
+
+  private static final class MeasuresWithVariationRepository {
+
+    private final Map<MeasureKey, MeasureWithVariations> measuresWithVariations = new HashMap<>();
+
+    public void add(Metric metric, final Measure measure, int variationIndex, double variationValue) {
+      MeasureKey measureKey = new MeasureKey(metric.getKey(), measure.getCharacteristicId(), measure.getRuleId());
+      MeasureWithVariations measureWithVariations = measuresWithVariations.get(measureKey);
+      if (measureWithVariations == null) {
+        measureWithVariations = new MeasureWithVariations(metric, measure);
+        measuresWithVariations.put(measureKey, measureWithVariations);
+      }
+      measureWithVariations.setVariation(variationIndex, variationValue);
+    }
+
+    public Collection<MeasureWithVariations> measures() {
+      return measuresWithVariations.values();
+    }
+  }
+
+  private static final class MeasureWithVariations {
+    private final Metric metric;
+    private final Measure measure;
+    private final Double[] variations = new Double[5];
+
+    public MeasureWithVariations(Metric metric, Measure measure) {
+      this.metric = metric;
+      this.measure = measure;
+    }
+
+    public Measure getMeasure() {
+      return measure;
+    }
+
+    public Metric getMetric() {
+      return metric;
+    }
+
+    public void setVariation(int index, @Nullable Double value) {
+      variations[index - 1] = value;
+    }
+
+    @CheckForNull
+    public Double getVariation(int index) {
+      return variations[index - 1];
+    }
+  }
+
+  private enum MetricDtoToMetricId implements Function<Metric, Integer> {
+    INSTANCE;
+
+    @Nullable
+    @Override
+    public Integer apply(@Nonnull Metric metric) {
+      return metric.getId();
+    }
+  }
+
+  private enum MetricToKey implements Function<Metric, String> {
+    INSTANCE;
+
+    @Nullable
+    @Override
+    public String apply(@Nonnull Metric metric) {
+      return metric.getKey();
+    }
+  }
+
+  private enum NumericMetric implements Predicate<Metric> {
+    INSTANCE;
+
+    @Override
+    public boolean apply(@Nonnull Metric metric) {
+      Measure.ValueType valueType = metric.getType().getValueType();
+      return Measure.ValueType.INT.equals(valueType)
+        || Measure.ValueType.LONG.equals(valueType)
+        || Measure.ValueType.DOUBLE.equals(valueType)
+        || Measure.ValueType.BOOLEAN.equals(valueType);
+    }
+  }
+
+  @Override
+  public String getDescription() {
+    return "Compute measure variations";
+  }
+}
index 12806b26c391c1f8cb62097d5ed85e0b915ee2d5..c974dcd39113136b4df059182cfdde1c36f4b0e6 100644 (file)
@@ -122,6 +122,6 @@ public class ComputeQProfileMeasureStep implements ComputationStep {
 
   @Override
   public String getDescription() {
-    return "Computes Quality Profile measures";
+    return "Compute Quality Profile measures";
   }
 }
index 9f5501d3442c1ad75290858cd6473ae457086a96..31952e954613239c65070bac84a57d9c9b9c2367 100644 (file)
@@ -184,6 +184,6 @@ public class CoverageMeasuresStep implements ComputationStep {
 
   @Override
   public String getDescription() {
-    return "Aggregation of coverage measures";
+    return "Compute coverage measures";
   }
 }
index ae7020cb558c51295a355938dd6f459f457fa09e..b9e12564d2650e1b47ce28d656b795cdc9257261 100644 (file)
@@ -27,11 +27,11 @@ import org.sonar.server.computation.component.CrawlerDepthLimit;
 import org.sonar.server.computation.component.PathAwareCrawler;
 import org.sonar.server.computation.component.TreeRootHolder;
 import org.sonar.server.computation.formula.Counter;
+import org.sonar.server.computation.formula.CounterInitializationContext;
 import org.sonar.server.computation.formula.CreateMeasureContext;
 import org.sonar.server.computation.formula.Formula;
 import org.sonar.server.computation.formula.FormulaExecutorComponentVisitor;
 import org.sonar.server.computation.formula.counter.IntSumCounter;
-import org.sonar.server.computation.formula.CounterInitializationContext;
 import org.sonar.server.computation.measure.Measure;
 import org.sonar.server.computation.measure.MeasureRepository;
 import org.sonar.server.computation.metric.Metric;
@@ -197,6 +197,6 @@ public class DuplicationMeasuresStep implements ComputationStep {
 
   @Override
   public String getDescription() {
-    return "Aggregation of duplication measures";
+    return "Compute duplication measures";
   }
 }
index 0e87f65419cd6b2f54b8b52c7cd06485aff0cfcf..cf29c473e3c61472e5b4ad6f8bb90e96723163c0 100644 (file)
@@ -41,6 +41,6 @@ public class ExecuteVisitorsStep implements ComputationStep {
 
   @Override
   public String getDescription() {
-    return "Execute Visitors";
+    return "Execute visitors";
   }
 }
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ExtractReportStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ExtractReportStep.java
new file mode 100644 (file)
index 0000000..d7065e4
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.computation.step;
+
+import java.io.File;
+import java.io.IOException;
+import org.apache.commons.io.FileUtils;
+import org.sonar.api.utils.TempFolder;
+import org.sonar.api.utils.ZipUtils;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.server.computation.CeTask;
+import org.sonar.server.computation.ReportFiles;
+import org.sonar.server.computation.batch.MutableBatchReportDirectoryHolder;
+
+/**
+ * Extracts the content zip file of the {@link org.sonar.server.computation.CeTask} to a temp directory and adds a {@link File}
+ * representing that temp directory to the {@link MutableBatchReportDirectoryHolder}.
+ */
+public class ExtractReportStep implements ComputationStep {
+  private static final Logger LOG = Loggers.get(ExtractReportStep.class);
+
+  private final ReportFiles reportFiles;
+  private final CeTask task;
+  private final TempFolder tempFolder;
+  private final MutableBatchReportDirectoryHolder reportDirectoryHolder;
+
+  public ExtractReportStep(ReportFiles reportFiles, CeTask task, TempFolder tempFolder,
+    MutableBatchReportDirectoryHolder reportDirectoryHolder) {
+    this.reportFiles = reportFiles;
+    this.task = task;
+    this.tempFolder = tempFolder;
+    this.reportDirectoryHolder = reportDirectoryHolder;
+  }
+
+  @Override
+  public void execute() {
+    File dir = tempFolder.newDir();
+    File zip = reportFiles.fileForUuid(task.getUuid());
+    try {
+      ZipUtils.unzip(zip, dir);
+      reportDirectoryHolder.setDirectory(dir);
+      LOG.info("Analysis report extracted | size={} | compressed={}",
+        FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(dir)), FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(zip)));
+    } catch (IOException e) {
+      throw new IllegalStateException(String.format("Fail to unzip %s into %s", zip, dir), e);
+    }
+  }
+
+  @Override
+  public String getDescription() {
+    return "Extract report";
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/FeedActiveRulesStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/FeedActiveRulesStep.java
deleted file mode 100644 (file)
index 18fb9e5..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.computation.step;
-
-import com.google.common.base.Predicate;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import javax.annotation.Nonnull;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rule.RuleStatus;
-import org.sonar.batch.protocol.output.BatchReport;
-import org.sonar.core.util.CloseableIterator;
-import org.sonar.server.computation.batch.BatchReportReader;
-import org.sonar.server.computation.issue.Rule;
-import org.sonar.server.computation.issue.RuleRepository;
-import org.sonar.server.computation.qualityprofile.ActiveRule;
-import org.sonar.server.computation.qualityprofile.ActiveRulesHolderImpl;
-
-import static com.google.common.collect.FluentIterable.from;
-
-public class FeedActiveRulesStep implements ComputationStep {
-
-  private final BatchReportReader batchReportReader;
-  private final ActiveRulesHolderImpl activeRulesHolder;
-  private final RuleRepository ruleRepository;
-
-  public FeedActiveRulesStep(BatchReportReader batchReportReader, ActiveRulesHolderImpl activeRulesHolder, RuleRepository ruleRepository) {
-    this.batchReportReader = batchReportReader;
-    this.activeRulesHolder = activeRulesHolder;
-    this.ruleRepository = ruleRepository;
-  }
-
-  @Override
-  public void execute() {
-    List<ActiveRule> activeRules = new ArrayList<>();
-    try (CloseableIterator<BatchReport.ActiveRule> batchActiveRules = batchReportReader.readActiveRules()) {
-      while (batchActiveRules.hasNext()) {
-        BatchReport.ActiveRule batchActiveRule = batchActiveRules.next();
-        activeRules.add(convert(batchActiveRule));
-      }
-    }
-
-    List<ActiveRule> validActiveRules = from(activeRules).filter(new IsValid()).toList();
-    activeRulesHolder.set(validActiveRules);
-  }
-
-  private class IsValid implements Predicate<ActiveRule> {
-    @Override
-    public boolean apply(@Nonnull ActiveRule input) {
-      if (ruleRepository.hasKey(input.getRuleKey())) {
-        Rule rule = ruleRepository.getByKey(input.getRuleKey());
-        return rule.getStatus() != RuleStatus.REMOVED;
-      }
-      return false;
-    }
-  }
-
-  @Override
-  public String getDescription() {
-    return getClass().getSimpleName();
-  }
-
-  private ActiveRule convert(BatchReport.ActiveRule input) {
-    RuleKey key = RuleKey.of(input.getRuleRepository(), input.getRuleKey());
-    Map<String, String> params = new HashMap<>();
-    for (BatchReport.ActiveRule.ActiveRuleParam inputParam : input.getParamList()) {
-      params.put(inputParam.getKey(), inputParam.getValue());
-    }
-    return new ActiveRule(key, input.getSeverity().name(), params);
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/FeedDebtModelStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/FeedDebtModelStep.java
deleted file mode 100644 (file)
index 88358dd..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.computation.step;
-
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.debt.CharacteristicDto;
-import org.sonar.server.computation.debt.Characteristic;
-import org.sonar.server.computation.debt.CharacteristicImpl;
-import org.sonar.server.computation.debt.MutableDebtModelHolder;
-
-import static com.google.common.base.Predicates.not;
-import static com.google.common.collect.FluentIterable.from;
-
-/**
- * Populates the {@link org.sonar.server.computation.debt.DebtModelHolder}
- */
-public class FeedDebtModelStep implements ComputationStep {
-
-  private final DbClient dbClient;
-  private final MutableDebtModelHolder mutableDebtModelHolder;
-
-  public FeedDebtModelStep(DbClient dbClient, MutableDebtModelHolder mutableDebtModelHolder) {
-    this.dbClient = dbClient;
-    this.mutableDebtModelHolder = mutableDebtModelHolder;
-  }
-
-  @Override
-  public void execute() {
-    DbSession session = dbClient.openSession(false);
-    try {
-      feedDebtModel(session);
-    } finally {
-      session.close();
-    }
-  }
-
-  private void feedDebtModel(DbSession session) {
-    List<CharacteristicDto> characteristicDtos = dbClient.debtCharacteristicDao().selectEnabledCharacteristics(session);
-    Map<Integer, CharacteristicDto> rootCharacteristicsById = from(characteristicDtos)
-      .filter(IsRootPredicate.INSTANCE)
-      .uniqueIndex(CharacteristicDtoToId.INSTANCE);
-
-    for (Map.Entry<Integer, Collection<CharacteristicDto>> entry : from(characteristicDtos)
-      .filter(not(IsRootPredicate.INSTANCE))
-      .index(CharacteristicDtoToParentId.INSTANCE)
-      .asMap().entrySet()) {
-      mutableDebtModelHolder.addCharacteristics(
-        toCharacteristic(rootCharacteristicsById.get(entry.getKey())),
-        from(entry.getValue()).transform(CharacteristicDtoToCharacteristic.INSTANCE)
-        );
-    }
-  }
-
-  private static Characteristic toCharacteristic(CharacteristicDto dto) {
-    return new CharacteristicImpl(dto.getId(), dto.getKey(), dto.getParentId());
-  }
-
-  private enum CharacteristicDtoToId implements Function<CharacteristicDto, Integer> {
-    INSTANCE;
-
-    @Nullable
-    @Override
-    public Integer apply(@Nonnull CharacteristicDto dto) {
-      return dto.getId();
-    }
-  }
-
-  private enum CharacteristicDtoToCharacteristic implements Function<CharacteristicDto, Characteristic> {
-    INSTANCE;
-
-    @Nullable
-    @Override
-    public Characteristic apply(@Nonnull CharacteristicDto characteristicDto) {
-      return toCharacteristic(characteristicDto);
-    }
-  }
-
-  private enum CharacteristicDtoToParentId implements Function<CharacteristicDto, Integer> {
-    INSTANCE;
-
-    @Nullable
-    @Override
-    public Integer apply(@Nonnull CharacteristicDto characteristicDto) {
-      Integer parentId = characteristicDto.getParentId();
-      return parentId == null ? characteristicDto.getId() : parentId;
-    }
-  }
-
-  private enum IsRootPredicate implements Predicate<CharacteristicDto> {
-    INSTANCE;
-
-    @Override
-    public boolean apply(@Nonnull CharacteristicDto characteristicDto) {
-      return characteristicDto.getParentId() == null;
-    }
-  }
-
-  @Override
-  public String getDescription() {
-    return "Feed technical debt model";
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/FeedMeasureComputers.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/FeedMeasureComputers.java
deleted file mode 100644 (file)
index a9901ac..0000000
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.computation.step;
-
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import org.sonar.api.ce.measure.MeasureComputer;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.measures.Metrics;
-import org.sonar.api.utils.dag.DirectAcyclicGraph;
-import org.sonar.server.computation.measure.MutableMeasureComputersHolder;
-import org.sonar.server.computation.measure.api.MeasureComputerDefinitionImpl;
-import org.sonar.server.computation.measure.api.MeasureComputerWrapper;
-
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.FluentIterable.from;
-import static org.sonar.api.ce.measure.MeasureComputer.MeasureComputerDefinition;
-import static org.sonar.api.ce.measure.MeasureComputer.MeasureComputerDefinitionContext;
-
-public class FeedMeasureComputers implements ComputationStep {
-
-  private static final Set<String> CORE_METRIC_KEYS = from(CoreMetrics.getMetrics()).transform(MetricToKey.INSTANCE).toSet();
-  private Set<String> pluginMetricKeys;
-
-  private final MutableMeasureComputersHolder measureComputersHolder;
-  private final MeasureComputer[] measureComputers;
-
-  public FeedMeasureComputers(MutableMeasureComputersHolder measureComputersHolder, Metrics[] metricsRepositories, MeasureComputer[] measureComputers) {
-    this.measureComputersHolder = measureComputersHolder;
-    this.measureComputers = measureComputers;
-    this.pluginMetricKeys = from(Arrays.asList(metricsRepositories))
-      .transformAndConcat(MetricsToMetricList.INSTANCE)
-      .transform(MetricToKey.INSTANCE)
-      .toSet();
-  }
-
-  /**
-   * Constructor override used by Pico to instantiate the class when no plugin is defining metrics
-   */
-  public FeedMeasureComputers(MutableMeasureComputersHolder measureComputersHolder, MeasureComputer[] measureComputers) {
-    this(measureComputersHolder, new Metrics[] {}, measureComputers);
-  }
-
-  /**
-   * Constructor override used by Pico to instantiate the class when no plugin is defining measure computers
-   */
-  public FeedMeasureComputers(MutableMeasureComputersHolder measureComputersHolder, Metrics[] metricsRepositories) {
-    this(measureComputersHolder, metricsRepositories, new MeasureComputer[] {});
-  }
-
-  /**
-   * Constructor override used by Pico to instantiate the class when no plugin is defining metrics neither measure computers
-   */
-  public FeedMeasureComputers(MutableMeasureComputersHolder measureComputersHolder) {
-    this(measureComputersHolder, new Metrics[] {}, new MeasureComputer[] {});
-  }
-
-  @Override
-  public void execute() {
-    List<MeasureComputerWrapper> wrappers = from(Arrays.asList(measureComputers)).transform(ToMeasureWrapper.INSTANCE).toList();
-    validateMetrics(wrappers);
-    measureComputersHolder.setMeasureComputers(sortComputers(wrappers));
-  }
-
-  private static Iterable<MeasureComputerWrapper> sortComputers(List<MeasureComputerWrapper> wrappers) {
-    Map<String, MeasureComputerWrapper> computersByOutputMetric = new HashMap<>();
-    Map<String, MeasureComputerWrapper> computersByInputMetric = new HashMap<>();
-    feedComputersByMetric(wrappers, computersByOutputMetric, computersByInputMetric);
-    ToComputerByKey toComputerByOutputMetricKey = new ToComputerByKey(computersByOutputMetric);
-    ToComputerByKey toComputerByInputMetricKey = new ToComputerByKey(computersByInputMetric);
-
-    DirectAcyclicGraph dag = new DirectAcyclicGraph();
-    for (MeasureComputerWrapper computer : wrappers) {
-      dag.add(computer);
-      for (MeasureComputerWrapper dependency : getDependencies(computer, toComputerByOutputMetricKey)) {
-        dag.add(computer, dependency);
-      }
-      for (MeasureComputerWrapper generates : getDependents(computer, toComputerByInputMetricKey)) {
-        dag.add(generates, computer);
-      }
-    }
-    return dag.sort();
-  }
-
-  private static void feedComputersByMetric(List<MeasureComputerWrapper> wrappers, Map<String, MeasureComputerWrapper> computersByOutputMetric,
-                                            Map<String, MeasureComputerWrapper> computersByInputMetric) {
-    for (MeasureComputerWrapper computer : wrappers) {
-      for (String outputMetric : computer.getDefinition().getOutputMetrics()) {
-        computersByOutputMetric.put(outputMetric, computer);
-      }
-      for (String inputMetric : computer.getDefinition().getInputMetrics()) {
-        computersByInputMetric.put(inputMetric, computer);
-      }
-    }
-  }
-
-  private void validateMetrics(List<MeasureComputerWrapper> wrappers) {
-    from(wrappers).transformAndConcat(ToInputMetrics.INSTANCE).filter(new ValidateInputMetric()).size();
-    from(wrappers).transformAndConcat(ToOutputMetrics.INSTANCE).filter(new ValidateOutputMetric()).size();
-    from(wrappers).filter(new ValidateUniqueOutputMetric()).size();
-  }
-
-  private static Iterable<MeasureComputerWrapper> getDependencies(MeasureComputerWrapper measureComputer, ToComputerByKey toComputerByOutputMetricKey) {
-    // Remove null computer because a computer can depend on a metric that is only generated by a sensor or on a core metrics
-    return from(measureComputer.getDefinition().getInputMetrics()).transform(toComputerByOutputMetricKey).filter(Predicates.notNull());
-  }
-
-  private static Iterable<MeasureComputerWrapper> getDependents(MeasureComputerWrapper measureComputer, ToComputerByKey toComputerByInputMetricKey) {
-    return from(measureComputer.getDefinition().getInputMetrics()).transform(toComputerByInputMetricKey);
-  }
-
-  private static class ToComputerByKey implements Function<String, MeasureComputerWrapper> {
-    private final Map<String, MeasureComputerWrapper> computersByMetric;
-
-    private ToComputerByKey(Map<String, MeasureComputerWrapper> computersByMetric) {
-      this.computersByMetric = computersByMetric;
-    }
-
-    @Override
-    public MeasureComputerWrapper apply(@Nonnull String metricKey) {
-      return computersByMetric.get(metricKey);
-    }
-  }
-
-  private enum MetricToKey implements Function<Metric, String> {
-    INSTANCE;
-
-    @Nullable
-    @Override
-    public String apply(@Nonnull Metric input) {
-      return input.key();
-    }
-  }
-
-  private enum MetricsToMetricList implements Function<Metrics, List<Metric>> {
-    INSTANCE;
-
-    @Override
-    public List<Metric> apply(@Nonnull Metrics input) {
-      return input.getMetrics();
-    }
-  }
-
-  private enum ToMeasureWrapper implements Function<MeasureComputer, MeasureComputerWrapper> {
-    INSTANCE;
-
-    private final MeasureComputerDefinitionContextImpl context = new MeasureComputerDefinitionContextImpl();
-
-    @Override
-    public MeasureComputerWrapper apply(@Nonnull MeasureComputer measureComputer) {
-      MeasureComputerDefinition def = measureComputer.define(context);
-      return new MeasureComputerWrapper(measureComputer, validateDef(def));
-    }
-
-    private static MeasureComputerDefinition validateDef(MeasureComputerDefinition def) {
-      if (def instanceof MeasureComputerDefinitionImpl) {
-        return def;
-      }
-      // If the computer has not been created by the builder, we recreate it to make sure it's valid
-      Set<String> inputMetrics = def.getInputMetrics();
-      Set<String> outputMetrics = def.getOutputMetrics();
-      return new MeasureComputerDefinitionImpl.BuilderImpl()
-        .setInputMetrics(from(inputMetrics).toArray(String.class))
-        .setOutputMetrics(from(outputMetrics).toArray(String.class))
-        .build();
-    }
-  }
-
-  private enum ToInputMetrics implements Function<MeasureComputerWrapper, Collection<String>> {
-    INSTANCE;
-
-    @Override
-    public Collection<String> apply(@Nonnull MeasureComputerWrapper input) {
-      return input.getDefinition().getInputMetrics();
-    }
-  }
-
-  private class ValidateInputMetric implements Predicate<String> {
-    @Override
-    public boolean apply(@Nonnull String metric) {
-      checkState(pluginMetricKeys.contains(metric) || CORE_METRIC_KEYS.contains(metric),
-        String.format("Metric '%s' cannot be used as an input metric as it's not a core metric and no plugin declare this metric", metric));
-      return true;
-    }
-  }
-
-  private enum ToOutputMetrics implements Function<MeasureComputerWrapper, Collection<String>> {
-    INSTANCE;
-
-    @Override
-    public Collection<String> apply(@Nonnull MeasureComputerWrapper input) {
-      return input.getDefinition().getOutputMetrics();
-    }
-  }
-
-  private class ValidateOutputMetric implements Predicate<String> {
-    @Override
-    public boolean apply(@Nonnull String metric) {
-      checkState(!CORE_METRIC_KEYS.contains(metric), String.format("Metric '%s' cannot be used as an output metric as it's a core metric", metric));
-      checkState(pluginMetricKeys.contains(metric), String.format("Metric '%s' cannot be used as an output metric as no plugin declare this metric", metric));
-      return true;
-    }
-  }
-
-  private static class ValidateUniqueOutputMetric implements Predicate<MeasureComputerWrapper> {
-    private Set<String> allOutputMetrics = new HashSet<>();
-
-    @Override
-    public boolean apply(@Nonnull MeasureComputerWrapper wrapper ) {
-      for (String outputMetric : wrapper.getDefinition().getOutputMetrics()) {
-        checkState(!allOutputMetrics.contains(outputMetric),
-          String.format("Output metric '%s' is already defined by another measure computer '%s'", outputMetric, wrapper.getComputer()));
-        allOutputMetrics.add(outputMetric);
-      }
-      return true;
-    }
-  }
-
-  private static class MeasureComputerDefinitionContextImpl implements MeasureComputerDefinitionContext {
-    @Override
-    public MeasureComputerDefinition.Builder newDefinitionBuilder() {
-      return new MeasureComputerDefinitionImpl.BuilderImpl();
-    }
-  }
-
-  @Override
-  public String getDescription() {
-    return "Feed measure computers";
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/FeedPeriodsStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/FeedPeriodsStep.java
deleted file mode 100644 (file)
index 1da2605..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.computation.step;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Strings;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.config.Settings;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.SnapshotDto;
-import org.sonar.db.component.SnapshotQuery;
-import org.sonar.server.computation.analysis.AnalysisMetadataHolder;
-import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler;
-import org.sonar.server.computation.component.SettingsRepository;
-import org.sonar.server.computation.component.TreeRootHolder;
-import org.sonar.server.computation.component.TypeAwareVisitorAdapter;
-import org.sonar.server.computation.period.Period;
-import org.sonar.server.computation.period.PeriodsHolderImpl;
-
-import static org.sonar.db.component.SnapshotQuery.SORT_FIELD.BY_DATE;
-import static org.sonar.db.component.SnapshotQuery.SORT_ORDER.ASC;
-import static org.sonar.db.component.SnapshotQuery.SORT_ORDER.DESC;
-import static org.sonar.server.computation.component.Component.Type.PROJECT;
-import static org.sonar.server.computation.component.Component.Type.VIEW;
-import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;
-import static org.sonar.server.computation.component.CrawlerDepthLimit.reportMaxDepth;
-
-/**
- * Populates the {@link org.sonar.server.computation.period.PeriodsHolder}
- * <p/>
- * Here is how these periods are computed :
- * - Read the 5 period properties ${@link CoreProperties#TIMEMACHINE_PERIOD_PREFIX}
- * - Try to find the matching snapshots from the properties
- * - If a snapshot is found, a new period is added to the repository
- */
-public class FeedPeriodsStep implements ComputationStep {
-
-  private static final Logger LOG = Loggers.get(FeedPeriodsStep.class);
-
-  private static final int NUMBER_OF_PERIODS = 5;
-
-  private final DbClient dbClient;
-  private final SettingsRepository settingsRepository;
-  private final TreeRootHolder treeRootHolder;
-  private final AnalysisMetadataHolder analysisMetadataHolder;
-  private final PeriodsHolderImpl periodsHolder;
-
-  public FeedPeriodsStep(DbClient dbClient, SettingsRepository settingsRepository, TreeRootHolder treeRootHolder, AnalysisMetadataHolder analysisMetadataHolder,
-    PeriodsHolderImpl periodsHolder) {
-    this.dbClient = dbClient;
-    this.settingsRepository = settingsRepository;
-    this.treeRootHolder = treeRootHolder;
-    this.analysisMetadataHolder = analysisMetadataHolder;
-    this.periodsHolder = periodsHolder;
-  }
-
-  @Override
-  public void execute() {
-    new DepthTraversalTypeAwareCrawler(
-      new TypeAwareVisitorAdapter(reportMaxDepth(PROJECT).withViewsMaxDepth(VIEW), PRE_ORDER) {
-        @Override
-        public void visitProject(Component project) {
-          execute(project);
-        }
-
-        @Override
-        public void visitView(Component view) {
-          execute(view);
-        }
-      }).visit(treeRootHolder.getRoot());
-  }
-
-  public void execute(Component projectOrView) {
-    DbSession session = dbClient.openSession(false);
-    try {
-      periodsHolder.setPeriods(buildPeriods(projectOrView, session));
-    } finally {
-      dbClient.closeSession(session);
-    }
-  }
-
-  private List<Period> buildPeriods(Component projectOrView, DbSession session) {
-    Optional<ComponentDto> projectDto = dbClient.componentDao().selectByKey(session, projectOrView.getKey());
-    // No project on first analysis, no period
-    if (!projectDto.isPresent()) {
-      return Collections.emptyList();
-    }
-
-    boolean isReportType = projectOrView.getType().isReportType();
-    PeriodResolver periodResolver = new PeriodResolver(session, projectDto.get().getId(), analysisMetadataHolder.getAnalysisDate().getTime(),
-      isReportType ? projectOrView.getReportAttributes().getVersion() : null,
-      isReportType ? Qualifiers.PROJECT : Qualifiers.VIEW);
-
-    Settings settings = settingsRepository.getSettings(projectOrView);
-    List<Period> periods = new ArrayList<>(5);
-    for (int index = 1; index <= NUMBER_OF_PERIODS; index++) {
-      Period period = periodResolver.resolve(index, settings);
-      // SONAR-4700 Add a past snapshot only if it exists
-      if (period != null) {
-        periods.add(period);
-      }
-    }
-    return periods;
-  }
-
-  private class PeriodResolver {
-
-    private final DbSession session;
-    private final long projectId;
-    private final long analysisDate;
-    @CheckForNull
-    private final String currentVersion;
-    private final String qualifier;
-
-    public PeriodResolver(DbSession session, long projectId, long analysisDate, @Nullable String currentVersion, String qualifier) {
-      this.session = session;
-      this.projectId = projectId;
-      this.analysisDate = analysisDate;
-      this.currentVersion = currentVersion;
-      this.qualifier = qualifier;
-    }
-
-    @CheckForNull
-    public Period resolve(int index, Settings settings) {
-      String propertyValue = getPropertyValue(qualifier, settings, index);
-      if (StringUtils.isBlank(propertyValue)) {
-        return null;
-      }
-      Period period = resolve(index, propertyValue);
-      if (period == null && StringUtils.isNotBlank(propertyValue)) {
-        LOG.debug("Property " + CoreProperties.TIMEMACHINE_PERIOD_PREFIX + index + " is not valid: " + propertyValue);
-      }
-      return period;
-    }
-
-    @CheckForNull
-    private Period resolve(int index, String property) {
-      Integer days = tryToResolveByDays(property);
-      if (days != null) {
-        return findByDays(index, days);
-      }
-      Date date = tryToResolveByDate(property);
-      if (date != null) {
-        return findByDate(index, date);
-      }
-      if (StringUtils.equals(CoreProperties.TIMEMACHINE_MODE_PREVIOUS_ANALYSIS, property)) {
-        return findByPreviousAnalysis(index);
-      }
-      if (StringUtils.equals(CoreProperties.TIMEMACHINE_MODE_PREVIOUS_VERSION, property)) {
-        return findByPreviousVersion(index);
-      }
-      return findByVersion(index, property);
-    }
-
-    private Period findByDate(int index, Date date) {
-      SnapshotDto snapshot = findFirstSnapshot(session, createCommonQuery(projectId).setCreatedAfter(date.getTime()).setSort(BY_DATE, ASC));
-      if (snapshot == null) {
-        return null;
-      }
-      LOG.debug("Compare to date {} (analysis of {})", formatDate(date.getTime()), formatDate(snapshot.getCreatedAt()));
-      return new Period(index, CoreProperties.TIMEMACHINE_MODE_DATE, DateUtils.formatDate(date), snapshot.getCreatedAt(), snapshot.getId());
-    }
-
-    @CheckForNull
-    private Period findByDays(int index, int days) {
-      List<SnapshotDto> snapshots = dbClient.snapshotDao().selectSnapshotsByQuery(session, createCommonQuery(projectId).setCreatedBefore(analysisDate).setSort(BY_DATE, ASC));
-      long targetDate = DateUtils.addDays(new Date(analysisDate), -days).getTime();
-      SnapshotDto snapshot = findNearestSnapshotToTargetDate(snapshots, targetDate);
-      if (snapshot == null) {
-        return null;
-      }
-      LOG.debug("Compare over {} days ({}, analysis of {})", String.valueOf(days), formatDate(targetDate), formatDate(snapshot.getCreatedAt()));
-      return new Period(index, CoreProperties.TIMEMACHINE_MODE_DAYS, String.valueOf(days), snapshot.getCreatedAt(), snapshot.getId());
-    }
-
-    @CheckForNull
-    private Period findByPreviousAnalysis(int index) {
-      SnapshotDto snapshot = findFirstSnapshot(session, createCommonQuery(projectId).setCreatedBefore(analysisDate).setIsLast(true).setSort(BY_DATE, DESC));
-      if (snapshot == null) {
-        return null;
-      }
-      LOG.debug("Compare to previous analysis ({})", formatDate(snapshot.getCreatedAt()));
-      return new Period(index, CoreProperties.TIMEMACHINE_MODE_PREVIOUS_ANALYSIS, formatDate(snapshot.getCreatedAt()), snapshot.getCreatedAt(), snapshot.getId());
-    }
-
-    @CheckForNull
-    private Period findByPreviousVersion(int index) {
-      if (currentVersion == null) {
-        return null;
-      }
-      List<SnapshotDto> snapshotDtos = dbClient.snapshotDao().selectPreviousVersionSnapshots(session, projectId, currentVersion);
-      if (snapshotDtos.isEmpty()) {
-        return null;
-      }
-      SnapshotDto snapshotDto = snapshotDtos.get(0);
-      LOG.debug("Compare to previous version ({})", formatDate(snapshotDto.getCreatedAt()));
-      return new Period(index, CoreProperties.TIMEMACHINE_MODE_PREVIOUS_VERSION, snapshotDto.getVersion(), snapshotDto.getCreatedAt(), snapshotDto.getId());
-    }
-
-    @CheckForNull
-    private Period findByVersion(int index, String version) {
-      SnapshotDto snapshot = findFirstSnapshot(session, createCommonQuery(projectId).setVersion(version).setSort(BY_DATE, DESC));
-      if (snapshot == null) {
-        return null;
-      }
-      LOG.debug("Compare to version ({}) ({})", version, formatDate(snapshot.getCreatedAt()));
-      return new Period(index, CoreProperties.TIMEMACHINE_MODE_VERSION, version, snapshot.getCreatedAt(), snapshot.getId());
-    }
-
-    @CheckForNull
-    private SnapshotDto findFirstSnapshot(DbSession session, SnapshotQuery query) {
-      List<SnapshotDto> snapshots = dbClient.snapshotDao().selectSnapshotsByQuery(session, query);
-      if (!snapshots.isEmpty()) {
-        return snapshots.get(0);
-      }
-      return null;
-    }
-  }
-
-  @CheckForNull
-  private static Integer tryToResolveByDays(String property) {
-    try {
-      return Integer.parseInt(property);
-    } catch (NumberFormatException e) {
-      // Nothing to, it means that the property is not a number of days
-      return null;
-    }
-  }
-
-  @CheckForNull
-  private static Date tryToResolveByDate(String property) {
-    try {
-      return DateUtils.parseDate(property);
-    } catch (Exception e) {
-      // Nothing to, it means that the property is not a date
-      return null;
-    }
-  }
-
-  @CheckForNull
-  private static SnapshotDto findNearestSnapshotToTargetDate(List<SnapshotDto> snapshots, Long targetDate) {
-    long bestDistance = Long.MAX_VALUE;
-    SnapshotDto nearest = null;
-    for (SnapshotDto snapshot : snapshots) {
-      long distance = Math.abs(snapshot.getCreatedAt() - targetDate);
-      if (distance <= bestDistance) {
-        bestDistance = distance;
-        nearest = snapshot;
-      }
-    }
-    return nearest;
-  }
-
-  private static SnapshotQuery createCommonQuery(Long projectId) {
-    return new SnapshotQuery().setComponentId(projectId).setStatus(SnapshotDto.STATUS_PROCESSED);
-  }
-
-  private static String formatDate(long date) {
-    return DateUtils.formatDate(org.apache.commons.lang.time.DateUtils.truncate(new Date(date), Calendar.SECOND));
-  }
-
-  private static String getPropertyValue(@Nullable String qualifier, Settings settings, int index) {
-    String value = settings.getString(CoreProperties.TIMEMACHINE_PERIOD_PREFIX + index);
-    // For periods 4 and 5 we're also searching for a property prefixed by the qualifier
-    if (index > 3 && Strings.isNullOrEmpty(value)) {
-      value = settings.getString(CoreProperties.TIMEMACHINE_PERIOD_PREFIX + index + "." + qualifier);
-    }
-    return value;
-  }
-
-  @Override
-  public String getDescription() {
-    return "Feed differential periods";
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/FillMeasuresWithVariationsStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/FillMeasuresWithVariationsStep.java
deleted file mode 100644 (file)
index ff51847..0000000
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.computation.step;
-
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.measure.PastMeasureDto;
-import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.component.CrawlerDepthLimit;
-import org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler;
-import org.sonar.server.computation.component.TreeRootHolder;
-import org.sonar.server.computation.component.TypeAwareVisitorAdapter;
-import org.sonar.server.computation.measure.Measure;
-import org.sonar.server.computation.measure.MeasureKey;
-import org.sonar.server.computation.measure.MeasureRepository;
-import org.sonar.server.computation.measure.MeasureVariations;
-import org.sonar.server.computation.metric.Metric;
-import org.sonar.server.computation.metric.MetricRepository;
-import org.sonar.server.computation.period.Period;
-import org.sonar.server.computation.period.PeriodsHolder;
-
-import static com.google.common.collect.FluentIterable.from;
-import static org.sonar.server.computation.component.Component.Type.DIRECTORY;
-import static org.sonar.server.computation.component.Component.Type.SUBVIEW;
-import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;
-
-/**
- * Set variations on all numeric measures found in the repository.
- * This step MUST be executed after all steps that create some measures
- * <p/>
- * Note that measures on developer are not handle yet.
- */
-public class FillMeasuresWithVariationsStep implements ComputationStep {
-
-  private final DbClient dbClient;
-  private final TreeRootHolder treeRootHolder;
-  private final PeriodsHolder periodsHolder;
-  private final MetricRepository metricRepository;
-  private final MeasureRepository measureRepository;
-
-  private final Function<PastMeasureDto, MeasureKey> pastMeasureToMeasureKey = new Function<PastMeasureDto, MeasureKey>() {
-    @Nullable
-    @Override
-    public MeasureKey apply(@Nonnull PastMeasureDto input) {
-      Metric metric = metricRepository.getById(input.getMetricId());
-      return new MeasureKey(metric.getKey(), input.getCharacteristicId(), input.getRuleId());
-    }
-  };
-
-  public FillMeasuresWithVariationsStep(DbClient dbClient, TreeRootHolder treeRootHolder, PeriodsHolder periodsHolder, MetricRepository metricRepository,
-    MeasureRepository measureRepository) {
-    this.dbClient = dbClient;
-    this.treeRootHolder = treeRootHolder;
-    this.periodsHolder = periodsHolder;
-    this.metricRepository = metricRepository;
-    this.measureRepository = measureRepository;
-  }
-
-  @Override
-  public void execute() {
-    DbSession dbSession = dbClient.openSession(false);
-    try {
-      List<Metric> metrics = from(metricRepository.getAll()).filter(NumericMetric.INSTANCE).toList();
-      new DepthTraversalTypeAwareCrawler(new VariationMeasuresVisitor(dbSession, metrics))
-        .visit(treeRootHolder.getRoot());
-    } finally {
-      dbClient.closeSession(dbSession);
-    }
-  }
-
-  private class VariationMeasuresVisitor extends TypeAwareVisitorAdapter {
-
-    private final DbSession session;
-    private final Set<Integer> metricIds;
-    private final Map<String, Metric> metricByKeys;
-
-    public VariationMeasuresVisitor(DbSession session, Iterable<Metric> metrics) {
-      // measures on files are currently purged, so past measures are not available on files
-      super(CrawlerDepthLimit.reportMaxDepth(DIRECTORY).withViewsMaxDepth(SUBVIEW), PRE_ORDER);
-      this.session = session;
-      this.metricIds = from(metrics).transform(MetricDtoToMetricId.INSTANCE).toSet();
-      this.metricByKeys = from(metrics).uniqueIndex(MetricToKey.INSTANCE);
-    }
-
-    @Override
-    public void visitAny(Component component) {
-      MeasuresWithVariationRepository measuresWithVariationRepository = computeMeasuresWithVariations(component);
-      processMeasuresWithVariation(component, measuresWithVariationRepository);
-    }
-
-    private MeasuresWithVariationRepository computeMeasuresWithVariations(Component component) {
-      MeasuresWithVariationRepository measuresWithVariationRepository = new MeasuresWithVariationRepository();
-      for (Period period : periodsHolder.getPeriods()) {
-        List<PastMeasureDto> pastMeasures = dbClient.measureDao()
-          .selectByComponentUuidAndProjectSnapshotIdAndMetricIds(session, component.getUuid(), period.getSnapshotId(), metricIds);
-        setVariationMeasures(component, pastMeasures, period.getIndex(), measuresWithVariationRepository);
-      }
-      return measuresWithVariationRepository;
-    }
-
-    private void processMeasuresWithVariation(Component component, MeasuresWithVariationRepository measuresWithVariationRepository) {
-      for (MeasureWithVariations measureWithVariations : measuresWithVariationRepository.measures()) {
-        Metric metric = measureWithVariations.getMetric();
-        Measure measure = Measure.updatedMeasureBuilder(measureWithVariations.getMeasure())
-          .setVariations(new MeasureVariations(
-            measureWithVariations.getVariation(1),
-            measureWithVariations.getVariation(2),
-            measureWithVariations.getVariation(3),
-            measureWithVariations.getVariation(4),
-            measureWithVariations.getVariation(5)))
-          .create();
-        measureRepository.update(component, metric, measure);
-      }
-    }
-
-    private void setVariationMeasures(Component component, List<PastMeasureDto> pastMeasures, int period, MeasuresWithVariationRepository measuresWithVariationRepository) {
-      Map<MeasureKey, PastMeasureDto> pastMeasuresByMeasureKey = from(pastMeasures).uniqueIndex(pastMeasureToMeasureKey);
-      for (Map.Entry<String, Measure> entry : measureRepository.getRawMeasures(component).entries()) {
-        String metricKey = entry.getKey();
-        Measure measure = entry.getValue();
-        PastMeasureDto pastMeasure = pastMeasuresByMeasureKey.get(new MeasureKey(metricKey, measure.getCharacteristicId(), measure.getRuleId()));
-        if (pastMeasure != null && pastMeasure.hasValue()) {
-          Metric metric = metricByKeys.get(metricKey);
-          measuresWithVariationRepository.add(metric, measure, period, computeVariation(measure, pastMeasure.getValue()));
-        }
-      }
-    }
-  }
-
-  private static double computeVariation(Measure measure, Double pastValue) {
-    switch (measure.getValueType()) {
-      case INT:
-        return measure.getIntValue() - pastValue;
-      case LONG:
-        return measure.getLongValue() - pastValue;
-      case DOUBLE:
-        return measure.getDoubleValue() - pastValue;
-      case BOOLEAN:
-        return (measure.getBooleanValue() ? 1d : 0d) - pastValue;
-      default:
-        throw new IllegalArgumentException("Unsupported Measure.ValueType " + measure.getValueType());
-    }
-  }
-
-  private static final class MeasuresWithVariationRepository {
-
-    private final Map<MeasureKey, MeasureWithVariations> measuresWithVariations = new HashMap<>();
-
-    public void add(Metric metric, final Measure measure, int variationIndex, double variationValue) {
-      MeasureKey measureKey = new MeasureKey(metric.getKey(), measure.getCharacteristicId(), measure.getRuleId());
-      MeasureWithVariations measureWithVariations = measuresWithVariations.get(measureKey);
-      if (measureWithVariations == null) {
-        measureWithVariations = new MeasureWithVariations(metric, measure);
-        measuresWithVariations.put(measureKey, measureWithVariations);
-      }
-      measureWithVariations.setVariation(variationIndex, variationValue);
-    }
-
-    public Collection<MeasureWithVariations> measures() {
-      return measuresWithVariations.values();
-    }
-  }
-
-  private static final class MeasureWithVariations {
-    private final Metric metric;
-    private final Measure measure;
-    private final Double[] variations = new Double[5];
-
-    public MeasureWithVariations(Metric metric, Measure measure) {
-      this.metric = metric;
-      this.measure = measure;
-    }
-
-    public Measure getMeasure() {
-      return measure;
-    }
-
-    public Metric getMetric() {
-      return metric;
-    }
-
-    public void setVariation(int index, @Nullable Double value) {
-      variations[index - 1] = value;
-    }
-
-    @CheckForNull
-    public Double getVariation(int index) {
-      return variations[index - 1];
-    }
-  }
-
-  private enum MetricDtoToMetricId implements Function<Metric, Integer> {
-    INSTANCE;
-
-    @Nullable
-    @Override
-    public Integer apply(@Nonnull Metric metric) {
-      return metric.getId();
-    }
-  }
-
-  private enum MetricToKey implements Function<Metric, String> {
-    INSTANCE;
-
-    @Nullable
-    @Override
-    public String apply(@Nonnull Metric metric) {
-      return metric.getKey();
-    }
-  }
-
-  private enum NumericMetric implements Predicate<Metric> {
-    INSTANCE;
-
-    @Override
-    public boolean apply(@Nonnull Metric metric) {
-      Measure.ValueType valueType = metric.getType().getValueType();
-      return Measure.ValueType.INT.equals(valueType)
-        || Measure.ValueType.LONG.equals(valueType)
-        || Measure.ValueType.DOUBLE.equals(valueType)
-        || Measure.ValueType.BOOLEAN.equals(valueType);
-    }
-  }
-
-  @Override
-  public String getDescription() {
-    return "Compute differential measures";
-  }
-}
index afdb75a1b7a3b43a2c35c9bb2456a974df8e6b74..698d1b4167104f5b75c401f5a6d6cd18534711fe 100644 (file)
@@ -147,6 +147,6 @@ public class LanguageDistributionMeasuresStep implements ComputationStep {
 
   @Override
   public String getDescription() {
-    return "Compute language distribution measures";
+    return "Compute language distribution";
   }
 }
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadDebtModelStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadDebtModelStep.java
new file mode 100644 (file)
index 0000000..2c1ea54
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.computation.step;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.debt.CharacteristicDto;
+import org.sonar.server.computation.debt.Characteristic;
+import org.sonar.server.computation.debt.CharacteristicImpl;
+import org.sonar.server.computation.debt.MutableDebtModelHolder;
+
+import static com.google.common.base.Predicates.not;
+import static com.google.common.collect.FluentIterable.from;
+
+/**
+ * Populates the {@link org.sonar.server.computation.debt.DebtModelHolder}
+ */
+public class LoadDebtModelStep implements ComputationStep {
+
+  private final DbClient dbClient;
+  private final MutableDebtModelHolder mutableDebtModelHolder;
+
+  public LoadDebtModelStep(DbClient dbClient, MutableDebtModelHolder mutableDebtModelHolder) {
+    this.dbClient = dbClient;
+    this.mutableDebtModelHolder = mutableDebtModelHolder;
+  }
+
+  @Override
+  public void execute() {
+    DbSession session = dbClient.openSession(false);
+    try {
+      feedDebtModel(session);
+    } finally {
+      session.close();
+    }
+  }
+
+  private void feedDebtModel(DbSession session) {
+    List<CharacteristicDto> characteristicDtos = dbClient.debtCharacteristicDao().selectEnabledCharacteristics(session);
+    Map<Integer, CharacteristicDto> rootCharacteristicsById = from(characteristicDtos)
+      .filter(IsRootPredicate.INSTANCE)
+      .uniqueIndex(CharacteristicDtoToId.INSTANCE);
+
+    for (Map.Entry<Integer, Collection<CharacteristicDto>> entry : from(characteristicDtos)
+      .filter(not(IsRootPredicate.INSTANCE))
+      .index(CharacteristicDtoToParentId.INSTANCE)
+      .asMap().entrySet()) {
+      mutableDebtModelHolder.addCharacteristics(
+        toCharacteristic(rootCharacteristicsById.get(entry.getKey())),
+        from(entry.getValue()).transform(CharacteristicDtoToCharacteristic.INSTANCE)
+        );
+    }
+  }
+
+  private static Characteristic toCharacteristic(CharacteristicDto dto) {
+    return new CharacteristicImpl(dto.getId(), dto.getKey(), dto.getParentId());
+  }
+
+  private enum CharacteristicDtoToId implements Function<CharacteristicDto, Integer> {
+    INSTANCE;
+
+    @Nullable
+    @Override
+    public Integer apply(@Nonnull CharacteristicDto dto) {
+      return dto.getId();
+    }
+  }
+
+  private enum CharacteristicDtoToCharacteristic implements Function<CharacteristicDto, Characteristic> {
+    INSTANCE;
+
+    @Nullable
+    @Override
+    public Characteristic apply(@Nonnull CharacteristicDto characteristicDto) {
+      return toCharacteristic(characteristicDto);
+    }
+  }
+
+  private enum CharacteristicDtoToParentId implements Function<CharacteristicDto, Integer> {
+    INSTANCE;
+
+    @Nullable
+    @Override
+    public Integer apply(@Nonnull CharacteristicDto characteristicDto) {
+      Integer parentId = characteristicDto.getParentId();
+      return parentId == null ? characteristicDto.getId() : parentId;
+    }
+  }
+
+  private enum IsRootPredicate implements Predicate<CharacteristicDto> {
+    INSTANCE;
+
+    @Override
+    public boolean apply(@Nonnull CharacteristicDto characteristicDto) {
+      return characteristicDto.getParentId() == null;
+    }
+  }
+
+  @Override
+  public String getDescription() {
+    return "Load debt model";
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadMeasureComputersStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadMeasureComputersStep.java
new file mode 100644 (file)
index 0000000..dc176f6
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.computation.step;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.sonar.api.ce.measure.MeasureComputer;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.measures.Metrics;
+import org.sonar.api.utils.dag.DirectAcyclicGraph;
+import org.sonar.server.computation.measure.MutableMeasureComputersHolder;
+import org.sonar.server.computation.measure.api.MeasureComputerDefinitionImpl;
+import org.sonar.server.computation.measure.api.MeasureComputerWrapper;
+
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.FluentIterable.from;
+import static org.sonar.api.ce.measure.MeasureComputer.MeasureComputerDefinition;
+import static org.sonar.api.ce.measure.MeasureComputer.MeasureComputerDefinitionContext;
+
+public class LoadMeasureComputersStep implements ComputationStep {
+
+  private static final Set<String> CORE_METRIC_KEYS = from(CoreMetrics.getMetrics()).transform(MetricToKey.INSTANCE).toSet();
+  private Set<String> pluginMetricKeys;
+
+  private final MutableMeasureComputersHolder measureComputersHolder;
+  private final MeasureComputer[] measureComputers;
+
+  public LoadMeasureComputersStep(MutableMeasureComputersHolder measureComputersHolder, Metrics[] metricsRepositories, MeasureComputer[] measureComputers) {
+    this.measureComputersHolder = measureComputersHolder;
+    this.measureComputers = measureComputers;
+    this.pluginMetricKeys = from(Arrays.asList(metricsRepositories))
+      .transformAndConcat(MetricsToMetricList.INSTANCE)
+      .transform(MetricToKey.INSTANCE)
+      .toSet();
+  }
+
+  /**
+   * Constructor override used by Pico to instantiate the class when no plugin is defining metrics
+   */
+  public LoadMeasureComputersStep(MutableMeasureComputersHolder measureComputersHolder, MeasureComputer[] measureComputers) {
+    this(measureComputersHolder, new Metrics[] {}, measureComputers);
+  }
+
+  /**
+   * Constructor override used by Pico to instantiate the class when no plugin is defining measure computers
+   */
+  public LoadMeasureComputersStep(MutableMeasureComputersHolder measureComputersHolder, Metrics[] metricsRepositories) {
+    this(measureComputersHolder, metricsRepositories, new MeasureComputer[] {});
+  }
+
+  /**
+   * Constructor override used by Pico to instantiate the class when no plugin is defining metrics neither measure computers
+   */
+  public LoadMeasureComputersStep(MutableMeasureComputersHolder measureComputersHolder) {
+    this(measureComputersHolder, new Metrics[] {}, new MeasureComputer[] {});
+  }
+
+  @Override
+  public void execute() {
+    List<MeasureComputerWrapper> wrappers = from(Arrays.asList(measureComputers)).transform(ToMeasureWrapper.INSTANCE).toList();
+    validateMetrics(wrappers);
+    measureComputersHolder.setMeasureComputers(sortComputers(wrappers));
+  }
+
+  private static Iterable<MeasureComputerWrapper> sortComputers(List<MeasureComputerWrapper> wrappers) {
+    Map<String, MeasureComputerWrapper> computersByOutputMetric = new HashMap<>();
+    Map<String, MeasureComputerWrapper> computersByInputMetric = new HashMap<>();
+    feedComputersByMetric(wrappers, computersByOutputMetric, computersByInputMetric);
+    ToComputerByKey toComputerByOutputMetricKey = new ToComputerByKey(computersByOutputMetric);
+    ToComputerByKey toComputerByInputMetricKey = new ToComputerByKey(computersByInputMetric);
+
+    DirectAcyclicGraph dag = new DirectAcyclicGraph();
+    for (MeasureComputerWrapper computer : wrappers) {
+      dag.add(computer);
+      for (MeasureComputerWrapper dependency : getDependencies(computer, toComputerByOutputMetricKey)) {
+        dag.add(computer, dependency);
+      }
+      for (MeasureComputerWrapper generates : getDependents(computer, toComputerByInputMetricKey)) {
+        dag.add(generates, computer);
+      }
+    }
+    return dag.sort();
+  }
+
+  private static void feedComputersByMetric(List<MeasureComputerWrapper> wrappers, Map<String, MeasureComputerWrapper> computersByOutputMetric,
+                                            Map<String, MeasureComputerWrapper> computersByInputMetric) {
+    for (MeasureComputerWrapper computer : wrappers) {
+      for (String outputMetric : computer.getDefinition().getOutputMetrics()) {
+        computersByOutputMetric.put(outputMetric, computer);
+      }
+      for (String inputMetric : computer.getDefinition().getInputMetrics()) {
+        computersByInputMetric.put(inputMetric, computer);
+      }
+    }
+  }
+
+  private void validateMetrics(List<MeasureComputerWrapper> wrappers) {
+    from(wrappers).transformAndConcat(ToInputMetrics.INSTANCE).filter(new ValidateInputMetric()).size();
+    from(wrappers).transformAndConcat(ToOutputMetrics.INSTANCE).filter(new ValidateOutputMetric()).size();
+    from(wrappers).filter(new ValidateUniqueOutputMetric()).size();
+  }
+
+  private static Iterable<MeasureComputerWrapper> getDependencies(MeasureComputerWrapper measureComputer, ToComputerByKey toComputerByOutputMetricKey) {
+    // Remove null computer because a computer can depend on a metric that is only generated by a sensor or on a core metrics
+    return from(measureComputer.getDefinition().getInputMetrics()).transform(toComputerByOutputMetricKey).filter(Predicates.notNull());
+  }
+
+  private static Iterable<MeasureComputerWrapper> getDependents(MeasureComputerWrapper measureComputer, ToComputerByKey toComputerByInputMetricKey) {
+    return from(measureComputer.getDefinition().getInputMetrics()).transform(toComputerByInputMetricKey);
+  }
+
+  private static class ToComputerByKey implements Function<String, MeasureComputerWrapper> {
+    private final Map<String, MeasureComputerWrapper> computersByMetric;
+
+    private ToComputerByKey(Map<String, MeasureComputerWrapper> computersByMetric) {
+      this.computersByMetric = computersByMetric;
+    }
+
+    @Override
+    public MeasureComputerWrapper apply(@Nonnull String metricKey) {
+      return computersByMetric.get(metricKey);
+    }
+  }
+
+  private enum MetricToKey implements Function<Metric, String> {
+    INSTANCE;
+
+    @Nullable
+    @Override
+    public String apply(@Nonnull Metric input) {
+      return input.key();
+    }
+  }
+
+  private enum MetricsToMetricList implements Function<Metrics, List<Metric>> {
+    INSTANCE;
+
+    @Override
+    public List<Metric> apply(@Nonnull Metrics input) {
+      return input.getMetrics();
+    }
+  }
+
+  private enum ToMeasureWrapper implements Function<MeasureComputer, MeasureComputerWrapper> {
+    INSTANCE;
+
+    private final MeasureComputerDefinitionContextImpl context = new MeasureComputerDefinitionContextImpl();
+
+    @Override
+    public MeasureComputerWrapper apply(@Nonnull MeasureComputer measureComputer) {
+      MeasureComputerDefinition def = measureComputer.define(context);
+      return new MeasureComputerWrapper(measureComputer, validateDef(def));
+    }
+
+    private static MeasureComputerDefinition validateDef(MeasureComputerDefinition def) {
+      if (def instanceof MeasureComputerDefinitionImpl) {
+        return def;
+      }
+      // If the computer has not been created by the builder, we recreate it to make sure it's valid
+      Set<String> inputMetrics = def.getInputMetrics();
+      Set<String> outputMetrics = def.getOutputMetrics();
+      return new MeasureComputerDefinitionImpl.BuilderImpl()
+        .setInputMetrics(from(inputMetrics).toArray(String.class))
+        .setOutputMetrics(from(outputMetrics).toArray(String.class))
+        .build();
+    }
+  }
+
+  private enum ToInputMetrics implements Function<MeasureComputerWrapper, Collection<String>> {
+    INSTANCE;
+
+    @Override
+    public Collection<String> apply(@Nonnull MeasureComputerWrapper input) {
+      return input.getDefinition().getInputMetrics();
+    }
+  }
+
+  private class ValidateInputMetric implements Predicate<String> {
+    @Override
+    public boolean apply(@Nonnull String metric) {
+      checkState(pluginMetricKeys.contains(metric) || CORE_METRIC_KEYS.contains(metric),
+        String.format("Metric '%s' cannot be used as an input metric as it's not a core metric and no plugin declare this metric", metric));
+      return true;
+    }
+  }
+
+  private enum ToOutputMetrics implements Function<MeasureComputerWrapper, Collection<String>> {
+    INSTANCE;
+
+    @Override
+    public Collection<String> apply(@Nonnull MeasureComputerWrapper input) {
+      return input.getDefinition().getOutputMetrics();
+    }
+  }
+
+  private class ValidateOutputMetric implements Predicate<String> {
+    @Override
+    public boolean apply(@Nonnull String metric) {
+      checkState(!CORE_METRIC_KEYS.contains(metric), String.format("Metric '%s' cannot be used as an output metric as it's a core metric", metric));
+      checkState(pluginMetricKeys.contains(metric), String.format("Metric '%s' cannot be used as an output metric as no plugin declare this metric", metric));
+      return true;
+    }
+  }
+
+  private static class ValidateUniqueOutputMetric implements Predicate<MeasureComputerWrapper> {
+    private Set<String> allOutputMetrics = new HashSet<>();
+
+    @Override
+    public boolean apply(@Nonnull MeasureComputerWrapper wrapper ) {
+      for (String outputMetric : wrapper.getDefinition().getOutputMetrics()) {
+        checkState(!allOutputMetrics.contains(outputMetric),
+          String.format("Output metric '%s' is already defined by another measure computer '%s'", outputMetric, wrapper.getComputer()));
+        allOutputMetrics.add(outputMetric);
+      }
+      return true;
+    }
+  }
+
+  private static class MeasureComputerDefinitionContextImpl implements MeasureComputerDefinitionContext {
+    @Override
+    public MeasureComputerDefinition.Builder newDefinitionBuilder() {
+      return new MeasureComputerDefinitionImpl.BuilderImpl();
+    }
+  }
+
+  @Override
+  public String getDescription() {
+    return "Load measure computers";
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadPeriodsStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadPeriodsStep.java
new file mode 100644 (file)
index 0000000..cd2fe44
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.computation.step;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Strings;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.SnapshotDto;
+import org.sonar.db.component.SnapshotQuery;
+import org.sonar.server.computation.analysis.AnalysisMetadataHolder;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler;
+import org.sonar.server.computation.component.SettingsRepository;
+import org.sonar.server.computation.component.TreeRootHolder;
+import org.sonar.server.computation.component.TypeAwareVisitorAdapter;
+import org.sonar.server.computation.period.Period;
+import org.sonar.server.computation.period.PeriodsHolderImpl;
+
+import static org.sonar.db.component.SnapshotQuery.SORT_FIELD.BY_DATE;
+import static org.sonar.db.component.SnapshotQuery.SORT_ORDER.ASC;
+import static org.sonar.db.component.SnapshotQuery.SORT_ORDER.DESC;
+import static org.sonar.server.computation.component.Component.Type.PROJECT;
+import static org.sonar.server.computation.component.Component.Type.VIEW;
+import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;
+import static org.sonar.server.computation.component.CrawlerDepthLimit.reportMaxDepth;
+
+/**
+ * Populates the {@link org.sonar.server.computation.period.PeriodsHolder}
+ * <p/>
+ * Here is how these periods are computed :
+ * - Read the 5 period properties ${@link CoreProperties#TIMEMACHINE_PERIOD_PREFIX}
+ * - Try to find the matching snapshots from the properties
+ * - If a snapshot is found, a new period is added to the repository
+ */
+public class LoadPeriodsStep implements ComputationStep {
+
+  private static final Logger LOG = Loggers.get(LoadPeriodsStep.class);
+
+  private static final int NUMBER_OF_PERIODS = 5;
+
+  private final DbClient dbClient;
+  private final SettingsRepository settingsRepository;
+  private final TreeRootHolder treeRootHolder;
+  private final AnalysisMetadataHolder analysisMetadataHolder;
+  private final PeriodsHolderImpl periodsHolder;
+
+  public LoadPeriodsStep(DbClient dbClient, SettingsRepository settingsRepository, TreeRootHolder treeRootHolder, AnalysisMetadataHolder analysisMetadataHolder,
+    PeriodsHolderImpl periodsHolder) {
+    this.dbClient = dbClient;
+    this.settingsRepository = settingsRepository;
+    this.treeRootHolder = treeRootHolder;
+    this.analysisMetadataHolder = analysisMetadataHolder;
+    this.periodsHolder = periodsHolder;
+  }
+
+  @Override
+  public void execute() {
+    new DepthTraversalTypeAwareCrawler(
+      new TypeAwareVisitorAdapter(reportMaxDepth(PROJECT).withViewsMaxDepth(VIEW), PRE_ORDER) {
+        @Override
+        public void visitProject(Component project) {
+          execute(project);
+        }
+
+        @Override
+        public void visitView(Component view) {
+          execute(view);
+        }
+      }).visit(treeRootHolder.getRoot());
+  }
+
+  public void execute(Component projectOrView) {
+    DbSession session = dbClient.openSession(false);
+    try {
+      periodsHolder.setPeriods(buildPeriods(projectOrView, session));
+    } finally {
+      dbClient.closeSession(session);
+    }
+  }
+
+  private List<Period> buildPeriods(Component projectOrView, DbSession session) {
+    Optional<ComponentDto> projectDto = dbClient.componentDao().selectByKey(session, projectOrView.getKey());
+    // No project on first analysis, no period
+    if (!projectDto.isPresent()) {
+      return Collections.emptyList();
+    }
+
+    boolean isReportType = projectOrView.getType().isReportType();
+    PeriodResolver periodResolver = new PeriodResolver(session, projectDto.get().getId(), analysisMetadataHolder.getAnalysisDate().getTime(),
+      isReportType ? projectOrView.getReportAttributes().getVersion() : null,
+      isReportType ? Qualifiers.PROJECT : Qualifiers.VIEW);
+
+    Settings settings = settingsRepository.getSettings(projectOrView);
+    List<Period> periods = new ArrayList<>(5);
+    for (int index = 1; index <= NUMBER_OF_PERIODS; index++) {
+      Period period = periodResolver.resolve(index, settings);
+      // SONAR-4700 Add a past snapshot only if it exists
+      if (period != null) {
+        periods.add(period);
+      }
+    }
+    return periods;
+  }
+
+  private class PeriodResolver {
+
+    private final DbSession session;
+    private final long projectId;
+    private final long analysisDate;
+    @CheckForNull
+    private final String currentVersion;
+    private final String qualifier;
+
+    public PeriodResolver(DbSession session, long projectId, long analysisDate, @Nullable String currentVersion, String qualifier) {
+      this.session = session;
+      this.projectId = projectId;
+      this.analysisDate = analysisDate;
+      this.currentVersion = currentVersion;
+      this.qualifier = qualifier;
+    }
+
+    @CheckForNull
+    public Period resolve(int index, Settings settings) {
+      String propertyValue = getPropertyValue(qualifier, settings, index);
+      if (StringUtils.isBlank(propertyValue)) {
+        return null;
+      }
+      Period period = resolve(index, propertyValue);
+      if (period == null && StringUtils.isNotBlank(propertyValue)) {
+        LOG.debug("Property " + CoreProperties.TIMEMACHINE_PERIOD_PREFIX + index + " is not valid: " + propertyValue);
+      }
+      return period;
+    }
+
+    @CheckForNull
+    private Period resolve(int index, String property) {
+      Integer days = tryToResolveByDays(property);
+      if (days != null) {
+        return findByDays(index, days);
+      }
+      Date date = DateUtils.parseDateQuietly(property);
+      if (date != null) {
+        return findByDate(index, date);
+      }
+      if (StringUtils.equals(CoreProperties.TIMEMACHINE_MODE_PREVIOUS_ANALYSIS, property)) {
+        return findByPreviousAnalysis(index);
+      }
+      if (StringUtils.equals(CoreProperties.TIMEMACHINE_MODE_PREVIOUS_VERSION, property)) {
+        return findByPreviousVersion(index);
+      }
+      return findByVersion(index, property);
+    }
+
+    private Period findByDate(int index, Date date) {
+      SnapshotDto snapshot = findFirstSnapshot(session, createCommonQuery(projectId).setCreatedAfter(date.getTime()).setSort(BY_DATE, ASC));
+      if (snapshot == null) {
+        return null;
+      }
+      LOG.debug("Compare to date {} (analysis of {})", formatDate(date.getTime()), formatDate(snapshot.getCreatedAt()));
+      return new Period(index, CoreProperties.TIMEMACHINE_MODE_DATE, DateUtils.formatDate(date), snapshot.getCreatedAt(), snapshot.getId());
+    }
+
+    @CheckForNull
+    private Period findByDays(int index, int days) {
+      List<SnapshotDto> snapshots = dbClient.snapshotDao().selectSnapshotsByQuery(session, createCommonQuery(projectId).setCreatedBefore(analysisDate).setSort(BY_DATE, ASC));
+      long targetDate = DateUtils.addDays(new Date(analysisDate), -days).getTime();
+      SnapshotDto snapshot = findNearestSnapshotToTargetDate(snapshots, targetDate);
+      if (snapshot == null) {
+        return null;
+      }
+      LOG.debug("Compare over {} days ({}, analysis of {})", String.valueOf(days), formatDate(targetDate), formatDate(snapshot.getCreatedAt()));
+      return new Period(index, CoreProperties.TIMEMACHINE_MODE_DAYS, String.valueOf(days), snapshot.getCreatedAt(), snapshot.getId());
+    }
+
+    @CheckForNull
+    private Period findByPreviousAnalysis(int index) {
+      SnapshotDto snapshot = findFirstSnapshot(session, createCommonQuery(projectId).setCreatedBefore(analysisDate).setIsLast(true).setSort(BY_DATE, DESC));
+      if (snapshot == null) {
+        return null;
+      }
+      LOG.debug("Compare to previous analysis ({})", formatDate(snapshot.getCreatedAt()));
+      return new Period(index, CoreProperties.TIMEMACHINE_MODE_PREVIOUS_ANALYSIS, formatDate(snapshot.getCreatedAt()), snapshot.getCreatedAt(), snapshot.getId());
+    }
+
+    @CheckForNull
+    private Period findByPreviousVersion(int index) {
+      if (currentVersion == null) {
+        return null;
+      }
+      List<SnapshotDto> snapshotDtos = dbClient.snapshotDao().selectPreviousVersionSnapshots(session, projectId, currentVersion);
+      if (snapshotDtos.isEmpty()) {
+        return null;
+      }
+      SnapshotDto snapshotDto = snapshotDtos.get(0);
+      LOG.debug("Compare to previous version ({})", formatDate(snapshotDto.getCreatedAt()));
+      return new Period(index, CoreProperties.TIMEMACHINE_MODE_PREVIOUS_VERSION, snapshotDto.getVersion(), snapshotDto.getCreatedAt(), snapshotDto.getId());
+    }
+
+    @CheckForNull
+    private Period findByVersion(int index, String version) {
+      SnapshotDto snapshot = findFirstSnapshot(session, createCommonQuery(projectId).setVersion(version).setSort(BY_DATE, DESC));
+      if (snapshot == null) {
+        return null;
+      }
+      LOG.debug("Compare to version ({}) ({})", version, formatDate(snapshot.getCreatedAt()));
+      return new Period(index, CoreProperties.TIMEMACHINE_MODE_VERSION, version, snapshot.getCreatedAt(), snapshot.getId());
+    }
+
+    @CheckForNull
+    private SnapshotDto findFirstSnapshot(DbSession session, SnapshotQuery query) {
+      List<SnapshotDto> snapshots = dbClient.snapshotDao().selectSnapshotsByQuery(session, query);
+      if (!snapshots.isEmpty()) {
+        return snapshots.get(0);
+      }
+      return null;
+    }
+  }
+
+  @CheckForNull
+  private static Integer tryToResolveByDays(String property) {
+    try {
+      return Integer.parseInt(property);
+    } catch (NumberFormatException e) {
+      // Nothing to, it means that the property is not a number of days
+      return null;
+    }
+  }
+
+  @CheckForNull
+  private static SnapshotDto findNearestSnapshotToTargetDate(List<SnapshotDto> snapshots, Long targetDate) {
+    long bestDistance = Long.MAX_VALUE;
+    SnapshotDto nearest = null;
+    for (SnapshotDto snapshot : snapshots) {
+      long distance = Math.abs(snapshot.getCreatedAt() - targetDate);
+      if (distance <= bestDistance) {
+        bestDistance = distance;
+        nearest = snapshot;
+      }
+    }
+    return nearest;
+  }
+
+  private static SnapshotQuery createCommonQuery(Long projectId) {
+    return new SnapshotQuery().setComponentId(projectId).setStatus(SnapshotDto.STATUS_PROCESSED);
+  }
+
+  private static String formatDate(long date) {
+    return DateUtils.formatDate(org.apache.commons.lang.time.DateUtils.truncate(new Date(date), Calendar.SECOND));
+  }
+
+  private static String getPropertyValue(@Nullable String qualifier, Settings settings, int index) {
+    String value = settings.getString(CoreProperties.TIMEMACHINE_PERIOD_PREFIX + index);
+    // For periods 4 and 5 we're also searching for a property prefixed by the qualifier
+    if (index > 3 && Strings.isNullOrEmpty(value)) {
+      value = settings.getString(CoreProperties.TIMEMACHINE_PERIOD_PREFIX + index + "." + qualifier);
+    }
+    return value;
+  }
+
+  @Override
+  public String getDescription() {
+    return "Load differential periods";
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadQualityGateStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadQualityGateStep.java
new file mode 100644 (file)
index 0000000..265e805
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.computation.step;
+
+import com.google.common.base.Optional;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.config.Settings;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.CrawlerDepthLimit;
+import org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler;
+import org.sonar.server.computation.component.SettingsRepository;
+import org.sonar.server.computation.component.TreeRootHolder;
+import org.sonar.server.computation.component.TypeAwareVisitorAdapter;
+import org.sonar.server.computation.qualitygate.MutableQualityGateHolder;
+import org.sonar.server.computation.qualitygate.QualityGate;
+import org.sonar.server.computation.qualitygate.QualityGateService;
+
+import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;
+
+/**
+ * This step retrieves the QualityGate and stores it in
+ * {@link MutableQualityGateHolder}.
+ */
+public class LoadQualityGateStep implements ComputationStep {
+  private static final Logger LOGGER = Loggers.get(LoadQualityGateStep.class);
+
+  private static final String PROPERTY_QUALITY_GATE = "sonar.qualitygate";
+
+  private final TreeRootHolder treeRootHolder;
+  private final SettingsRepository settingsRepository;
+  private final QualityGateService qualityGateService;
+  private final MutableQualityGateHolder qualityGateHolder;
+
+  public LoadQualityGateStep(TreeRootHolder treeRootHolder, SettingsRepository settingsRepository,
+                             QualityGateService qualityGateService, MutableQualityGateHolder qualityGateHolder) {
+    this.treeRootHolder = treeRootHolder;
+    this.settingsRepository = settingsRepository;
+    this.qualityGateService = qualityGateService;
+    this.qualityGateHolder = qualityGateHolder;
+  }
+
+  @Override
+  public void execute() {
+    new DepthTraversalTypeAwareCrawler(
+      new TypeAwareVisitorAdapter(CrawlerDepthLimit.PROJECT, PRE_ORDER) {
+        @Override
+        public void visitProject(Component project) {
+          executeForProject(project);
+        }
+      }).visit(treeRootHolder.getRoot());
+  }
+
+  private void executeForProject(Component project) {
+    String projectKey = project.getKey();
+    Settings settings = settingsRepository.getSettings(project);
+    String qualityGateSetting = settings.getString(PROPERTY_QUALITY_GATE);
+
+    if (qualityGateSetting == null || StringUtils.isBlank(qualityGateSetting)) {
+      LOGGER.debug("No quality gate is configured for project " + projectKey);
+      qualityGateHolder.setNoQualityGate();
+      return;
+    }
+
+    try {
+      long qualityGateId = Long.parseLong(qualityGateSetting);
+      Optional<QualityGate> qualityGate = qualityGateService.findById(qualityGateId);
+      if (qualityGate.isPresent()) {
+        qualityGateHolder.setQualityGate(qualityGate.get());
+      } else {
+        qualityGateHolder.setNoQualityGate();
+      }
+    } catch (NumberFormatException e) {
+      throw new IllegalStateException(
+        String.format("Unsupported value (%s) in property %s", qualityGateSetting, PROPERTY_QUALITY_GATE),
+        e);
+    }
+  }
+
+  @Override
+  public String getDescription() {
+    return "Load Quality gate";
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadQualityProfilesStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadQualityProfilesStep.java
new file mode 100644 (file)
index 0000000..bf19a62
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.computation.step;
+
+import com.google.common.base.Predicate;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Nonnull;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.core.util.CloseableIterator;
+import org.sonar.server.computation.batch.BatchReportReader;
+import org.sonar.server.computation.issue.Rule;
+import org.sonar.server.computation.issue.RuleRepository;
+import org.sonar.server.computation.qualityprofile.ActiveRule;
+import org.sonar.server.computation.qualityprofile.ActiveRulesHolderImpl;
+
+import static com.google.common.collect.FluentIterable.from;
+
+public class LoadQualityProfilesStep implements ComputationStep {
+
+  private final BatchReportReader batchReportReader;
+  private final ActiveRulesHolderImpl activeRulesHolder;
+  private final RuleRepository ruleRepository;
+
+  public LoadQualityProfilesStep(BatchReportReader batchReportReader, ActiveRulesHolderImpl activeRulesHolder, RuleRepository ruleRepository) {
+    this.batchReportReader = batchReportReader;
+    this.activeRulesHolder = activeRulesHolder;
+    this.ruleRepository = ruleRepository;
+  }
+
+  @Override
+  public void execute() {
+    List<ActiveRule> activeRules = new ArrayList<>();
+    try (CloseableIterator<BatchReport.ActiveRule> batchActiveRules = batchReportReader.readActiveRules()) {
+      while (batchActiveRules.hasNext()) {
+        BatchReport.ActiveRule batchActiveRule = batchActiveRules.next();
+        activeRules.add(convert(batchActiveRule));
+      }
+    }
+
+    List<ActiveRule> validActiveRules = from(activeRules).filter(new IsValid()).toList();
+    activeRulesHolder.set(validActiveRules);
+  }
+
+  private class IsValid implements Predicate<ActiveRule> {
+    @Override
+    public boolean apply(@Nonnull ActiveRule input) {
+      if (ruleRepository.hasKey(input.getRuleKey())) {
+        Rule rule = ruleRepository.getByKey(input.getRuleKey());
+        return rule.getStatus() != RuleStatus.REMOVED;
+      }
+      return false;
+    }
+  }
+
+  @Override
+  public String getDescription() {
+    return "Load quality profiles";
+  }
+
+  private static ActiveRule convert(BatchReport.ActiveRule input) {
+    RuleKey key = RuleKey.of(input.getRuleRepository(), input.getRuleKey());
+    Map<String, String> params = new HashMap<>();
+    for (BatchReport.ActiveRule.ActiveRuleParam inputParam : input.getParamList()) {
+      params.put(inputParam.getKey(), inputParam.getValue());
+    }
+    return new ActiveRule(key, input.getSeverity().name(), params);
+  }
+}
index eee963c6af00b8db25efe54902a55347f07e8d17..d3da00d000c31da8a6fc774043134373160165ba 100644 (file)
@@ -123,7 +123,7 @@ public class NewCoverageMeasuresStep implements ComputationStep {
 
   @Override
   public String getDescription() {
-    return "Computation of New Coverage measures";
+    return "Compute new coverage";
   }
 
   private static class NewLinesAndConditionsCoverageFormula extends NewLinesAndConditionsFormula {
index ed09fb80b120f14c6f2578250baac8675afac17b..4dd6a24f7d737b4ff590a4bf5191c312c993eaab 100644 (file)
@@ -133,7 +133,7 @@ public class PersistEventsStep implements ComputationStep {
 
   @Override
   public String getDescription() {
-    return "Persist component links";
+    return "Persist events";
   }
 
   private class PersistEventComponentVisitor extends TypeAwareVisitorAdapter {
index 9625d2ea8bd1c082e69ce32203321f75aefc9522..305a19690681d47c6aeaa9dafe9d7c91eeb4dd54 100644 (file)
@@ -205,6 +205,6 @@ public class PersistFileSourcesStep implements ComputationStep {
 
   @Override
   public String getDescription() {
-    return "Persist file sources";
+    return "Persist sources";
   }
 }
index 0583017085dd28f8f0897df5dea2ffa6a1e1a698..b9bc585dc82790fe1066a6dcb22f31404b8772b6 100644 (file)
@@ -158,6 +158,6 @@ public class PersistProjectLinksStep implements ComputationStep {
 
   @Override
   public String getDescription() {
-    return "Persist component links";
+    return "Persist project links";
   }
 }
index 99f259c1c6eaab316067ce262b4a7824ffa6f6ed..9cd2a478cdebe2f161fd7e5cc59fe4258d4a0f76 100644 (file)
@@ -81,6 +81,6 @@ public class PurgeDatastoresStep implements ComputationStep {
 
   @Override
   public String getDescription() {
-    return "Purge datastores";
+    return "Purge db";
   }
 }
index b1f1851ff575377cb84d595d7eba8f4443513b68..eae85fb71c9f0856c7f1b1d68a018073b804cf62 100644 (file)
@@ -137,6 +137,6 @@ public class QualityGateEventsStep implements ComputationStep {
 
   @Override
   public String getDescription() {
-    return "Generate Quality Gate Events";
+    return "Generate Quality gate events";
   }
 }
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityGateLoadingStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityGateLoadingStep.java
deleted file mode 100644 (file)
index 49a0636..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.computation.step;
-
-import com.google.common.base.Optional;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.config.Settings;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.component.CrawlerDepthLimit;
-import org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler;
-import org.sonar.server.computation.component.SettingsRepository;
-import org.sonar.server.computation.component.TreeRootHolder;
-import org.sonar.server.computation.component.TypeAwareVisitorAdapter;
-import org.sonar.server.computation.qualitygate.MutableQualityGateHolder;
-import org.sonar.server.computation.qualitygate.QualityGate;
-import org.sonar.server.computation.qualitygate.QualityGateService;
-
-import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;
-
-/**
- * This step retrieves the QualityGate and stores it in
- * {@link MutableQualityGateHolder}.
- */
-public class QualityGateLoadingStep implements ComputationStep {
-  private static final Logger LOGGER = Loggers.get(QualityGateLoadingStep.class);
-
-  private static final String PROPERTY_QUALITY_GATE = "sonar.qualitygate";
-
-  private final TreeRootHolder treeRootHolder;
-  private final SettingsRepository settingsRepository;
-  private final QualityGateService qualityGateService;
-  private final MutableQualityGateHolder qualityGateHolder;
-
-  public QualityGateLoadingStep(TreeRootHolder treeRootHolder, SettingsRepository settingsRepository,
-    QualityGateService qualityGateService, MutableQualityGateHolder qualityGateHolder) {
-    this.treeRootHolder = treeRootHolder;
-    this.settingsRepository = settingsRepository;
-    this.qualityGateService = qualityGateService;
-    this.qualityGateHolder = qualityGateHolder;
-  }
-
-  @Override
-  public void execute() {
-    new DepthTraversalTypeAwareCrawler(
-      new TypeAwareVisitorAdapter(CrawlerDepthLimit.PROJECT, PRE_ORDER) {
-        @Override
-        public void visitProject(Component project) {
-          executeForProject(project);
-        }
-      }).visit(treeRootHolder.getRoot());
-  }
-
-  private void executeForProject(Component project) {
-    String projectKey = project.getKey();
-    Settings settings = settingsRepository.getSettings(project);
-    String qualityGateSetting = settings.getString(PROPERTY_QUALITY_GATE);
-
-    if (qualityGateSetting == null || StringUtils.isBlank(qualityGateSetting)) {
-      LOGGER.debug("No quality gate is configured for project " + projectKey);
-      qualityGateHolder.setNoQualityGate();
-      return;
-    }
-
-    try {
-      long qualityGateId = Long.parseLong(qualityGateSetting);
-      Optional<QualityGate> qualityGate = qualityGateService.findById(qualityGateId);
-      if (qualityGate.isPresent()) {
-        qualityGateHolder.setQualityGate(qualityGate.get());
-      } else {
-        qualityGateHolder.setNoQualityGate();
-      }
-    } catch (NumberFormatException e) {
-      throw new IllegalStateException(
-        String.format("Unsupported value (%s) in property %s", qualityGateSetting, PROPERTY_QUALITY_GATE),
-        e);
-    }
-  }
-
-  @Override
-  public String getDescription() {
-    return "Retrieve Quality Gate";
-  }
-}
index 28cc46d63dc45b2c2d0fe56ed754f84422d81cfc..730a8ebd7ab653c0a68e790a71b763c388210a88 100644 (file)
@@ -56,7 +56,7 @@ import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_
  * {@link CoreMetrics#ALERT_STATUS_KEY}</li>
  * </ul>
  *
- * It must be executed after the computation of differential measures {@link FillMeasuresWithVariationsStep}
+ * It must be executed after the computation of differential measures {@link ComputeMeasureVariationsStep}
  */
 public class QualityGateMeasuresStep implements ComputationStep {
 
index 452d418b521034a9ab213d91d0e355f06d3d8bd0..6a8bd53a219e0bf50e04bcc192bc031cdb50f869 100644 (file)
@@ -166,6 +166,6 @@ public class QualityProfileEventsStep implements ComputationStep {
 
   @Override
   public String getDescription() {
-    return "Compute Quality Profile events";
+    return "Generate Quality profile events";
   }
 }
index 57eaba6ac64aef695ba73682850b25c05cecca56..ea8e690ec1bc71b2cec3c41b5664b22b46f4f067 100644 (file)
@@ -23,6 +23,7 @@ import com.google.common.base.Function;
 import com.google.common.collect.Iterables;
 import java.util.Arrays;
 import java.util.List;
+import javax.annotation.Nonnull;
 import org.sonar.server.computation.container.ComputeEngineContainer;
 
 /**
@@ -38,19 +39,19 @@ public class ReportComputationSteps implements ComputationSteps {
   public List<Class<? extends ComputationStep>> orderedStepClasses() {
     return Arrays.asList(
       // extract report to a temp directory
-      ReportExtractionStep.class,
+      ExtractReportStep.class,
 
       // Builds Component tree
       BuildComponentTreeStep.class,
       FillComponentsStep.class,
       ValidateProjectStep.class,
 
-      FeedDebtModelStep.class,
-      FeedActiveRulesStep.class,
+      LoadDebtModelStep.class,
+      LoadQualityProfilesStep.class,
 
       // load project related stuffs
-      QualityGateLoadingStep.class,
-      FeedPeriodsStep.class,
+      LoadQualityGateStep.class,
+      LoadPeriodsStep.class,
 
       // data computation
       SizeMeasuresStep.class,
@@ -63,11 +64,11 @@ public class ReportComputationSteps implements ComputationSteps {
       UnitTestMeasuresStep.class,
       ComplexityMeasuresStep.class,
 
-      FeedMeasureComputers.class,
+      LoadMeasureComputersStep.class,
       ExecuteVisitorsStep.class,
 
       // Must be executed after computation of all measures
-      FillMeasuresWithVariationsStep.class,
+      ComputeMeasureVariationsStep.class,
 
       // Must be executed after computation of differential measures
       QualityGateMeasuresStep.class,
@@ -113,7 +114,7 @@ public class ReportComputationSteps implements ComputationSteps {
   public Iterable<ComputationStep> instances() {
     return Iterables.transform(orderedStepClasses(), new Function<Class<? extends ComputationStep>, ComputationStep>() {
       @Override
-      public ComputationStep apply(Class<? extends ComputationStep> input) {
+      public ComputationStep apply(@Nonnull Class<? extends ComputationStep> input) {
         ComputationStep computationStepType = computeEngineContainer.getComponentByType(input);
         if (computationStepType == null) {
           throw new IllegalStateException(String.format("Component not found: %s", input));
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ReportExtractionStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ReportExtractionStep.java
deleted file mode 100644 (file)
index 77a5971..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.computation.step;
-
-import java.io.File;
-import java.io.IOException;
-import org.apache.commons.io.FileUtils;
-import org.sonar.api.utils.TempFolder;
-import org.sonar.api.utils.ZipUtils;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.server.computation.CeTask;
-import org.sonar.server.computation.ReportFiles;
-import org.sonar.server.computation.batch.MutableBatchReportDirectoryHolder;
-
-/**
- * Extracts the content zip file of the {@link org.sonar.server.computation.CeTask} to a temp directory and adds a {@link File}
- * representing that temp directory to the {@link MutableBatchReportDirectoryHolder}.
- */
-public class ReportExtractionStep implements ComputationStep {
-  private static final Logger LOG = Loggers.get(ReportExtractionStep.class);
-
-  private final ReportFiles reportFiles;
-  private final CeTask task;
-  private final TempFolder tempFolder;
-  private final MutableBatchReportDirectoryHolder reportDirectoryHolder;
-
-  public ReportExtractionStep(ReportFiles reportFiles, CeTask task, TempFolder tempFolder,
-    MutableBatchReportDirectoryHolder reportDirectoryHolder) {
-    this.reportFiles = reportFiles;
-    this.task = task;
-    this.tempFolder = tempFolder;
-    this.reportDirectoryHolder = reportDirectoryHolder;
-  }
-
-  @Override
-  public void execute() {
-    File dir = tempFolder.newDir();
-    File zip = reportFiles.fileForUuid(task.getUuid());
-    try {
-      ZipUtils.unzip(zip, dir);
-      reportDirectoryHolder.setDirectory(dir);
-      LOG.info("Analysis report extracted | size={} | compressed={}",
-        FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(dir)), FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(zip)));
-    } catch (IOException e) {
-      throw new IllegalStateException(String.format("Fail to unzip %s into %s", zip, dir), e);
-    }
-  }
-
-  @Override
-  public String getDescription() {
-    return "Uncompress report";
-  }
-
-}
index ebdf6b09058b9635225c527eeca5efbc1691268b..d153893f306e380bb2833cbf8319f5e51a061386 100644 (file)
@@ -86,7 +86,7 @@ public class SizeMeasuresStep implements ComputationStep {
 
   @Override
   public String getDescription() {
-    return "File and Directory measures";
+    return "Compute size measures";
   }
 
   private class FileAndDirectoryMeasureVisitor extends PathAwareVisitorAdapter<Counter> {
index 8a566bcee38db1ca11d5c734e1ef16eb35640303..067ae344bd2262527ce2fa9a00f62a64c35ae880 100644 (file)
 package org.sonar.server.computation.step;
 
 import java.util.List;
-import org.sonar.db.component.SnapshotDto;
+import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.MyBatis;
 import org.sonar.db.component.SnapshotDao;
+import org.sonar.db.component.SnapshotDto;
 import org.sonar.server.computation.component.Component;
 import org.sonar.server.computation.component.DbIdsRepository;
 import org.sonar.server.computation.component.TreeRootHolder;
-import org.sonar.db.DbClient;
 
 import static org.sonar.db.component.SnapshotDao.isLast;
 
@@ -59,7 +59,7 @@ public class SwitchSnapshotStep implements ComputationStep {
 
   @Override
   public String getDescription() {
-    return "Switch last snapshot flag";
+    return "Enable snapshot";
   }
 
   private void disablePreviousSnapshot(DbSession session, long reportSnapshotId) {
index f49d64297821e5377bebe4f954f0e097dbc10264..61a87ac128353b177d62d731f8516e067277e51d 100644 (file)
@@ -27,10 +27,10 @@ import org.sonar.server.computation.component.CrawlerDepthLimit;
 import org.sonar.server.computation.component.PathAwareCrawler;
 import org.sonar.server.computation.component.TreeRootHolder;
 import org.sonar.server.computation.formula.Counter;
+import org.sonar.server.computation.formula.CounterInitializationContext;
 import org.sonar.server.computation.formula.CreateMeasureContext;
 import org.sonar.server.computation.formula.Formula;
 import org.sonar.server.computation.formula.FormulaExecutorComponentVisitor;
-import org.sonar.server.computation.formula.CounterInitializationContext;
 import org.sonar.server.computation.formula.counter.IntSumCounter;
 import org.sonar.server.computation.measure.Measure;
 import org.sonar.server.computation.measure.MeasureRepository;
@@ -151,6 +151,6 @@ public class UnitTestMeasuresStep implements ComputationStep {
 
   @Override
   public String getDescription() {
-    return "Aggregation of comment measures";
+    return "Compute test measures";
   }
 }
index 5e06c59522e67ccadfe4f6747696837e7ae3c2b4..7177a62e46ea166333122a1970569a811ddddf50 100644 (file)
@@ -28,7 +28,6 @@ import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import javax.annotation.CheckForNull;
-import org.sonar.api.config.Settings;
 import org.sonar.api.utils.MessageException;
 import org.sonar.batch.protocol.output.BatchReport;
 import org.sonar.core.component.ComponentKeys;
@@ -63,13 +62,11 @@ public class ValidateProjectStep implements ComputationStep {
   private static final Joiner MESSAGES_JOINER = Joiner.on("\n  o ");
 
   private final DbClient dbClient;
-  private final Settings settings;
   private final BatchReportReader reportReader;
   private final TreeRootHolder treeRootHolder;
 
-  public ValidateProjectStep(DbClient dbClient, Settings settings, BatchReportReader reportReader, TreeRootHolder treeRootHolder) {
+  public ValidateProjectStep(DbClient dbClient, BatchReportReader reportReader, TreeRootHolder treeRootHolder) {
     this.dbClient = dbClient;
-    this.settings = settings;
     this.reportReader = reportReader;
     this.treeRootHolder = treeRootHolder;
   }
@@ -88,13 +85,13 @@ public class ValidateProjectStep implements ComputationStep {
         throw MessageException.of("Validation of project failed:\n  o " + MESSAGES_JOINER.join(visitor.validationMessages));
       }
     } finally {
-      session.close();
+      dbClient.closeSession(session);
     }
   }
 
   @Override
   public String getDescription() {
-    return "Validate project and modules keys";
+    return "Validate project";
   }
 
   private class ValidateProjectsVisitor extends TypeAwareVisitorAdapter {
@@ -130,7 +127,7 @@ public class ValidateProjectStep implements ComputationStep {
         // Project key is already used as a module of another project
         ComponentDto anotherBaseProject = componentDao.selectOrFailByUuid(session, baseProject.get().projectUuid());
         validationMessages.add(String.format("The project \"%s\" is already defined in SonarQube but as a module of project \"%s\". "
-            + "If you really want to stop directly analysing project \"%s\", please first delete it from SonarQube and then relaunch the analysis of project \"%s\".",
+          + "If you really want to stop directly analysing project \"%s\", please first delete it from SonarQube and then relaunch the analysis of project \"%s\".",
           rawProjectKey, anotherBaseProject.key(), anotherBaseProject.key(), rawProjectKey));
       }
     }
@@ -142,7 +139,7 @@ public class ValidateProjectStep implements ComputationStep {
         Long lastAnalysisDate = snapshotDto != null ? snapshotDto.getCreatedAt() : null;
         if (lastAnalysisDate != null && currentAnalysisDate <= snapshotDto.getCreatedAt()) {
           validationMessages.add(String.format("Date of analysis cannot be older than the date of the last known analysis on this project. Value: \"%s\". " +
-              "Latest analysis: \"%s\". It's only possible to rebuild the past in a chronological order.",
+            "Latest analysis: \"%s\". It's only possible to rebuild the past in a chronological order.",
             formatDateTime(new Date(currentAnalysisDate)), formatDateTime(new Date(lastAnalysisDate))));
         }
       }
@@ -166,7 +163,7 @@ public class ValidateProjectStep implements ComputationStep {
       if (baseModule.projectUuid().equals(baseModule.uuid())) {
         // module is actually a project
         validationMessages.add(String.format("The project \"%s\" is already defined in SonarQube but not as a module of project \"%s\". "
-            + "If you really want to stop directly analysing project \"%s\", please first delete it from SonarQube and then relaunch the analysis of project \"%s\".",
+          + "If you really want to stop directly analysing project \"%s\", please first delete it from SonarQube and then relaunch the analysis of project \"%s\".",
           rawModuleKey, rawProjectKey, rawModuleKey, rawProjectKey));
       }
     }
index d45bc634ad516a29253cd06e2d5dea1ee56def81..97cffa83c23b4fd8a1708269f15af070974cf25d 100644 (file)
@@ -24,7 +24,6 @@ import javax.annotation.Nullable;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.internal.TempFolderCleaner;
 import org.sonar.core.config.CorePropertyDefinitions;
-import org.sonar.core.config.Logback;
 import org.sonar.core.util.UuidFactoryImpl;
 import org.sonar.db.DaoModule;
 import org.sonar.db.DatabaseChecker;
@@ -74,7 +73,6 @@ public class PlatformLevel1 extends PlatformLevel {
     add(
       ServerSettings.class,
       ServerImpl.class,
-      Logback.class,
       UuidFactoryImpl.INSTANCE,
       EmbeddedDatabaseFactory.class,
       DefaultDatabase.class,
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/FeedActiveRulesStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/FeedActiveRulesStepTest.java
deleted file mode 100644 (file)
index 4003d77..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.computation.step;
-
-import com.google.common.base.Optional;
-import org.assertj.core.data.MapEntry;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.rule.RuleStatus;
-import org.sonar.api.rule.Severity;
-import org.sonar.batch.protocol.Constants;
-import org.sonar.batch.protocol.output.BatchReport;
-import org.sonar.server.computation.batch.BatchReportReaderRule;
-import org.sonar.server.computation.issue.DumbRule;
-import org.sonar.server.computation.issue.RuleRepositoryRule;
-import org.sonar.server.computation.qualityprofile.ActiveRule;
-import org.sonar.server.computation.qualityprofile.ActiveRulesHolderImpl;
-
-import static java.util.Arrays.asList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.db.rule.RuleTesting.XOO_X1;
-import static org.sonar.db.rule.RuleTesting.XOO_X2;
-
-public class FeedActiveRulesStepTest {
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  @Rule
-  public BatchReportReaderRule batchReportReader = new BatchReportReaderRule();
-
-  @Rule
-  public RuleRepositoryRule ruleRepository = new RuleRepositoryRule();
-
-  ActiveRulesHolderImpl activeRulesHolder = new ActiveRulesHolderImpl();
-  FeedActiveRulesStep underTest = new FeedActiveRulesStep(batchReportReader, activeRulesHolder, ruleRepository);
-
-  @Test
-  public void feed_active_rules() throws Exception {
-    ruleRepository.add(XOO_X1);
-    ruleRepository.add(XOO_X2);
-
-    BatchReport.ActiveRule.Builder batch1 = BatchReport.ActiveRule.newBuilder()
-      .setRuleRepository(XOO_X1.repository()).setRuleKey(XOO_X1.rule())
-      .setSeverity(Constants.Severity.BLOCKER);
-    batch1.addParamBuilder().setKey("p1").setValue("v1").build();
-
-    BatchReport.ActiveRule.Builder batch2 = BatchReport.ActiveRule.newBuilder()
-      .setRuleRepository(XOO_X2.repository()).setRuleKey(XOO_X2.rule()).setSeverity(Constants.Severity.MAJOR);
-    batchReportReader.putActiveRules(asList(batch1.build(), batch2.build()));
-
-    underTest.execute();
-
-    assertThat(activeRulesHolder.getAll()).hasSize(2);
-
-    Optional<ActiveRule> ar1 = activeRulesHolder.get(XOO_X1);
-    assertThat(ar1.get().getSeverity()).isEqualTo(Severity.BLOCKER);
-    assertThat(ar1.get().getParams()).containsExactly(MapEntry.entry("p1", "v1"));
-
-    Optional<ActiveRule> ar2 = activeRulesHolder.get(XOO_X2);
-    assertThat(ar2.get().getSeverity()).isEqualTo(Severity.MAJOR);
-    assertThat(ar2.get().getParams()).isEmpty();
-  }
-
-  @Test
-  public void ignore_rules_with_status_REMOVED() throws Exception {
-    ruleRepository.add(new DumbRule(XOO_X1).setStatus(RuleStatus.REMOVED));
-
-    BatchReport.ActiveRule.Builder batch1 = BatchReport.ActiveRule.newBuilder()
-      .setRuleRepository(XOO_X1.repository()).setRuleKey(XOO_X1.rule())
-      .setSeverity(Constants.Severity.BLOCKER);
-    batchReportReader.putActiveRules(asList(batch1.build()));
-
-    underTest.execute();
-
-    assertThat(activeRulesHolder.getAll()).isEmpty();
-  }
-
-  @Test
-  public void ignore_not_found_rules() throws Exception {
-    BatchReport.ActiveRule.Builder batch1 = BatchReport.ActiveRule.newBuilder()
-      .setRuleRepository(XOO_X1.repository()).setRuleKey(XOO_X1.rule())
-      .setSeverity(Constants.Severity.BLOCKER);
-    batchReportReader.putActiveRules(asList(batch1.build()));
-
-    underTest.execute();
-
-    assertThat(activeRulesHolder.getAll()).isEmpty();
-  }
-}
index b6b09740edf3d6b6c59f5e37249284a1f0a157b3..605337f911b3550edabb54806c39233258ef538a 100644 (file)
@@ -48,14 +48,14 @@ public class FeedDebtModelStepTest extends BaseStepTest {
 
   MutableDebtModelHolder debtModelHolder = new DebtModelHolderImpl();
 
-  FeedDebtModelStep underTest;
+  LoadDebtModelStep underTest;
 
   @Before
   public void setUp() {
     dbTester.truncateTables();
     dbSession = dbClient.openSession(false);
 
-    underTest = new FeedDebtModelStep(dbClient, debtModelHolder);
+    underTest = new LoadDebtModelStep(dbClient, debtModelHolder);
   }
 
   @After
index b8eac165d797f9b55ff98c3e181cfad943137a08..b5824d978bb67551ff8b9b6e68f2d045f9363bf1 100644 (file)
@@ -59,7 +59,7 @@ public class FeedMeasureComputersTest {
   @Test
   public void support_core_metrics_as_input_metrics() throws Exception {
     MeasureComputer[] computers = new MeasureComputer[] {newMeasureComputer(array(NCLOC_KEY), array(NEW_METRIC_1))};
-    ComputationStep underTest = new FeedMeasureComputers(holder, array(new TestMetrics()), computers);
+    ComputationStep underTest = new LoadMeasureComputersStep(holder, array(new TestMetrics()), computers);
     underTest.execute();
 
     assertThat(holder.getMeasureComputers()).hasSize(1);
@@ -68,7 +68,7 @@ public class FeedMeasureComputersTest {
   @Test
   public void support_plugin_metrics_as_input_metrics() throws Exception {
     MeasureComputer[] computers = new MeasureComputer[] {newMeasureComputer(array(NEW_METRIC_1), array(NEW_METRIC_2))};
-    ComputationStep underTest = new FeedMeasureComputers(holder, array(new TestMetrics()), computers);
+    ComputationStep underTest = new LoadMeasureComputersStep(holder, array(new TestMetrics()), computers);
     underTest.execute();
 
     assertThat(holder.getMeasureComputers()).hasSize(1);
@@ -84,7 +84,7 @@ public class FeedMeasureComputersTest {
     MeasureComputer measureComputer3 = newMeasureComputer(array(NEW_METRIC_2), array(NEW_METRIC_3));
     MeasureComputer[] computers = new MeasureComputer[] {measureComputer1, measureComputer2, measureComputer3};
 
-    ComputationStep underTest = new FeedMeasureComputers(holder, array(new TestMetrics()), computers);
+    ComputationStep underTest = new LoadMeasureComputersStep(holder, array(new TestMetrics()), computers);
     underTest.execute();
 
     List<MeasureComputerWrapper> result = newArrayList(holder.getMeasureComputers());
@@ -104,7 +104,7 @@ public class FeedMeasureComputersTest {
     MeasureComputer measureComputer3 = newMeasureComputer(array(NEW_METRIC_2), array(NEW_METRIC_3));
     MeasureComputer[] computers = new MeasureComputer[] {measureComputer1, measureComputer2, measureComputer3};
 
-    ComputationStep underTest = new FeedMeasureComputers(holder, array(new TestMetrics()), computers);
+    ComputationStep underTest = new LoadMeasureComputersStep(holder, array(new TestMetrics()), computers);
     underTest.execute();
 
     List<MeasureComputerWrapper> result = newArrayList(holder.getMeasureComputers());
@@ -120,7 +120,7 @@ public class FeedMeasureComputersTest {
     thrown.expectMessage("Metric 'unknown' cannot be used as an input metric as it's not a core metric and no plugin declare this metric");
 
     MeasureComputer[] computers = new MeasureComputer[] {newMeasureComputer(array("unknown"), array(NEW_METRIC_4))};
-    ComputationStep underTest = new FeedMeasureComputers(holder, array(new TestMetrics()), computers);
+    ComputationStep underTest = new LoadMeasureComputersStep(holder, array(new TestMetrics()), computers);
     underTest.execute();
   }
 
@@ -130,7 +130,7 @@ public class FeedMeasureComputersTest {
     thrown.expectMessage("Metric 'unknown' cannot be used as an output metric as no plugin declare this metric");
 
     MeasureComputer[] computers = new MeasureComputer[] {newMeasureComputer(array(NEW_METRIC_4), array("unknown"))};
-    ComputationStep underTest = new FeedMeasureComputers(holder, array(new TestMetrics()), computers);
+    ComputationStep underTest = new LoadMeasureComputersStep(holder, array(new TestMetrics()), computers);
     underTest.execute();
   }
 
@@ -140,14 +140,14 @@ public class FeedMeasureComputersTest {
     thrown.expectMessage("Metric 'ncloc' cannot be used as an output metric as it's a core metric");
 
     MeasureComputer[] computers = new MeasureComputer[] {newMeasureComputer(array(NEW_METRIC_4), array(NCLOC_KEY))};
-    ComputationStep underTest = new FeedMeasureComputers(holder, array(new TestMetrics()), computers);
+    ComputationStep underTest = new LoadMeasureComputersStep(holder, array(new TestMetrics()), computers);
     underTest.execute();
   }
 
   @Test
   public void not_fail_if_input_metrics_are_same_as_output_metrics() throws Exception {
     MeasureComputer[] computers = new MeasureComputer[] {newMeasureComputer(array(NEW_METRIC_1), array(NEW_METRIC_1))};
-    ComputationStep underTest = new FeedMeasureComputers(holder, array(new TestMetrics()), computers);
+    ComputationStep underTest = new LoadMeasureComputersStep(holder, array(new TestMetrics()), computers);
     underTest.execute();
 
     assertThat(holder.getMeasureComputers()).hasSize(1);
@@ -155,7 +155,7 @@ public class FeedMeasureComputersTest {
 
   @Test
   public void return_empty_list_when_no_measure_computers() throws Exception {
-    ComputationStep underTest = new FeedMeasureComputers(holder, array(new TestMetrics()));
+    ComputationStep underTest = new LoadMeasureComputersStep(holder, array(new TestMetrics()));
     underTest.execute();
 
     assertThat(holder.getMeasureComputers()).isEmpty();
@@ -163,7 +163,7 @@ public class FeedMeasureComputersTest {
 
   @Test
   public void return_empty_list_when_no_metrics_neither_measure_computers() throws Exception {
-    ComputationStep underTest = new FeedMeasureComputers(holder);
+    ComputationStep underTest = new LoadMeasureComputersStep(holder);
     underTest.execute();
 
     assertThat(holder.getMeasureComputers()).isEmpty();
@@ -175,7 +175,7 @@ public class FeedMeasureComputersTest {
     thrown.expectMessage("Metric 'metric1' cannot be used as an output metric as no plugin declare this metric");
 
     MeasureComputer[] computers = new MeasureComputer[] {newMeasureComputer(array(NCLOC_KEY), array(NEW_METRIC_1))};
-    ComputationStep underTest = new FeedMeasureComputers(holder, computers);
+    ComputationStep underTest = new LoadMeasureComputersStep(holder, computers);
     underTest.execute();
   }
 
@@ -185,7 +185,7 @@ public class FeedMeasureComputersTest {
     thrown.expectMessage("Output metric 'metric1' is already defined by another measure computer 'TestMeasureComputer'");
 
     MeasureComputer[] computers = new MeasureComputer[] {newMeasureComputer(array(NCLOC_KEY), array(NEW_METRIC_1)), newMeasureComputer(array(CLASSES_KEY), array(NEW_METRIC_1))};
-    ComputationStep underTest = new FeedMeasureComputers(holder, array(new TestMetrics()), computers);
+    ComputationStep underTest = new LoadMeasureComputersStep(holder, array(new TestMetrics()), computers);
     underTest.execute();
   }
 
@@ -219,7 +219,7 @@ public class FeedMeasureComputersTest {
     };
 
     MeasureComputer[] computers = new MeasureComputer[] {measureComputer};
-    ComputationStep underTest = new FeedMeasureComputers(holder, array(new TestMetrics()), computers);
+    ComputationStep underTest = new LoadMeasureComputersStep(holder, array(new TestMetrics()), computers);
     underTest.execute();
   }
 
index 83a23649c7b574e3afa64dc04903ae4621396ec6..49438cab704fb144b2ede374b5208c831a8333fa 100644 (file)
@@ -73,7 +73,7 @@ public class FeedPeriodsStepTest extends BaseStepTest {
   Settings settings = new Settings();
   SettingsRepository settingsRepository = mock(SettingsRepository.class);
 
-  FeedPeriodsStep underTest;
+  LoadPeriodsStep underTest;
 
   @Override
   protected ComputationStep step() {
@@ -84,7 +84,7 @@ public class FeedPeriodsStepTest extends BaseStepTest {
   public void setUp() throws Exception {
     analysisMetadataHolder.setAnalysisDate(DATE_FORMAT.parse("2008-11-30"));
 
-    underTest = new FeedPeriodsStep(dbClient, settingsRepository, treeRootHolder, analysisMetadataHolder, periodsHolder);
+    underTest = new LoadPeriodsStep(dbClient, settingsRepository, treeRootHolder, analysisMetadataHolder, periodsHolder);
   }
 
   private void setupRoot(Component root) {
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/LoadQualityProfilesStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/LoadQualityProfilesStepTest.java
new file mode 100644 (file)
index 0000000..42ae222
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.computation.step;
+
+import com.google.common.base.Optional;
+import org.assertj.core.data.MapEntry;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.rule.Severity;
+import org.sonar.batch.protocol.Constants;
+import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.server.computation.batch.BatchReportReaderRule;
+import org.sonar.server.computation.issue.DumbRule;
+import org.sonar.server.computation.issue.RuleRepositoryRule;
+import org.sonar.server.computation.qualityprofile.ActiveRule;
+import org.sonar.server.computation.qualityprofile.ActiveRulesHolderImpl;
+
+import static java.util.Arrays.asList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.db.rule.RuleTesting.XOO_X1;
+import static org.sonar.db.rule.RuleTesting.XOO_X2;
+
+public class LoadQualityProfilesStepTest {
+
+  @Rule
+  public BatchReportReaderRule batchReportReader = new BatchReportReaderRule();
+
+  @Rule
+  public RuleRepositoryRule ruleRepository = new RuleRepositoryRule();
+
+  ActiveRulesHolderImpl activeRulesHolder = new ActiveRulesHolderImpl();
+  LoadQualityProfilesStep underTest = new LoadQualityProfilesStep(batchReportReader, activeRulesHolder, ruleRepository);
+
+  @Test
+  public void feed_active_rules() throws Exception {
+    ruleRepository.add(XOO_X1);
+    ruleRepository.add(XOO_X2);
+
+    BatchReport.ActiveRule.Builder batch1 = BatchReport.ActiveRule.newBuilder()
+      .setRuleRepository(XOO_X1.repository()).setRuleKey(XOO_X1.rule())
+      .setSeverity(Constants.Severity.BLOCKER);
+    batch1.addParamBuilder().setKey("p1").setValue("v1").build();
+
+    BatchReport.ActiveRule.Builder batch2 = BatchReport.ActiveRule.newBuilder()
+      .setRuleRepository(XOO_X2.repository()).setRuleKey(XOO_X2.rule()).setSeverity(Constants.Severity.MAJOR);
+    batchReportReader.putActiveRules(asList(batch1.build(), batch2.build()));
+
+    underTest.execute();
+
+    assertThat(activeRulesHolder.getAll()).hasSize(2);
+
+    Optional<ActiveRule> ar1 = activeRulesHolder.get(XOO_X1);
+    assertThat(ar1.get().getSeverity()).isEqualTo(Severity.BLOCKER);
+    assertThat(ar1.get().getParams()).containsExactly(MapEntry.entry("p1", "v1"));
+
+    Optional<ActiveRule> ar2 = activeRulesHolder.get(XOO_X2);
+    assertThat(ar2.get().getSeverity()).isEqualTo(Severity.MAJOR);
+    assertThat(ar2.get().getParams()).isEmpty();
+  }
+
+  @Test
+  public void ignore_rules_with_status_REMOVED() throws Exception {
+    ruleRepository.add(new DumbRule(XOO_X1).setStatus(RuleStatus.REMOVED));
+
+    BatchReport.ActiveRule.Builder batch1 = BatchReport.ActiveRule.newBuilder()
+      .setRuleRepository(XOO_X1.repository()).setRuleKey(XOO_X1.rule())
+      .setSeverity(Constants.Severity.BLOCKER);
+    batchReportReader.putActiveRules(asList(batch1.build()));
+
+    underTest.execute();
+
+    assertThat(activeRulesHolder.getAll()).isEmpty();
+  }
+
+  @Test
+  public void ignore_not_found_rules() throws Exception {
+    BatchReport.ActiveRule.Builder batch1 = BatchReport.ActiveRule.newBuilder()
+      .setRuleRepository(XOO_X1.repository()).setRuleKey(XOO_X1.rule())
+      .setSeverity(Constants.Severity.BLOCKER);
+    batchReportReader.putActiveRules(asList(batch1.build()));
+
+    underTest.execute();
+
+    assertThat(activeRulesHolder.getAll()).isEmpty();
+  }
+}
index ba15c22f7ec643834035bbd9f77e3f927facbf91..b50e8c69f6d997e6e506afba73214f421c3227b9 100644 (file)
@@ -55,7 +55,7 @@ public class QualityGateLoadingStepTest {
   private SettingsRepository settingsRepository = mock(SettingsRepository.class);
   private QualityGateService qualityGateService = mock(QualityGateService.class);
 
-  private QualityGateLoadingStep underTest = new QualityGateLoadingStep(treeRootHolder, settingsRepository, qualityGateService, mutableQualityGateHolder);
+  private LoadQualityGateStep underTest = new LoadQualityGateStep(treeRootHolder, settingsRepository, qualityGateService, mutableQualityGateHolder);
 
   @Test
   public void execute_sets_default_QualityGate_when_project_has_no_settings() {
index e8e5f7057f5bfaf37403d59ff3993bbab3415057..3c8bc5db711b02cee260f7f50f7ae68fcf4cfa46 100644 (file)
@@ -37,7 +37,7 @@ public class ReportComputationStepsTest {
   @Test
   public void instances_throws_ISE_if_container_does_not_have_any_step() throws Exception {
     expectedException.expect(IllegalStateException.class);
-    expectedException.expectMessage("Component not found: class org.sonar.server.computation.step.ReportExtractionStep");
+    expectedException.expectMessage("Component not found: " + ExtractReportStep.class);
 
     ComputeEngineContainerImpl computeEngineContainer = new ComputeEngineContainerImpl(new ComponentContainer(), new ContainerPopulator<ComputeEngineContainer>() {
       @Override
@@ -54,7 +54,7 @@ public class ReportComputationStepsTest {
     expectedException.expect(IllegalStateException.class);
     expectedException.expectMessage("Component not found: class org.sonar.server.computation.step.BuildComponentTreeStep");
 
-    final ReportExtractionStep reportExtractionStep = mock(ReportExtractionStep.class);
+    final ExtractReportStep reportExtractionStep = mock(ExtractReportStep.class);
     ComponentContainer componentContainer = new ComponentContainer() {
       {
         addSingleton(reportExtractionStep);
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ReportComputeMeasureVariationsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ReportComputeMeasureVariationsStepTest.java
new file mode 100644 (file)
index 0000000..a072dfd
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.computation.step;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ComponentTesting;
+import org.sonar.db.component.SnapshotDto;
+import org.sonar.db.measure.MeasureDto;
+import org.sonar.server.computation.batch.BatchReportReaderRule;
+import org.sonar.server.computation.batch.TreeRootHolderRule;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.ReportComponent;
+import org.sonar.server.computation.measure.Measure;
+import org.sonar.server.computation.measure.MeasureRepositoryRule;
+import org.sonar.server.computation.metric.Metric;
+import org.sonar.server.computation.metric.MetricImpl;
+import org.sonar.server.computation.metric.MetricRepositoryRule;
+import org.sonar.server.computation.period.Period;
+import org.sonar.server.computation.period.PeriodsHolderRule;
+import org.sonar.test.DbTests;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.server.component.SnapshotTesting.createForComponent;
+import static org.sonar.server.component.SnapshotTesting.createForProject;
+
+@Category(DbTests.class)
+public class ReportComputeMeasureVariationsStepTest {
+
+  static final Metric ISSUES_METRIC = new MetricImpl(1, "violations", "violations", Metric.MetricType.INT);
+  static final Metric DEBT_METRIC = new MetricImpl(2, "sqale_index", "sqale_index", Metric.MetricType.WORK_DUR);
+  static final Metric FILE_COMPLEXITY_METRIC = new MetricImpl(3, "file_complexity", "file_complexity", Metric.MetricType.FLOAT);
+  static final Metric BUILD_BREAKER_METRIC = new MetricImpl(4, "build_breaker", "build_breaker", Metric.MetricType.BOOL);
+
+  static final ComponentDto PROJECT_DTO = ComponentTesting.newProjectDto();
+
+  static final Component PROJECT = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_DTO.uuid()).build();
+
+  @Rule
+  public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+  @Rule
+  public BatchReportReaderRule reportReader = new BatchReportReaderRule();
+
+  @Rule
+  public PeriodsHolderRule periodsHolder = new PeriodsHolderRule();
+
+  @Rule
+  public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
+
+  @Rule
+  public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
+    .add(ISSUES_METRIC)
+    .add(DEBT_METRIC)
+    .add(FILE_COMPLEXITY_METRIC)
+    .add(BUILD_BREAKER_METRIC);
+
+  @Rule
+  public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
+
+  DbSession session = dbTester.getSession();
+
+  DbClient dbClient = dbTester.getDbClient();
+
+  ComputeMeasureVariationsStep underTest;
+
+  @Before
+  public void setUp() {
+    dbTester.truncateTables();
+    dbClient.componentDao().insert(session, PROJECT_DTO);
+    session.commit();
+
+    underTest = new ComputeMeasureVariationsStep(dbClient, treeRootHolder, periodsHolder, metricRepository, measureRepository);
+  }
+
+  @Test
+  public void do_nothing_when_no_raw_measure() {
+    SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO);
+    dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
+    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d));
+    session.commit();
+
+    periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
+
+    treeRootHolder.setRoot(PROJECT);
+
+    underTest.execute();
+
+    assertThat(measureRepository.getRawMeasures(PROJECT).keys()).isEmpty();
+  }
+
+  @Test
+  public void do_nothing_when_no_period() {
+    Component project = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_DTO.uuid()).build();
+    treeRootHolder.setRoot(project);
+    periodsHolder.setPeriods();
+
+    underTest.execute();
+
+    assertThat(measureRepository.getRawMeasures(project).keys()).isEmpty();
+  }
+
+  @Test
+  public void set_variation() {
+    // Project
+    SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO);
+    dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
+    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d));
+
+    // Directory
+    ComponentDto directoryDto = ComponentTesting.newDirectory(PROJECT_DTO, "dir");
+    dbClient.componentDao().insert(session, directoryDto);
+    SnapshotDto period1DirectorySnapshot = createForComponent(directoryDto, period1ProjectSnapshot);
+    dbClient.snapshotDao().insert(session, period1DirectorySnapshot);
+    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), directoryDto.getId(), period1DirectorySnapshot.getId(), 10d));
+    session.commit();
+
+    periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
+
+    Component directory = ReportComponent.builder(Component.Type.DIRECTORY, 2).setUuid(directoryDto.uuid()).build();
+    Component project = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_DTO.uuid()).addChildren(directory).build();
+    treeRootHolder.setRoot(project);
+
+    addRawMeasure(project, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
+    addRawMeasure(directory, ISSUES_METRIC, Measure.newMeasureBuilder().create(20, null));
+
+    underTest.execute();
+
+    assertThat(measureRepository.getRawMeasure(project, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d);
+    assertThat(measureRepository.getRawMeasure(directory, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(10d);
+  }
+
+  @Test
+  public void set_variations_on_all_periods() {
+    SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
+    SnapshotDto period2ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
+    SnapshotDto period3ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
+    SnapshotDto period4ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
+    SnapshotDto period5ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
+    dbClient.snapshotDao().insert(session, period1ProjectSnapshot, period2ProjectSnapshot, period3ProjectSnapshot, period4ProjectSnapshot, period5ProjectSnapshot);
+
+    dbClient.measureDao().insert(session,
+      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 0d),
+      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period2ProjectSnapshot.getId(), 20d),
+      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period3ProjectSnapshot.getId(), 40d),
+      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period4ProjectSnapshot.getId(), 80d),
+      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period5ProjectSnapshot.getId(), 100d));
+    session.commit();
+
+    periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot),
+      newPeriod(2, period2ProjectSnapshot),
+      newPeriod(3, period3ProjectSnapshot),
+      newPeriod(4, period4ProjectSnapshot),
+      newPeriod(5, period5ProjectSnapshot));
+
+    treeRootHolder.setRoot(PROJECT);
+
+    addRawMeasure(PROJECT, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
+
+    underTest.execute();
+
+    assertThat(measureRepository.getRawMeasures(PROJECT).keys()).hasSize(1);
+
+    Measure measure = measureRepository.getRawMeasure(PROJECT, ISSUES_METRIC).get();
+    assertThat(measure.hasVariations()).isTrue();
+    assertThat(measure.getVariations().getVariation1()).isEqualTo(80d);
+    assertThat(measure.getVariations().getVariation2()).isEqualTo(60d);
+    assertThat(measure.getVariations().getVariation3()).isEqualTo(40d);
+    assertThat(measure.getVariations().getVariation4()).isEqualTo(0d);
+    assertThat(measure.getVariations().getVariation5()).isEqualTo(-20d);
+  }
+
+  @Test
+  public void set_variation_on_all_numeric_metrics() {
+    SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO);
+    dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
+    dbClient.measureDao().insert(session,
+      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d),
+      newMeasureDto(DEBT_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 10d),
+      newMeasureDto(FILE_COMPLEXITY_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 2d),
+      newMeasureDto(BUILD_BREAKER_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 1d)
+    );
+    session.commit();
+
+    periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
+
+    treeRootHolder.setRoot(PROJECT);
+
+    addRawMeasure(PROJECT, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
+    addRawMeasure(PROJECT, DEBT_METRIC, Measure.newMeasureBuilder().create(5L, null));
+    addRawMeasure(PROJECT, FILE_COMPLEXITY_METRIC, Measure.newMeasureBuilder().create(3d, null));
+    addRawMeasure(PROJECT, BUILD_BREAKER_METRIC, Measure.newMeasureBuilder().create(false, null));
+
+    underTest.execute();
+
+    assertThat(measureRepository.getRawMeasures(PROJECT).keys()).hasSize(4);
+
+    assertThat(measureRepository.getRawMeasure(PROJECT, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d);
+    assertThat(measureRepository.getRawMeasure(PROJECT, DEBT_METRIC).get().getVariations().getVariation1()).isEqualTo(-5d);
+    assertThat(measureRepository.getRawMeasure(PROJECT, FILE_COMPLEXITY_METRIC).get().getVariations().getVariation1()).isEqualTo(1d);
+    assertThat(measureRepository.getRawMeasure(PROJECT, BUILD_BREAKER_METRIC).get().getVariations().getVariation1()).isEqualTo(-1d);
+  }
+
+  private static MeasureDto newMeasureDto(int metricId, long projectId, long snapshotId, double value) {
+    return new MeasureDto().setMetricId(metricId).setComponentId(projectId).setSnapshotId(snapshotId).setValue(value);
+  }
+
+  private static Period newPeriod(int index, SnapshotDto snapshotDto) {
+    return new Period(index, "mode", null, snapshotDto.getCreatedAt(), snapshotDto.getId());
+  }
+
+  private void addRawMeasure(Component component, Metric metric, Measure measure) {
+    measureRepository.addRawMeasure(component.getReportAttributes().getRef(), metric.getKey(), measure);
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ReportFillMeasuresWithVariationsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ReportFillMeasuresWithVariationsStepTest.java
deleted file mode 100644 (file)
index 6b28ebf..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.computation.step;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.SnapshotDto;
-import org.sonar.db.measure.MeasureDto;
-import org.sonar.db.component.ComponentTesting;
-import org.sonar.server.computation.batch.BatchReportReaderRule;
-import org.sonar.server.computation.batch.TreeRootHolderRule;
-import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.component.ReportComponent;
-import org.sonar.server.computation.measure.Measure;
-import org.sonar.server.computation.measure.MeasureRepositoryRule;
-import org.sonar.server.computation.metric.Metric;
-import org.sonar.server.computation.metric.MetricImpl;
-import org.sonar.server.computation.metric.MetricRepositoryRule;
-import org.sonar.server.computation.period.Period;
-import org.sonar.server.computation.period.PeriodsHolderRule;
-import org.sonar.test.DbTests;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.server.component.SnapshotTesting.createForComponent;
-import static org.sonar.server.component.SnapshotTesting.createForProject;
-
-@Category(DbTests.class)
-public class ReportFillMeasuresWithVariationsStepTest {
-
-  static final Metric ISSUES_METRIC = new MetricImpl(1, "violations", "violations", Metric.MetricType.INT);
-  static final Metric DEBT_METRIC = new MetricImpl(2, "sqale_index", "sqale_index", Metric.MetricType.WORK_DUR);
-  static final Metric FILE_COMPLEXITY_METRIC = new MetricImpl(3, "file_complexity", "file_complexity", Metric.MetricType.FLOAT);
-  static final Metric BUILD_BREAKER_METRIC = new MetricImpl(4, "build_breaker", "build_breaker", Metric.MetricType.BOOL);
-
-  static final ComponentDto PROJECT_DTO = ComponentTesting.newProjectDto();
-
-  static final Component PROJECT = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_DTO.uuid()).build();
-
-  @Rule
-  public DbTester dbTester = DbTester.create(System2.INSTANCE);
-
-  @Rule
-  public BatchReportReaderRule reportReader = new BatchReportReaderRule();
-
-  @Rule
-  public PeriodsHolderRule periodsHolder = new PeriodsHolderRule();
-
-  @Rule
-  public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
-
-  @Rule
-  public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
-    .add(ISSUES_METRIC)
-    .add(DEBT_METRIC)
-    .add(FILE_COMPLEXITY_METRIC)
-    .add(BUILD_BREAKER_METRIC);
-
-  @Rule
-  public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
-
-  DbSession session = dbTester.getSession();
-
-  DbClient dbClient = dbTester.getDbClient();
-
-  FillMeasuresWithVariationsStep underTest;
-
-  @Before
-  public void setUp() {
-    dbTester.truncateTables();
-    dbClient.componentDao().insert(session, PROJECT_DTO);
-    session.commit();
-
-    underTest = new FillMeasuresWithVariationsStep(dbClient, treeRootHolder, periodsHolder, metricRepository, measureRepository);
-  }
-
-  @Test
-  public void do_nothing_when_no_raw_measure() {
-    SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO);
-    dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
-    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d));
-    session.commit();
-
-    periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
-
-    treeRootHolder.setRoot(PROJECT);
-
-    underTest.execute();
-
-    assertThat(measureRepository.getRawMeasures(PROJECT).keys()).isEmpty();
-  }
-
-  @Test
-  public void do_nothing_when_no_period() {
-    Component project = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_DTO.uuid()).build();
-    treeRootHolder.setRoot(project);
-    periodsHolder.setPeriods();
-
-    underTest.execute();
-
-    assertThat(measureRepository.getRawMeasures(project).keys()).isEmpty();
-  }
-
-  @Test
-  public void set_variation() {
-    // Project
-    SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO);
-    dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
-    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d));
-
-    // Directory
-    ComponentDto directoryDto = ComponentTesting.newDirectory(PROJECT_DTO, "dir");
-    dbClient.componentDao().insert(session, directoryDto);
-    SnapshotDto period1DirectorySnapshot = createForComponent(directoryDto, period1ProjectSnapshot);
-    dbClient.snapshotDao().insert(session, period1DirectorySnapshot);
-    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), directoryDto.getId(), period1DirectorySnapshot.getId(), 10d));
-    session.commit();
-
-    periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
-
-    Component directory = ReportComponent.builder(Component.Type.DIRECTORY, 2).setUuid(directoryDto.uuid()).build();
-    Component project = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_DTO.uuid()).addChildren(directory).build();
-    treeRootHolder.setRoot(project);
-
-    addRawMeasure(project, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
-    addRawMeasure(directory, ISSUES_METRIC, Measure.newMeasureBuilder().create(20, null));
-
-    underTest.execute();
-
-    assertThat(measureRepository.getRawMeasure(project, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d);
-    assertThat(measureRepository.getRawMeasure(directory, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(10d);
-  }
-
-  @Test
-  public void set_variations_on_all_periods() {
-    SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
-    SnapshotDto period2ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
-    SnapshotDto period3ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
-    SnapshotDto period4ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
-    SnapshotDto period5ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
-    dbClient.snapshotDao().insert(session, period1ProjectSnapshot, period2ProjectSnapshot, period3ProjectSnapshot, period4ProjectSnapshot, period5ProjectSnapshot);
-
-    dbClient.measureDao().insert(session,
-      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 0d),
-      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period2ProjectSnapshot.getId(), 20d),
-      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period3ProjectSnapshot.getId(), 40d),
-      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period4ProjectSnapshot.getId(), 80d),
-      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period5ProjectSnapshot.getId(), 100d));
-    session.commit();
-
-    periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot),
-      newPeriod(2, period2ProjectSnapshot),
-      newPeriod(3, period3ProjectSnapshot),
-      newPeriod(4, period4ProjectSnapshot),
-      newPeriod(5, period5ProjectSnapshot));
-
-    treeRootHolder.setRoot(PROJECT);
-
-    addRawMeasure(PROJECT, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
-
-    underTest.execute();
-
-    assertThat(measureRepository.getRawMeasures(PROJECT).keys()).hasSize(1);
-
-    Measure measure = measureRepository.getRawMeasure(PROJECT, ISSUES_METRIC).get();
-    assertThat(measure.hasVariations()).isTrue();
-    assertThat(measure.getVariations().getVariation1()).isEqualTo(80d);
-    assertThat(measure.getVariations().getVariation2()).isEqualTo(60d);
-    assertThat(measure.getVariations().getVariation3()).isEqualTo(40d);
-    assertThat(measure.getVariations().getVariation4()).isEqualTo(0d);
-    assertThat(measure.getVariations().getVariation5()).isEqualTo(-20d);
-  }
-
-  @Test
-  public void set_variation_on_all_numeric_metrics() {
-    SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO);
-    dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
-    dbClient.measureDao().insert(session,
-      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d),
-      newMeasureDto(DEBT_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 10d),
-      newMeasureDto(FILE_COMPLEXITY_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 2d),
-      newMeasureDto(BUILD_BREAKER_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 1d)
-    );
-    session.commit();
-
-    periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
-
-    treeRootHolder.setRoot(PROJECT);
-
-    addRawMeasure(PROJECT, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
-    addRawMeasure(PROJECT, DEBT_METRIC, Measure.newMeasureBuilder().create(5L, null));
-    addRawMeasure(PROJECT, FILE_COMPLEXITY_METRIC, Measure.newMeasureBuilder().create(3d, null));
-    addRawMeasure(PROJECT, BUILD_BREAKER_METRIC, Measure.newMeasureBuilder().create(false, null));
-
-    underTest.execute();
-
-    assertThat(measureRepository.getRawMeasures(PROJECT).keys()).hasSize(4);
-
-    assertThat(measureRepository.getRawMeasure(PROJECT, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d);
-    assertThat(measureRepository.getRawMeasure(PROJECT, DEBT_METRIC).get().getVariations().getVariation1()).isEqualTo(-5d);
-    assertThat(measureRepository.getRawMeasure(PROJECT, FILE_COMPLEXITY_METRIC).get().getVariations().getVariation1()).isEqualTo(1d);
-    assertThat(measureRepository.getRawMeasure(PROJECT, BUILD_BREAKER_METRIC).get().getVariations().getVariation1()).isEqualTo(-1d);
-  }
-
-  private static MeasureDto newMeasureDto(int metricId, long projectId, long snapshotId, double value) {
-    return new MeasureDto().setMetricId(metricId).setComponentId(projectId).setSnapshotId(snapshotId).setValue(value);
-  }
-
-  private static Period newPeriod(int index, SnapshotDto snapshotDto) {
-    return new Period(index, "mode", null, snapshotDto.getCreatedAt(), snapshotDto.getId());
-  }
-
-  private void addRawMeasure(Component component, Metric metric, Measure measure) {
-    measureRepository.addRawMeasure(component.getReportAttributes().getRef(), metric.getKey(), measure);
-  }
-}
index 512e5a9819bfd01a7f3d591dd5a972f6487883e6..7a32cee3485c9773113fed5453ce3c6697bcf996 100644 (file)
@@ -25,7 +25,6 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.config.Settings;
 import org.sonar.api.utils.MessageException;
 import org.sonar.api.utils.System2;
 import org.sonar.batch.protocol.Constants;
@@ -62,16 +61,11 @@ public class ValidateProjectStepTest {
 
   DbClient dbClient = dbTester.getDbClient();
 
-  Settings settings;
-
-  ValidateProjectStep underTest;
+  ValidateProjectStep underTest = new ValidateProjectStep(dbClient, reportReader, treeRootHolder);
 
   @Before
   public void setUp() {
     dbTester.truncateTables();
-    settings = new Settings();
-
-    underTest = new ValidateProjectStep(dbClient, settings, reportReader, treeRootHolder);
   }
 
   @Test
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ViewsComputeMeasureVariationsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ViewsComputeMeasureVariationsStepTest.java
new file mode 100644 (file)
index 0000000..90408c5
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.computation.step;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ComponentTesting;
+import org.sonar.db.component.SnapshotDto;
+import org.sonar.db.measure.MeasureDto;
+import org.sonar.server.computation.batch.BatchReportReaderRule;
+import org.sonar.server.computation.batch.TreeRootHolderRule;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.ViewsComponent;
+import org.sonar.server.computation.measure.Measure;
+import org.sonar.server.computation.measure.MeasureRepositoryRule;
+import org.sonar.server.computation.metric.Metric;
+import org.sonar.server.computation.metric.MetricImpl;
+import org.sonar.server.computation.metric.MetricRepositoryRule;
+import org.sonar.server.computation.period.Period;
+import org.sonar.server.computation.period.PeriodsHolderRule;
+import org.sonar.test.DbTests;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.server.component.SnapshotTesting.createForComponent;
+import static org.sonar.server.component.SnapshotTesting.createForProject;
+import static org.sonar.server.component.SnapshotTesting.createForView;
+
+@Category(DbTests.class)
+public class ViewsComputeMeasureVariationsStepTest {
+
+  static final Metric ISSUES_METRIC = new MetricImpl(1, "violations", "violations", Metric.MetricType.INT);
+  static final Metric DEBT_METRIC = new MetricImpl(2, "sqale_index", "sqale_index", Metric.MetricType.WORK_DUR);
+  static final Metric FILE_COMPLEXITY_METRIC = new MetricImpl(3, "file_complexity", "file_complexity", Metric.MetricType.FLOAT);
+  static final Metric BUILD_BREAKER_METRIC = new MetricImpl(4, "build_breaker", "build_breaker", Metric.MetricType.BOOL);
+
+  static final ComponentDto VIEW_DTO = ComponentTesting.newView();
+
+  static final Component VIEW = ViewsComponent.builder(Component.Type.VIEW, 1).setUuid(VIEW_DTO.uuid()).build();
+
+  @Rule
+  public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+  @Rule
+  public BatchReportReaderRule reportReader = new BatchReportReaderRule();
+
+  @Rule
+  public PeriodsHolderRule periodsHolder = new PeriodsHolderRule();
+
+  @Rule
+  public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
+
+  @Rule
+  public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
+    .add(ISSUES_METRIC)
+    .add(DEBT_METRIC)
+    .add(FILE_COMPLEXITY_METRIC)
+    .add(BUILD_BREAKER_METRIC);
+
+  @Rule
+  public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
+
+  DbSession session = dbTester.getSession();
+
+  DbClient dbClient = dbTester.getDbClient();
+
+  ComputeMeasureVariationsStep underTest;
+
+  @Before
+  public void setUp() {
+    dbTester.truncateTables();
+    dbClient.componentDao().insert(session, VIEW_DTO);
+    session.commit();
+
+    underTest = new ComputeMeasureVariationsStep(dbClient, treeRootHolder, periodsHolder, metricRepository, measureRepository);
+  }
+
+  @Test
+  public void do_nothing_when_no_raw_measure() {
+    SnapshotDto period1ViewSnapshot = createForView(VIEW_DTO);
+    dbClient.snapshotDao().insert(session, period1ViewSnapshot);
+    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 60d));
+    session.commit();
+
+    periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot));
+
+    treeRootHolder.setRoot(VIEW);
+
+    underTest.execute();
+
+    assertThat(measureRepository.getRawMeasures(VIEW).keys()).isEmpty();
+  }
+
+  @Test
+  public void do_nothing_when_no_period() {
+    Component view = ViewsComponent.builder(Component.Type.VIEW, 1).setUuid(VIEW_DTO.uuid()).build();
+    treeRootHolder.setRoot(view);
+    periodsHolder.setPeriods();
+
+    underTest.execute();
+
+    assertThat(measureRepository.getRawMeasures(view).keys()).isEmpty();
+  }
+
+  @Test
+  public void set_variation() {
+    // View
+    SnapshotDto period1ViewSnapshot = createForView(VIEW_DTO);
+    dbClient.snapshotDao().insert(session, period1ViewSnapshot);
+    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 60d));
+
+    // SubView
+    ComponentDto subviewDto = ComponentTesting.newSubView(VIEW_DTO, "dir", "key");
+    dbClient.componentDao().insert(session, subviewDto);
+    SnapshotDto period1SubviewSnapshot = createForComponent(subviewDto, period1ViewSnapshot);
+    dbClient.snapshotDao().insert(session, period1SubviewSnapshot);
+    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), subviewDto.getId(), period1SubviewSnapshot.getId(), 10d));
+    session.commit();
+
+    periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot));
+
+    Component subview = ViewsComponent.builder(Component.Type.SUBVIEW, 2).setUuid(subviewDto.uuid()).build();
+    Component view = ViewsComponent.builder(Component.Type.VIEW, 1).setUuid(VIEW_DTO.uuid()).addChildren(subview).build();
+    treeRootHolder.setRoot(view);
+
+    addRawMeasure(view, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
+    addRawMeasure(subview, ISSUES_METRIC, Measure.newMeasureBuilder().create(20, null));
+
+    underTest.execute();
+
+    assertThat(measureRepository.getRawMeasure(view, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d);
+    assertThat(measureRepository.getRawMeasure(subview, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(10d);
+  }
+
+  @Test
+  public void set_variations_on_all_periods() {
+    SnapshotDto period1ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
+    SnapshotDto period2ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
+    SnapshotDto period3ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
+    SnapshotDto period4ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
+    SnapshotDto period5ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
+    dbClient.snapshotDao().insert(session, period1ViewSnapshot, period2ViewSnapshot, period3ViewSnapshot, period4ViewSnapshot, period5ViewSnapshot);
+
+    dbClient.measureDao().insert(session,
+      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 0d),
+      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period2ViewSnapshot.getId(), 20d),
+      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period3ViewSnapshot.getId(), 40d),
+      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period4ViewSnapshot.getId(), 80d),
+      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period5ViewSnapshot.getId(), 100d));
+    session.commit();
+
+    periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot),
+      newPeriod(2, period2ViewSnapshot),
+      newPeriod(3, period3ViewSnapshot),
+      newPeriod(4, period4ViewSnapshot),
+      newPeriod(5, period5ViewSnapshot));
+
+    treeRootHolder.setRoot(VIEW);
+
+    addRawMeasure(VIEW, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
+
+    underTest.execute();
+
+    assertThat(measureRepository.getRawMeasures(VIEW).keys()).hasSize(1);
+
+    Measure measure = measureRepository.getRawMeasure(VIEW, ISSUES_METRIC).get();
+    assertThat(measure.hasVariations()).isTrue();
+    assertThat(measure.getVariations().getVariation1()).isEqualTo(80d);
+    assertThat(measure.getVariations().getVariation2()).isEqualTo(60d);
+    assertThat(measure.getVariations().getVariation3()).isEqualTo(40d);
+    assertThat(measure.getVariations().getVariation4()).isEqualTo(0d);
+    assertThat(measure.getVariations().getVariation5()).isEqualTo(-20d);
+  }
+
+  @Test
+  public void set_variation_on_all_numeric_metrics() {
+    SnapshotDto period1ViewSnapshot = createForProject(VIEW_DTO);
+    dbClient.snapshotDao().insert(session, period1ViewSnapshot);
+    dbClient.measureDao().insert(session,
+      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 60d),
+      newMeasureDto(DEBT_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 10d),
+      newMeasureDto(FILE_COMPLEXITY_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 2d),
+      newMeasureDto(BUILD_BREAKER_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 1d)
+    );
+    session.commit();
+
+    periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot));
+
+    treeRootHolder.setRoot(VIEW);
+
+    addRawMeasure(VIEW, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
+    addRawMeasure(VIEW, DEBT_METRIC, Measure.newMeasureBuilder().create(5L, null));
+    addRawMeasure(VIEW, FILE_COMPLEXITY_METRIC, Measure.newMeasureBuilder().create(3d, null));
+    addRawMeasure(VIEW, BUILD_BREAKER_METRIC, Measure.newMeasureBuilder().create(false, null));
+
+    underTest.execute();
+
+    assertThat(measureRepository.getRawMeasures(VIEW).keys()).hasSize(4);
+
+    assertThat(measureRepository.getRawMeasure(VIEW, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d);
+    assertThat(measureRepository.getRawMeasure(VIEW, DEBT_METRIC).get().getVariations().getVariation1()).isEqualTo(-5d);
+    assertThat(measureRepository.getRawMeasure(VIEW, FILE_COMPLEXITY_METRIC).get().getVariations().getVariation1()).isEqualTo(1d);
+    assertThat(measureRepository.getRawMeasure(VIEW, BUILD_BREAKER_METRIC).get().getVariations().getVariation1()).isEqualTo(-1d);
+  }
+
+  private static MeasureDto newMeasureDto(int metricId, long projectId, long snapshotId, double value) {
+    return new MeasureDto().setMetricId(metricId).setComponentId(projectId).setSnapshotId(snapshotId).setValue(value);
+  }
+
+  private static Period newPeriod(int index, SnapshotDto snapshotDto) {
+    return new Period(index, "mode", null, snapshotDto.getCreatedAt(), snapshotDto.getId());
+  }
+
+  private void addRawMeasure(Component component, Metric metric, Measure measure) {
+    measureRepository.add(component, metric, measure);
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ViewsFillMeasuresWithVariationsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ViewsFillMeasuresWithVariationsStepTest.java
deleted file mode 100644 (file)
index 5b5bbc8..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.computation.step;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.ComponentTesting;
-import org.sonar.db.component.SnapshotDto;
-import org.sonar.db.measure.MeasureDto;
-import org.sonar.server.computation.batch.BatchReportReaderRule;
-import org.sonar.server.computation.batch.TreeRootHolderRule;
-import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.component.ViewsComponent;
-import org.sonar.server.computation.measure.Measure;
-import org.sonar.server.computation.measure.MeasureRepositoryRule;
-import org.sonar.server.computation.metric.Metric;
-import org.sonar.server.computation.metric.MetricImpl;
-import org.sonar.server.computation.metric.MetricRepositoryRule;
-import org.sonar.server.computation.period.Period;
-import org.sonar.server.computation.period.PeriodsHolderRule;
-import org.sonar.test.DbTests;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.server.component.SnapshotTesting.createForComponent;
-import static org.sonar.server.component.SnapshotTesting.createForProject;
-import static org.sonar.server.component.SnapshotTesting.createForView;
-
-@Category(DbTests.class)
-public class ViewsFillMeasuresWithVariationsStepTest {
-
-  static final Metric ISSUES_METRIC = new MetricImpl(1, "violations", "violations", Metric.MetricType.INT);
-  static final Metric DEBT_METRIC = new MetricImpl(2, "sqale_index", "sqale_index", Metric.MetricType.WORK_DUR);
-  static final Metric FILE_COMPLEXITY_METRIC = new MetricImpl(3, "file_complexity", "file_complexity", Metric.MetricType.FLOAT);
-  static final Metric BUILD_BREAKER_METRIC = new MetricImpl(4, "build_breaker", "build_breaker", Metric.MetricType.BOOL);
-
-  static final ComponentDto VIEW_DTO = ComponentTesting.newView();
-
-  static final Component VIEW = ViewsComponent.builder(Component.Type.VIEW, 1).setUuid(VIEW_DTO.uuid()).build();
-
-  @Rule
-  public DbTester dbTester = DbTester.create(System2.INSTANCE);
-
-  @Rule
-  public BatchReportReaderRule reportReader = new BatchReportReaderRule();
-
-  @Rule
-  public PeriodsHolderRule periodsHolder = new PeriodsHolderRule();
-
-  @Rule
-  public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
-
-  @Rule
-  public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
-    .add(ISSUES_METRIC)
-    .add(DEBT_METRIC)
-    .add(FILE_COMPLEXITY_METRIC)
-    .add(BUILD_BREAKER_METRIC);
-
-  @Rule
-  public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
-
-  DbSession session = dbTester.getSession();
-
-  DbClient dbClient = dbTester.getDbClient();
-
-  FillMeasuresWithVariationsStep underTest;
-
-  @Before
-  public void setUp() {
-    dbTester.truncateTables();
-    dbClient.componentDao().insert(session, VIEW_DTO);
-    session.commit();
-
-    underTest = new FillMeasuresWithVariationsStep(dbClient, treeRootHolder, periodsHolder, metricRepository, measureRepository);
-  }
-
-  @Test
-  public void do_nothing_when_no_raw_measure() {
-    SnapshotDto period1ViewSnapshot = createForView(VIEW_DTO);
-    dbClient.snapshotDao().insert(session, period1ViewSnapshot);
-    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 60d));
-    session.commit();
-
-    periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot));
-
-    treeRootHolder.setRoot(VIEW);
-
-    underTest.execute();
-
-    assertThat(measureRepository.getRawMeasures(VIEW).keys()).isEmpty();
-  }
-
-  @Test
-  public void do_nothing_when_no_period() {
-    Component view = ViewsComponent.builder(Component.Type.VIEW, 1).setUuid(VIEW_DTO.uuid()).build();
-    treeRootHolder.setRoot(view);
-    periodsHolder.setPeriods();
-
-    underTest.execute();
-
-    assertThat(measureRepository.getRawMeasures(view).keys()).isEmpty();
-  }
-
-  @Test
-  public void set_variation() {
-    // View
-    SnapshotDto period1ViewSnapshot = createForView(VIEW_DTO);
-    dbClient.snapshotDao().insert(session, period1ViewSnapshot);
-    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 60d));
-
-    // SubView
-    ComponentDto subviewDto = ComponentTesting.newSubView(VIEW_DTO, "dir", "key");
-    dbClient.componentDao().insert(session, subviewDto);
-    SnapshotDto period1SubviewSnapshot = createForComponent(subviewDto, period1ViewSnapshot);
-    dbClient.snapshotDao().insert(session, period1SubviewSnapshot);
-    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), subviewDto.getId(), period1SubviewSnapshot.getId(), 10d));
-    session.commit();
-
-    periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot));
-
-    Component subview = ViewsComponent.builder(Component.Type.SUBVIEW, 2).setUuid(subviewDto.uuid()).build();
-    Component view = ViewsComponent.builder(Component.Type.VIEW, 1).setUuid(VIEW_DTO.uuid()).addChildren(subview).build();
-    treeRootHolder.setRoot(view);
-
-    addRawMeasure(view, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
-    addRawMeasure(subview, ISSUES_METRIC, Measure.newMeasureBuilder().create(20, null));
-
-    underTest.execute();
-
-    assertThat(measureRepository.getRawMeasure(view, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d);
-    assertThat(measureRepository.getRawMeasure(subview, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(10d);
-  }
-
-  @Test
-  public void set_variations_on_all_periods() {
-    SnapshotDto period1ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
-    SnapshotDto period2ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
-    SnapshotDto period3ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
-    SnapshotDto period4ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
-    SnapshotDto period5ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
-    dbClient.snapshotDao().insert(session, period1ViewSnapshot, period2ViewSnapshot, period3ViewSnapshot, period4ViewSnapshot, period5ViewSnapshot);
-
-    dbClient.measureDao().insert(session,
-      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 0d),
-      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period2ViewSnapshot.getId(), 20d),
-      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period3ViewSnapshot.getId(), 40d),
-      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period4ViewSnapshot.getId(), 80d),
-      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period5ViewSnapshot.getId(), 100d));
-    session.commit();
-
-    periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot),
-      newPeriod(2, period2ViewSnapshot),
-      newPeriod(3, period3ViewSnapshot),
-      newPeriod(4, period4ViewSnapshot),
-      newPeriod(5, period5ViewSnapshot));
-
-    treeRootHolder.setRoot(VIEW);
-
-    addRawMeasure(VIEW, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
-
-    underTest.execute();
-
-    assertThat(measureRepository.getRawMeasures(VIEW).keys()).hasSize(1);
-
-    Measure measure = measureRepository.getRawMeasure(VIEW, ISSUES_METRIC).get();
-    assertThat(measure.hasVariations()).isTrue();
-    assertThat(measure.getVariations().getVariation1()).isEqualTo(80d);
-    assertThat(measure.getVariations().getVariation2()).isEqualTo(60d);
-    assertThat(measure.getVariations().getVariation3()).isEqualTo(40d);
-    assertThat(measure.getVariations().getVariation4()).isEqualTo(0d);
-    assertThat(measure.getVariations().getVariation5()).isEqualTo(-20d);
-  }
-
-  @Test
-  public void set_variation_on_all_numeric_metrics() {
-    SnapshotDto period1ViewSnapshot = createForProject(VIEW_DTO);
-    dbClient.snapshotDao().insert(session, period1ViewSnapshot);
-    dbClient.measureDao().insert(session,
-      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 60d),
-      newMeasureDto(DEBT_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 10d),
-      newMeasureDto(FILE_COMPLEXITY_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 2d),
-      newMeasureDto(BUILD_BREAKER_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 1d)
-    );
-    session.commit();
-
-    periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot));
-
-    treeRootHolder.setRoot(VIEW);
-
-    addRawMeasure(VIEW, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
-    addRawMeasure(VIEW, DEBT_METRIC, Measure.newMeasureBuilder().create(5L, null));
-    addRawMeasure(VIEW, FILE_COMPLEXITY_METRIC, Measure.newMeasureBuilder().create(3d, null));
-    addRawMeasure(VIEW, BUILD_BREAKER_METRIC, Measure.newMeasureBuilder().create(false, null));
-
-    underTest.execute();
-
-    assertThat(measureRepository.getRawMeasures(VIEW).keys()).hasSize(4);
-
-    assertThat(measureRepository.getRawMeasure(VIEW, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d);
-    assertThat(measureRepository.getRawMeasure(VIEW, DEBT_METRIC).get().getVariations().getVariation1()).isEqualTo(-5d);
-    assertThat(measureRepository.getRawMeasure(VIEW, FILE_COMPLEXITY_METRIC).get().getVariations().getVariation1()).isEqualTo(1d);
-    assertThat(measureRepository.getRawMeasure(VIEW, BUILD_BREAKER_METRIC).get().getVariations().getVariation1()).isEqualTo(-1d);
-  }
-
-  private static MeasureDto newMeasureDto(int metricId, long projectId, long snapshotId, double value) {
-    return new MeasureDto().setMetricId(metricId).setComponentId(projectId).setSnapshotId(snapshotId).setValue(value);
-  }
-
-  private static Period newPeriod(int index, SnapshotDto snapshotDto) {
-    return new Period(index, "mode", null, snapshotDto.getCreatedAt(), snapshotDto.getId());
-  }
-
-  private void addRawMeasure(Component component, Metric metric, Measure measure) {
-    measureRepository.add(component, metric, measure);
-  }
-}
index c4f09fcbac802128c60a3eaa7be7310e97c31d71..2a802f6be1be10421aeadf6fbbb6fd6f757d5d36 100644 (file)
  */
 package org.sonar.batch.bootstrap;
 
-import javax.annotation.CheckForNull;
-
-import org.sonar.batch.analysis.DefaultAnalysisMode;
-import org.sonar.batch.cache.PersistentCacheProvider;
-import org.sonar.batch.cache.WSLoader.LoadStrategy;
-import org.sonar.batch.analysis.AnalysisProperties;
-import org.sonar.batch.cache.StrategyWSLoaderProvider;
-import org.sonar.batch.cache.ProjectSyncContainer;
-import org.sonar.batch.rule.RulesLoader;
-import org.sonar.batch.rule.DefaultRulesLoader;
-import org.sonar.batch.rule.RulesProvider;
-
 import java.util.List;
 import java.util.Map;
-
+import javax.annotation.CheckForNull;
 import org.sonar.api.CoreProperties;
 import org.sonar.api.SonarPlugin;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.UriReader;
+import org.sonar.batch.analysis.AnalysisProperties;
+import org.sonar.batch.analysis.DefaultAnalysisMode;
+import org.sonar.batch.cache.PersistentCacheProvider;
+import org.sonar.batch.cache.ProjectSyncContainer;
+import org.sonar.batch.cache.StrategyWSLoaderProvider;
+import org.sonar.batch.cache.WSLoader.LoadStrategy;
 import org.sonar.batch.index.CachesManager;
 import org.sonar.batch.platform.DefaultServer;
 import org.sonar.batch.repository.DefaultGlobalRepositoriesLoader;
 import org.sonar.batch.repository.GlobalRepositoriesLoader;
 import org.sonar.batch.repository.GlobalRepositoriesProvider;
+import org.sonar.batch.rule.DefaultRulesLoader;
+import org.sonar.batch.rule.RulesLoader;
+import org.sonar.batch.rule.RulesProvider;
 import org.sonar.batch.scan.ProjectScanContainer;
-import org.sonar.core.config.Logback;
 import org.sonar.core.platform.ComponentContainer;
 import org.sonar.core.platform.PluginClassloaderFactory;
 import org.sonar.core.platform.PluginInfo;
@@ -94,7 +90,6 @@ public class GlobalContainer extends ComponentContainer {
       GlobalSettings.class,
       new RulesProvider(),
       ServerClient.class,
-      Logback.class,
       DefaultServer.class,
       new GlobalTempFolderProvider(),
       DefaultHttpDownloader.class,
index 0ac0c6e43980a5abe10f072dc6a4980b566a7e5b..c65e624aac522e074d02c7bcc490686258041487 100644 (file)
  */
 package org.sonar.batch.bootstrap;
 
-import org.sonar.api.batch.BatchSide;
-
-import org.junit.Rule;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.CoreProperties;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Lists;
-import org.junit.Test;
-import org.sonar.api.utils.TempFolder;
-import org.sonar.core.config.Logback;
-
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.batch.BatchSide;
+import org.sonar.api.utils.TempFolder;
+import org.sonar.core.util.UuidFactory;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -53,7 +51,7 @@ public class GlobalContainerTest {
   public void should_add_components() {
     GlobalContainer container = createContainer(Collections.emptyList());
 
-    assertThat(container.getComponentByType(Logback.class)).isNotNull();
+    assertThat(container.getComponentByType(UuidFactory.class)).isNotNull();
     assertThat(container.getComponentByType(TempFolder.class)).isNotNull();
   }
 
index efe9aede004632a709aba736c249e291488295f6..9c8f25ebc624c1be6d7ab3a6ed4111ad8bac8ee9 100644 (file)
@@ -32,7 +32,6 @@ import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.batch.BatchSide;
-import org.sonar.api.server.ServerSide;
 
 /**
  * Configure Logback
@@ -40,9 +39,12 @@ import org.sonar.api.server.ServerSide;
  * @since 2.12
  */
 @BatchSide
-@ServerSide
 public class Logback {
 
+  private Logback() {
+    // only statics
+  }
+
   public static void configure(String classloaderPath, Map<String, String> substitutionVariables) {
     InputStream input = Logback.class.getResourceAsStream(classloaderPath);
     if (input == null) {
index dcb95c2fd62a43d29eb72d6d834451d1b527c652..9abeb23dca3a5ad3bbcd9a0779c014785b507efc 100644 (file)
@@ -87,9 +87,10 @@ public final class DateUtils {
    * Parse format {@link #DATE_FORMAT}. This method never throws exception.
    *
    * @param s any string
-   * @return the date, null if parsing error or null string
+   * @return the date, {@code null} if parsing error or if parameter is {@code null}
    * @since 3.0
    */
+  @CheckForNull
   public static Date parseDateQuietly(@Nullable String s) {
     Date date = null;
     if (s != null) {
@@ -121,8 +122,9 @@ public final class DateUtils {
    * Parse format {@link #DATETIME_FORMAT}. This method never throws exception.
    *
    * @param s any string
-   * @return the datetime, null if parsing error or null string
+   * @return the datetime, {@code null} if parsing error or if parameter is {@code null}
    */
+  @CheckForNull
   public static Date parseDateTimeQuietly(@Nullable String s) {
     Date datetime = null;
     if (s != null) {