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 */ 020 package org.sonar.plugins.cpd; 021 022 import com.google.common.collect.Lists; 023 import com.google.common.collect.Sets; 024 import org.sonar.api.batch.SensorContext; 025 import org.sonar.api.measures.CoreMetrics; 026 import org.sonar.api.measures.Measure; 027 import org.sonar.api.measures.PersistenceMode; 028 import org.sonar.api.resources.Resource; 029 030 import java.util.Collections; 031 import java.util.Comparator; 032 import java.util.List; 033 import java.util.Set; 034 035 public class DuplicationsData { 036 037 private final String resourceKey; 038 private final Set<Integer> duplicatedLines = Sets.newHashSet(); 039 private final List<XmlEntry> duplicationXMLEntries = Lists.newArrayList(); 040 041 private double duplicatedBlocks; 042 043 public DuplicationsData(String resourceKey) { 044 this.resourceKey = resourceKey; 045 } 046 047 public void cumulate(String targetResourceKey, int targetDuplicationStartLine, int duplicationStartLine, int duplicatedLines) { 048 duplicationXMLEntries.add(new XmlEntry(targetResourceKey, targetDuplicationStartLine, duplicationStartLine, duplicatedLines)); 049 for (int duplicatedLine = duplicationStartLine; duplicatedLine < duplicationStartLine + duplicatedLines; duplicatedLine++) { 050 this.duplicatedLines.add(duplicatedLine); 051 } 052 } 053 054 public void incrementDuplicatedBlock() { 055 duplicatedBlocks++; 056 } 057 058 public void save(SensorContext context, Resource resource) { 059 context.saveMeasure(resource, CoreMetrics.DUPLICATED_FILES, 1d); 060 context.saveMeasure(resource, CoreMetrics.DUPLICATED_LINES, (double) duplicatedLines.size()); 061 context.saveMeasure(resource, CoreMetrics.DUPLICATED_BLOCKS, duplicatedBlocks); 062 063 Measure data = new Measure(CoreMetrics.DUPLICATIONS_DATA, getDuplicationXMLData()) 064 .setPersistenceMode(PersistenceMode.DATABASE); 065 context.saveMeasure(resource, data); 066 } 067 068 private String getDuplicationXMLData() { 069 Collections.sort(duplicationXMLEntries, COMPARATOR); 070 StringBuilder duplicationXML = new StringBuilder("<duplications>"); 071 for (XmlEntry xmlEntry : duplicationXMLEntries) { 072 duplicationXML.append(xmlEntry.toString()); 073 } 074 duplicationXML.append("</duplications>"); 075 return duplicationXML.toString(); 076 } 077 078 private static final Comparator<XmlEntry> COMPARATOR = new Comparator<XmlEntry>() { 079 public int compare(XmlEntry o1, XmlEntry o2) { 080 if (o1.startLine == o2.startLine) { 081 return o1.lines - o2.lines; 082 } 083 return o1.startLine - o2.startLine; 084 } 085 }; 086 087 private final class XmlEntry { 088 private final String target; 089 private final int targetStartLine; 090 private final int startLine; 091 private final int lines; 092 093 private XmlEntry(String target, int targetStartLine, int startLine, int lines) { 094 this.target = target; 095 this.targetStartLine = targetStartLine; 096 this.startLine = startLine; 097 this.lines = lines; 098 } 099 100 @Override 101 public String toString() { 102 return new StringBuilder() 103 .append("<g>") 104 .append("<b s=\"").append(startLine).append("\" l=\"").append(lines).append("\" r=\"").append(resourceKey).append("\" />") 105 .append("<b s=\"").append(targetStartLine).append("\" l=\"").append(lines).append("\" r=\"").append(target).append("\" />") 106 .append("</g>") 107 .toString(); 108 } 109 } 110 111 }