1
2
3
4 package net.sourceforge.pmd.cpd;
5
6 import java.util.ArrayList;
7 import java.util.Collections;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.TreeMap;
11
12 public class MatchCollector {
13 private List<Match> matchList = new ArrayList<Match>();
14 private Map<Integer, Map<Integer, Match>> matchTree = new TreeMap<Integer, Map<Integer, Match>>();
15 private MatchAlgorithm ma;
16
17 public MatchCollector(MatchAlgorithm ma) {
18 this.ma = ma;
19 }
20
21 public void collect(List<TokenEntry> marks) {
22
23 for (int i = 0; i < marks.size() - 1; i++) {
24 TokenEntry mark1 = marks.get(i);
25 for (int j = i + 1; j < marks.size(); j++) {
26 TokenEntry mark2 = marks.get(j);
27 int diff = mark1.getIndex() - mark2.getIndex();
28 if (-diff < ma.getMinimumTileSize()) {
29 continue;
30 }
31 if (hasPreviousDupe(mark1, mark2)) {
32 continue;
33 }
34
35
36 int dupes = countDuplicateTokens(mark1, mark2);
37 if (dupes < ma.getMinimumTileSize()) {
38 continue;
39 }
40
41 if (diff + dupes >= 1) {
42 continue;
43 }
44 reportMatch(mark1, mark2, dupes);
45 }
46 }
47 }
48
49 private void reportMatch(TokenEntry mark1, TokenEntry mark2, int dupes) {
50 Map<Integer, Match> matches = matchTree.get(dupes);
51 if (matches == null) {
52 matches = new TreeMap<Integer, Match>();
53 matchTree.put(dupes, matches);
54 addNewMatch(mark1, mark2, dupes, matches);
55 } else {
56 Match matchA = matchTree.get(dupes).get(mark1.getIndex());
57 Match matchB = matchTree.get(dupes).get(mark2.getIndex());
58
59 if (matchA == null && matchB == null) {
60 addNewMatch(mark1, mark2, dupes, matches);
61 } else if(matchA == null) {
62 matchB.addTokenEntry(mark1);
63 matches.put(mark1.getIndex(), matchB);
64 } else if(matchB == null) {
65 matchA.addTokenEntry(mark2);
66 matches.put(mark2.getIndex(), matchA);
67 }
68 }
69 }
70
71 private void addNewMatch(TokenEntry mark1, TokenEntry mark2, int dupes, Map<Integer, Match> matches){
72 Match match = new Match(dupes, mark1, mark2);
73 matches.put(mark1.getIndex(), match);
74 matches.put(mark2.getIndex(), match);
75 matchList.add(match);
76 }
77
78 @SuppressWarnings("PMD.CompareObjectsWithEquals")
79 public List<Match> getMatches() {
80 Collections.sort(matchList);
81 return matchList;
82 }
83
84 private boolean hasPreviousDupe(TokenEntry mark1, TokenEntry mark2) {
85 if (mark1.getIndex() == 0) {
86 return false;
87 }
88 return !matchEnded(ma.tokenAt(-1, mark1), ma.tokenAt(-1, mark2));
89 }
90
91 private int countDuplicateTokens(TokenEntry mark1, TokenEntry mark2) {
92 int index = 0;
93 while (!matchEnded(ma.tokenAt(index, mark1), ma.tokenAt(index, mark2))) {
94 index++;
95 }
96 return index;
97 }
98
99 private boolean matchEnded(TokenEntry token1, TokenEntry token2) {
100 return token1.getIdentifier() != token2.getIdentifier() || token1 == TokenEntry.EOF || token2 == TokenEntry.EOF;
101 }
102 }