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.sensors; 021 022 import com.google.common.collect.Multiset; 023 import com.google.common.collect.TreeMultiset; 024 import org.sonar.api.CoreProperties; 025 import org.sonar.api.Properties; 026 import org.sonar.api.Property; 027 import org.sonar.api.batch.Decorator; 028 import org.sonar.api.batch.DecoratorContext; 029 import org.sonar.api.batch.DependedUpon; 030 import org.sonar.api.batch.DependsUpon; 031 import org.sonar.api.config.Settings; 032 import org.sonar.api.measures.CoreMetrics; 033 import org.sonar.api.measures.Measure; 034 import org.sonar.api.measures.MeasureUtils; 035 import org.sonar.api.measures.Metric; 036 import org.sonar.api.resources.Project; 037 import org.sonar.api.resources.Resource; 038 import org.sonar.api.rules.RulePriority; 039 import org.sonar.api.utils.KeyValueFormat; 040 041 import java.util.Arrays; 042 import java.util.List; 043 import java.util.Map; 044 045 @Properties( 046 @Property( 047 key = CoreProperties.CORE_RULE_WEIGHTS_PROPERTY, 048 defaultValue = CoreProperties.CORE_RULE_WEIGHTS_DEFAULT_VALUE, 049 name = "Rules weight", 050 description = "A weight is associated to each severity to calculate the Rules Compliance Index.", 051 project = false, 052 global = true, 053 category = CoreProperties.CATEGORY_GENERAL) 054 ) 055 public class WeightedViolationsDecorator implements Decorator { 056 057 private Settings settings; 058 private Map<RulePriority, Integer> weightsBySeverity; 059 060 public WeightedViolationsDecorator(Settings settings) { 061 this.settings = settings; 062 } 063 064 @DependsUpon 065 public List<Metric> dependsUponViolations() { 066 return Arrays.asList(CoreMetrics.BLOCKER_VIOLATIONS, CoreMetrics.CRITICAL_VIOLATIONS, 067 CoreMetrics.MAJOR_VIOLATIONS, CoreMetrics.MINOR_VIOLATIONS, CoreMetrics.INFO_VIOLATIONS); 068 } 069 070 @DependedUpon 071 public Metric generatesWeightedViolations() { 072 return CoreMetrics.WEIGHTED_VIOLATIONS; 073 } 074 075 public boolean shouldExecuteOnProject(Project project) { 076 return true; 077 } 078 079 public void start() { 080 weightsBySeverity = getWeights(settings); 081 } 082 083 Map<RulePriority, Integer> getWeightsBySeverity() { 084 return weightsBySeverity; 085 } 086 087 static Map<RulePriority, Integer> getWeights(final Settings settings) { 088 String value = settings.getString(CoreProperties.CORE_RULE_WEIGHTS_PROPERTY); 089 090 Map<RulePriority, Integer> weights = KeyValueFormat.parse(value, KeyValueFormat.newPriorityConverter(), KeyValueFormat.newIntegerConverter()); 091 092 for (RulePriority priority : RulePriority.values()) { 093 if (!weights.containsKey(priority)) { 094 weights.put(priority, 1); 095 } 096 } 097 return weights; 098 } 099 100 101 public void decorate(Resource resource, DecoratorContext context) { 102 decorate(context); 103 } 104 105 void decorate(DecoratorContext context) { 106 double debt = 0.0; 107 Multiset<RulePriority> distribution = TreeMultiset.create(); 108 109 for (RulePriority severity : RulePriority.values()) { 110 Measure measure = context.getMeasure(SeverityUtils.severityToViolationMetric(severity)); 111 if (measure != null && MeasureUtils.hasValue(measure)) { 112 distribution.add(severity, measure.getIntValue()); 113 double add = weightsBySeverity.get(severity) * measure.getIntValue(); 114 debt += add; 115 } 116 } 117 118 Measure debtMeasure = new Measure(CoreMetrics.WEIGHTED_VIOLATIONS, debt, KeyValueFormat.format(distribution)); 119 context.saveMeasure(debtMeasure); 120 } 121 122 }