001: /*
002: Copyright (c) 2007, Dennis M. Sosnoski
003: All rights reserved.
004:
005: Redistribution and use in source and binary forms, with or without modification,
006: are permitted provided that the following conditions are met:
007:
008: * Redistributions of source code must retain the above copyright notice, this
009: list of conditions and the following disclaimer.
010: * Redistributions in binary form must reproduce the above copyright notice,
011: this list of conditions and the following disclaimer in the documentation
012: and/or other materials provided with the distribution.
013: * Neither the name of JiBX nor the names of its contributors may be used
014: to endorse or promote products derived from this software without specific
015: prior written permission.
016:
017: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
018: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
019: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
020: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
021: ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
022: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
023: LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
024: ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
026: SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027: */
028:
029: package org.jibx.util;
030:
031: import java.util.AbstractSet;
032: import java.util.ArrayList;
033: import java.util.Collection;
034: import java.util.HashMap;
035: import java.util.Iterator;
036: import java.util.List;
037: import java.util.Map;
038: import java.util.Set;
039:
040: /**
041: * Map with keys iterated in insertion order. This is similar to the Java 1.4
042: * java.util.LinkedHashMap class, but compatible with earlier JVM versions. It
043: * also guarantees insertion ordering only for iterating through the key values,
044: * not for other iterations. This implementation is optimized for insert-only
045: * maps.
046: */
047: public class InsertionOrderedMap implements Map {
048: private final Map m_baseMap;
049: private final ArrayList m_insertList;
050:
051: public InsertionOrderedMap() {
052: m_baseMap = new HashMap();
053: m_insertList = new ArrayList();
054: }
055:
056: /* (non-Javadoc)
057: * @see java.util.Map#clear()
058: */
059: public void clear() {
060: m_baseMap.clear();
061: m_insertList.clear();
062: }
063:
064: /* (non-Javadoc)
065: * @see java.util.Map#containsKey(java.lang.Object)
066: */
067: public boolean containsKey(Object key) {
068: return m_baseMap.containsKey(key);
069: }
070:
071: /* (non-Javadoc)
072: * @see java.util.Map#containsValue(java.lang.Object)
073: */
074: public boolean containsValue(Object value) {
075: return m_baseMap.containsValue(value);
076: }
077:
078: /* (non-Javadoc)
079: * @see java.util.Map#entrySet()
080: */
081: public Set entrySet() {
082: return m_baseMap.entrySet();
083: }
084:
085: /* (non-Javadoc)
086: * @see java.util.Map#get(java.lang.Object)
087: */
088: public Object get(Object key) {
089: return m_baseMap.get(key);
090: }
091:
092: /* (non-Javadoc)
093: * @see java.util.Map#isEmpty()
094: */
095: public boolean isEmpty() {
096: return m_baseMap.isEmpty();
097: }
098:
099: /* (non-Javadoc)
100: * @see java.util.Map#keySet()
101: */
102: public Set keySet() {
103: return new ListSet(m_insertList);
104: }
105:
106: /* (non-Javadoc)
107: * @see java.util.Map#put(java.lang.Object, java.lang.Object)
108: */
109: public Object put(Object key, Object value) {
110: if (!m_baseMap.containsKey(key)) {
111: m_insertList.add(key);
112: }
113: return m_baseMap.put(key, value);
114: }
115:
116: /* (non-Javadoc)
117: * @see java.util.Map#putAll(java.util.Map)
118: */
119: public void putAll(Map t) {
120: for (Iterator iter = t.entrySet().iterator(); iter.hasNext();) {
121: Entry entry = (Entry) iter.next();
122: put(entry.getKey(), entry.getValue());
123: }
124: }
125:
126: /* (non-Javadoc)
127: * @see java.util.Map#remove(java.lang.Object)
128: */
129: public Object remove(Object key) {
130: if (m_baseMap.containsKey(key)) {
131: m_insertList.remove(key);
132: return m_baseMap.remove(key);
133: } else {
134: return null;
135: }
136: }
137:
138: /* (non-Javadoc)
139: * @see java.util.Map#size()
140: */
141: public int size() {
142: return m_baseMap.size();
143: }
144:
145: /* (non-Javadoc)
146: * @see java.util.Map#values()
147: */
148: public Collection values() {
149: return m_baseMap.values();
150: }
151:
152: /**
153: * Get list of keys in order added. The returned list is live, and will
154: * grow or shrink as pairs are added to or removed from the map.
155: *
156: * @return key list
157: */
158: public ArrayList keyList() {
159: return m_insertList;
160: }
161:
162: /**
163: * Set implementation backed by a list.
164: */
165: private static class ListSet extends AbstractSet {
166: private final List m_list;
167:
168: public ListSet(List list) {
169: m_list = list;
170: }
171:
172: public Iterator iterator() {
173: return m_list.iterator();
174: }
175:
176: public int size() {
177: return m_list.size();
178: }
179: }
180: }
|