1 package org.apache.turbine.util;
2
3 /* ====================================================================
4 * The Apache Software License, Version 1.1
5 *
6 * Copyright (c) 2001 The Apache Software Foundation. All rights
7 * reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. The end-user documentation included with the redistribution,
22 * if any, must include the following acknowledgment:
23 * "This product includes software developed by the
24 * Apache Software Foundation (http://www.apache.org/)."
25 * Alternately, this acknowledgment may appear in the software itself,
26 * if and wherever such third-party acknowledgments normally appear.
27 *
28 * 4. The names "Apache" and "Apache Software Foundation" and
29 * "Apache Turbine" must not be used to endorse or promote products
30 * derived from this software without prior written permission. For
31 * written permission, please contact apache@apache.org.
32 *
33 * 5. Products derived from this software may not be called "Apache",
34 * "Apache Turbine", nor may "Apache" appear in their name, without
35 * prior written permission of the Apache Software Foundation.
36 *
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This software consists of voluntary contributions made by many
52 * individuals on behalf of the Apache Software Foundation. For more
53 * information on the Apache Software Foundation, please see
54 * <http://www.apache.org/>.
55 */
56
57 import java.util.Collection;
58 import java.util.Hashtable;
59 import java.util.Iterator;
60 import java.util.LinkedList;
61 import java.util.Map;
62 import java.util.Set;
63
64 /***
65 * A {@link java.util.Hashtable} whose keys are sequenced. The
66 * sequencing of the keys allow easy access to the values in the order
67 * which they were added in. This class is thread safe.
68 * <p>
69 * Implementing the List interface is not possible due to a instance
70 * method name clash. Java does not support method renaming.
71 * <p>
72 * A slightly more complex implementation and interface could involve
73 * the use of a list of <code>Map.Entry</code> objects.
74 *
75 * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
76 * @version $Id: SequencedHashtable.java,v 1.4 2001/05/20 02:38:52 dlr Exp $
77 */
78 public class SequencedHashtable extends Hashtable
79 {
80 /***
81 * Indicator for an unknown index.
82 */
83 private static final int UKNOWN_INDEX = -1;
84
85 /***
86 * The sequence used to keep track of the hash keys. Younger objects are
87 * kept towards the end of the list. Does not allow duplicates.
88 */
89 private LinkedList keySequence;
90
91 /***
92 * Creates a new instance with default storage.
93 */
94 public SequencedHashtable ()
95 {
96 keySequence = new LinkedList();
97 }
98
99 /***
100 * Creates a new instance with the specified storage.
101 *
102 * @param size The storage to allocate up front.
103 */
104 public SequencedHashtable (int size)
105 {
106 super(size);
107 keySequence = new LinkedList();
108 }
109
110 /***
111 * Clears all elements.
112 */
113 public synchronized void clear ()
114 {
115 super.clear();
116 keySequence.clear();
117 }
118
119 /***
120 * Creates a shallow copy of this object, preserving the internal
121 * structure by copying only references. The keys, values, and
122 * sequence are not <code>clone()</code>'d.
123 *
124 * @return A clone of this instance.
125 */
126 public synchronized Object clone ()
127 {
128 SequencedHashtable seqHash = (SequencedHashtable) super.clone();
129 seqHash.keySequence = (LinkedList) keySequence.clone();
130 return seqHash;
131 }
132
133 /***
134 * Returns the key at the specified index.
135 */
136 public Object get (int index)
137 {
138 return keySequence.get(index);
139 }
140
141 /***
142 * Returns the value at the specified index.
143 */
144 public Object getValue (int index)
145 {
146 return get(get(index));
147 }
148
149 /***
150 * Returns the index of the specified key.
151 */
152 public int indexOf (Object key)
153 {
154 return keySequence.indexOf(key);
155 }
156
157 /***
158 * Returns a key iterator.
159 */
160 public Iterator iterator ()
161 {
162 return keySequence.iterator();
163 }
164
165 /***
166 * Returns the last index of the specified key.
167 */
168 public int lastIndexOf (Object key)
169 {
170 return keySequence.lastIndexOf(key);
171 }
172
173 /***
174 * Stores the provided key/value pair. Freshens the sequence of existing
175 * elements.
176 *
177 * @param key The key to the provided value.
178 * @param value The value to store.
179 * @return The previous value for the specified key, or
180 * <code>null</code> if none.
181 */
182 public synchronized Object put (Object key, Object value)
183 {
184 Object prevValue = super.put(key, value);
185 freshenSequence(key, prevValue);
186 return prevValue;
187 }
188
189 /***
190 * Freshens the sequence of the element <code>value</code> if
191 * <code>value</code> is not <code>null</code>.
192 *
193 * @param key The key whose sequence to freshen.
194 * @param value The value whose existance to check before removing the old
195 * key sequence.
196 */
197 protected void freshenSequence(Object key, Object value)
198 {
199 if (value != null)
200 {
201 // Freshening existing element's sequence.
202 keySequence.remove(key);
203 }
204 keySequence.add(key);
205 }
206
207 /***
208 * Stores the provided key/value pairs.
209 *
210 * @param t The key/value pairs to store.
211 */
212 public synchronized void putAll (Map t)
213 {
214 Set set = t.entrySet();
215 for (Iterator iter = set.iterator(); iter.hasNext(); )
216 {
217 Map.Entry e = (Map.Entry)iter.next();
218 put(e.getKey(), e.getValue());
219 }
220 }
221
222 /***
223 * Removes the element at the specified index.
224 *
225 * @param index The index of the object to remove.
226 * @return The previous value coressponding the <code>key</code>, or
227 * <code>null</code> if none existed.
228 */
229 public Object remove (int index)
230 {
231 return remove(index, null);
232 }
233
234 /***
235 * Removes the element with the specified key.
236 *
237 * @param key The <code>Map</code> key of the object to remove.
238 * @return The previous value coressponding the <code>key</code>, or
239 * <code>null</code> if none existed.
240 */
241 public Object remove (Object key)
242 {
243 return remove(UKNOWN_INDEX, key);
244 }
245
246 /***
247 * Removes the element with the specified key or index.
248 *
249 * @param index The index of the object to remove, or
250 * <code>UKNOWN_INDEX</code> if not known.
251 * @param key The <code>Map</code> key of the object to remove.
252 * @return The previous value coressponding the <code>key</code>, or
253 * <code>null</code> if none existed.
254 */
255 private final synchronized Object remove (int index, Object key)
256 {
257 if (index == UKNOWN_INDEX) index = indexOf(key);
258 if (key == null) key = get(index);
259 if (index != UKNOWN_INDEX) keySequence.remove(index);
260 return super.remove(key);
261 }
262
263 /***
264 * Slightly cheaper implementation of <code>values()</code> method.
265 */
266 public Collection values ()
267 {
268 return keySequence;
269 }
270 }
This page was automatically generated by Maven