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.core.timemachine;
021
022import org.apache.commons.lang.ArrayUtils;
023import org.sonar.api.batch.Decorator;
024import org.sonar.api.batch.DecoratorBarriers;
025import org.sonar.api.batch.DecoratorContext;
026import org.sonar.api.batch.DependedUpon;
027import org.sonar.api.measures.CoreMetrics;
028import org.sonar.api.measures.Measure;
029import org.sonar.api.measures.Metric;
030import org.sonar.api.resources.Project;
031import org.sonar.api.resources.Qualifiers;
032import org.sonar.api.resources.Resource;
033import org.sonar.api.resources.Scopes;
034
035import java.util.Arrays;
036import java.util.List;
037
038@DependedUpon(DecoratorBarriers.END_OF_TIME_MACHINE)
039public final class NewCoverageAggregator implements Decorator {
040
041  public boolean shouldExecuteOnProject(Project project) {
042    return true;
043  }
044
045  @DependedUpon
046  public List<Metric> generatesNewCoverageMetrics() {
047    return Arrays.asList(
048      CoreMetrics.NEW_LINES_TO_COVER, CoreMetrics.NEW_UNCOVERED_LINES, CoreMetrics.NEW_CONDITIONS_TO_COVER, CoreMetrics.NEW_UNCOVERED_CONDITIONS,
049      CoreMetrics.NEW_IT_LINES_TO_COVER, CoreMetrics.NEW_IT_UNCOVERED_LINES, CoreMetrics.NEW_IT_CONDITIONS_TO_COVER, CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS);
050  }
051
052  public void decorate(Resource resource, DecoratorContext context) {
053    if (shouldDecorate(resource)) {
054      int maxPeriods = (Qualifiers.isView(resource, true) ? 3 : 5);
055      aggregate(context, CoreMetrics.NEW_LINES_TO_COVER, maxPeriods);
056      aggregate(context, CoreMetrics.NEW_UNCOVERED_LINES, maxPeriods);
057      aggregate(context, CoreMetrics.NEW_CONDITIONS_TO_COVER, maxPeriods);
058      aggregate(context, CoreMetrics.NEW_UNCOVERED_CONDITIONS, maxPeriods);
059      aggregate(context, CoreMetrics.NEW_IT_LINES_TO_COVER, maxPeriods);
060      aggregate(context, CoreMetrics.NEW_IT_UNCOVERED_LINES, maxPeriods);
061      aggregate(context, CoreMetrics.NEW_IT_CONDITIONS_TO_COVER, maxPeriods);
062      aggregate(context, CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS, maxPeriods);
063    }
064  }
065
066  void aggregate(DecoratorContext context, Metric metric, int maxPeriods) {
067    int[] variations = {0,0,0,0,0};
068    boolean[] hasValues = {false,false,false,false,false};
069    for (Measure child : context.getChildrenMeasures(metric)) {
070      for (int indexPeriod=1 ; indexPeriod<=maxPeriods ; indexPeriod++) {
071        Double variation = child.getVariation(indexPeriod);
072        if (variation!=null) {
073          variations[indexPeriod-1]=variations[indexPeriod-1] + variation.intValue();
074          hasValues[indexPeriod-1]=true;
075        }
076      }
077    }
078
079    if (ArrayUtils.contains(hasValues, true)) {
080      Measure measure = new Measure(metric);
081      for (int index=0 ; index<5 ; index++) {
082        if (hasValues[index]) {
083          measure.setVariation(index+1, (double)variations[index]);
084        }
085      }
086      context.saveMeasure(measure);
087    }
088  }
089
090  boolean shouldDecorate(Resource resource) {
091    return Scopes.isHigherThan(resource, Scopes.FILE);
092  }
093}