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.api.measures;
021
022import com.google.common.collect.Lists;
023import com.google.common.collect.Maps;
024import org.sonar.api.utils.KeyValueFormat;
025
026import java.util.*;
027
028/**
029 * @since 2.7
030 */
031public final class CoverageMeasuresBuilder {
032
033  /**
034   * Metrics of generated measures
035   */
036  public static final List<Metric> METRICS = Arrays.asList(
037      CoreMetrics.LINES_TO_COVER, CoreMetrics.UNCOVERED_LINES, CoreMetrics.COVERAGE_LINE_HITS_DATA,
038      CoreMetrics.CONDITIONS_TO_COVER, CoreMetrics.UNCOVERED_CONDITIONS, CoreMetrics.CONDITIONS_BY_LINE,
039      CoreMetrics.COVERED_CONDITIONS_BY_LINE);
040
041
042  private int totalCoveredLines = 0, totalConditions = 0, totalCoveredConditions = 0;
043  private SortedMap<Integer, Integer> hitsByLine = Maps.newTreeMap();
044  private SortedMap<Integer, Integer> conditionsByLine = Maps.newTreeMap();
045  private SortedMap<Integer, Integer> coveredConditionsByLine = Maps.newTreeMap();
046
047  private CoverageMeasuresBuilder() {
048    // use the factory
049  }
050
051  public CoverageMeasuresBuilder reset() {
052    totalCoveredLines = 0;
053    totalConditions = 0;
054    totalCoveredConditions = 0;
055    hitsByLine.clear();
056    conditionsByLine.clear();
057    coveredConditionsByLine.clear();
058    return this;
059  }
060
061  public CoverageMeasuresBuilder setHits(int lineId, int hits) {
062    if (!hitsByLine.containsKey(lineId)) {
063      hitsByLine.put(lineId, hits);
064      if (hits > 0) {
065        totalCoveredLines += 1;
066      }
067    }
068    return this;
069  }
070
071  public CoverageMeasuresBuilder setConditions(int lineId, int conditions, int coveredConditions) {
072    if (!conditionsByLine.containsKey(lineId)) {
073      if (conditions > 0) {
074        totalConditions += conditions;
075        totalCoveredConditions += coveredConditions;
076        conditionsByLine.put(lineId, conditions);
077        coveredConditionsByLine.put(lineId, coveredConditions);
078      }
079    }
080    return this;
081  }
082
083  public int getCoveredLines() {
084    return totalCoveredLines;
085  }
086
087  public int getLinesToCover() {
088    return hitsByLine.size();
089  }
090
091  public int getConditions() {
092    return totalConditions;
093  }
094
095  public int getCoveredConditions() {
096    return totalCoveredConditions;
097  }
098
099  public SortedMap<Integer, Integer> getHitsByLine() {
100    return Collections.unmodifiableSortedMap(hitsByLine);
101  }
102
103  public SortedMap<Integer, Integer> getConditionsByLine() {
104    return Collections.unmodifiableSortedMap(conditionsByLine);
105  }
106
107  public SortedMap<Integer, Integer> getCoveredConditionsByLine() {
108    return Collections.unmodifiableSortedMap(coveredConditionsByLine);
109  }
110
111  public Collection<Measure> createMeasures() {
112    Collection<Measure> measures = Lists.newArrayList();
113    if (getLinesToCover() > 0) {
114      measures.add(new Measure(CoreMetrics.LINES_TO_COVER, (double) getLinesToCover()));
115      measures.add(new Measure(CoreMetrics.UNCOVERED_LINES, (double) (getLinesToCover() - getCoveredLines())));
116      measures.add(new Measure(CoreMetrics.COVERAGE_LINE_HITS_DATA).setData(KeyValueFormat.format(hitsByLine)).setPersistenceMode(PersistenceMode.DATABASE));
117    }
118    if (getConditions() > 0) {
119      measures.add(new Measure(CoreMetrics.CONDITIONS_TO_COVER, (double) getConditions()));
120      measures.add(new Measure(CoreMetrics.UNCOVERED_CONDITIONS, (double) (getConditions() - getCoveredConditions())));
121      measures.add(createConditionsByLine());
122      measures.add(createCoveredConditionsByLine());
123    }
124    return measures;
125  }
126
127  private Measure createCoveredConditionsByLine() {
128    return new Measure(CoreMetrics.COVERED_CONDITIONS_BY_LINE)
129        .setData(KeyValueFormat.format(coveredConditionsByLine))
130        .setPersistenceMode(PersistenceMode.DATABASE);
131  }
132
133  private Measure createConditionsByLine() {
134    return new Measure(CoreMetrics.CONDITIONS_BY_LINE)
135        .setData(KeyValueFormat.format(conditionsByLine))
136        .setPersistenceMode(PersistenceMode.DATABASE);
137  }
138
139  public static CoverageMeasuresBuilder create() {
140    return new CoverageMeasuresBuilder();
141  }
142}