]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6253 Rename some steps
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Wed, 13 May 2015 08:29:33 +0000 (10:29 +0200)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Wed, 13 May 2015 08:54:57 +0000 (10:54 +0200)
server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistComponentLinksStep.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistDuplicationMeasuresStep.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistDuplicationsStep.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistProjectLinksStep.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputationStepsTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistComponentLinksStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistDuplicationMeasuresStepTest.java

index e4c0b273fa8a5be9e8c986b79323852f3ec2e918..b391f9fd64c9ee7a71ca4223fa2e59c67bc589bd 100644 (file)
@@ -44,9 +44,9 @@ public class ComputationSteps {
       PersistNumberOfDaysSinceLastCommitStep.class,
       PersistMeasuresStep.class,
       PersistIssuesStep.class,
-      PersistComponentLinksStep.class,
+      PersistProjectLinksStep.class,
       PersistEventsStep.class,
-      PersistDuplicationMeasuresStep.class,
+      PersistDuplicationsStep.class,
       PersistFileSourcesStep.class,
       PersistTestsStep.class,
       PersistFileDependenciesStep.class,
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistComponentLinksStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistComponentLinksStep.java
deleted file mode 100644 (file)
index fbd0e7b..0000000
+++ /dev/null
@@ -1,149 +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 com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-import org.sonar.api.i18n.I18n;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.batch.protocol.Constants;
-import org.sonar.batch.protocol.output.BatchReport;
-import org.sonar.batch.protocol.output.BatchReportReader;
-import org.sonar.core.component.ComponentLinkDto;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.server.computation.ComputationContext;
-import org.sonar.server.db.DbClient;
-
-import javax.annotation.Nullable;
-
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-
-import static com.google.common.collect.Sets.newHashSet;
-
-public class PersistComponentLinksStep implements ComputationStep {
-
-  private final DbClient dbClient;
-  private final I18n i18n;
-
-  private static final Map<Constants.ComponentLinkType, String> typesConverter = ImmutableMap.of(
-    Constants.ComponentLinkType.HOME, ComponentLinkDto.TYPE_HOME_PAGE,
-    Constants.ComponentLinkType.SCM, ComponentLinkDto.TYPE_SOURCES,
-    Constants.ComponentLinkType.SCM_DEV, ComponentLinkDto.TYPE_SOURCES_DEV,
-    Constants.ComponentLinkType.CI, ComponentLinkDto.TYPE_CI,
-    Constants.ComponentLinkType.ISSUE, ComponentLinkDto.TYPE_ISSUE_TRACKER
-    );
-
-  public PersistComponentLinksStep(DbClient dbClient, I18n i18n) {
-    this.dbClient = dbClient;
-    this.i18n = i18n;
-  }
-
-  @Override
-  public String[] supportedProjectQualifiers() {
-    return new String[] {Qualifiers.PROJECT};
-  }
-
-  @Override
-  public void execute(ComputationContext context) {
-    DbSession session = dbClient.openSession(false);
-    try {
-      int rootComponentRef = context.getReportMetadata().getRootComponentRef();
-      recursivelyProcessComponent(session, context, rootComponentRef);
-      session.commit();
-    } finally {
-      MyBatis.closeQuietly(session);
-    }
-  }
-
-  private void recursivelyProcessComponent(DbSession session, ComputationContext context, int componentRef) {
-    BatchReportReader reportReader = context.getReportReader();
-    BatchReport.Component component = reportReader.readComponent(componentRef);
-    processLinks(session, component);
-
-    for (Integer childRef : component.getChildRefList()) {
-      recursivelyProcessComponent(session, context, childRef);
-    }
-  }
-
-  private void processLinks(DbSession session, BatchReport.Component component) {
-    if (component.getType().equals(Constants.ComponentType.PROJECT) || component.getType().equals(Constants.ComponentType.MODULE)) {
-      List<BatchReport.ComponentLink> links = component.getLinkList();
-      List<ComponentLinkDto> previousLinks = dbClient.componentLinkDao().selectByComponentUuid(session, component.getUuid());
-      mergeLinks(session, component.getUuid(), links, previousLinks);
-    }
-  }
-
-  private void mergeLinks(DbSession session, String componentUuid, List<BatchReport.ComponentLink> links, List<ComponentLinkDto> previousLinks) {
-    Set<String> linkType = newHashSet();
-    for (final BatchReport.ComponentLink link : links) {
-      String type = convertType(link.getType());
-      if (!linkType.contains(type)) {
-        linkType.add(type);
-      } else {
-        throw new IllegalArgumentException(String.format("Link of type '%s' has already been declared on component '%s'", type, componentUuid));
-      }
-
-      ComponentLinkDto previousLink = Iterables.find(previousLinks, new Predicate<ComponentLinkDto>() {
-        @Override
-        public boolean apply(@Nullable ComponentLinkDto input) {
-          return input != null && input.getType().equals(convertType(link.getType()));
-        }
-      }, null);
-      if (previousLink == null) {
-        dbClient.componentLinkDao().insert(session,
-          new ComponentLinkDto()
-            .setComponentUuid(componentUuid)
-            .setType(type)
-            .setName(i18n.message(Locale.ENGLISH, "project_links." + type, null))
-            .setHref(link.getHref())
-          );
-      } else {
-        previousLink.setHref(link.getHref());
-        dbClient.componentLinkDao().update(session, previousLink);
-      }
-    }
-
-    for (ComponentLinkDto dto : previousLinks) {
-      if (!linkType.contains(dto.getType()) && ComponentLinkDto.PROVIDED_TYPES.contains(dto.getType())) {
-        dbClient.componentLinkDao().delete(session, dto.getId());
-      }
-    }
-  }
-
-  private static String convertType(Constants.ComponentLinkType reportType) {
-    String type = typesConverter.get(reportType);
-    if (type != null) {
-      return type;
-    } else {
-      throw new IllegalArgumentException(String.format("Unsupported type %s", reportType.name()));
-    }
-  }
-
-  @Override
-  public String getDescription() {
-    return "Persist component links";
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistDuplicationMeasuresStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistDuplicationMeasuresStep.java
deleted file mode 100644 (file)
index 3f9f538..0000000
+++ /dev/null
@@ -1,174 +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.apache.commons.lang.StringEscapeUtils;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.batch.protocol.Constants;
-import org.sonar.batch.protocol.output.BatchReport;
-import org.sonar.batch.protocol.output.BatchReport.Range;
-import org.sonar.batch.protocol.output.BatchReportReader;
-import org.sonar.core.component.ComponentKeys;
-import org.sonar.core.measure.db.MeasureDto;
-import org.sonar.core.measure.db.MetricDto;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.server.computation.ComputationContext;
-import org.sonar.server.db.DbClient;
-
-import java.util.List;
-
-public class PersistDuplicationMeasuresStep implements ComputationStep {
-
-  private final DbClient dbClient;
-
-  public PersistDuplicationMeasuresStep(DbClient dbClient) {
-    this.dbClient = dbClient;
-  }
-
-  @Override
-  public String[] supportedProjectQualifiers() {
-    return new String[] {Qualifiers.PROJECT};
-  }
-
-  @Override
-  public void execute(ComputationContext context) {
-    DbSession session = dbClient.openSession(true);
-    try {
-      MetricDto duplicationMetric = dbClient.metricDao().selectByKey(session, CoreMetrics.DUPLICATIONS_DATA_KEY);
-      DuplicationContext duplicationContext = new DuplicationContext(context, duplicationMetric, session);
-      int rootComponentRef = context.getReportMetadata().getRootComponentRef();
-      recursivelyProcessComponent(duplicationContext, rootComponentRef, rootComponentRef);
-      session.commit();
-    } finally {
-      MyBatis.closeQuietly(session);
-    }
-  }
-
-  private void recursivelyProcessComponent(DuplicationContext duplicationContext, int parentModuleRef, int componentRef) {
-    BatchReportReader reportReader = duplicationContext.context().getReportReader();
-    BatchReport.Component component = reportReader.readComponent(componentRef);
-    List<BatchReport.Duplication> duplications = reportReader.readComponentDuplications(componentRef);
-    if (!duplications.isEmpty()) {
-      saveDuplications(duplicationContext, reportReader.readComponent(parentModuleRef), component, duplications);
-    }
-
-    for (Integer childRef : component.getChildRefList()) {
-      // If current component is a folder, we need to keep the parent reference to module parent
-      int nextParent = !component.getType().equals(Constants.ComponentType.PROJECT) && !component.getType().equals(Constants.ComponentType.MODULE) ?
-        parentModuleRef : componentRef;
-      recursivelyProcessComponent(duplicationContext, nextParent, childRef);
-    }
-  }
-
-  private void saveDuplications(DuplicationContext duplicationContext, BatchReport.Component parentComponent, BatchReport.Component component,
-    List<BatchReport.Duplication> duplications) {
-
-    String duplicationXml = createXmlDuplications(duplicationContext, parentComponent, component.getPath(), duplications);
-    MeasureDto measureDto = new MeasureDto()
-      .setMetricId(duplicationContext.metric().getId())
-      .setData(duplicationXml)
-      .setComponentId(component.getId())
-      .setSnapshotId(component.getSnapshotId());
-    dbClient.measureDao().insert(duplicationContext.session(), measureDto);
-  }
-
-  private String createXmlDuplications(DuplicationContext duplicationContext, BatchReport.Component parentComponent, String componentPath,
-    Iterable<BatchReport.Duplication> duplications) {
-
-    StringBuilder xml = new StringBuilder();
-    xml.append("<duplications>");
-    for (BatchReport.Duplication duplication : duplications) {
-      xml.append("<g>");
-      appendDuplication(xml, ComponentKeys.createKey(parentComponent.getKey(), componentPath, duplicationContext.context().getReportMetadata().getBranch()),
-        duplication.getOriginPosition());
-      for (BatchReport.Duplicate duplicationBlock : duplication.getDuplicateList()) {
-        processDuplicationBlock(duplicationContext, xml, duplicationBlock, parentComponent.getKey(), componentPath);
-      }
-      xml.append("</g>");
-    }
-    xml.append("</duplications>");
-    return xml.toString();
-  }
-
-  private void processDuplicationBlock(DuplicationContext duplicationContext, StringBuilder xml, BatchReport.Duplicate duplicate, String parentComponentKey,
-    String componentPath) {
-
-    if (duplicate.hasOtherFileKey()) {
-      // componentKey is only set for cross project duplications
-      String crossProjectComponentKey = duplicate.getOtherFileKey();
-      appendDuplication(xml, crossProjectComponentKey, duplicate);
-    } else {
-      String branch = duplicationContext.context().getReportMetadata().getBranch();
-      if (duplicate.hasOtherFileRef()) {
-        // Duplication is on a different file
-        BatchReport.Component duplicationComponent = duplicationContext.context().getReportReader().readComponent(duplicate.getOtherFileRef());
-        appendDuplication(xml, ComponentKeys.createKey(parentComponentKey, duplicationComponent.getPath(), branch), duplicate);
-      } else {
-        // Duplication is on a the same file
-        appendDuplication(xml, ComponentKeys.createKey(parentComponentKey, componentPath, branch), duplicate);
-      }
-    }
-  }
-
-  private static void appendDuplication(StringBuilder xml, String componentKey, BatchReport.Duplicate duplicate) {
-    appendDuplication(xml, componentKey, duplicate.getRange());
-  }
-
-  private static void appendDuplication(StringBuilder xml, String componentKey, Range range) {
-    int length = range.getEndLine() - range.getStartLine() + 1;
-    xml.append("<b s=\"").append(range.getStartLine())
-      .append("\" l=\"").append(length)
-      .append("\" r=\"").append(StringEscapeUtils.escapeXml(componentKey))
-      .append("\"/>");
-  }
-
-  private static class DuplicationContext {
-    private DbSession session;
-    private ComputationContext context;
-    private MetricDto duplicationMetric;
-
-    DuplicationContext(ComputationContext context, MetricDto duplicationMetric, DbSession session) {
-      this.context = context;
-      this.duplicationMetric = duplicationMetric;
-      this.session = session;
-    }
-
-    public ComputationContext context() {
-      return context;
-    }
-
-    public MetricDto metric() {
-      return duplicationMetric;
-    }
-
-    public DbSession session() {
-      return session;
-    }
-  }
-
-  @Override
-  public String getDescription() {
-    return "Persist duplications";
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistDuplicationsStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistDuplicationsStep.java
new file mode 100644 (file)
index 0000000..582a469
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * 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.apache.commons.lang.StringEscapeUtils;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.batch.protocol.Constants;
+import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.batch.protocol.output.BatchReport.Range;
+import org.sonar.batch.protocol.output.BatchReportReader;
+import org.sonar.core.component.ComponentKeys;
+import org.sonar.core.measure.db.MeasureDto;
+import org.sonar.core.measure.db.MetricDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.server.computation.ComputationContext;
+import org.sonar.server.db.DbClient;
+
+import java.util.List;
+
+/**
+ * Persist duplications into
+ */
+public class PersistDuplicationsStep implements ComputationStep {
+
+  private final DbClient dbClient;
+
+  public PersistDuplicationsStep(DbClient dbClient) {
+    this.dbClient = dbClient;
+  }
+
+  @Override
+  public String[] supportedProjectQualifiers() {
+    return new String[] {Qualifiers.PROJECT};
+  }
+
+  @Override
+  public void execute(ComputationContext context) {
+    DbSession session = dbClient.openSession(true);
+    try {
+      MetricDto duplicationMetric = dbClient.metricDao().selectByKey(session, CoreMetrics.DUPLICATIONS_DATA_KEY);
+      DuplicationContext duplicationContext = new DuplicationContext(context, duplicationMetric, session);
+      int rootComponentRef = context.getReportMetadata().getRootComponentRef();
+      recursivelyProcessComponent(duplicationContext, rootComponentRef, rootComponentRef);
+      session.commit();
+    } finally {
+      MyBatis.closeQuietly(session);
+    }
+  }
+
+  private void recursivelyProcessComponent(DuplicationContext duplicationContext, int parentModuleRef, int componentRef) {
+    BatchReportReader reportReader = duplicationContext.context().getReportReader();
+    BatchReport.Component component = reportReader.readComponent(componentRef);
+    List<BatchReport.Duplication> duplications = reportReader.readComponentDuplications(componentRef);
+    if (!duplications.isEmpty()) {
+      saveDuplications(duplicationContext, reportReader.readComponent(parentModuleRef), component, duplications);
+    }
+
+    for (Integer childRef : component.getChildRefList()) {
+      // If current component is a folder, we need to keep the parent reference to module parent
+      int nextParent = !component.getType().equals(Constants.ComponentType.PROJECT) && !component.getType().equals(Constants.ComponentType.MODULE) ?
+        parentModuleRef : componentRef;
+      recursivelyProcessComponent(duplicationContext, nextParent, childRef);
+    }
+  }
+
+  private void saveDuplications(DuplicationContext duplicationContext, BatchReport.Component parentComponent, BatchReport.Component component,
+    List<BatchReport.Duplication> duplications) {
+
+    String duplicationXml = createXmlDuplications(duplicationContext, parentComponent, component.getPath(), duplications);
+    MeasureDto measureDto = new MeasureDto()
+      .setMetricId(duplicationContext.metric().getId())
+      .setData(duplicationXml)
+      .setComponentId(component.getId())
+      .setSnapshotId(component.getSnapshotId());
+    dbClient.measureDao().insert(duplicationContext.session(), measureDto);
+  }
+
+  private String createXmlDuplications(DuplicationContext duplicationContext, BatchReport.Component parentComponent, String componentPath,
+    Iterable<BatchReport.Duplication> duplications) {
+
+    StringBuilder xml = new StringBuilder();
+    xml.append("<duplications>");
+    for (BatchReport.Duplication duplication : duplications) {
+      xml.append("<g>");
+      appendDuplication(xml, ComponentKeys.createKey(parentComponent.getKey(), componentPath, duplicationContext.context().getReportMetadata().getBranch()),
+        duplication.getOriginPosition());
+      for (BatchReport.Duplicate duplicationBlock : duplication.getDuplicateList()) {
+        processDuplicationBlock(duplicationContext, xml, duplicationBlock, parentComponent.getKey(), componentPath);
+      }
+      xml.append("</g>");
+    }
+    xml.append("</duplications>");
+    return xml.toString();
+  }
+
+  private void processDuplicationBlock(DuplicationContext duplicationContext, StringBuilder xml, BatchReport.Duplicate duplicate, String parentComponentKey,
+    String componentPath) {
+
+    if (duplicate.hasOtherFileKey()) {
+      // componentKey is only set for cross project duplications
+      String crossProjectComponentKey = duplicate.getOtherFileKey();
+      appendDuplication(xml, crossProjectComponentKey, duplicate);
+    } else {
+      String branch = duplicationContext.context().getReportMetadata().getBranch();
+      if (duplicate.hasOtherFileRef()) {
+        // Duplication is on a different file
+        BatchReport.Component duplicationComponent = duplicationContext.context().getReportReader().readComponent(duplicate.getOtherFileRef());
+        appendDuplication(xml, ComponentKeys.createKey(parentComponentKey, duplicationComponent.getPath(), branch), duplicate);
+      } else {
+        // Duplication is on a the same file
+        appendDuplication(xml, ComponentKeys.createKey(parentComponentKey, componentPath, branch), duplicate);
+      }
+    }
+  }
+
+  private static void appendDuplication(StringBuilder xml, String componentKey, BatchReport.Duplicate duplicate) {
+    appendDuplication(xml, componentKey, duplicate.getRange());
+  }
+
+  private static void appendDuplication(StringBuilder xml, String componentKey, Range range) {
+    int length = range.getEndLine() - range.getStartLine() + 1;
+    xml.append("<b s=\"").append(range.getStartLine())
+      .append("\" l=\"").append(length)
+      .append("\" r=\"").append(StringEscapeUtils.escapeXml(componentKey))
+      .append("\"/>");
+  }
+
+  private static class DuplicationContext {
+    private DbSession session;
+    private ComputationContext context;
+    private MetricDto duplicationMetric;
+
+    DuplicationContext(ComputationContext context, MetricDto duplicationMetric, DbSession session) {
+      this.context = context;
+      this.duplicationMetric = duplicationMetric;
+      this.session = session;
+    }
+
+    public ComputationContext context() {
+      return context;
+    }
+
+    public MetricDto metric() {
+      return duplicationMetric;
+    }
+
+    public DbSession session() {
+      return session;
+    }
+  }
+
+  @Override
+  public String getDescription() {
+    return "Persist duplications";
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistProjectLinksStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistProjectLinksStep.java
new file mode 100644 (file)
index 0000000..e94a1aa
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * 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 com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import org.sonar.api.i18n.I18n;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.batch.protocol.Constants;
+import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.batch.protocol.output.BatchReportReader;
+import org.sonar.core.component.ComponentLinkDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.server.computation.ComputationContext;
+import org.sonar.server.db.DbClient;
+
+import javax.annotation.Nullable;
+
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import static com.google.common.collect.Sets.newHashSet;
+
+/**
+ * Persist project and module links
+ */
+public class PersistProjectLinksStep implements ComputationStep {
+
+  private final DbClient dbClient;
+  private final I18n i18n;
+
+  private static final Map<Constants.ComponentLinkType, String> typesConverter = ImmutableMap.of(
+    Constants.ComponentLinkType.HOME, ComponentLinkDto.TYPE_HOME_PAGE,
+    Constants.ComponentLinkType.SCM, ComponentLinkDto.TYPE_SOURCES,
+    Constants.ComponentLinkType.SCM_DEV, ComponentLinkDto.TYPE_SOURCES_DEV,
+    Constants.ComponentLinkType.CI, ComponentLinkDto.TYPE_CI,
+    Constants.ComponentLinkType.ISSUE, ComponentLinkDto.TYPE_ISSUE_TRACKER
+    );
+
+  public PersistProjectLinksStep(DbClient dbClient, I18n i18n) {
+    this.dbClient = dbClient;
+    this.i18n = i18n;
+  }
+
+  @Override
+  public String[] supportedProjectQualifiers() {
+    return new String[] {Qualifiers.PROJECT};
+  }
+
+  @Override
+  public void execute(ComputationContext context) {
+    DbSession session = dbClient.openSession(false);
+    try {
+      int rootComponentRef = context.getReportMetadata().getRootComponentRef();
+      recursivelyProcessComponent(session, context, rootComponentRef);
+      session.commit();
+    } finally {
+      MyBatis.closeQuietly(session);
+    }
+  }
+
+  private void recursivelyProcessComponent(DbSession session, ComputationContext context, int componentRef) {
+    BatchReportReader reportReader = context.getReportReader();
+    BatchReport.Component component = reportReader.readComponent(componentRef);
+    processLinks(session, component);
+
+    for (Integer childRef : component.getChildRefList()) {
+      recursivelyProcessComponent(session, context, childRef);
+    }
+  }
+
+  private void processLinks(DbSession session, BatchReport.Component component) {
+    if (component.getType().equals(Constants.ComponentType.PROJECT) || component.getType().equals(Constants.ComponentType.MODULE)) {
+      List<BatchReport.ComponentLink> links = component.getLinkList();
+      List<ComponentLinkDto> previousLinks = dbClient.componentLinkDao().selectByComponentUuid(session, component.getUuid());
+      mergeLinks(session, component.getUuid(), links, previousLinks);
+    }
+  }
+
+  private void mergeLinks(DbSession session, String componentUuid, List<BatchReport.ComponentLink> links, List<ComponentLinkDto> previousLinks) {
+    Set<String> linkType = newHashSet();
+    for (final BatchReport.ComponentLink link : links) {
+      String type = convertType(link.getType());
+      if (!linkType.contains(type)) {
+        linkType.add(type);
+      } else {
+        throw new IllegalArgumentException(String.format("Link of type '%s' has already been declared on component '%s'", type, componentUuid));
+      }
+
+      ComponentLinkDto previousLink = Iterables.find(previousLinks, new Predicate<ComponentLinkDto>() {
+        @Override
+        public boolean apply(@Nullable ComponentLinkDto input) {
+          return input != null && input.getType().equals(convertType(link.getType()));
+        }
+      }, null);
+      if (previousLink == null) {
+        dbClient.componentLinkDao().insert(session,
+          new ComponentLinkDto()
+            .setComponentUuid(componentUuid)
+            .setType(type)
+            .setName(i18n.message(Locale.ENGLISH, "project_links." + type, null))
+            .setHref(link.getHref())
+          );
+      } else {
+        previousLink.setHref(link.getHref());
+        dbClient.componentLinkDao().update(session, previousLink);
+      }
+    }
+
+    for (ComponentLinkDto dto : previousLinks) {
+      if (!linkType.contains(dto.getType()) && ComponentLinkDto.PROVIDED_TYPES.contains(dto.getType())) {
+        dbClient.componentLinkDao().delete(session, dto.getId());
+      }
+    }
+  }
+
+  private static String convertType(Constants.ComponentLinkType reportType) {
+    String type = typesConverter.get(reportType);
+    if (type != null) {
+      return type;
+    } else {
+      throw new IllegalArgumentException(String.format("Unsupported type %s", reportType.name()));
+    }
+  }
+
+  @Override
+  public String getDescription() {
+    return "Persist component links";
+  }
+}
index 493e4e153b1a16e8c45966513537f7167972f03a..020036506d1b3826861ec1bf9fc1f17b8324f379 100644 (file)
@@ -43,10 +43,10 @@ public class ComputationStepsTest {
       mock(PurgeDatastoresStep.class),
       mock(SendIssueNotificationsStep.class),
       mock(IndexComponentsStep.class),
-      mock(PersistComponentLinksStep.class),
+      mock(PersistProjectLinksStep.class),
       mock(PersistMeasuresStep.class),
       mock(PersistEventsStep.class),
-      mock(PersistDuplicationMeasuresStep.class),
+      mock(PersistDuplicationsStep.class),
       mock(PersistNumberOfDaysSinceLastCommitStep.class),
       mock(PersistFileSourcesStep.class),
       mock(PersistFileDependenciesStep.class),
index 12f5cb1345104b80382170b654c0fcaccc83bfcf..6677e55b24a32afd80722fa8769f3997eb9ed539 100644 (file)
 
 package org.sonar.server.computation.step;
 
-import org.junit.*;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
 import org.junit.experimental.categories.Category;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.i18n.I18n;
@@ -59,7 +63,7 @@ public class PersistComponentLinksStepTest extends BaseStepTest {
 
   I18n i18n;
 
-  PersistComponentLinksStep step;
+  PersistProjectLinksStep step;
 
   @Before
   public void setup() {
@@ -74,7 +78,7 @@ public class PersistComponentLinksStepTest extends BaseStepTest {
     when(i18n.message(Locale.ENGLISH, "project_links.ci", null)).thenReturn("Continuous integration");
     when(i18n.message(Locale.ENGLISH, "project_links.issue", null)).thenReturn("Issues");
 
-    step = new PersistComponentLinksStep(dbClient, i18n);
+    step = new PersistProjectLinksStep(dbClient, i18n);
   }
 
   @Override
index b1c5871de2b5dbb02bd2778c128c9f6b36d723da..aa88b178334b686390426995da32b428e0e4bf0d 100644 (file)
 
 package org.sonar.server.computation.step;
 
-import org.junit.*;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
 import org.junit.experimental.categories.Category;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.measures.CoreMetrics;
@@ -61,7 +65,7 @@ public class
 
   DbClient dbClient;
 
-  PersistDuplicationMeasuresStep sut;
+  PersistDuplicationsStep sut;
 
   @Before
   public void setup() throws Exception {
@@ -71,7 +75,7 @@ public class
 
     reportDir = temp.newFolder();
 
-    sut = new PersistDuplicationMeasuresStep(dbClient);
+    sut = new PersistDuplicationsStep(dbClient);
   }
 
   @Override