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 }