package metrics; import java.io.BufferedWriter; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.Vector; import util.Log; public class MetricsProcessor { /** * Identificador de anota��o de m�trica. */ public static final String IDENTIFIER = "//@#$LPS-"; /** * Informa se iniciou-se um coment�rio. */ private boolean startComment; /** * Map para armazenar as m�tricas de granularidade. */ private Map<String, Integer> granMetrics; /** * Map para armazenar as m�tricas de localiza��o. */ private Map<String, Integer> localMetrics; /** * Map para armazenar outras m�tricas. */ private Map<String, Integer> otherMetrics; /** * Vetor que armazena as m�tricas processadas */ private Vector<Metric> metrics; /** * Armazena m�trica LOC. */ private Integer locMetric; /** * Contador de classes */ private static Integer CLASS_COUNTER; /** * String para cria��o de m�tricas que n�o est�o mapeadas diretamente nas classes. */ private static final String FAKEMETRICIDENTIFIER = "//@#$LPS-%s:%s:N/A"; /** * Construtor padr�o. */ public MetricsProcessor(){ granMetrics = new HashMap<String, Integer>(); localMetrics = new HashMap<String, Integer>(); otherMetrics = new HashMap<String, Integer>(); metrics = new Vector<Metric>(); locMetric = 0; startComment = false; CLASS_COUNTER = 0; } /** * Insere uma m�trica j� contabilizada * @param line Indentificador da linha, para processamento posterior * @param metricType Tipo da m�trica * @param value Valor calculado */ private void insertMetric(String line, MetricType metricType, Integer value) { otherMetrics.put(line, value); } /** * Contabilizar as m�tricas por tipo. * @param line linha lida da classe Java. * @param metricType Tipo de m�trica. */ private void insertMetric(String line, MetricType metricType) { if (MetricType.LOC.equals(metricType)) { locMetric++; } else { Map<String, Integer> metricMap; if (MetricType.GRANULARITY.equals(metricType)) { metricMap = granMetrics; } else if(MetricType.LOCALIZATION.equals(metricType)) { metricMap = localMetrics; } else { metricMap = otherMetrics; } Integer value = 1; if (metricMap.containsKey(line)) { value = metricMap.get(line); value++; } metricMap.put(line, value); } } /** * Verifica se a linha � um coment�rio ou linha em branco * @param line linha a ser verificada * @return <code>true</code> se a linha for coment�rio ou branco, * <code>false</code> caso contr�rio. */ private boolean isCommentOrBlankLine(String line) { if (line.startsWith("/*")) { if (line.endsWith("*/")) { return true; } else if (!line.contains("*/")) { startComment = true; return true; } } else if (startComment && line.endsWith("*/")) { startComment = false; return true; } else if (startComment) { return true; } else { return (line.startsWith("//") || line.startsWith("*") || line.isEmpty()); } return false; } /** * Insere uma m�trica que n�o depende do conte�do do arquivo Java. * @param metricType Tipo da m�trica. * @param line Valor da m�trica */ public void insertMetric(MetricType metricType, Integer value) { insertMetric(String.format(FAKEMETRICIDENTIFIER, "TODAS", metricType.getIdentifier()), metricType, value); } /** * Contabiliza a m�trica encontrada na linha do arquivo Java. * @param value linha lida da classe Java. */ public void insertMetric(String value) { // Common Metrics if (value.contains(MetricsProcessor.IDENTIFIER)) { if (value.contains(MetricType.GRANULARITY.getIdentifier())) { insertMetric(value, MetricType.GRANULARITY); } else if (value.contains(MetricType.LOCALIZATION.getIdentifier())) { insertMetric(value, MetricType.LOCALIZATION); } else{ Log.info("Identificador inv�lido. Dados: " + value); } } // AND, OR e SD Metrics else if (value.matches("//#if defined\\(.*\\).*")) { String feature1 = value.substring(value.indexOf("(")+1, value.indexOf(")")); // AND e OR if (value.matches("//#if defined\\(.*\\) (and|or) defined\\(.*\\)")) { String feature2 = value.substring(value.lastIndexOf("(")+1, value.lastIndexOf(")")); MetricType type; if (value.toLowerCase().contains(MetricType.OR.getIdentifier().toLowerCase())) { type = MetricType.OR; } else { type = MetricType.AND; } // Inserir m�tricas AND e OR insertMetric(String.format(FAKEMETRICIDENTIFIER, feature1, type.getIdentifier()), type); insertMetric(String.format(FAKEMETRICIDENTIFIER, feature2, type.getIdentifier()), type); // Inserir m�trica SD insertMetric(String.format(FAKEMETRICIDENTIFIER, feature2, MetricType.SD.getIdentifier()), MetricType.SD); } // Inserir m�trica SD insertMetric(String.format(FAKEMETRICIDENTIFIER, feature1, MetricType.SD.getIdentifier()), MetricType.SD); } // LOC Metric else if (!isCommentOrBlankLine(value)) { insertMetric(value, MetricType.LOC); // Contabilizar classes if (value.matches("(public|protected|private|static|abstract|final|native|synchronized|transient|volatile|strictfp| )*class .*")) { CLASS_COUNTER++; } } } /** * Retorna o �ndice da feature no Vetor de metricas. * Caso a feature n�o exista no vetor, ela ser� inserida. * @param feature Nome da feature * @return �ndice da feature no vetor de metricas */ private Integer getFeatureMetricIndex(String feature) { Integer index = -1; for (int i = 0; i < metrics.size(); i++) { Metric m = (Metric) metrics.get(i); if (m.getFeature().equals(feature)) { index = i; } } if (index == -1) { metrics.add(new Metric(feature)); index = metrics.size()-1; } return index; } /** * Processa as m�tricas colhidas. * @param onlyBasicMetrics Informa se � para processar apenas m�tricas b�sicas. * @return <code>true</code> se processamento correto, <false> caso contr�rio. */ public boolean processGatheredMetrics(Boolean onlyBasicMetrics) { // Inserir m�trica que contabiliza o n�mero de classes insertMetric(MetricType.CLASS_NUMBER, CLASS_COUNTER); // Processar demais m�tricas. boolean result = this.processGatheredMetrics(otherMetrics); if (!onlyBasicMetrics) { result = result && this.processGatheredMetrics(granMetrics); result = result && this.processGatheredMetrics(localMetrics); } return result; } /** * Processa as m�tricas colhidas. * @param metricMap Map contendo as m�tricas * @return <code>true</code> se processamento correto, <false> caso contr�rio. */ private boolean processGatheredMetrics(Map<String, Integer> metricMap) { try { Set<String> keySet = metricMap.keySet(); for (Iterator<String> iterator = keySet.iterator(); iterator.hasNext();) { String key = iterator.next(); if(key != null) { Log.debug(key + " - " + metricMap.get(key)); String feature = key.substring(key.indexOf("-")+1, key.indexOf(":")); String[] metricsTypeAndSubType = key.substring(key.indexOf(":")+1).split(":"); Integer featureIndex = getFeatureMetricIndex(feature); Metric metric = metrics.get(featureIndex); metric.storeMetric(MetricType.getByIdentifier(metricsTypeAndSubType[0]), metricsTypeAndSubType[1], metricMap.get(key)); } } return true; } catch (Exception e) { Log.error(e.getMessage()); return false; } } /** * Salva as m�tricas em arquivo, no formado CSV. * @param filename nome do arquivo. */ public void saveGatheredMetrics(String filename) { String separator = ","; try { PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(filename))); pw.println("FEATURE" + separator + "TIPO_METRICA" + separator + "METRICA" + separator + "VALOR"); // Gravar LOC StringBuilder textOutput = new StringBuilder(); textOutput.append("TODAS"); textOutput.append(separator); textOutput.append(MetricType.LOC.getIdentifier()); textOutput.append(separator); textOutput.append("N/A"); textOutput.append(separator); textOutput.append(this.locMetric); pw.println(textOutput); for (Iterator<Metric> it = metrics.iterator(); it.hasNext();) { Metric metric = (Metric) it.next(); for (int i=0; i<MetricType.values().length-1; i++) { Set<String> keySet = metric.getSubMetric(MetricType.values()[i]).getValues().keySet(); for (Iterator<String> iterator = keySet.iterator(); iterator.hasNext();) { String key = iterator.next(); if(key != null) { textOutput = new StringBuilder(); textOutput.append(metric.getFeature()); textOutput.append(separator); textOutput.append(MetricType.values()[i].getIdentifier()); textOutput.append(separator); textOutput.append(key); textOutput.append(separator); textOutput.append(metric.getSubMetric(MetricType.values()[i]).getValues().get(key)); pw.println(textOutput); } } pw.flush(); } } pw.close(); } catch (FileNotFoundException e) { Log.error(e.getMessage()); e.printStackTrace(); } catch (IOException e) { Log.error(e.getMessage()); e.printStackTrace(); } } }