KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > turbine > util > SequencedHashtable


1 package org.apache.turbine.util;
2
3 /*
4  * Copyright 2001-2004 The Apache Software Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License")
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18
19 import java.util.Collection JavaDoc;
20 import java.util.Hashtable JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.LinkedList JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Map JavaDoc;
25 import java.util.Set JavaDoc;
26
27 /**
28  * A {@link java.util.Hashtable} whose keys are sequenced. The
29  * sequencing of the keys allow easy access to the values in the order
30  * which they were added in. This class is thread safe.
31  * <p>
32  * Implementing the List interface is not possible due to a instance
33  * method name clash between the Collection and the List interface:
34  *
35  * <table>
36  * <tr><td>Collections</td><td>boolean remove(Object o)</td></tr>
37  * <tr><td>Lists</td><td>Object remove(Object o)</td></tr>
38  * </table>
39  *
40  * So one cannot implement both interfaces at the same, which is unfortunate
41  * because the List interface would be very nice in conjuction with Velocity.
42  * <p>
43  * A slightly more complex implementation and interface could involve
44  * the use of a list of <code>Map.Entry</code> objects.
45  *
46  * @author <a HREF="mailto:dlr@collab.net">Daniel Rall</a>
47  * @version $Id: SequencedHashtable.java,v 1.4.2.2 2004/05/20 03:16:38 seade Exp $
48  * @deprecated Use SequencedHashMap from the commons collections.
49  */

50 public class SequencedHashtable extends Hashtable JavaDoc
51 {
52     /**
53      * Indicator for an unknown index.
54      */

55     private static final int UNKNOWN_INDEX = -1;
56
57     /**
58      * The sequence used to keep track of the hash keys. Younger objects are
59      * kept towards the end of the list. Does not allow duplicates.
60      */

61     private LinkedList JavaDoc keySequence;
62
63     /**
64      * Creates a new instance with default storage.
65      */

66     public SequencedHashtable()
67     {
68         keySequence = new LinkedList JavaDoc();
69     }
70
71     /**
72      * Creates a new instance with the specified storage.
73      *
74      * @param size The storage to allocate up front.
75      */

76     public SequencedHashtable(int size)
77     {
78         super(size);
79         keySequence = new LinkedList JavaDoc();
80     }
81
82     /**
83      * Clears all elements.
84      */

85     public synchronized void clear()
86     {
87         super.clear();
88         keySequence.clear();
89     }
90
91     /**
92      * Creates a shallow copy of this object, preserving the internal
93      * structure by copying only references. The keys, values, and
94      * sequence are not <code>clone()</code>'d.
95      *
96      * @return A clone of this instance.
97      */

98     public synchronized Object JavaDoc clone()
99     {
100         SequencedHashtable seqHash = (SequencedHashtable) super.clone();
101         seqHash.keySequence = (LinkedList JavaDoc) keySequence.clone();
102         return seqHash;
103     }
104
105     /**
106      * Returns the key at the specified index.
107      */

108     public Object JavaDoc get(int index)
109     {
110         return keySequence.get(index);
111     }
112
113     /**
114      * Returns the value at the specified index.
115      */

116     public Object JavaDoc getValue(int index)
117     {
118         return get(get(index));
119     }
120
121     /**
122      * Returns the index of the specified key.
123      */

124     public int indexOf(Object JavaDoc key)
125     {
126         return keySequence.indexOf(key);
127     }
128
129     /**
130      * Returns a key iterator.
131      */

132     public Iterator JavaDoc iterator()
133     {
134         return keySequence.iterator();
135     }
136
137     /**
138      * Returns the last index of the specified key.
139      */

140     public int lastIndexOf(Object JavaDoc key)
141     {
142         return keySequence.lastIndexOf(key);
143     }
144
145     /**
146      * Returns the ordered sequence of keys.
147      *
148      * This method is meant to be used for retrieval of Key / Value pairs
149      * in e.g. Velocity:
150      * <PRE>
151      * ## $table contains a sequenced hashtable
152      * #foreach ($key in $table.sequence())
153      * &lt;TR&gt;
154      * &lt;TD&gt;Key: $key&lt;/TD&gt;
155      * &lt;/TD&gt;Value: $table.get($key)&lt;/TD&gt;
156      * &lt;/TR&gt;
157      * #end
158      * </PRE>
159      *
160      * @return The ordered list of keys.
161      */

162     public List JavaDoc sequence()
163     {
164         return keySequence;
165     }
166
167     /**
168      * Stores the provided key/value pair. Freshens the sequence of existing
169      * elements.
170      *
171      * @param key The key to the provided value.
172      * @param value The value to store.
173      * @return The previous value for the specified key, or
174      * <code>null</code> if none.
175      */

176     public synchronized Object JavaDoc put(Object JavaDoc key, Object JavaDoc value)
177     {
178         Object JavaDoc prevValue = super.put(key, value);
179         freshenSequence(key, prevValue);
180         return prevValue;
181     }
182
183     /**
184      * Freshens the sequence of the element <code>value</code> if
185      * <code>value</code> is not <code>null</code>.
186      *
187      * @param key The key whose sequence to freshen.
188      * @param value The value whose existance to check before removing the old
189      * key sequence.
190      */

191     protected void freshenSequence(Object JavaDoc key, Object JavaDoc value)
192     {
193         if (value != null)
194         {
195             // Freshening existing element's sequence.
196
keySequence.remove(key);
197         }
198         keySequence.add(key);
199     }
200
201     /**
202      * Stores the provided key/value pairs.
203      *
204      * @param t The key/value pairs to store.
205      */

206     public synchronized void putAll(Map JavaDoc t)
207     {
208         Set JavaDoc set = t.entrySet();
209         for (Iterator JavaDoc iter = set.iterator(); iter.hasNext();)
210         {
211             Map.Entry JavaDoc e = (Map.Entry JavaDoc) iter.next();
212             put(e.getKey(), e.getValue());
213         }
214     }
215
216     /**
217      * Removes the element at the specified index.
218      *
219      * @param index The index of the object to remove.
220      * @return The previous value coressponding the <code>key</code>, or
221      * <code>null</code> if none existed.
222      */

223     public Object JavaDoc remove(int index)
224     {
225         return remove(index, null);
226     }
227
228     /**
229      * Removes the element with the specified key.
230      *
231      * @param key The <code>Map</code> key of the object to remove.
232      * @return The previous value coressponding the <code>key</code>, or
233      * <code>null</code> if none existed.
234      */

235     public Object JavaDoc remove(Object JavaDoc key)
236     {
237         return remove(UNKNOWN_INDEX, key);
238     }
239
240     /**
241      * Removes the element with the specified key or index.
242      *
243      * @param index The index of the object to remove, or
244      * <code>UNKNOWN_INDEX</code> if not known.
245      * @param key The <code>Map</code> key of the object to remove.
246      * @return The previous value coressponding the <code>key</code>, or
247      * <code>null</code> if none existed.
248      */

249     private final synchronized Object JavaDoc remove(int index, Object JavaDoc key)
250     {
251         if (index == UNKNOWN_INDEX) index = indexOf(key);
252         if (key == null) key = get(index);
253         if (index != UNKNOWN_INDEX) keySequence.remove(index);
254         return super.remove(key);
255     }
256
257     /**
258      * Slightly cheaper implementation of <code>values()</code> method.
259      */

260     public Collection JavaDoc values()
261     {
262         return keySequence;
263     }
264 }
265
Popular Tags