View Javadoc
1   /*
2    * reserved comment block
3    * DO NOT REMOVE OR ALTER!
4    */
5   /*
6    * Copyright 2000-2002,2004 The Apache Software Foundation.
7    *
8    * Licensed under the Apache License, Version 2.0 (the "License");
9    * you may not use this file except in compliance with the License.
10   * You may obtain a copy of the License at
11   *
12   *      http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  
21  package com.sun.org.apache.xerces.internal.util;
22  
23  import java.util.Hashtable;
24  import java.util.Enumeration;
25  
26  import com.sun.org.apache.xerces.internal.xni.Augmentations;
27  
28  /**
29   * This class provides an implementation for Augmentations interface.
30   * Augmentations interface defines a hashtable of additional data that could
31   * be passed along the document pipeline. The information can contain extra
32   * arguments or infoset augmentations, for example PSVI. This additional
33   * information is identified by a String key.
34   * <p>
35   *
36   * @author Elena Litani, IBM
37   */
38  public class AugmentationsImpl implements Augmentations{
39  
40      private AugmentationsItemsContainer fAugmentationsContainer =
41                                          new SmallContainer();
42  
43      /**
44       * Add additional information identified by a key to the Augmentations structure.
45       *
46       * @param key    Identifier, can't be <code>null</code>
47       * @param item   Additional information
48       *
49       * @return the previous value of the specified key in the Augmentations strucutre,
50       *         or <code>null</code> if it did not have one.
51       */
52      public Object putItem (String key, Object item){
53          Object oldValue = fAugmentationsContainer.putItem(key, item);
54  
55          if (oldValue == null && fAugmentationsContainer.isFull()) {
56              fAugmentationsContainer = fAugmentationsContainer.expand();
57          }
58  
59          return oldValue;
60      }
61  
62  
63      /**
64       * Get information identified by a key from the Augmentations structure
65       *
66       * @param key    Identifier, can't be <code>null</code>
67       *
68       * @return the value to which the key is mapped in the Augmentations structure;
69       *         <code>null</code> if the key is not mapped to any value.
70       */
71      public Object getItem(String key){
72          return fAugmentationsContainer.getItem(key);
73      }
74  
75  
76      /**
77       * Remove additional info from the Augmentations structure
78       *
79       * @param key    Identifier, can't be <code>null</code>
80       */
81      public Object removeItem (String key){
82          return fAugmentationsContainer.removeItem(key);
83      }
84  
85      /**
86       * Returns an enumeration of the keys in the Augmentations structure
87       *
88       */
89      public Enumeration keys (){
90          return fAugmentationsContainer.keys();
91      }
92  
93      /**
94       * Remove all objects from the Augmentations structure.
95       */
96      public void removeAllItems() {
97          fAugmentationsContainer.clear();
98      }
99  
100     public String toString() {
101         return fAugmentationsContainer.toString();
102     }
103 
104     abstract class AugmentationsItemsContainer {
105         abstract public Object putItem(Object key, Object item);
106         abstract public Object getItem(Object key);
107         abstract public Object removeItem(Object key);
108         abstract public Enumeration keys();
109         abstract public void clear();
110         abstract public boolean isFull();
111         abstract public AugmentationsItemsContainer expand();
112     }
113 
114     class SmallContainer extends AugmentationsItemsContainer {
115         final static int SIZE_LIMIT = 10;
116         final Object[] fAugmentations = new Object[SIZE_LIMIT*2];
117         int fNumEntries = 0;
118 
119         public Enumeration keys() {
120             return new SmallContainerKeyEnumeration();
121         }
122 
123         public Object getItem(Object key) {
124             for (int i = 0; i < fNumEntries*2; i = i + 2) {
125                 if (fAugmentations[i].equals(key)) {
126                     return fAugmentations[i+1];
127                 }
128             }
129 
130             return null;
131         }
132 
133         public Object putItem(Object key, Object item) {
134             for (int i = 0; i < fNumEntries*2; i = i + 2) {
135                 if (fAugmentations[i].equals(key)) {
136                     Object oldValue = fAugmentations[i+1];
137                     fAugmentations[i+1] = item;
138 
139                     return oldValue;
140                 }
141             }
142 
143             fAugmentations[fNumEntries*2] = key;
144             fAugmentations[fNumEntries*2+1] = item;
145             fNumEntries++;
146 
147             return null;
148         }
149 
150 
151         public Object removeItem(Object key) {
152             for (int i = 0; i < fNumEntries*2; i = i + 2) {
153                 if (fAugmentations[i].equals(key)) {
154                     Object oldValue = fAugmentations[i+1];
155 
156                     for (int j = i; j < fNumEntries*2 - 2; j = j + 2) {
157                         fAugmentations[j] = fAugmentations[j+2];
158                         fAugmentations[j+1] = fAugmentations[j+3];
159                     }
160 
161                     fAugmentations[fNumEntries*2-2] = null;
162                     fAugmentations[fNumEntries*2-1] = null;
163                     fNumEntries--;
164 
165                     return oldValue;
166                 }
167             }
168 
169             return null;
170         }
171 
172         public void clear() {
173             for (int i = 0; i < fNumEntries*2; i = i + 2) {
174                 fAugmentations[i] = null;
175                 fAugmentations[i+1] = null;
176             }
177 
178             fNumEntries = 0;
179         }
180 
181         public boolean isFull() {
182             return (fNumEntries == SIZE_LIMIT);
183         }
184 
185         public AugmentationsItemsContainer expand() {
186             LargeContainer expandedContainer = new LargeContainer();
187 
188             for (int i = 0; i < fNumEntries*2; i = i + 2) {
189                 expandedContainer.putItem(fAugmentations[i],
190                                           fAugmentations[i+1]);
191             }
192 
193             return expandedContainer;
194         }
195 
196         public String toString() {
197             StringBuffer buff = new StringBuffer();
198             buff.append("SmallContainer - fNumEntries == " + fNumEntries);
199 
200             for (int i = 0; i < SIZE_LIMIT*2; i=i+2) {
201                 buff.append("\nfAugmentations[");
202                 buff.append(i);
203                 buff.append("] == ");
204                 buff.append(fAugmentations[i]);
205                 buff.append("; fAugmentations[");
206                 buff.append(i+1);
207                 buff.append("] == ");
208                 buff.append(fAugmentations[i+1]);
209             }
210 
211             return buff.toString();
212         }
213 
214         class SmallContainerKeyEnumeration implements Enumeration {
215             Object [] enumArray = new Object[fNumEntries];
216             int next = 0;
217 
218             SmallContainerKeyEnumeration() {
219                 for (int i = 0; i < fNumEntries; i++) {
220                     enumArray[i] = fAugmentations[i*2];
221                 }
222             }
223 
224             public boolean hasMoreElements() {
225                 return next < enumArray.length;
226             }
227 
228             public Object nextElement() {
229                 if (next >= enumArray.length) {
230                     throw new java.util.NoSuchElementException();
231                 }
232 
233                 Object nextVal = enumArray[next];
234                 enumArray[next] = null;
235                 next++;
236 
237                 return nextVal;
238             }
239         }
240     }
241 
242     class LargeContainer extends AugmentationsItemsContainer {
243         final Hashtable fAugmentations = new Hashtable();
244 
245         public Object getItem(Object key) {
246             return fAugmentations.get(key);
247         }
248 
249         public Object putItem(Object key, Object item) {
250             return fAugmentations.put(key, item);
251         }
252 
253         public Object removeItem(Object key) {
254             return fAugmentations.remove(key);
255         }
256 
257         public Enumeration keys() {
258             return fAugmentations.keys();
259         }
260 
261         public void clear() {
262             fAugmentations.clear();
263         }
264 
265         public boolean isFull() {
266             return false;
267         }
268 
269         public AugmentationsItemsContainer expand() {
270             return this;
271         }
272 
273         public String toString() {
274             StringBuffer buff = new StringBuffer();
275             buff.append("LargeContainer");
276             Enumeration keys = fAugmentations.keys();
277 
278             while (keys.hasMoreElements()) {
279                 Object key = keys.nextElement();
280                 buff.append("\nkey == ");
281                 buff.append(key);
282                 buff.append("; value == ");
283                 buff.append(fAugmentations.get(key));
284             }
285 
286             return buff.toString();
287         }
288     }
289 }