org.sonar.plugins.technicaldebt.TechnicalDebtDecorator.java Source code

Java tutorial

Introduction

Here is the source code for org.sonar.plugins.technicaldebt.TechnicalDebtDecorator.java

Source

/*
 * Sonar, open source software quality management tool.
 * Copyright (C) 2009 SonarSource
 * mailto:contact AT sonarsource DOT com
 *
 * Sonar is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * Sonar is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with Sonar; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
 */

package org.sonar.plugins.technicaldebt;

import com.google.common.collect.Lists;
import org.apache.commons.configuration.Configuration;
import org.sonar.api.batch.Decorator;
import org.sonar.api.batch.DecoratorContext;
import org.sonar.api.batch.DependedUpon;
import org.sonar.api.batch.DependsUpon;
import org.sonar.api.measures.Metric;
import org.sonar.api.measures.PropertiesBuilder;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.plugins.technicaldebt.axis.*;

import java.util.Arrays;
import java.util.List;

/**
 * {@inheritDoc}
 */
public final class TechnicalDebtDecorator implements Decorator {

    private List<AxisDebtCalculator> axisList;
    private Configuration configuration;

    /**
     * {@inheritDoc}
     */
    public TechnicalDebtDecorator(Configuration configuration, Project project) {
        this.configuration = configuration;
        axisList = Arrays.asList(new CommentDebtCalculator(configuration),
                new ComplexityDebtCalculator(configuration, project), new CoverageDebtCalculator(configuration),
                new DuplicationDebtCalculator(configuration), new ViolationsDebtCalculator(configuration),
                new DesignDebtCalculator(configuration));
    }

    /**
     * {@inheritDoc}
     */
    public boolean shouldExecuteOnProject(Project project) {
        return true;
    }

    @DependsUpon
    public List<Metric> dependsOnMetrics() {
        List<Metric> list = Lists.newLinkedList();
        for (AxisDebtCalculator axis : axisList) {
            list.addAll(axis.dependsOn());
        }
        return list;
    }

    @DependedUpon
    public List<Metric> generatesMetrics() {
        return Arrays.asList(TechnicalDebtMetrics.TECHNICAL_DEBT, TechnicalDebtMetrics.TECHNICAL_DEBT_DAYS,
                TechnicalDebtMetrics.TECHNICAL_DEBT_RATIO, TechnicalDebtMetrics.TECHNICAL_DEBT_REPARTITION);
    }

    /**
     * {@inheritDoc}
     */
    public void decorate(Resource resource, DecoratorContext context) {
        double sonarDebt = 0.0;
        double denominatorDensity = 0.0;
        PropertiesBuilder<String, Double> techDebtRepartition = new PropertiesBuilder<String, Double>(
                TechnicalDebtMetrics.TECHNICAL_DEBT_REPARTITION);

        // We calculate the total absolute debt and total maximum debt
        for (AxisDebtCalculator axis : axisList) {
            sonarDebt += axis.calculateAbsoluteDebt(context);
            denominatorDensity += axis.calculateTotalPossibleDebt(context);
        }

        // Then we calculate the % of each axis for this debt
        for (AxisDebtCalculator axis : axisList) {
            addToRepartition(techDebtRepartition, axis.getName(),
                    axis.calculateAbsoluteDebt(context) / sonarDebt * 100);
        }

        double dailyRate = configuration.getDouble(TechnicalDebtPlugin.DAILY_RATE,
                TechnicalDebtPlugin.DAILY_RATE_DEFVAL);

        saveMeasure(context, TechnicalDebtMetrics.TECHNICAL_DEBT, sonarDebt * dailyRate);
        saveMeasure(context, TechnicalDebtMetrics.TECHNICAL_DEBT_DAYS, sonarDebt);
        if (denominatorDensity != 0.0) {
            saveMeasure(context, TechnicalDebtMetrics.TECHNICAL_DEBT_RATIO, sonarDebt / denominatorDensity * 100);
        }
        context.saveMeasure(techDebtRepartition.build());
    }

    private void saveMeasure(DecoratorContext decoratorContext, Metric metric, double measure) {
        if (measure * 10 > 5) {
            decoratorContext.saveMeasure(metric, measure);
        }
    }

    private void addToRepartition(PropertiesBuilder<String, Double> techDebtRepartition, String key, double value) {
        if (value > 0d) {
            // Math.floor is important to avoid getting very long doubles... see SONAR-859
            techDebtRepartition.add(key, Math.floor(value * 100.0) / 100);
        }
    }
}