001/*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2008-2012 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * Sonar is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * Sonar is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public
017 * License along with Sonar; if not, write to the Free Software
018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
019 */
020package org.sonar.plugins.cpd.decorators;
021
022import org.sonar.api.batch.Decorator;
023import org.sonar.api.batch.DecoratorContext;
024import org.sonar.api.batch.DependedUpon;
025import org.sonar.api.batch.DependsUpon;
026import org.sonar.api.measures.CoreMetrics;
027import org.sonar.api.measures.Measure;
028import org.sonar.api.measures.Metric;
029import org.sonar.api.resources.Project;
030import org.sonar.api.resources.Resource;
031
032import java.util.Arrays;
033import java.util.List;
034
035public class DuplicationDensityDecorator implements Decorator {
036
037  @DependsUpon
038  public List<Metric> dependsUponMetrics() {
039    return Arrays.asList(
040        CoreMetrics.NCLOC,
041        CoreMetrics.COMMENT_LINES,
042        CoreMetrics.DUPLICATED_LINES,
043        CoreMetrics.LINES);
044  }
045
046  @DependedUpon
047  public Metric generatesMetric() {
048    return CoreMetrics.DUPLICATED_LINES_DENSITY;
049  }
050
051  public boolean shouldExecuteOnProject(Project project) {
052    return true;
053  }
054
055  public void decorate(Resource resource, DecoratorContext context) {
056    Measure nbDuplicatedLines = context.getMeasure(CoreMetrics.DUPLICATED_LINES);
057    if (nbDuplicatedLines == null) {
058      return;
059    }
060
061    Double divisor = getNbLinesFromLocOrNcloc(context);
062    if (divisor != null && divisor > 0.0) {
063      context.saveMeasure(CoreMetrics.DUPLICATED_LINES_DENSITY, calculate(nbDuplicatedLines.getValue(), divisor));
064    }
065  }
066
067  private Double getNbLinesFromLocOrNcloc(DecoratorContext context) {
068    Measure nbLoc = context.getMeasure(CoreMetrics.LINES);
069    if (nbLoc != null) {
070      // TODO test this branch
071      return nbLoc.getValue();
072    }
073    Measure nbNcloc = context.getMeasure(CoreMetrics.NCLOC);
074    if (nbNcloc != null) {
075      Measure nbComments = context.getMeasure(CoreMetrics.COMMENT_LINES);
076      Double nbLines = nbNcloc.getValue();
077      return nbComments != null ? nbLines + nbComments.getValue() : nbLines;
078    }
079    return null;
080  }
081
082  protected Double calculate(Double dividend, Double divisor) {
083    Double result = 100.0 * dividend / divisor;
084    if (result < 100.0) {
085      return result;
086    }
087    return 100.0;
088  }
089
090}