View Javadoc
1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.cpd;
5   
6   import java.util.ArrayList;
7   import java.util.HashMap;
8   import java.util.List;
9   import java.util.Map;
10  import java.util.concurrent.atomic.AtomicInteger;
11  
12  public class TokenEntry implements Comparable<TokenEntry> {
13  
14      public static final TokenEntry EOF = new TokenEntry();
15  
16      private String tokenSrcID;
17      private int beginLine;
18      private int index;
19      private int identifier;
20      private int hashCode;
21  
22      private static final ThreadLocal<Map<String, Integer>> TOKENS = new ThreadLocal<Map<String, Integer>>(){
23          @Override
24          protected Map<String, Integer> initialValue() {
25              return new HashMap<>();
26          }
27      };
28      private static final ThreadLocal<AtomicInteger> TOKEN_COUNT = new ThreadLocal<AtomicInteger>(){
29          @Override
30          protected AtomicInteger initialValue() {
31              return new AtomicInteger(0);
32          }
33      };
34  
35      private TokenEntry() {
36          this.identifier = 0;
37          this.tokenSrcID = "EOFMarker";
38      }
39  
40      public TokenEntry(String image, String tokenSrcID, int beginLine) {
41          Integer i = TOKENS.get().get(image);
42          if (i == null) {
43              i = TOKENS.get().size() + 1;
44              TOKENS.get().put(image, i);
45          }
46          this.identifier = i.intValue();
47          this.tokenSrcID = tokenSrcID;
48          this.beginLine = beginLine;
49          this.index = TOKEN_COUNT.get().getAndIncrement();
50      }
51  
52      public static TokenEntry getEOF() {
53          TOKEN_COUNT.get().getAndIncrement();
54          return EOF;
55      }
56  
57      public static void clearImages() {
58          TOKENS.get().clear();
59          TOKENS.remove();
60          TOKEN_COUNT.remove();
61      }
62      /**
63       * Helper class to preserve and restore the current state
64       * of the token entries.
65       */
66      public static class State {
67          private int tokenCount;
68          private Map<String, Integer> tokens;
69          private List<TokenEntry> entries;
70          public State(List<TokenEntry> entries) {
71              this.tokenCount = TokenEntry.TOKEN_COUNT.get().intValue();
72              this.tokens = new HashMap<>(TokenEntry.TOKENS.get());
73              this.entries = new ArrayList<>(entries);
74          }
75          public List<TokenEntry> restore() {
76              TokenEntry.TOKEN_COUNT.get().set(tokenCount);
77              TOKENS.get().clear();
78              TOKENS.get().putAll(tokens);
79              return entries;
80          }
81      }
82  
83      public String getTokenSrcID() {
84          return tokenSrcID;
85      }
86  
87      public int getBeginLine() {
88          return beginLine;
89      }
90  
91      public int getIdentifier() {
92          return this.identifier;
93      }
94  
95      public int getIndex() {
96          return this.index;
97      }
98  
99      public int hashCode() {
100         return hashCode;
101     }
102 
103     public void setHashCode(int hashCode) {
104         this.hashCode = hashCode;
105     }
106 
107     public boolean equals(Object o) {
108         if (!(o instanceof TokenEntry)) {
109             return false;
110         }
111         TokenEntry other = (TokenEntry) o;
112         return other.hashCode == hashCode;
113     }
114 
115     public int compareTo(TokenEntry other) {
116         return getIndex() - other.getIndex();
117     }
118 
119     @Override
120     public String toString() {
121         if (this == EOF) {
122             return "EOF";
123         }
124         for (Map.Entry<String, Integer> e : TOKENS.get().entrySet()) {
125             if (e.getValue().intValue() == identifier) {
126                 return e.getKey();
127             }
128         }
129         return "--unkown--";
130     }
131 }