/* * Sonar Sonargraph Plugin * Copyright (C) 2009, 2010, 2011 hello2morrow GmbH * mailto: info AT hello2morrow DOT com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.hello2morrow.sonarplugin; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.batch.AbstractSumChildrenDecorator; import org.sonar.api.batch.DecoratorContext; import org.sonar.api.batch.DependedUpon; import org.sonar.api.measures.Measure; import org.sonar.api.measures.Metric; import org.sonar.api.resources.Resource; import java.util.Arrays; import java.util.List; public final class SonargraphMetricAggregator extends AbstractSumChildrenDecorator { private static final Logger LOG = LoggerFactory.getLogger(SonargraphMetricAggregator.class); @Override @DependedUpon public List<Metric> generatesMetrics() { return Arrays.asList(SonargraphMetrics.VIOLATING_TYPES, SonargraphMetrics.EROSION_INDEX, SonargraphMetrics.CYCLIC_PACKAGES, SonargraphMetrics.CYCLICITY, SonargraphMetrics.EROSION_COST, SonargraphMetrics.EROSION_REFS, SonargraphMetrics.EROSION_TYPES, SonargraphMetrics.IGNORED_VIOLATONS, SonargraphMetrics.IGNORED_WARNINGS, SonargraphMetrics.INSTRUCTIONS, SonargraphMetrics.INTERNAL_PACKAGES, SonargraphMetrics.INTERNAL_TYPES, SonargraphMetrics.JAVA_FILES, SonargraphMetrics.TASKS, SonargraphMetrics.TASK_REFS, SonargraphMetrics.THRESHOLD_WARNINGS, SonargraphMetrics.DUPLICATE_WARNINGS, SonargraphMetrics.ALL_WARNINGS, SonargraphMetrics.CYCLE_WARNINGS, SonargraphMetrics.WORKSPACE_WARNINGS, SonargraphMetrics.TYPE_DEPENDENCIES, SonargraphMetrics.VIOLATING_DEPENDENCIES, SonargraphMetrics.ARCHITECTURE_VIOLATIONS, SonargraphMetrics.UNASSIGNED_TYPES); } @Override protected boolean shouldSaveZeroIfNoChildMeasures() { return false; } @SuppressWarnings("unchecked") @Override public void decorate(Resource resource, DecoratorContext context) { if (!shouldDecorateResource(resource)) { return; } if (context.getChildrenMeasures(SonargraphMetrics.INSTRUCTIONS).size() == 0) { return; } super.decorate(resource, context); double biggestCycleGroupSize = -1.0; double highestACD = -1.0; double highestNCCD = -1.0; for (DecoratorContext childContext : context.getChildren()) { Measure cycleGroup = childContext.getMeasure(SonargraphMetrics.BIGGEST_CYCLE_GROUP); Measure acd = childContext.getMeasure(SonargraphMetrics.ACD); Measure nccd = childContext.getMeasure(SonargraphMetrics.NCCD); Measure localHighestACD = childContext.getMeasure(SonargraphMetrics.HIGHEST_ACD); Measure localHighestNCCD = childContext.getMeasure(SonargraphMetrics.HIGHEST_NCCD); if (cycleGroup != null && cycleGroup.getValue() > biggestCycleGroupSize) { biggestCycleGroupSize = cycleGroup.getValue(); } if (acd != null && acd.getValue() > highestACD) { highestACD = acd.getValue(); } else if (localHighestACD != null && localHighestACD.getValue() > highestACD) { highestACD = localHighestACD.getValue(); } if (nccd != null && nccd.getValue() > highestNCCD) { highestNCCD = nccd.getValue(); } else if (localHighestNCCD != null && localHighestNCCD.getValue() > highestNCCD) { highestNCCD = localHighestNCCD.getValue(); } } if (biggestCycleGroupSize >= 0.0 && context.getMeasure(SonargraphMetrics.BIGGEST_CYCLE_GROUP) == null) { context.saveMeasure(SonargraphMetrics.BIGGEST_CYCLE_GROUP, biggestCycleGroupSize); } if (highestACD >= 0.0 && context.getMeasure(SonargraphMetrics.HIGHEST_ACD) == null) { context.saveMeasure(SonargraphMetrics.HIGHEST_ACD, highestACD); } if (highestNCCD >= 0.0 && context.getMeasure(SonargraphMetrics.HIGHEST_NCCD) == null) { context.saveMeasure(SonargraphMetrics.HIGHEST_NCCD, highestNCCD); } Measure cyclicity = context.getMeasure(SonargraphMetrics.CYCLICITY); Measure packages = context.getMeasure(SonargraphMetrics.INTERNAL_PACKAGES); Measure cyclicPackages = context.getMeasure(SonargraphMetrics.CYCLIC_PACKAGES); if (cyclicity == null || packages == null || cyclicPackages == null) { LOG.error("Problem in aggregator on project: " + context.getProject().getKey()); } else { double relCyclicity = 100.0 * Math.sqrt(cyclicity.getValue()) / packages.getValue(); double relCyclicPackages = 100.0 * cyclicPackages.getValue() / packages.getValue(); context.saveMeasure(SonargraphMetrics.RELATIVE_CYCLICITY, relCyclicity); context.saveMeasure(SonargraphMetrics.CYCLIC_PACKAGES_PERCENT, relCyclicPackages); } Measure violatingTypes = context.getMeasure(SonargraphMetrics.VIOLATING_TYPES); Measure internalTypes = context.getMeasure(SonargraphMetrics.INTERNAL_TYPES); Measure unassignedTypes = context.getMeasure(SonargraphMetrics.UNASSIGNED_TYPES); if (internalTypes != null && internalTypes.getValue() > 0) { if (violatingTypes != null) { context.saveMeasure(SonargraphMetrics.VIOLATING_TYPES_PERCENT, 100.0 * violatingTypes.getValue() / internalTypes.getValue()); } if (unassignedTypes != null) { context.saveMeasure(SonargraphMetrics.UNASSIGNED_TYPES_PERCENT, 100 * unassignedTypes.getValue() / internalTypes.getValue()); } } AlertDecorator.setAlertLevels(new DecoratorProjectContext(context)); } @SuppressWarnings("unchecked") @Override public boolean shouldDecorateResource(Resource resource) { return Arrays.asList(Resource.QUALIFIER_PROJECT, Resource.QUALIFIER_MODULE, Resource.QUALIFIER_VIEW, Resource.QUALIFIER_SUBVIEW).contains(resource.getQualifier()); } }