001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.openejb.util;
017:
018: import java.lang.reflect.Array;
019: import java.util.AbstractList;
020: import java.util.AbstractMap;
021: import java.util.AbstractSet;
022: import java.util.Iterator;
023: import java.util.LinkedHashMap;
024: import java.util.List;
025: import java.util.ListIterator;
026: import java.util.Map;
027: import java.util.Set;
028:
029: /**
030: * @version $Revision: 495820 $ $Date: 2007-01-12 18:25:48 -0800 $
031: */
032: public class Index<K, V> extends AbstractMap<K, V> {
033:
034: private final IndexEntry<K, V>[] entries;
035: private final LinkedHashMap<K, Integer> keyIndicies;
036: private final IndexEntrySet entrySet;
037: private IndexValueList<V> indexValueList;
038:
039: public Index(Map<K, V> map) {
040: entries = new IndexEntry[map.size()];
041: keyIndicies = new LinkedHashMap<K, Integer>(map.size());
042:
043: int i = 0;
044: for (Entry<K, V> entry : map.entrySet()) {
045: entries[i] = new IndexEntry<K, V>(entry);
046: keyIndicies.put(entry.getKey(), new Integer(i));
047: i++;
048: }
049:
050: entrySet = new IndexEntrySet();
051: }
052:
053: public Index(List<K> keys) {
054: entries = new IndexEntry[keys.size()];
055: keyIndicies = new LinkedHashMap<K, Integer>(keys.size());
056: for (int i = 0; i < keys.size(); i++) {
057: K key = keys.get(i);
058: entries[i] = new IndexEntry<K, V>(key, null);
059: keyIndicies.put(key, new Integer(i));
060: }
061:
062: entrySet = new IndexEntrySet();
063: }
064:
065: public Index(K[] keys) {
066: entries = new IndexEntry[keys.length];
067: keyIndicies = new LinkedHashMap<K, Integer>(keys.length);
068: for (int i = 0; i < keys.length; i++) {
069: K key = keys[i];
070: entries[i] = new IndexEntry<K, V>(key, null);
071: keyIndicies.put(key, new Integer(i));
072: }
073:
074: entrySet = new IndexEntrySet();
075: }
076:
077: public List<V> values() {
078: if (indexValueList == null) {
079: indexValueList = new IndexValueList<V>();
080: }
081: return indexValueList;
082: }
083:
084: public Set<Entry<K, V>> entrySet() {
085: return entrySet;
086: }
087:
088: public K getKey(int index) {
089: if (index < 0 || index >= entries.length)
090: throw new IndexOutOfBoundsException("" + index);
091: return entries[index].getKey();
092: }
093:
094: public V get(int index) {
095: if (index < 0 || index >= entries.length)
096: throw new IndexOutOfBoundsException("" + index);
097: return entries[index].getValue();
098: }
099:
100: public V set(int index, V value) {
101: if (index < 0 || index >= entries.length)
102: throw new IndexOutOfBoundsException("" + index);
103: IndexEntry<K, V> entry = entries[index];
104: V oldValue = entry.getValue();
105: entry.setValue(value);
106: return oldValue;
107: }
108:
109: public V put(K key, V value) {
110: int i = indexOf(key);
111: if (i < 0) {
112: throw new IllegalArgumentException(
113: "Index does not contain this key and new entries cannot be added: "
114: + (K) key);
115: }
116:
117: IndexEntry<K, V> entry = entries[i];
118: V oldValue = entry.getValue();
119: entry.setValue(value);
120: return oldValue;
121: }
122:
123: public boolean containsKey(Object key) {
124: return keyIndicies.containsKey(key);
125: }
126:
127: public int indexOf(K key) {
128: Integer index = keyIndicies.get(key);
129: if (index == null) {
130: return -1;
131: }
132: return index;
133: }
134:
135: public V get(Object key) {
136: int i = indexOf((K) key);
137: if (i < 0) {
138: return null;
139: }
140:
141: IndexEntry<K, V> entryMetadata = entries[i];
142: V value = entryMetadata.getValue();
143: return value;
144: }
145:
146: public Iterator<V> iterator() {
147: return new IndexIterator<V>();
148: }
149:
150: public ListIterator<V> listIterator() {
151: return new IndexListIterator<V>(0);
152: }
153:
154: public ListIterator<V> listIterator(int index) {
155: if (index < 0 || index >= entries.length)
156: throw new IndexOutOfBoundsException("" + index);
157: return new IndexListIterator<V>(index);
158: }
159:
160: public Object[] toArray() {
161: return toArray(new Object[entries.length]);
162: }
163:
164: public static interface ListSet extends List, Set {
165: }
166:
167: public Object[] toArray(Object values[]) {
168: if (values.length < entries.length) {
169: values = (Object[]) Array.newInstance(values.getClass()
170: .getComponentType(), entries.length);
171: }
172:
173: for (int i = 0; i < entries.length; i++) {
174: IndexEntry indexEntry = entries[i];
175: values[i] = indexEntry.getValue();
176: }
177: return values;
178: }
179:
180: private static class IndexEntry<K, V> implements Map.Entry<K, V> {
181: private final K key;
182: private V value;
183:
184: private IndexEntry(K key, V value) {
185: this .key = key;
186: this .value = value;
187: }
188:
189: private IndexEntry(Map.Entry<K, V> entry) {
190: this .key = entry.getKey();
191: this .value = entry.getValue();
192: }
193:
194: public K getKey() {
195: return key;
196: }
197:
198: public V getValue() {
199: return value;
200: }
201:
202: public V setValue(V value) {
203: V oldValue = this .value;
204: this .value = value;
205: return oldValue;
206: }
207: }
208:
209: private class IndexEntrySet extends AbstractSet {
210: public Iterator iterator() {
211: return new Iterator() {
212: private int index = 0;
213:
214: public boolean hasNext() {
215: return index < entries.length;
216: }
217:
218: public Object next() {
219: return entries[index++];
220: }
221:
222: public void remove() {
223: throw new UnsupportedOperationException(
224: "Index entries cannot be removed");
225: }
226: };
227: }
228:
229: public int size() {
230: return entries.length;
231: }
232: }
233:
234: private class IndexValueList<E> extends AbstractList<E> {
235: public E get(int index) {
236: return (E) Index.this .get(index);
237: }
238:
239: public E set(int index, E element) {
240: return (E) Index.this .set(index, (V) element);
241: }
242:
243: public int size() {
244: return Index.this .size();
245: }
246: }
247:
248: private class IndexIterator<E> implements Iterator<E> {
249: protected int index;
250:
251: public boolean hasNext() {
252: return index < entries.length;
253: }
254:
255: public E next() {
256: IndexEntry<K, V> entryMetadata = entries[index++];
257: return (E) entryMetadata.getValue();
258: }
259:
260: public void remove() {
261: throw new UnsupportedOperationException(
262: "Index entries cannot be removed");
263: }
264: }
265:
266: private class IndexListIterator<E> extends IndexIterator<E>
267: implements ListIterator<E> {
268: public IndexListIterator(int index) {
269: this .index = index;
270: }
271:
272: public int nextIndex() {
273: return index;
274: }
275:
276: public boolean hasPrevious() {
277: return index > 0;
278: }
279:
280: public E previous() {
281: return (E) entries[--index].getValue();
282: }
283:
284: public int previousIndex() {
285: return index - 1;
286: }
287:
288: public void set(E o) {
289: entries[index].setValue((V) o);
290: }
291:
292: public void add(E o) {
293: throw new UnsupportedOperationException(
294: "Entries cannot be added to a Index");
295: }
296:
297: }
298: }
|