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 }