Annotation of java/classes/org/w3c/util/LookupTable.java, revision 1.2
1.1 bmahe 1: // LookupTable.java
1.2 ! bmahe 2: // $Id: LookupTable.java,v 1.1 1999/12/07 10:07:05 bmahe Exp $
1.1 bmahe 3: // (c) COPYRIGHT MIT, INRIA and Keio, 1999.
4: // Please first read the full copyright statement in file COPYRIGHT.html
5: package org.w3c.util;
6:
7: import java.io.Serializable;
8:
9: import java.util.Enumeration;
10:
11: /**
12: * A kind of hashtable (maps keys to values), useful for a limited number
13: * of elements.
1.2 ! bmahe 14: * @version $Revision: 1.1 $
1.1 bmahe 15: * @author BenoοΏ½t MahοΏ½ (bmahe@w3.org)
16: */
17: public class LookupTable implements Cloneable, Serializable {
18:
19: /**
20: * The default capacity.
21: */
22: public static final int DEFAULT_CAPACITY = 10;
23:
24: private Object elements[] = null;
25:
26: private Object keys[] = null;
27:
28: private int count = 0;
29:
30: private int capacity = 0;
31:
32: /**
33: * Returns the number of keys in this lookuptable.
34: *
35: * @return the number of keys in this lookuptable.
36: */
37: public int size() {
38: return count;
39: }
40:
41: /**
42: * Tests if this lookuptable maps no keys to values.
43: * @return <code>true</code> if this lookuptable maps no keys to values;
44: * <code>false</code> otherwise.
45: */
46: public boolean isEmpty() {
47: return count == 0;
48: }
49:
50: /**
51: * Returns an enumeration of the keys in this lookuptable.
52: *
53: * @return an enumeration of the keys in this lookuptable.
54: * @see java.util.Enumeration
55: * @see #elements()
56: */
57: public synchronized Enumeration keys() {
58: return new ArrayEnumeration(keys, count);
59: }
60:
61: /**
62: * Returns an enumeration of the values in this lookuptable.
63: * Use the Enumeration methods on the returned object to fetch the elements
64: * sequentially.
65: *
66: * @return an enumeration of the values in this lookuptable.
67: * @see java.util.Enumeration
68: * @see #keys()
69: */
70: public synchronized Enumeration elements() {
71: return new ArrayEnumeration(elements, count);
72: }
73:
74: /**
75: * Tests if some key maps into the specified value in this lookuptable.
76: * @param value a value to search for.
77: * @return <code>true</code> if and only if some key maps to the
78: * <code>value</code> argument in this lookuptable as
79: * determined by the <tt>equals</tt> method;
80: * <code>false</code> otherwise.
81: * @exception NullPointerException if the value is <code>null</code>.
82: * @see #containsKey(Object)
83: */
84: public synchronized boolean contains(Object value) {
85: return (contains(elements, count, value) != -1);
86: }
87:
88: /**
89: * Tests if the specified object is a key in this lookuptable.
90: * @param key possible key.
91: * @return <code>true</code> if and only if the specified object
92: * is a key in this lookuptable, as determined by the
93: * <tt>equals</tt> method; <code>false</code> otherwise.
94: * @see #contains(Object)
95: */
96: public synchronized boolean containsKey(Object key) {
97: return (contains(keys, count, key) != -1);
98: }
99:
100: private int contains(Object array[], int size, Object value) {
101: if (value == null) {
102: throw new NullPointerException();
103: }
104: for (int i = 0 ; i < size ; i++) {
105: if (array[i].equals(value))
106: return i;
107: }
108: return -1;
109: }
110:
111: /**
112: * Returns the value to which the specified key is mapped in this
113: * lookuptable.
114: * @param key a key in the lookuptable.
115: * @return the value to which the key is mapped in this lookuptable;
116: * <code>null</code> if the key is not mapped to any value in
117: * this lookuptable.
118: * @see #put(Object, Object)
119: */
120: public synchronized Object get(Object key) {
121: int idx = contains(keys, count, key);
122: if (idx != -1)
123: return elements[idx];
124: return null;
125: }
126:
127: /**
128: * Maps the specified <code>key</code> to the specified
129: * <code>value</code> in this lookuptable. Neither the key nor the
130: * value can be <code>null</code>. <p>
131: *
132: * The value can be retrieved by calling the <code>get</code> method
133: * with a key that is equal to the original key.
134: *
135: * @param key the lookuptable key.
136: * @param value the value.
137: * @return the previous value of the specified key in this lookuptable,
138: * or <code>null</code> if it did not have one.
139: * @exception NullPointerException if the key or value is
140: * <code>null</code>.
141: * @see Object#equals(Object)
142: * @see #get(Object)
143: */
144: public synchronized Object put(Object key, Object value) {
145: if (value == null) {
146: throw new NullPointerException();
147: }
148: int idx = contains(keys, count, key);
149: if (idx == -1) {
150: if (count >= capacity) {
151: grow();
152: }
153: keys[count] = key;
154: elements[count] = value;
155: count++;
156: return null;
157: } else {
158: Object previousValue = elements[idx];
159: elements[idx] = value;
160: return previousValue;
161: }
162: }
163:
164: /**
165: * Increases the capacity. This method is called automatically when the
166: * number of keys in the lookuptable exceeds this lookuptable's capacity.
167: */
168: protected void grow() {
169: int newCapacity = capacity * 2 + 1;
170: Object newElements[] = new Object[newCapacity];
171: Object newKeys[] = new Object[newCapacity];
172: System.arraycopy(elements, 0, newElements, 0, count);
173: System.arraycopy(keys, 0, newKeys, 0, count);
174: this.keys = newKeys;
175: this.elements = newElements;
176: this.capacity = newCapacity;
177: }
178:
179: /**
180: * Removes the key (and its corresponding value) from this
181: * lookuptable. This method does nothing if the key is not in the
182: * lookuptable.
183: *
184: * @param key the key that needs to be removed.
185: * @return the value to which the key had been mapped in this lookuptable,
186: * or <code>null</code> if the key did not have a mapping.
187: */
188: public synchronized Object remove(Object key) {
189: int idx = contains(keys, count, key);
190: if (idx != -1) {
191: //remove this one by moving the last one here.
192: Object oldvalue = elements[idx];
193: count--;
194: keys[idx] = keys[count];
195: elements[idx] = elements[count];
196: keys[count] = null;
197: elements[count] = null;
198: return oldvalue;
199: }
200: return null;
201: }
202:
203: /**
204: * Clears this lookuptable so that it contains no keys.
205: */
206: public synchronized void clear() {
207: this.count = 0;
208: this.keys = new Object[capacity];
209: this.elements = new Object[capacity];
210: }
211:
212: /**
213: * Creates a shallow copy of this lookuptable. All the structure of the
214: * lookuptable itself is copied, but the keys and values are not cloned.
215: * This is a relatively expensive operation.
216: *
217: * @return a clone of the lookuptable.
218: */
219: public synchronized Object clone() {
220: try {
221: LookupTable l = (LookupTable)super.clone();
222: l.keys = new Object[capacity];
223: System.arraycopy(keys, 0, l.keys, 0, count);
224: l.elements = new Object[capacity];
225: System.arraycopy(elements, 0, l.elements, 0, count);
226: l.capacity = capacity;
227: l.count = count;
228: return l;
229: } catch (CloneNotSupportedException e) {
230: // this shouldn't happen, since we are Cloneable
231: throw new InternalError();
232: }
233: }
234:
235: /**
236: * Returns a string representation of this <tt>Lookuptable</tt> object
237: * in the form of a set of entries, enclosed in braces and separated
238: * by the ASCII characters "<tt>, </tt>" (comma and space). Each
239: * entry is rendered as the key, an equals sign <tt>=</tt>, and the
240: * associated element, where the <tt>toString</tt> method is used to
241: * convert the key and element to strings. <p>Overrides to
242: * <tt>toString</tt> method of <tt>Object</tt>.
243: *
244: * @return a string representation of this lookuptable.
245: */
246: public synchronized String toString() {
1.2 ! bmahe 247: StringBuffer buffer = new StringBuffer();
! 248: for (int i = 0 ; i < count ; i++) {
! 249: buffer.append("["+keys[i]+","+elements[i]+"]");
! 250: }
! 251: return buffer.toString();
1.1 bmahe 252: }
253:
254: /**
255: * Constructor.
256: * @param capacity the initial capacity
257: */
258: public LookupTable(int capacity) {
259: this.count = 0;
260: this.capacity = capacity;
261: this.elements = new Object[capacity];
262: this.keys = new Object[capacity];
263: }
264:
265: /**
266: * Constructor, build a LookupTable with a initial capacity set to
267: * DEFAULT_CAPACITY.
268: */
269: public LookupTable() {
270: this(DEFAULT_CAPACITY);
271: }
272:
273: }
Webmaster