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 */ 020 package org.sonar.plugins.core.timemachine; 021 022 import com.google.common.collect.ArrayListMultimap; 023 import com.google.common.collect.ListMultimap; 024 import com.google.common.collect.Lists; 025 import org.apache.commons.lang.StringUtils; 026 import org.apache.commons.lang.time.DateUtils; 027 import org.sonar.api.batch.*; 028 import org.sonar.api.measures.Measure; 029 import org.sonar.api.measures.Metric; 030 import org.sonar.api.measures.MetricFinder; 031 import org.sonar.api.resources.Project; 032 import org.sonar.api.resources.Resource; 033 import org.sonar.api.resources.Scopes; 034 import org.sonar.batch.components.TimeMachineConfiguration; 035 import org.sonar.core.NotDryRun; 036 037 import java.util.List; 038 039 @NotDryRun 040 @DependedUpon(DecoratorBarriers.END_OF_TIME_MACHINE) 041 public class TendencyDecorator implements Decorator { 042 043 public static final String PROP_DAYS_DESCRIPTION = "Number of days the tendency should be calculated on."; 044 045 private TimeMachine timeMachine; 046 private TimeMachineQuery query; 047 private TendencyAnalyser analyser; 048 private TimeMachineConfiguration configuration; 049 private List<Metric> metrics; 050 051 public TendencyDecorator(TimeMachine timeMachine, MetricFinder metricFinder, TimeMachineConfiguration configuration) { 052 this.timeMachine = timeMachine; 053 this.analyser = new TendencyAnalyser(); 054 this.configuration = configuration; 055 this.metrics = Lists.newLinkedList(); 056 for (Metric metric : metricFinder.findAll()) { 057 if (metric.isNumericType()) { 058 metrics.add(metric); 059 } 060 } 061 } 062 063 TendencyDecorator(TimeMachine timeMachine, TimeMachineQuery query, TendencyAnalyser analyser, TimeMachineConfiguration configuration) { 064 this.timeMachine = timeMachine; 065 this.query = query; 066 this.analyser = analyser; 067 this.configuration = configuration; 068 } 069 070 @DependsUpon 071 public List<Metric> dependsUponMetrics() { 072 return metrics; 073 } 074 075 protected TimeMachineQuery initQuery(Project project) { 076 int days = configuration.getTendencyPeriodInDays(); 077 078 query = new TimeMachineQuery(null) // resource is set after 079 .setFrom(DateUtils.addDays(project.getAnalysisDate(), -days)) 080 .setToCurrentAnalysis(true) 081 .setMetrics(metrics); 082 return query; 083 } 084 085 protected TimeMachineQuery resetQuery(Project project, Resource resource) { 086 if (query == null) { 087 initQuery(project); 088 } 089 query.setResource(resource); 090 return query; 091 } 092 093 public boolean shouldExecuteOnProject(Project project) { 094 return !configuration.skipTendencies(); 095 } 096 097 public void decorate(Resource resource, DecoratorContext context) { 098 if (shouldDecorateResource(resource)) { 099 resetQuery(context.getProject(), resource); 100 List<Object[]> fields = timeMachine.getMeasuresFields(query); 101 ListMultimap<Metric, Double> valuesPerMetric = ArrayListMultimap.create(); 102 for (Object[] field : fields) { 103 valuesPerMetric.put((Metric) field[1], (Double) field[2]); 104 } 105 106 for (Metric metric : query.getMetrics()) { 107 Measure measure = context.getMeasure(metric); 108 if (measure != null) { 109 List<Double> values = valuesPerMetric.get(metric); 110 values.add(measure.getValue()); 111 112 measure.setTendency(analyser.analyseLevel(valuesPerMetric.get(metric))); 113 context.saveMeasure(measure); 114 } 115 } 116 } 117 } 118 119 private boolean shouldDecorateResource(Resource resource) { 120 return StringUtils.equals(Scopes.PROJECT, resource.getScope()) || StringUtils.equals(Scopes.DIRECTORY, resource.getScope()); 121 } 122 }