001: /*
002: * Distributed as part of c3p0 v.0.9.1.2
003: *
004: * Copyright (C) 2005 Machinery For Change, Inc.
005: *
006: * Author: Steve Waldman <swaldman@mchange.com>
007: *
008: * This library is free software; you can redistribute it and/or modify
009: * it under the terms of the GNU Lesser General Public License version 2.1, as
010: * published by the Free Software Foundation.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public License
018: * along with this software; see the file LICENSE. If not, write to the
019: * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020: * Boston, MA 02111-1307, USA.
021: */
022:
023: package com.mchange.v1.identicator;
024:
025: import java.lang.ref.*;
026: import java.util.*;
027: import com.mchange.v1.util.WrapperIterator;
028:
029: /**
030: * IdWeakHashMap is NOT null-accepting!
031: */
032: public final class IdWeakHashMap extends IdMap implements Map {
033: ReferenceQueue rq;
034:
035: public IdWeakHashMap(Identicator id) {
036: super (new HashMap(), id);
037: this .rq = new ReferenceQueue();
038: }
039:
040: //all methods from Map interface
041: public int size() {
042: // doing cleanCleared() afterwards, as with other methods
043: // would be just as "correct", as weak collections
044: // make no guarantees about when things disappear,
045: // but for size(), it feels a little more accurate
046: // this way.
047: cleanCleared();
048: return super .size();
049: }
050:
051: public boolean isEmpty() {
052: try {
053: return super .isEmpty();
054: } finally {
055: cleanCleared();
056: }
057: }
058:
059: public boolean containsKey(Object o) {
060: try {
061: return super .containsKey(o);
062: } finally {
063: cleanCleared();
064: }
065: }
066:
067: public boolean containsValue(Object o) {
068: try {
069: return super .containsValue(o);
070: } finally {
071: cleanCleared();
072: }
073: }
074:
075: public Object get(Object o) {
076: try {
077: return super .get(o);
078: } finally {
079: cleanCleared();
080: }
081: }
082:
083: public Object put(Object k, Object v) {
084: try {
085: return super .put(k, v);
086: } finally {
087: cleanCleared();
088: }
089: }
090:
091: public Object remove(Object o) {
092: try {
093: return super .remove(o);
094: } finally {
095: cleanCleared();
096: }
097: }
098:
099: public void putAll(Map m) {
100: try {
101: super .putAll(m);
102: } finally {
103: cleanCleared();
104: }
105: }
106:
107: public void clear() {
108: try {
109: super .clear();
110: } finally {
111: cleanCleared();
112: }
113: }
114:
115: public Set keySet() {
116: try {
117: return super .keySet();
118: } finally {
119: cleanCleared();
120: }
121: }
122:
123: public Collection values() {
124: try {
125: return super .values();
126: } finally {
127: cleanCleared();
128: }
129: }
130:
131: /*
132: * entrySet() is the basis of the implementation of the other
133: * Collection returning methods. Get this right and the rest
134: * follow.
135: */
136: public Set entrySet() {
137: try {
138: return new WeakUserEntrySet();
139: } finally {
140: cleanCleared();
141: }
142: }
143:
144: public boolean equals(Object o) {
145: try {
146: return super .equals(o);
147: } finally {
148: cleanCleared();
149: }
150: }
151:
152: public int hashCode() {
153: try {
154: return super .hashCode();
155: } finally {
156: cleanCleared();
157: }
158: }
159:
160: //internal methods
161: protected IdHashKey createIdKey(Object o) {
162: return new WeakIdHashKey(o, id, rq);
163: }
164:
165: private void cleanCleared() {
166: WeakIdHashKey.Ref ref;
167: while ((ref = (WeakIdHashKey.Ref) rq.poll()) != null)
168: this .removeIdHashKey(ref.getKey());
169: }
170:
171: private final class WeakUserEntrySet extends AbstractSet {
172: Set innerEntries = internalEntrySet();
173:
174: public Iterator iterator() {
175: try {
176: return new WrapperIterator(innerEntries.iterator(),
177: true) {
178: protected Object transformObject(Object o) {
179: Entry innerEntry = (Entry) o;
180: final Object userKey = ((IdHashKey) innerEntry
181: .getKey()).getKeyObj();
182: if (userKey == null)
183: return WrapperIterator.SKIP_TOKEN;
184: else
185: return new UserEntry(innerEntry) {
186: Object preventRefClear = userKey;
187: };
188: }
189: };
190: } finally {
191: cleanCleared();
192: }
193: }
194:
195: public int size() {
196: // doing cleanCleared() afterwards, as with other methods
197: // would be just as "correct", as weak collections
198: // make no guarantees about when things disappear,
199: // but for size(), it feels a little more accurate
200: // this way.
201: cleanCleared();
202: return innerEntries.size();
203: }
204:
205: public boolean contains(Object o) {
206: try {
207: if (o instanceof Entry) {
208: Entry entry = (Entry) o;
209: return innerEntries.contains(createIdEntry(entry));
210: } else
211: return false;
212: } finally {
213: cleanCleared();
214: }
215: }
216:
217: public boolean remove(Object o) {
218: try {
219: if (o instanceof Entry) {
220: Entry entry = (Entry) o;
221: return innerEntries.remove(createIdEntry(entry));
222: } else
223: return false;
224: } finally {
225: cleanCleared();
226: }
227: }
228:
229: public void clear() {
230: try {
231: inner.clear();
232: } finally {
233: cleanCleared();
234: }
235: }
236: }
237: }
|