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 021 /** 022 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html 023 */ 024 package org.sonar.duplications.cpd; 025 026 import net.sourceforge.pmd.cpd.TokenEntry; 027 028 import java.util.Comparator; 029 import java.util.Iterator; 030 import java.util.Set; 031 import java.util.TreeSet; 032 033 public class Match implements Comparable<Match> { 034 035 public static final String EOL = System.getProperty("line.separator", "\n"); 036 037 private int tokenCount; 038 private int lineCount; 039 private Set<TokenEntry> markSet = new TreeSet<TokenEntry>(); 040 private TokenEntry[] marks = new TokenEntry[2]; 041 private String code; 042 private MatchCode mc; 043 private String label; 044 045 public static final Comparator<Match> MatchesComparator = new Comparator<Match>() { 046 047 public int compare(Match ma, Match mb) { 048 return mb.getMarkCount() - ma.getMarkCount(); 049 } 050 }; 051 052 public static final Comparator<Match> LinesComparator = new Comparator<Match>() { 053 054 public int compare(Match ma, Match mb) { 055 return mb.getLineCount() - ma.getLineCount(); 056 } 057 }; 058 059 public static final Comparator<Match> LabelComparator = new Comparator<Match>() { 060 061 public int compare(Match ma, Match mb) { 062 if (ma.getLabel() == null) { 063 return 1; 064 } 065 if (mb.getLabel() == null) { 066 return -1; 067 } 068 return mb.getLabel().compareTo(ma.getLabel()); 069 } 070 }; 071 072 public static final Comparator<Match> LengthComparator = new Comparator<Match>() { 073 074 public int compare(Match ma, Match mb) { 075 return mb.getLineCount() - ma.getLineCount(); 076 } 077 }; 078 079 public static class MatchCode { 080 081 private int first; 082 private int second; 083 084 public MatchCode() { 085 } 086 087 public MatchCode(TokenEntry m1, TokenEntry m2) { 088 first = m1.getIndex(); 089 second = m2.getIndex(); 090 } 091 092 @Override 093 public int hashCode() { 094 return first + 37 * second; 095 } 096 097 @Override 098 public boolean equals(Object other) { 099 if (!(other instanceof MatchCode)) { 100 return false; 101 } 102 MatchCode mc = (MatchCode) other; 103 return mc.first == first && mc.second == second; 104 } 105 106 public void setFirst(int first) { 107 this.first = first; 108 } 109 110 public void setSecond(int second) { 111 this.second = second; 112 } 113 114 } 115 116 public Match(int tokenCount, TokenEntry first, TokenEntry second) { 117 markSet.add(first); 118 markSet.add(second); 119 marks[0] = first; 120 marks[1] = second; 121 this.tokenCount = tokenCount; 122 } 123 124 public int getMarkCount() { 125 return markSet.size(); 126 } 127 128 public void setLineCount(int lineCount) { 129 this.lineCount = lineCount; 130 } 131 132 public int getLineCount() { 133 return this.lineCount; 134 } 135 136 public int getTokenCount() { 137 return this.tokenCount; 138 } 139 140 public String getSourceCodeSlice() { 141 return this.code; 142 } 143 144 public void setSourceCodeSlice(String code) { 145 this.code = code; 146 } 147 148 public Iterator<TokenEntry> iterator() { 149 return markSet.iterator(); 150 } 151 152 public int compareTo(Match other) { 153 int diff = other.getTokenCount() - getTokenCount(); // NOSONAR Bad practice - Class defines compareTo(...) and uses Object.equals() 154 if (diff != 0) { 155 return diff; 156 } 157 return other.getFirstMark().getIndex() - getFirstMark().getIndex(); 158 } 159 160 public TokenEntry getFirstMark() { 161 return marks[0]; 162 } 163 164 public TokenEntry getSecondMark() { 165 return marks[1]; 166 } 167 168 @Override 169 public String toString() { 170 return "Match: " + EOL + "tokenCount = " + tokenCount + EOL + "marks = " + markSet.size(); 171 } 172 173 public Set<TokenEntry> getMarkSet() { 174 return markSet; 175 } 176 177 public MatchCode getMatchCode() { 178 if (mc == null) { 179 mc = new MatchCode(marks[0], marks[1]); 180 } 181 return mc; 182 } 183 184 public int getEndIndex() { 185 return marks[1].getIndex() + getTokenCount() - 1; 186 } 187 188 public void setMarkSet(Set<TokenEntry> markSet) { 189 this.markSet = markSet; 190 } 191 192 public void setLabel(String aLabel) { 193 label = aLabel; 194 } 195 196 public String getLabel() { 197 return label; 198 } 199 }