All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sonar.server.computation.step.DuplicationDataMeasuresStep Maven / Gradle / Ivy

There is a newer version: 7.0
Show newest version
/*
 * SonarQube
 * Copyright (C) 2009-2016 SonarSource SA
 * mailto:contact AT sonarsource DOT com
 *
 * This program 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.
 *
 * This program 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.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.duplication.CrossProjectDuplicate;
import org.sonar.server.computation.duplication.Duplicate;
import org.sonar.server.computation.duplication.Duplication;
import org.sonar.server.computation.duplication.DuplicationRepository;
import org.sonar.server.computation.duplication.InProjectDuplicate;
import org.sonar.server.computation.duplication.InnerDuplicate;
import org.sonar.server.computation.duplication.TextBlock;
import org.sonar.server.computation.measure.Measure;
import org.sonar.server.computation.measure.MeasureRepository;
import org.sonar.server.computation.metric.Metric;
import org.sonar.server.computation.metric.MetricRepository;

import static com.google.common.collect.Iterables.isEmpty;
import static org.sonar.api.measures.CoreMetrics.DUPLICATIONS_DATA_KEY;
import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;

/**
 * Compute duplication data measures on files, based on the {@link DuplicationRepository}
 */
public class DuplicationDataMeasuresStep implements ComputationStep {

  private final MeasureRepository measureRepository;
  private final TreeRootHolder treeRootHolder;
  private final DuplicationRepository duplicationRepository;

  private final Metric duplicationDataMetric;

  public DuplicationDataMeasuresStep(TreeRootHolder treeRootHolder, MetricRepository metricRepository, MeasureRepository measureRepository,
    DuplicationRepository duplicationRepository) {
    this.measureRepository = measureRepository;
    this.treeRootHolder = treeRootHolder;
    this.duplicationRepository = duplicationRepository;
    this.duplicationDataMetric = metricRepository.getByKey(DUPLICATIONS_DATA_KEY);
  }

  @Override
  public void execute() {
    new DepthTraversalTypeAwareCrawler(new DuplicationVisitor())
      .visit(treeRootHolder.getRoot());
  }

  private class DuplicationVisitor extends TypeAwareVisitorAdapter {

    private DuplicationVisitor() {
      super(CrawlerDepthLimit.FILE, PRE_ORDER);
    }

    @Override
    public void visitFile(Component file) {
      Iterable duplications = duplicationRepository.getDuplications(file);
      if (!isEmpty(duplications)) {
        computeDuplications(file, duplications);
      }
    }

    private void computeDuplications(Component component, Iterable duplications) {
      String duplicationXml = createXmlDuplications(component.getKey(), duplications);
      measureRepository.add(
        component,
        duplicationDataMetric,
        Measure.newMeasureBuilder().create(duplicationXml)
        );
    }

    private String createXmlDuplications(String componentKey, Iterable duplications) {
      StringBuilder xml = new StringBuilder();
      xml.append("");
      for (Duplication duplication : duplications) {
        xml.append("");
        appendDuplication(xml, componentKey, duplication.getOriginal());
        for (Duplicate duplicate : duplication.getDuplicates()) {
          processDuplicationBlock(xml, duplicate, componentKey);
        }
        xml.append("");
      }
      xml.append("");
      return xml.toString();
    }

    private void processDuplicationBlock(StringBuilder xml, Duplicate duplicate, String componentKey) {
      if (duplicate instanceof InnerDuplicate) {
        // Duplication is on a the same file
        appendDuplication(xml, componentKey, duplicate);
      } else if (duplicate instanceof InProjectDuplicate) {
        // Duplication is on a different file
        appendDuplication(xml, ((InProjectDuplicate) duplicate).getFile().getKey(), duplicate);
      } else if (duplicate instanceof CrossProjectDuplicate) {
        // componentKey is only set for cross project duplications
        String crossProjectComponentKey = ((CrossProjectDuplicate) duplicate).getFileKey();
        appendDuplication(xml, crossProjectComponentKey, duplicate);
      } else {
        throw new IllegalArgumentException("Unsupported type of Duplicate " + duplicate.getClass().getName());
      }
    }

    private void appendDuplication(StringBuilder xml, String componentKey, Duplicate duplicate) {
      appendDuplication(xml, componentKey, duplicate.getTextBlock());
    }

    private void appendDuplication(StringBuilder xml, String componentKey, TextBlock textBlock) {
      int length = textBlock.getEnd() - textBlock.getStart() + 1;
      xml.append("");
    }
  }

  @Override
  public String getDescription() {
    return "Compute duplication data measures";
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy