Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/thermidor/xml/TokenTable.java


1   package com.thermidor.xml;
2   /*@LEGAL*/
3   import java.util.HashMap;
4   import java.util.Iterator;
5   
6   /**
7   * The TokenTable class is a genric token table used to maintain an list of 
8   * string identifiers to token mappings, and finds particular use in the 
9   * implementation of parsers.
10  * @author James Turnock
11   */
12  public class TokenTable {
13      /**
14       * Constant used to indicate that no mapping was defined for a given
15       * identifier.
16       */
17      public static final int NO_TOKEN_DEFINED = -1;
18  
19      /**
20       * Essentially the token table for storing the mapping between given 
21       * identifiers and their tokens.
22       */
23      private HashMap tokenTable = new HashMap(89);
24  
25      /**
26       * Flag indicating whether the TokenTable instance has been declared ready.
27       * Ready means that no more mappings will be added to the token table and
28       * it is ready to be used by clients.
29       */
30      private boolean ready = false;
31  
32      /**
33       * Flag indication whether the TokenTable instance should check for the 
34       * integrity of the proposed mappings.
35       */
36      private final boolean checkIntegrity;
37  
38      /**
39       * Default constructor. Instantiates a token table with integrity checking.
40       */
41      public TokenTable() {
42          this(true);
43      }
44  
45      /**
46       * Instantiates a token table with integrity checking.
47       * @param checkIntegrity Whether the TokenTable should ensure integrity
48       *  by not allowing duplicate identifiers and tokens.
49       */
50      public TokenTable(boolean checkIntegrity) {
51          this.checkIntegrity = checkIntegrity;
52      }
53  
54      /**
55       * Stores the mapping between the identifier and the token.
56       * @param identifier The identifier to be associated with the token.
57       * @param token The token to associated with the identifier.
58       */
59      public final void put(String identifier, int token) {
60          if (ready) {
61              throw new IllegalStateException("Cannot add token mappings once " +
62                                              " ready has been called");
63  
64          } else {
65              synchronized (tokenTable) {
66                  if (checkIntegrity) {
67                      assertIntegrity(identifier, token);
68                  }
69  
70                  tokenTable.put(identifier, new Integer(token));
71              }
72          }
73      }
74  
75      /**
76       * Performs a series of integrity checks on the proposed identifier 
77       * and token: (a) that the identifier is not NULL (b) that the token 
78       * is not the reserved value for designating an unknown mapping and 
79       * (c) that there is no duplication of previously held mapping information.
80       * @param identifier The proposed identifier.
81       * @param token The proposed token.
82       */
83      private void assertIntegrity(String identifier, int token) {
84          assertNotNull(identifier);
85          assertNotUndefinedToken(token);
86          assertNoDuplicates(identifier, token);
87      }
88  
89      /**
90       * Asserts that the proposed identifier is not Null.
91       * @param identifier The proposed identifier.
92       */
93      private static void assertNotNull(String identifier) {
94          if (identifier == null) {
95              throw new NullPointerException("Proposed token identitifer" +
96                                             "is NULL");
97          }
98      }
99      /**
100        Message constant <code>A token cannot posses value 
101        used to define an undefined mapping:</code>.
102     */
103     private static final String MSG_UNDEFINED_TOKEN;
104     /**
105        Message constant <code>Duplicate identifier and token added.
106              [Identifier,TOKEN]=</code>.
107     */
108     private static final String MSG_TOKEN_REASSIGNMENT;
109     /**
110        Message constant <code>Duplicate token. [Existing,Token,Identifier]
111        =</code>.
112     */
113     private static final String MSG_DUPLICATE_TOKEN;
114     /**
115        Message constant <code>Duplicate identifier [Identifier]
116        =</code>.
117     */
118     private static final String MSG_DUPLICATE_IDENTIFIER;
119     static{
120         MSG_UNDEFINED_TOKEN = "A token cannot posses value " +
121             "used to define an undefined mapping:" + NO_TOKEN_DEFINED;
122         MSG_DUPLICATE_TOKEN = "Duplicate identifier and token added." +
123             " [Identifier,TOKEN]=";
124         MSG_TOKEN_REASSIGNMENT = "Duplicate token. [Existing,Token," +
125             "Identifier]=";
126         MSG_DUPLICATE_IDENTIFIER = "Duplicate identifier [Identifier]=";
127     }
128     
129     /**
130      * Asserts that the proposed token is not the same as the constant used to
131      * designate an undefined mapping.
132      * @param proposedToken The proposed token.
133      */
134     private static void assertNotUndefinedToken(int proposedToken) {
135         if (proposedToken == NO_TOKEN_DEFINED) {
136             throw new IllegalArgumentException(MSG_UNDEFINED_TOKEN);
137         }
138     }
139 
140     /**
141      *Asserts that the TokenTable is in the state specified in the isReady
142      * parameter.
143      *@param isReady The test state to compare to the internal state.
144      */
145     private void assertReady(boolean isReady) {
146         if (ready != isReady) {
147             throw new IllegalStateException();
148         }
149     }
150 
151     /**
152      * Asserts that there is no duplication of previously held mapping
153      * information.
154      * @param proposedIdentifier The proposed identifier.
155      * @param proposedToken The proposed token.
156      */
157     private void assertNoDuplicates(String proposedIdentifier,
158                                     int proposedToken) {
159         Iterator it = tokenTable.entrySet().iterator();
160 
161         while (it.hasNext()) {
162 
163             java.util.Map.Entry
164             entry
165             = (java.util.Map.Entry
166               )it.next();
167 
168             int declaredToken = ((Integer)entry.getValue()).intValue();
169 
170             String declaredIdentifier = (String)entry.getKey();
171 
172             boolean tokenDuplicate = (declaredToken == proposedToken);
173 
174             boolean identifierDuplicate =
175                 declaredIdentifier.equals(proposedIdentifier);
176 
177             if (tokenDuplicate && identifierDuplicate) {
178                 throw new IllegalArgumentException(MSG_DUPLICATE_TOKEN +
179                                                     proposedIdentifier +
180                                                    "," + proposedToken);
181 
182             } else if (tokenDuplicate) {
183                 throw new IllegalArgumentException(MSG_TOKEN_REASSIGNMENT +
184                                                    declaredIdentifier + 
185                                                    "," + proposedToken +
186                                                    "," + proposedIdentifier);
187 
188             } else if (identifierDuplicate) {
189                 throw new IllegalArgumentException(MSG_DUPLICATE_IDENTIFIER +
190                                                    proposedIdentifier);
191             }
192         }
193     }
194 
195     /**
196      * @param identifier The identifier for which the mapped token is required.
197      * @return The mapped value of the identifier or -1 if no mapping was 
198      * defined.
199      */
200     public final int getToken(String identifier) {
201         assertReady(true);
202         Integer token = (Integer)tokenTable.get(identifier);
203         return token == null ? (NO_TOKEN_DEFINED) : (token.intValue());
204     }
205 
206     /**
207      * Signals that the population of the token table has finished. This
208      * prevents further mappings from being added to the TokenTable.
209      */
210     public void ready() {
211         ready = true;
212     }
213 
214     /**
215      * Utility method for discovering whether the token table has been declared
216      * ready.
217      * @return Whether the TokenTable instance has been transitioned to the
218      * ready state.
219      */
220     public boolean isReady() {
221         return ready;
222     }
223 }
224 
225 
226 
227