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 */
020package org.sonar.plugins.design.batch;
021
022import org.sonar.api.batch.Decorator;
023import org.sonar.api.batch.DecoratorContext;
024import org.sonar.api.batch.DependedUpon;
025import org.sonar.api.measures.CoreMetrics;
026import org.sonar.api.measures.Measure;
027import org.sonar.api.measures.MeasureUtils;
028import org.sonar.api.measures.Metric;
029import org.sonar.api.resources.Project;
030import org.sonar.api.resources.Resource;
031import org.sonar.api.resources.ResourceUtils;
032import org.sonar.api.resources.Scopes;
033
034import java.util.Collection;
035import java.util.List;
036
037public class SuspectLcom4DensityDecorator implements Decorator {
038
039  public boolean shouldExecuteOnProject(Project project) {
040    return true;
041  }
042
043  @DependedUpon
044  public final Metric generatesMetric() {
045    return CoreMetrics.SUSPECT_LCOM4_DENSITY;
046  }
047
048  public void decorate(Resource resource, DecoratorContext context) {
049    if (ResourceUtils.isFile(resource)) {
050      // do nothing
051    } else if (Scopes.isDirectory(resource)) {
052      decorateDirectory(context);
053
054    } else if (Scopes.isProject(resource)) {
055      decorateProject(context);
056    }
057  }
058
059  private void decorateProject(DecoratorContext context) {
060    double total = 0.0;
061    int totalFiles = 0;
062
063    List<DecoratorContext> children = context.getChildren();
064    boolean hasLcom4=false;
065    for (DecoratorContext child : children) {
066      int files = MeasureUtils.getValue(child.getMeasure(CoreMetrics.FILES), 0.0).intValue();
067      totalFiles += files;
068      Measure childSuspectDensity = child.getMeasure(CoreMetrics.SUSPECT_LCOM4_DENSITY);
069      if (childSuspectDensity!=null && childSuspectDensity.getValue()!=null) {
070        hasLcom4=true;
071        total += childSuspectDensity.getValue() * files;
072      }
073    }
074
075    if (hasLcom4 && totalFiles > 0) {
076      context.saveMeasure(CoreMetrics.SUSPECT_LCOM4_DENSITY, (total / totalFiles));
077    }
078  }
079
080  private void decorateDirectory(DecoratorContext context) {
081    Collection<Measure> fileLcoms = context.getChildrenMeasures(CoreMetrics.LCOM4);
082    double files = MeasureUtils.getValue(context.getMeasure(CoreMetrics.FILES), 0.0);
083    if (!fileLcoms.isEmpty() && files>0.0) {
084      double suspectFiles = 0.0;
085
086      // directory children are files
087      for (Measure fileLcom : fileLcoms) {
088        if (MeasureUtils.getValue(fileLcom, 0.0) > 1.0) {
089          suspectFiles++;
090        }
091      }
092      double density = (suspectFiles / files) * 100.0;
093      context.saveMeasure(CoreMetrics.SUSPECT_LCOM4_DENSITY, density);
094    }
095  }
096}