001: package com.sun.portal.common.collection;
002:
003: import java.util.Map;
004: import java.util.HashMap;
005: import java.util.Set;
006: import java.util.HashSet;
007: import java.util.List;
008: import java.util.ArrayList;
009: import java.util.Iterator;
010: import java.util.Collection;
011: import java.util.Collections;
012:
013: /**
014: * The DeltaMap introduces deferred changes to a Map, this allows a map to be
015: * use from several threads without synchronization supporting concurrent access/changes
016: *
017: * to synch up the main map with the values of a delta use the applyDelta() method,
018: * when this method is being executed no other threads should be operating on the main
019: * map.
020: *
021: * the use pattern is, for each thread a DeltaMap instance is created with the main map,
022: * each thread uses the DeltaMap instance to access/change the map. a collector thread
023: * applies the delta to the main map for all the DeltaMaps (when all the threads have
024: * finished execution).
025: *
026: *
027: */
028: public class DeltaMap implements Map {
029:
030: public static final int PUT = 0;
031:
032: public static final int REMOVE = 1;
033:
034: public static class DeltaEntry {
035:
036: private int _action;
037: private Object _key;
038: private Object _value;
039:
040: private DeltaEntry(int action, Object key, Object value) {
041: _action = action;
042: _key = key;
043: _value = value;
044: }
045:
046: public int getAction() {
047: return _action;
048: }
049:
050: public Object getKey() {
051: return _key;
052: }
053:
054: public Object getValue() {
055: return _value;
056: }
057:
058: public String toString() {
059: return "Delta: action="
060: + ((_action == PUT) ? "PUT" : "REMOVE") + " key="
061: + _key + " value=" + _value;
062: }
063: }
064:
065: private static class MapEntry implements Map.Entry {
066: private Object _key;
067: private Object _value;
068:
069: public MapEntry(Object key, Object value) {
070: _key = key;
071: _value = value;
072: }
073:
074: public Object getKey() {
075: return _key;
076: }
077:
078: public Object getValue() {
079: return _value;
080: }
081:
082: public Object setValue(Object value) {
083: throw new UnsupportedOperationException(
084: "ParallelHashMap.MapEntry.setValue()");
085: }
086:
087: public String toString() {
088: return "(" + _key + "," + _value + ")";
089: }
090:
091: }
092:
093: private Map _mainMap;
094: private Map _deltas;
095: private boolean _removedAll;
096: private boolean _changed;
097:
098: // Parallel MAP API
099:
100: public DeltaMap(Map map) {
101: _mainMap = map;
102: _deltas = new HashMap();
103: }
104:
105: // returns main map
106: public Map getMainMap() {
107: return _mainMap;
108: }
109:
110: public boolean hasDeltas() {
111: return _changed;
112: }
113:
114: // returns a Collection of DeltaEntries
115: public Collection getDeltas() {
116: return _deltas.values();
117: }
118:
119: // applies the deltas to the main map
120: public void applyDeltas() {
121: if (_changed) {
122: if (_removedAll) {
123: _mainMap.clear();
124: }
125: Iterator iterator = _deltas.keySet().iterator();
126: while (iterator.hasNext()) {
127: Object key = iterator.next();
128: DeltaEntry entry = (DeltaEntry) _deltas.get(key);
129: if (entry._action == PUT) {
130: _mainMap.put(key, entry._value);
131: } else { // entry.REMOVE
132: _mainMap.remove(key);
133: }
134: }
135: _deltas.clear();
136: _changed = false;
137: }
138: }
139:
140: // MAP public API
141:
142: public int size() {
143: int size = (_removedAll) ? 0 : _mainMap.size();
144: Iterator iterator = _deltas.keySet().iterator();
145: while (iterator.hasNext()) {
146: Object key = iterator.next();
147: DeltaEntry entry = (DeltaEntry) _deltas.get(key);
148: if (entry._action == PUT) {
149: size += (_mainMap.containsKey(key)) ? 0 : 1;
150: } else { // entry.REMOVE
151: size--;
152: }
153: }
154: return size;
155: }
156:
157: public boolean isEmpty() {
158: return _deltas.isEmpty() && (_removedAll || _mainMap.isEmpty());
159: }
160:
161: public boolean containsKey(Object key) {
162: boolean isIn = (_removedAll) ? false : _mainMap
163: .containsKey(key);
164: DeltaEntry entry = (DeltaEntry) _deltas.get(key);
165: return (entry == null) ? isIn : (entry._action == PUT);
166: }
167:
168: public boolean containsValue(Object value) {
169: return values().contains(value);
170: }
171:
172: public Object get(Object key) {
173: Object value = (_removedAll) ? null : _mainMap.get(key);
174: DeltaEntry entry = (DeltaEntry) _deltas.get(key);
175: if (entry != null) {
176: if (entry._action == PUT) {
177: value = entry._value;
178: } else {
179: value = null;
180: }
181: }
182: return value;
183: }
184:
185: public Object put(Object key, Object value) {
186: _changed = true;
187: Object oldValue = get(key);
188: _deltas.put(key, new DeltaEntry(PUT, key, value));
189: return oldValue;
190: }
191:
192: public Object remove(Object key) {
193: _changed = true;
194: Object oldValue = get(key);
195: _deltas.put(key, new DeltaEntry(REMOVE, key, null));
196: return oldValue;
197: }
198:
199: public void putAll(Map t) {
200: Iterator iterator = t.keySet().iterator();
201: while (iterator.hasNext()) {
202: Object key = iterator.next();
203: Object value = t.get(key);
204: put(key, value);
205: }
206: }
207:
208: public void clear() {
209: _changed = true;
210: _removedAll = true;
211: _deltas.clear();
212: }
213:
214: public Set keySet() {
215: Set keys = (_removedAll) ? new HashSet() : new HashSet(_mainMap
216: .keySet());
217: Iterator iterator = _deltas.keySet().iterator();
218: while (iterator.hasNext()) {
219: Object key = iterator.next();
220: DeltaEntry entry = (DeltaEntry) _deltas.get(key);
221: if (entry._action == PUT) {
222: keys.add(key);
223: } else { // entry.REMOVE
224: keys.remove(key);
225: }
226: }
227: return Collections.unmodifiableSet(keys);
228: }
229:
230: public Collection values() {
231: List values = new ArrayList();
232: Iterator iterator = entrySet().iterator();
233: while (iterator.hasNext()) {
234: Map.Entry entry = (Map.Entry) iterator.next();
235: values.add(entry.getValue());
236: }
237: return Collections.unmodifiableCollection(values);
238: }
239:
240: public Set entrySet() {
241: Set entrySet = new HashSet();
242: Iterator iterator = keySet().iterator();
243: while (iterator.hasNext()) {
244: Object key = iterator.next();
245: Object value = get(key);
246: entrySet.add(new MapEntry(key, value));
247: }
248: return entrySet;
249: }
250:
251: }
|