All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hello2morrow.sonarplugin.foundation.Utilities Maven / Gradle / Ivy

Go to download

Provides architecture governance features accompanied by metrics about cyclic dependencies and other structural aspects.

There is a newer version: 3.4.2
Show newest version
/*
 * 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.foundation;

import java.text.ParseException;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.DecoratorContext;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.Metric;
import org.sonar.api.resources.JavaFile;
import org.sonar.api.resources.JavaPackage;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RulePriority;
import org.sonar.api.rules.Violation;

import com.hello2morrow.sonarplugin.xsd.XsdAttribute;
import com.hello2morrow.sonarplugin.xsd.XsdAttributeCategory;
import com.hello2morrow.sonarplugin.xsd.XsdAttributeRoot;
import com.hello2morrow.sonarplugin.xsd.XsdCycleGroup;
import com.hello2morrow.sonarplugin.xsd.XsdWarning;

public final class Utilities {

  public static final String DEFAULT_BUILD_UNIT = "(Default Build Unit)";
  private static final String SPACE = " ";
  private static final String START_LINE = "Start line";
  private static final String ELEMENT = "Element";
  private static final String ATTRIBUTE_VALUE = "Attribute value";
  private static final String ELEMENT_TYPE = "Element type";
  private static final String BUILD_UNIT = "Build unit";
  private static final String PROJECT = "Project";
  private static final String BLOCK_ID = "Block id";
  private static final String SPACE_ENTITY = " ";
  private static final String UNKNOWN = "";
  private static final Logger LOG = LoggerFactory.getLogger(Utilities.class);

  private Utilities() {
  }

  public static String getAttribute(List list, String name) {
    String value = null;

    for (XsdAttribute attr : list) {
      if (attr.getName().equals(name)) {
        value = attr.getValue();
        break;
      }
    }
    return value;
  }

  public static String getBuildUnitName(String fqName) {
    String buName = UNKNOWN;

    if (fqName != null) {
      int colonPos = fqName.indexOf("::");

      if (colonPos != -1) {
        buName = fqName.substring(colonPos + 2);
        if (DEFAULT_BUILD_UNIT.equals(buName)) {
          // Compatibility with old SonarJ versions
          buName = fqName.substring(0, colonPos);
        }
      }
    }
    return buName;
  }

  public static String getBuildUnitName(XsdCycleGroup group) {
    if (DEFAULT_BUILD_UNIT.equals(group.getParent())) {
      return group.getElementScope();
    }
    return group.getParent();
  }

  public static String relativeFileNameToFqName(String fileName) {
    int lastDot = fileName.lastIndexOf('.');

    return fileName.substring(0, lastDot).replace('/', '.');
  }

  public static void readAttributesToMap(XsdAttributeRoot root, final Map attributeMap) {
    attributeMap.clear();

    for (XsdAttributeCategory cat : root.getAttributeCategory()) {
      for (XsdAttribute attr : cat.getAttribute()) {
        String attrName = attr.getStandardName();
        String value = attr.getValue();

        try {
          if (value.contains(".")) {
            attributeMap.put(attrName, SonargraphPluginBase.FLOAT_FORMAT.parse(value));
          } else {
            attributeMap.put(attrName, SonargraphPluginBase.INTEGER_FORMAT.parse(value));
          }
        } catch (ParseException e) {
          // Ignore this value
          LOG.error("Failed to parse value : " + value + ", " + e.getMessage());
        }
      }
    }
  }

  public static boolean isAggregationProject(DecoratorContext context, final Metric indicator) {
    return context.getChildrenMeasures(indicator).size() > 0;
  }

  public static boolean isRootParentProject(final Project project) {
    boolean isRootParentProject = false;
    if (project == null) {
      return false;
    }
    List modules = project.getModules();
    if (project.getParent() == null && modules != null && !modules.isEmpty()) {
      isRootParentProject = true;
    }
    return isRootParentProject;
  }

  public static boolean isSingleModuleProject(final Project project) {
    if (project == null) {
      return false;
    }
    
    if (project.getModules().isEmpty() && project.getParent() == null) {
      return true;
    }
    return false;
  }

  public static String generateSpaceEntity(int numberOfSpaces) {
    StringBuffer buffer = new StringBuffer();
    for (int i = 0; i < numberOfSpaces; i++) {
      buffer.append(SPACE_ENTITY);
    }
    return buffer.toString();
  }

  public static String generateSpaces(int numberOfSpaces) {
    StringBuffer buffer = new StringBuffer();
    for (int i = 0; i < numberOfSpaces; i++) {
      buffer.append(SPACE);
    }
    return buffer.toString();
  }

  public static DuplicateCodeBlock createDuplicateCodeBlock(XsdWarning warning) {
    DuplicateCodeBlock block = new DuplicateCodeBlock();
    String attribute = getAttribute(warning.getAttribute(), BLOCK_ID);
    if (null == attribute) {
      LOG.error("Duplicate code block warning does not contain the required attribute \"Block id\"");
      return null;
    }
    block.setBlockId(Integer.parseInt(attribute));
    block.setProjectName(getAttribute(warning.getAttribute(), PROJECT));
    block.setBuildUnitName(getAttribute(warning.getAttribute(), BUILD_UNIT));
    block.setElementType(getAttribute(warning.getAttribute(), ELEMENT_TYPE));

    String blockLength = getAttribute(warning.getAttribute(), ATTRIBUTE_VALUE);
    int pos = blockLength.indexOf(" lines");
    block.setBlockLength(Integer.parseInt(blockLength.substring(0, pos)));

    block.setElementName(getAttribute(warning.getAttribute(), ELEMENT));
    block.setStartLine(Integer.parseInt(getAttribute(warning.getAttribute(), START_LINE)));
    return block;
  }

  public static void addAttributeToList(List attributeList, String name, String value) {
    XsdAttribute attribute = new XsdAttribute();
    attribute.setName(name);
    attribute.setValue(value);
    attributeList.add(attribute);
  }

  public static String generateDuplicateCodeBlockMessage(DuplicateCodeBlock block, List blocks) {
    final int endLine = block.getBlockLength() + block.getStartLine() - 1;

    final StringBuilder message = new StringBuilder();
    message.append("Line ").append(block.getStartLine()).append(" to ").append(endLine).append(" is a duplicate of\n");

    final int toBeDescribed = blocks.size() - 1;
    int yetToDescribe = toBeDescribed;

    for (final DuplicateCodeBlock duplicate : blocks) {
      if (duplicate == block) {
        continue;
      }

      // No connection for first described element.
      if (toBeDescribed != yetToDescribe) {
        if (yetToDescribe == 1) {
          // Last.
          switch (toBeDescribed) {
            case 2:
              // Just two parts.
              message.append(" and\n");
              break;
            default:
              // More than two parts: Enumeration.
              message.append(", and\n");
              break;
          }
        } else {
          // Not last, and not first: enumerate.
          message.append(", ");
        }
      }

      final int endLineDuplicate = duplicate.getBlockLength() + duplicate.getStartLine() - 1;
      message.append("line " + duplicate.getStartLine() + " to " + endLineDuplicate + " of "
          + duplicate.getElementName());

      yetToDescribe--;
    }
    message.append(".");
    return message.toString();
  }

  public static void saveViolation(SensorContext sensorContext, Rule rule, RulePriority priority, String fqName,
      int line, String msg) {
    Resource javaFile = sensorContext.getResource(new JavaFile(fqName));

    if (javaFile == null) {
      LOG.error("Cannot obtain resource " + fqName);
    } else {
      Violation v = Violation.create(rule, javaFile);

      v.setMessage(msg);
      if (line == 0) {
        v.setLineId(null);
      } else {
        v.setLineId(line);
      }
      if (priority != null) {
        v.setSeverity(priority);
      }
      sensorContext.saveViolation(v);
    }
  }

  /**
   * Retrieves the metric from the build unit and saves it as a measure to the sensor context.
   * 
   * @param sensorContext
   * @param metrics
   * @param key
   * @param metric
   * @param precision
   * @return the saved measure
   */
  public static Measure saveExistingMeasureToContext(SensorContext sensorContext, Map metrics,
      String key, Metric metric, int precision) {
    double value = Utilities.getBuildUnitMetricValue(metrics, key);

    return Utilities.saveMeasureToContext(sensorContext, metric, value, precision);
  }

  /**
   * Creates a new measure for the specified metric and saves it to the sensor context.
   * 
   * @param sensorContext
   * @param metric
   * @param value
   * @param precision
   * @return
   */
  public static Measure saveMeasureToContext(SensorContext sensorContext, Metric metric, double value, int precision) {
    Measure m = new Measure(metric, value, precision);
    sensorContext.saveMeasure(m);
    return m;
  }

  public static double getBuildUnitMetricValue(Map metrics, String key) {
    return getMetricValueFromMap(key, metrics);
  }

  public static double getMetricValueFromMap(String key, Map metrics) {
    Number num = metrics.get(key);

    if (num == null) {
      LOG.error("Cannot find metric <" + key + "> in generated report");
      LOG.error("Make sure you set the prepareForSonar option to true (see documentation).");
      LOG.error("If you used Sonargraph Quality for report generation: "
          + "Check that your quality model used during snapshot generation contains the required Sonar metrics!");
      return 0.0;
    }
    return num.doubleValue();
  }

  public static boolean buildUnitMatchesAnalyzedProject(String buName, String projectKey) {
    final String[] elements = projectKey.split(":");
    assert elements.length >= 1 : "project.getKey() must not return an empty string";
    final String artifactId = elements[elements.length - 1];
    final String groupId = elements[0];
    final String longName = artifactId + "[" + groupId + "]";
    final String longName2 = groupId + ':' + artifactId;
  
    if (buName.equalsIgnoreCase(artifactId)){
      return true;
    }
    if (buName.equalsIgnoreCase(longName))
    {
      return true;
    }
    if (buName.equalsIgnoreCase(longName2)) {
      return true;
    }
    
    if (buName.startsWith("...") && longName2.endsWith(buName.substring(2))) {
      return true;
    }
    return false;
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy