View Javadoc
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.List; 62 import java.util.Map; 63 import java.util.Set; 64 65 /*** 66 * A {@link java.util.Hashtable} whose keys are sequenced. The 67 * sequencing of the keys allow easy access to the values in the order 68 * which they were added in. This class is thread safe. 69 * <p> 70 * Implementing the List interface is not possible due to a instance 71 * method name clash between the Collection and the List interface: 72 * 73 * <table> 74 * <tr><td>Collections</td><td>boolean remove(Object o)</td></tr> 75 * <tr><td>Lists</td><td>Object remove(Object o)</td></tr> 76 * </table> 77 * 78 * So one cannot implement both interfaces at the same, which is unfortunate 79 * because the List interface would be very nice in conjuction with Velocity. 80 * <p> 81 * A slightly more complex implementation and interface could involve 82 * the use of a list of <code>Map.Entry</code> objects. 83 * 84 * @author <a href="mailto:dlr@collab.net">Daniel Rall</a> 85 * @version $Id: SequencedHashtable.java,v 1.1.1.1 2001/08/16 05:09:41 jvanzyl Exp $ 86 */ 87 public class SequencedHashtable extends Hashtable 88 { 89 /*** 90 * Indicator for an unknown index. 91 */ 92 private static final int UNKNOWN_INDEX = -1; 93 94 /*** 95 * The sequence used to keep track of the hash keys. Younger objects are 96 * kept towards the end of the list. Does not allow duplicates. 97 */ 98 private LinkedList keySequence; 99 100 /*** 101 * Creates a new instance with default storage. 102 */ 103 public SequencedHashtable () 104 { 105 keySequence = new LinkedList(); 106 } 107 108 /*** 109 * Creates a new instance with the specified storage. 110 * 111 * @param size The storage to allocate up front. 112 */ 113 public SequencedHashtable (int size) 114 { 115 super(size); 116 keySequence = new LinkedList(); 117 } 118 119 /*** 120 * Clears all elements. 121 */ 122 public synchronized void clear () 123 { 124 super.clear(); 125 keySequence.clear(); 126 } 127 128 /*** 129 * Creates a shallow copy of this object, preserving the internal 130 * structure by copying only references. The keys, values, and 131 * sequence are not <code>clone()</code>'d. 132 * 133 * @return A clone of this instance. 134 */ 135 public synchronized Object clone () 136 { 137 SequencedHashtable seqHash = (SequencedHashtable) super.clone(); 138 seqHash.keySequence = (LinkedList) keySequence.clone(); 139 return seqHash; 140 } 141 142 /*** 143 * Returns the key at the specified index. 144 */ 145 public Object get (int index) 146 { 147 return keySequence.get(index); 148 } 149 150 /*** 151 * Returns the value at the specified index. 152 */ 153 public Object getValue (int index) 154 { 155 return get(get(index)); 156 } 157 158 /*** 159 * Returns the index of the specified key. 160 */ 161 public int indexOf (Object key) 162 { 163 return keySequence.indexOf(key); 164 } 165 166 /*** 167 * Returns a key iterator. 168 */ 169 public Iterator iterator () 170 { 171 return keySequence.iterator(); 172 } 173 174 /*** 175 * Returns the last index of the specified key. 176 */ 177 public int lastIndexOf (Object key) 178 { 179 return keySequence.lastIndexOf(key); 180 } 181 182 /*** 183 * Returns the ordered sequence of keys. 184 * 185 * This method is meant to be used for retrieval of Key / Value pairs 186 * in e.g. Velocity: 187 * <PRE> 188 * ## $table contains a sequenced hashtable 189 * #foreach ($key in $table.sequence()) 190 * <TR> 191 * <TD>Key: $key</TD> 192 * </TD>Value: $table.get($key)</TD> 193 * </TR> 194 * #end 195 * </PRE> 196 * 197 * @return The ordered list of keys. 198 */ 199 public List sequence() 200 { 201 return keySequence; 202 } 203 204 /*** 205 * Stores the provided key/value pair. Freshens the sequence of existing 206 * elements. 207 * 208 * @param key The key to the provided value. 209 * @param value The value to store. 210 * @return The previous value for the specified key, or 211 * <code>null</code> if none. 212 */ 213 public synchronized Object put (Object key, Object value) 214 { 215 Object prevValue = super.put(key, value); 216 freshenSequence(key, prevValue); 217 return prevValue; 218 } 219 220 /*** 221 * Freshens the sequence of the element <code>value</code> if 222 * <code>value</code> is not <code>null</code>. 223 * 224 * @param key The key whose sequence to freshen. 225 * @param value The value whose existance to check before removing the old 226 * key sequence. 227 */ 228 protected void freshenSequence(Object key, Object value) 229 { 230 if (value != null) 231 { 232 // Freshening existing element's sequence. 233 keySequence.remove(key); 234 } 235 keySequence.add(key); 236 } 237 238 /*** 239 * Stores the provided key/value pairs. 240 * 241 * @param t The key/value pairs to store. 242 */ 243 public synchronized void putAll (Map t) 244 { 245 Set set = t.entrySet(); 246 for (Iterator iter = set.iterator(); iter.hasNext(); ) 247 { 248 Map.Entry e = (Map.Entry)iter.next(); 249 put(e.getKey(), e.getValue()); 250 } 251 } 252 253 /*** 254 * Removes the element at the specified index. 255 * 256 * @param index The index of the object to remove. 257 * @return The previous value coressponding the <code>key</code>, or 258 * <code>null</code> if none existed. 259 */ 260 public Object remove (int index) 261 { 262 return remove(index, null); 263 } 264 265 /*** 266 * Removes the element with the specified key. 267 * 268 * @param key The <code>Map</code> key of the object to remove. 269 * @return The previous value coressponding the <code>key</code>, or 270 * <code>null</code> if none existed. 271 */ 272 public Object remove (Object key) 273 { 274 return remove(UNKNOWN_INDEX, key); 275 } 276 277 /*** 278 * Removes the element with the specified key or index. 279 * 280 * @param index The index of the object to remove, or 281 * <code>UNKNOWN_INDEX</code> if not known. 282 * @param key The <code>Map</code> key of the object to remove. 283 * @return The previous value coressponding the <code>key</code>, or 284 * <code>null</code> if none existed. 285 */ 286 private final synchronized Object remove (int index, Object key) 287 { 288 if (index == UNKNOWN_INDEX) index = indexOf(key); 289 if (key == null) key = get(index); 290 if (index != UNKNOWN_INDEX) keySequence.remove(index); 291 return super.remove(key); 292 } 293 294 /*** 295 * Slightly cheaper implementation of <code>values()</code> method. 296 */ 297 public Collection values () 298 { 299 return keySequence; 300 } 301 }

This page was automatically generated by Maven