001: /*
002: * $Id: MicroMap.java 458489 2006-01-04 09:28:14Z ivaynberg $ $Revision:
003: * 1.4 $ $Date: 2006-01-04 10:28:14 +0100 (Wed, 04 Jan 2006) $
004: *
005: * ==============================================================================
006: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
007: * use this file except in compliance with the License. You may obtain a copy of
008: * the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
014: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
015: * License for the specific language governing permissions and limitations under
016: * the License.
017: */
018: package wicket.util.collections;
019:
020: import java.io.Serializable;
021: import java.util.AbstractList;
022: import java.util.AbstractSet;
023: import java.util.Collection;
024: import java.util.Iterator;
025: import java.util.Map;
026: import java.util.Set;
027:
028: /**
029: * An implementation of the java.util.Map interface which can only hold a single
030: * object. This is particularly useful to control memory usage in Wicket because
031: * many containers hold only a single component.
032: *
033: * @author Jonathan Locke
034: */
035: public final class MicroMap implements Map, Serializable {
036: private static final long serialVersionUID = 1L;
037:
038: /** The maximum number of entries this map supports. */
039: public static final int MAX_ENTRIES = 1;
040:
041: /** The one and only key in this tiny map */
042: private Object key;
043:
044: /** The value for the only key in this tiny map */
045: private Object value;
046:
047: /**
048: * Constructor
049: */
050: public MicroMap() {
051: }
052:
053: /**
054: * Constructs map with a single key and value pair.
055: *
056: * @param key
057: * The key
058: * @param value
059: * The value
060: */
061: public MicroMap(final Object key, final Object value) {
062: put(key, value);
063: }
064:
065: /**
066: * @return True if this MicroMap is full
067: */
068: public boolean isFull() {
069: return size() == MAX_ENTRIES;
070: }
071:
072: /**
073: * @see java.util.Map#size()
074: */
075: public int size() {
076: return (key != null) ? 1 : 0;
077: }
078:
079: /**
080: * @see java.util.Map#isEmpty()
081: */
082: public boolean isEmpty() {
083: return size() == 0;
084: }
085:
086: /**
087: * @see java.util.Map#containsKey(java.lang.Object)
088: */
089: public boolean containsKey(final Object key) {
090: return key.equals(this .key);
091: }
092:
093: /**
094: * @see java.util.Map#containsValue(java.lang.Object)
095: */
096: public boolean containsValue(final Object value) {
097: return value.equals(this .value);
098: }
099:
100: /**
101: * @see java.util.Map#get(java.lang.Object)
102: */
103: public Object get(final Object key) {
104: if (key.equals(this .key)) {
105: return value;
106: }
107:
108: return null;
109: }
110:
111: /**
112: * @see java.util.Map#put(java.lang.Object, java.lang.Object)
113: */
114: public Object put(final Object key, final Object value) {
115: // Replace?
116: if (key.equals(this .key)) {
117: final Object oldValue = this .value;
118:
119: this .value = value;
120:
121: return oldValue;
122: } else {
123: // Is there room for a new entry?
124: if (size() < MAX_ENTRIES) {
125: // Store
126: this .key = key;
127: this .value = value;
128:
129: return null;
130: } else {
131: throw new IllegalStateException("Map full");
132: }
133: }
134: }
135:
136: /**
137: * @see java.util.Map#remove(java.lang.Object)
138: */
139: public Object remove(final Object key) {
140: if (key.equals(this .key)) {
141: final Object oldValue = this .value;
142:
143: this .key = null;
144: this .value = null;
145:
146: return oldValue;
147: }
148:
149: return null;
150: }
151:
152: /**
153: * @see java.util.Map#putAll(java.util.Map)
154: */
155: public void putAll(final Map map) {
156: if (map.size() <= MAX_ENTRIES) {
157: final Map.Entry e = (Map.Entry) map.entrySet().iterator()
158: .next();
159:
160: put(e.getKey(), e.getValue());
161: } else {
162: throw new IllegalStateException("Map full. Cannot add "
163: + map.size() + " entries");
164: }
165: }
166:
167: /**
168: * @see java.util.Map#clear()
169: */
170: public void clear() {
171: key = null;
172: value = null;
173: }
174:
175: /**
176: * @see java.util.Map#keySet()
177: */
178: public Set keySet() {
179: return new AbstractSet() {
180: public Iterator iterator() {
181: return new Iterator() {
182: public boolean hasNext() {
183: return index < MicroMap.this .size();
184: }
185:
186: public Object next() {
187: index++;
188:
189: return key;
190: }
191:
192: public void remove() {
193: MicroMap.this .clear();
194: }
195:
196: int index;
197: };
198: }
199:
200: public int size() {
201: return MicroMap.this .size();
202: }
203: };
204: }
205:
206: /**
207: * @see java.util.Map#values()
208: */
209: public Collection values() {
210: return new AbstractList() {
211: public Object get(final int index) {
212: return value;
213: }
214:
215: public int size() {
216: return MicroMap.this .size();
217: }
218: };
219: }
220:
221: /**
222: * @see java.util.Map#entrySet()
223: */
224: public Set entrySet() {
225: return new AbstractSet() {
226: public Iterator iterator() {
227: return new Iterator() {
228: public boolean hasNext() {
229: return index < MicroMap.this .size();
230: }
231:
232: public Object next() {
233: index++;
234:
235: return new Map.Entry() {
236: public Object getKey() {
237: return key;
238: }
239:
240: public Object getValue() {
241: return value;
242: }
243:
244: public Object setValue(final Object value) {
245: final Object oldValue = MicroMap.this .value;
246:
247: MicroMap.this .value = value;
248:
249: return oldValue;
250: }
251: };
252: }
253:
254: public void remove() {
255: clear();
256: }
257:
258: int index = 0;
259: };
260: }
261:
262: public int size() {
263: return MicroMap.this.size();
264: }
265: };
266: }
267: }
|