001/* 002 * SonarQube, open source software quality management tool. 003 * Copyright (C) 2008-2014 SonarSource 004 * mailto:contact AT sonarsource DOT com 005 * 006 * SonarQube 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 * SonarQube 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 License 017 * along with this program; if not, write to the Free Software Foundation, 018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 019 */ 020 021package org.sonar.api.measures; 022 023import java.util.List; 024import org.sonar.api.resources.ResourceUtils; 025 026import static com.google.common.collect.Lists.newArrayList; 027 028/** 029 * Formula used to compute an average for a given metric A, which is the result of the sum of measures of this metric (A) divided by another metric (B). 030 * <p/> 031 * For example: to compute the metric "complexity by file", the main metric (A) is "complexity" and the other metric (B) is "file". 032 * 033 * @since 3.0 034 * @deprecated since 5.2 decorators are no more executed on batch side 035 */ 036@Deprecated 037public class AverageFormula implements Formula { 038 039 private Metric mainMetric; 040 private Metric byMetric; 041 private Metric fallbackMetric; 042 043 /** 044 * This method should be private but it kep package-protected because of AverageComplexityFormula. 045 */ 046 AverageFormula(Metric mainMetric, Metric byMetric) { 047 this.mainMetric = mainMetric; 048 this.byMetric = byMetric; 049 } 050 051 /** 052 * Creates a new {@link AverageFormula} class. 053 * 054 * @param main The metric on which average should be calculated (ex.: "complexity") 055 * @param by The metric used to divide the main metric to compute average (ex.: "file" for "complexity by file") 056 */ 057 public static AverageFormula create(Metric main, Metric by) { 058 return new AverageFormula(main, by); 059 } 060 061 /** 062 * Set a fallback metric if no measures found for the main metric. 063 * 064 * @param fallbackMetric The fallback metric 065 * @since 3.6 066 */ 067 public AverageFormula setFallbackForMainMetric(Metric fallbackMetric) { 068 this.fallbackMetric = fallbackMetric; 069 return this; 070 } 071 072 /** 073 * {@inheritDoc} 074 */ 075 @Override 076 public List<Metric> dependsUponMetrics() { 077 return fallbackMetric != null ? newArrayList(mainMetric, fallbackMetric, byMetric) : newArrayList(mainMetric, byMetric); 078 } 079 080 /** 081 * {@inheritDoc} 082 */ 083 @Override 084 public Measure calculate(FormulaData data, FormulaContext context) { 085 if (!shouldDecorateResource(data, context)) { 086 return null; 087 } 088 089 Measure result; 090 if (ResourceUtils.isFile(context.getResource())) { 091 result = calculateForFile(data, context); 092 } else { 093 result = calculateOnChildren(data, context); 094 } 095 return result; 096 } 097 098 private Measure calculateOnChildren(FormulaData data, FormulaContext context) { 099 Measure result = null; 100 101 double totalByMeasure = 0; 102 double totalMainMeasure = 0; 103 boolean hasApplicableChildren = false; 104 105 for (FormulaData childrenData : data.getChildren()) { 106 Double fallbackMeasure = fallbackMetric != null ? MeasureUtils.getValue(childrenData.getMeasure(fallbackMetric), null) : null; 107 Double childrenByMeasure = MeasureUtils.getValue(childrenData.getMeasure(byMetric), null); 108 Double childrenMainMeasure = MeasureUtils.getValue(childrenData.getMeasure(mainMetric), fallbackMeasure); 109 if (childrenMainMeasure != null && childrenByMeasure != null && childrenByMeasure > 0.0) { 110 totalByMeasure += childrenByMeasure; 111 totalMainMeasure += childrenMainMeasure; 112 hasApplicableChildren = true; 113 } 114 } 115 if (hasApplicableChildren) { 116 result = new Measure(context.getTargetMetric(), totalMainMeasure / totalByMeasure); 117 } 118 return result; 119 } 120 121 private Measure calculateForFile(FormulaData data, FormulaContext context) { 122 Measure result = null; 123 124 Double fallbackMeasure = fallbackMetric != null ? MeasureUtils.getValue(data.getMeasure(fallbackMetric), null) : null; 125 Double byMeasure = MeasureUtils.getValue(data.getMeasure(byMetric), null); 126 Double mainMeasure = MeasureUtils.getValue(data.getMeasure(mainMetric), fallbackMeasure); 127 if (mainMeasure != null && byMeasure != null && byMeasure > 0.0) { 128 result = new Measure(context.getTargetMetric(), mainMeasure / byMeasure); 129 } 130 131 return result; 132 } 133 134 private static boolean shouldDecorateResource(FormulaData data, FormulaContext context) { 135 return !MeasureUtils.hasValue(data.getMeasure(context.getTargetMetric())); 136 } 137}