Source Code Cross Referenced for ReferenceMap.java in  » Database-ORM » db-ojb » org » apache » ojb » broker » util » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database ORM » db ojb » org.apache.ojb.broker.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package org.apache.ojb.broker.util;
002:
003:        /* Copyright 2004-2005 The Apache Software Foundation
004:         *
005:         * Licensed under the Apache License, Version 2.0 (the "License");
006:         * you may not use this file except in compliance with the License.
007:         * 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:         */
017:
018:        import java.io.IOException;
019:        import java.io.ObjectInputStream;
020:        import java.io.ObjectOutputStream;
021:        import java.lang.ref.Reference;
022:        import java.lang.ref.ReferenceQueue;
023:        import java.lang.ref.SoftReference;
024:        import java.lang.ref.WeakReference;
025:        import java.util.AbstractCollection;
026:        import java.util.AbstractMap;
027:        import java.util.AbstractSet;
028:        import java.util.ArrayList;
029:        import java.util.Arrays;
030:        import java.util.Collection;
031:        import java.util.ConcurrentModificationException;
032:        import java.util.Iterator;
033:        import java.util.Map;
034:        import java.util.NoSuchElementException;
035:        import java.util.Set;
036:
037:        /**
038:         * <p>
039:         * Modified version of {@link org.apache.commons.collections.ReferenceMap}, using
040:         * object identity for key comparison (). This class
041:         * simply extended {@link org.apache.commons.collections.ReferenceMap} with an extra field
042:         * "useSystemIdentity" which is initialized in constructor and is used every time we
043:         * want to compare (or hash) keys or values.
044:         * </p>
045:         * <p>
046:         * Javadoc of ReferenceMap starts here:
047:         * <br/>
048:         * Hashtable-based {@link java.util.Map} implementation that allows
049:         *  mappings to be removed by the garbage collector.
050:         * </p>
051:         * <P>
052:         *  When you construct a <Code>ReferenceMap</Code>, you can
053:         *  specify what kind of references are used to store the
054:         *  map's keys and values.  If non-hard references are
055:         *  used, then the garbage collector can remove mappings
056:         *  if a key or value becomes unreachable, or if the
057:         *  JVM's memory is running low.  For information on how
058:         *  the different reference types behave, see
059:         *  {@link java.lang.ref.Reference}.<P>
060:         *
061:         *  Different types of references can be specified for keys
062:         *  and values.  The keys can be configured to be weak but
063:         *  the values hard, in which case this class will behave
064:         *  like a <A HREF="http://java.sun.com/j2se/1.4/docs/api/java/util/WeakHashMap.html">
065:         *  <Code>WeakHashMap</Code></A>.  However, you
066:         *  can also specify hard keys and weak values, or any other
067:         *  combination.  The default constructor uses hard keys
068:         *  and soft values, providing a memory-sensitive cache.<P>
069:         *
070:         *  The algorithms used are basically the same as those
071:         *  in {@link java.util.HashMap}.  In particular, you
072:         *  can specify a load factor and capacity to suit your
073:         *  needs.  All optional {@link java.util.Map} operations are
074:         *  supported.<P>
075:         *
076:         *  However, this {@link java.util.Map} implementation does <I>not</I>
077:         *  allow null elements.  Attempting to add a null key or
078:         *  or a null value to the map will raise a
079:         *  <Code>NullPointerException</Code>.<P>
080:         *
081:         *  As usual, this implementation is not synchronized.  You
082:         *  can use {@link java.util.Collections#synchronizedMap} to
083:         *  provide synchronized access to a <Code>ReferenceMap</Code>.
084:         *
085:         * @deprecated use {@link org.apache.commons.collections.map.ReferenceIdentityMap} instead.
086:         *  @author Andy Malakov
087:         *  @version $Id: ReferenceMap.java,v 1.6.2.2 2005/12/21 22:27:47 tomdz Exp $
088:         */
089:        public class ReferenceMap extends AbstractMap {
090:
091:            /**
092:             *  For serialization.
093:             */
094:            final private static long serialVersionUID = -3370601314380922368L;
095:
096:            /**
097:             *  Constant indicating that hard references should be used.
098:             */
099:            final public static int HARD = 0;
100:
101:            /**
102:             *  Constant indiciating that soft references should be used.
103:             */
104:            final public static int SOFT = 1;
105:
106:            /**
107:             *  Constant indicating that weak references should be used.
108:             */
109:            final public static int WEAK = 2;
110:
111:            // --- serialized instance variables:
112:
113:            /**
114:             *  The reference type for keys.  Must be HARD, SOFT, WEAK.
115:             *  Note: I originally marked this field as final, but then this class
116:             *   didn't compile under JDK1.2.2.
117:             *  @serial
118:             */
119:            private int keyType;
120:
121:            /**
122:             *  The reference type for values.  Must be HARD, SOFT, WEAK.
123:             *  Note: I originally marked this field as final, but then this class
124:             *   didn't compile under JDK1.2.2.
125:             *  @serial
126:             */
127:            private int valueType;
128:
129:            /**
130:             *  The threshold variable is calculated by multiplying
131:             *  table.length and loadFactor.
132:             *  Note: I originally marked this field as final, but then this class
133:             *   didn't compile under JDK1.2.2.
134:             *  @serial
135:             */
136:            private float loadFactor;
137:
138:            // -- Non-serialized instance variables
139:
140:            /**
141:             *  ReferenceQueue used to eliminate stale mappings.
142:             *  @see #purge
143:             */
144:            private transient ReferenceQueue queue = new ReferenceQueue();
145:
146:            /**
147:             *  The hash table.  Its length is always a power of two.
148:             */
149:            private transient Entry[] table;
150:
151:            /**
152:             *  Number of mappings in this map.
153:             */
154:            private transient int size;
155:
156:            /**
157:             *  When size reaches threshold, the map is resized.
158:             *  @see #resize
159:             */
160:            private transient int threshold;
161:
162:            /**
163:             *  Number of times this map has been modified.
164:             */
165:            private transient volatile int modCount;
166:
167:            /**
168:             *  Cached key set.  May be null if key set is never accessed.
169:             */
170:            private transient Set keySet;
171:
172:            /**
173:             *  Cached entry set.  May be null if entry set is never accessed.
174:             */
175:            private transient Set entrySet;
176:
177:            /**
178:             *  Cached values.  May be null if values() is never accessed.
179:             */
180:            private transient Collection values;
181:
182:            /**
183:             *  Note: I originally marked this field as final, but then this class
184:             *   didn't compile under JDK1.2.2.
185:             */
186:            private boolean useSystemIdentity;
187:
188:            /**
189:             *  Constructs a new <Code>ReferenceMap</Code> that will
190:             *  use hard references to keys and soft references to values.
191:             */
192:            public ReferenceMap() {
193:                this (HARD, SOFT);
194:            }
195:
196:            /**
197:             *  Constructs a new <Code>ReferenceMap</Code> that will
198:             *  use the specified types of references.
199:             *
200:             *  @param keyType  the type of reference to use for keys;
201:             *   must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
202:             *  @param valueType  the type of reference to use for values;
203:             *   must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
204:             */
205:            public ReferenceMap(int keyType, int valueType) {
206:                this (keyType, valueType, 16, 0.75f, false);
207:            }
208:
209:            /**
210:             *  Constructs a new <Code>ReferenceMap</Code> with the
211:             *  specified reference types, load factor and initial
212:             *  capacity.
213:             *
214:             *  @param keyType  the type of reference to use for keys;
215:             *   must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
216:             *  @param valueType  the type of reference to use for values;
217:             *   must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
218:             *  @param capacity  the initial capacity for the map
219:             *  @param loadFactor  the load factor for the map
220:             *  @param useSystemIdentity if true System.identityHashCode() and comparision operator (==) will be used
221:             *         in place of Object.hashCode and Object.equals (Please read {@link java.util.WeakHashMap}
222:             *         java doc for more information).
223:             */
224:            public ReferenceMap(int keyType, int valueType, int capacity,
225:                    float loadFactor, boolean useSystemIdentity) {
226:                super ();
227:
228:                verify("keyType", keyType);
229:                verify("valueType", valueType);
230:
231:                this .useSystemIdentity = useSystemIdentity;
232:
233:                if (capacity <= 0) {
234:                    throw new IllegalArgumentException(
235:                            "capacity must be positive");
236:                }
237:                if ((loadFactor <= 0.0f) || (loadFactor >= 1.0f)) {
238:                    throw new IllegalArgumentException(
239:                            "Load factor must be greater than 0 and less than 1.");
240:                }
241:
242:                this .keyType = keyType;
243:                this .valueType = valueType;
244:
245:                int v = 1;
246:                while (v < capacity)
247:                    v *= 2;
248:
249:                this .table = new Entry[v];
250:                this .loadFactor = loadFactor;
251:                this .threshold = (int) (v * loadFactor);
252:            }
253:
254:            // used by constructor
255:            private static void verify(String name, int type) {
256:                if ((type < HARD) || (type > WEAK)) {
257:                    throw new IllegalArgumentException(name
258:                            + " must be HARD, SOFT, WEAK.");
259:                }
260:            }
261:
262:            /**
263:             *  Writes this object to the given output stream.
264:             *
265:             *  @param out  the output stream to write to
266:             *  @throws java.io.IOException  if the stream raises it
267:             */
268:            private void writeObject(ObjectOutputStream out) throws IOException {
269:                out.defaultWriteObject();
270:                out.writeInt(table.length);
271:
272:                // Have to use null-terminated list because size might shrink
273:                // during iteration
274:
275:                for (Iterator iter = entrySet().iterator(); iter.hasNext();) {
276:                    Map.Entry entry = (Map.Entry) iter.next();
277:                    out.writeObject(entry.getKey());
278:                    out.writeObject(entry.getValue());
279:                }
280:                out.writeObject(null);
281:            }
282:
283:            /**
284:             *  Reads the contents of this object from the given input stream.
285:             *
286:             *  @param inp  the input stream to read from
287:             *  @throws java.io.IOException  if the stream raises it
288:             *  @throws java.lang.ClassNotFoundException  if the stream raises it
289:             */
290:            private void readObject(ObjectInputStream inp) throws IOException,
291:                    ClassNotFoundException {
292:                inp.defaultReadObject();
293:                table = new Entry[inp.readInt()];
294:                threshold = (int) (table.length * loadFactor);
295:                queue = new ReferenceQueue();
296:                Object key = inp.readObject();
297:                while (key != null) {
298:                    Object value = inp.readObject();
299:                    put(key, value);
300:                    key = inp.readObject();
301:                }
302:            }
303:
304:            /**
305:             *  Constructs a reference of the given type to the given
306:             *  referent.  The reference is registered with the queue
307:             *  for later purging.
308:             *
309:             *  @param type  HARD, SOFT or WEAK
310:             *  @param referent  the object to refer to
311:             *  @param hash  the hash code of the <I>key</I> of the mapping;
312:             *    this number might be different from referent.hashCode() if
313:             *    the referent represents a value and not a key
314:             */
315:            private Object toReference(int type, Object referent, int hash) {
316:                switch (type) {
317:                case HARD:
318:                    return referent;
319:                case SOFT:
320:                    return new SoftRef(hash, referent, queue);
321:                case WEAK:
322:                    return new WeakRef(hash, referent, queue);
323:                default:
324:                    throw new Error();
325:                }
326:            }
327:
328:            /**
329:             *  Returns the entry associated with the given key.
330:             *
331:             *  @param key  the key of the entry to look up
332:             *  @return  the entry associated with that key, or null
333:             *    if the key is not in this map
334:             */
335:            private Entry getEntry(Object key) {
336:                if (key == null)
337:                    return null;
338:                int hash = hashCode(key);
339:                int index = indexFor(hash);
340:                for (Entry entry = table[index]; entry != null; entry = entry.next) {
341:                    if ((entry.hash == hash) && equals(key, entry.getKey())) {
342:                        return entry;
343:                    }
344:                }
345:                return null;
346:            }
347:
348:            /**
349:             *  Converts the given hash code into an index into the
350:             *  hash table.
351:             */
352:            private int indexFor(int hash) {
353:                // mix the bits to avoid bucket collisions...
354:                hash += ~(hash << 15);
355:                hash ^= (hash >>> 10);
356:                hash += (hash << 3);
357:                hash ^= (hash >>> 6);
358:                hash += ~(hash << 11);
359:                hash ^= (hash >>> 16);
360:                return hash & (table.length - 1);
361:            }
362:
363:            /**
364:             *  Resizes this hash table by doubling its capacity.
365:             *  This is an expensive operation, as entries must
366:             *  be copied from the old smaller table to the new
367:             *  bigger table.
368:             */
369:            private void resize() {
370:                Entry[] old = table;
371:                table = new Entry[old.length * 2];
372:
373:                for (int i = 0; i < old.length; i++) {
374:                    Entry next = old[i];
375:                    while (next != null) {
376:                        Entry entry = next;
377:                        next = next.next;
378:                        int index = indexFor(entry.hash);
379:                        entry.next = table[index];
380:                        table[index] = entry;
381:                    }
382:                    old[i] = null;
383:                }
384:                threshold = (int) (table.length * loadFactor);
385:            }
386:
387:            /**
388:             *  Purges stale mappings from this map.<P>
389:             *
390:             *  Ordinarily, stale mappings are only removed during
391:             *  a write operation; typically a write operation will
392:             *  occur often enough that you'll never need to manually
393:             *  invoke this method.<P>
394:             *
395:             *  Note that this method is not synchronized!  Special
396:             *  care must be taken if, for instance, you want stale
397:             *  mappings to be removed on a periodic basis by some
398:             *  background thread.
399:             */
400:            private void purge() {
401:                Reference ref = queue.poll();
402:                while (ref != null) {
403:                    purge(ref);
404:                    ref = queue.poll();
405:                }
406:            }
407:
408:            private void purge(Reference ref) {
409:                // The hashCode of the reference is the hashCode of the
410:                // mapping key, even if the reference refers to the
411:                // mapping value...
412:                int hash = ref.hashCode(); // note: hashCode() is referined
413:                int index = indexFor(hash);
414:                Entry previous = null;
415:                Entry entry = table[index];
416:                while (entry != null) {
417:                    if (entry.purge(ref)) {
418:                        if (previous == null)
419:                            table[index] = entry.next;
420:                        else
421:                            previous.next = entry.next;
422:                        this .size--;
423:                        return;
424:                    }
425:                    previous = entry;
426:                    entry = entry.next;
427:                }
428:
429:            }
430:
431:            /**
432:             *  Returns the size of this map.
433:             *
434:             *  @return  the size of this map
435:             */
436:            public int size() {
437:                purge();
438:                return size;
439:            }
440:
441:            /**
442:             *  Returns <Code>true</Code> if this map is empty.
443:             *
444:             *  @return <Code>true</Code> if this map is empty
445:             */
446:            public boolean isEmpty() {
447:                purge();
448:                return size == 0;
449:            }
450:
451:            /**
452:             *  Returns <Code>true</Code> if this map contains the given key.
453:             *
454:             *  @return true if the given key is in this map
455:             */
456:            public boolean containsKey(Object key) {
457:                purge();
458:                Entry entry = getEntry(key);
459:                if (entry == null)
460:                    return false;
461:                return entry.getValue() != null;
462:            }
463:
464:            /**
465:             *  Returns the value associated with the given key, if any.
466:             *
467:             *  @return the value associated with the given key, or <Code>null</Code>
468:             *   if the key maps to no value
469:             */
470:            public Object get(Object key) {
471:                purge();
472:                Entry entry = getEntry(key);
473:                if (entry == null)
474:                    return null;
475:                return entry.getValue();
476:            }
477:
478:            /**
479:             *  Associates the given key with the given value.<P>
480:             *  Neither the key nor the value may be null.
481:             *
482:             *  @param key  the key of the mapping
483:             *  @param value  the value of the mapping
484:             *  @return  the last value associated with that key, or
485:             *   null if no value was associated with the key
486:             *  @throws java.lang.NullPointerException if either the key or value
487:             *   is null
488:             */
489:            public Object put(Object key, Object value) {
490:                if (key == null)
491:                    throw new NullPointerException("null keys not allowed");
492:                if (value == null)
493:                    throw new NullPointerException("null values not allowed");
494:
495:                purge();
496:                if (size + 1 > threshold)
497:                    resize();
498:
499:                int hash = hashCode(key);
500:                int index = indexFor(hash);
501:                Entry entry = table[index];
502:                while (entry != null) {
503:                    if ((hash == entry.hash) && equals(key, entry.getKey())) {
504:                        Object result = entry.getValue();
505:                        entry.setValue(value);
506:                        return result;
507:                    }
508:                    entry = entry.next;
509:                }
510:                this .size++;
511:                modCount++;
512:                key = toReference(keyType, key, hash);
513:                value = toReference(valueType, value, hash);
514:                table[index] = new Entry(key, hash, value, table[index]);
515:                return null;
516:            }
517:
518:            /**
519:             *  Removes the key and its associated value from this map.
520:             *
521:             *  @param key  the key to remove
522:             *  @return the value associated with that key, or null if
523:             *   the key was not in the map
524:             */
525:            public Object remove(Object key) {
526:                if (key == null)
527:                    return null;
528:                purge();
529:                int hash = hashCode(key);
530:                int index = indexFor(hash);
531:                Entry previous = null;
532:                Entry entry = table[index];
533:                while (entry != null) {
534:                    if ((hash == entry.hash) && equals(key, entry.getKey())) {
535:                        if (previous == null)
536:                            table[index] = entry.next;
537:                        else
538:                            previous.next = entry.next;
539:                        this .size--;
540:                        modCount++;
541:                        return entry.getValue();
542:                    }
543:                    previous = entry;
544:                    entry = entry.next;
545:                }
546:                return null;
547:            }
548:
549:            /**
550:             *  Clears this map.
551:             */
552:            public void clear() {
553:                Arrays.fill(table, null);
554:                size = 0;
555:                while (queue.poll() != null) {
556:                    // drain the queue
557:                }
558:            }
559:
560:            /**
561:             *  Returns a set view of this map's entries.
562:             *
563:             *  @return a set view of this map's entries
564:             */
565:            public Set entrySet() {
566:                if (entrySet != null)
567:                    return entrySet;
568:                entrySet = new AbstractSet() {
569:                    public int size() {
570:                        return ReferenceMap.this .size();
571:                    }
572:
573:                    public void clear() {
574:                        ReferenceMap.this .clear();
575:                    }
576:
577:                    public boolean contains(Object o) {
578:                        if (o == null)
579:                            return false;
580:                        if (!(o instanceof  Map.Entry))
581:                            return false;
582:                        Map.Entry e = (Map.Entry) o;
583:                        Entry e2 = getEntry(e.getKey());
584:                        return (e2 != null) && e.equals(e2);
585:                    }
586:
587:                    public boolean remove(Object o) {
588:                        boolean r = contains(o);
589:                        if (r) {
590:                            Map.Entry e = (Map.Entry) o;
591:                            ReferenceMap.this .remove(e.getKey());
592:                        }
593:                        return r;
594:                    }
595:
596:                    public Iterator iterator() {
597:                        return new EntryIterator();
598:                    }
599:
600:                    public Object[] toArray() {
601:                        return toArray(new Object[0]);
602:                    }
603:
604:                    public Object[] toArray(Object[] arr) {
605:                        ArrayList list = new ArrayList();
606:                        Iterator iterator = iterator();
607:                        while (iterator.hasNext()) {
608:                            Entry e = (Entry) iterator.next();
609:                            list.add(new DefaultMapEntry(e.getKey(), e
610:                                    .getValue()));
611:                        }
612:                        return list.toArray(arr);
613:                    }
614:                };
615:                return entrySet;
616:            }
617:
618:            /**
619:             *  Returns a set view of this map's keys.
620:             *
621:             *  @return a set view of this map's keys
622:             */
623:            public Set keySet() {
624:                if (keySet != null)
625:                    return keySet;
626:                keySet = new AbstractSet() {
627:                    public int size() {
628:                        return size;
629:                    }
630:
631:                    public Iterator iterator() {
632:                        return new KeyIterator();
633:                    }
634:
635:                    public boolean contains(Object o) {
636:                        return containsKey(o);
637:                    }
638:
639:                    public boolean remove(Object o) {
640:                        Object r = ReferenceMap.this .remove(o);
641:                        return r != null;
642:                    }
643:
644:                    public void clear() {
645:                        ReferenceMap.this .clear();
646:                    }
647:
648:                };
649:                return keySet;
650:            }
651:
652:            /**
653:             *  Returns a collection view of this map's values.
654:             *
655:             *  @return a collection view of this map's values.
656:             */
657:            public Collection values() {
658:                if (values != null)
659:                    return values;
660:                values = new AbstractCollection() {
661:                    public int size() {
662:                        return size;
663:                    }
664:
665:                    public void clear() {
666:                        ReferenceMap.this .clear();
667:                    }
668:
669:                    public Iterator iterator() {
670:                        return new ValueIterator();
671:                    }
672:                };
673:                return values;
674:            }
675:
676:            // If getKey() or getValue() returns null, it means
677:            // the mapping is stale and should be removed.
678:            private class Entry implements  Map.Entry {
679:
680:                Object key;
681:                Object value;
682:                int hash;
683:                Entry next;
684:
685:                public Entry(Object key, int hash, Object value, Entry next) {
686:                    this .key = key;
687:                    this .hash = hash;
688:                    this .value = value;
689:                    this .next = next;
690:                }
691:
692:                public Object getKey() {
693:                    return (keyType > HARD) ? ((Reference) key).get() : key;
694:                }
695:
696:                public Object getValue() {
697:                    return (valueType > HARD) ? ((Reference) value).get()
698:                            : value;
699:                }
700:
701:                public Object setValue(Object object) {
702:                    Object old = getValue();
703:                    if (valueType > HARD)
704:                        ((Reference) value).clear();
705:                    value = toReference(valueType, object, hash);
706:                    return old;
707:                }
708:
709:                public boolean equals(Object o) {
710:                    if (o == null)
711:                        return false;
712:                    if (o == this )
713:                        return true;
714:                    if (!(o instanceof  Map.Entry))
715:                        return false;
716:
717:                    Map.Entry entry = (Map.Entry) o;
718:                    Object _key = entry.getKey();
719:                    Object _value = entry.getValue();
720:                    if ((_key == null) || (_value == null))
721:                        return false;
722:                    return ReferenceMap.this .equals(_key, getKey())
723:                            && ReferenceMap.this .equals(_value, getValue());
724:                }
725:
726:                public int hashCode() {
727:                    Object v = getValue();
728:                    return hash ^ ((v == null) ? 0 : v.hashCode());
729:                }
730:
731:                public String toString() {
732:                    return getKey() + "=" + getValue();
733:                }
734:
735:                boolean purge(Reference ref) {
736:                    boolean r = (keyType > HARD) && (key == ref);
737:                    r = r || ((valueType > HARD) && (value == ref));
738:                    if (r) {
739:                        if (keyType > HARD)
740:                            ((Reference) key).clear();
741:                        if (valueType > HARD)
742:                            ((Reference) value).clear();
743:                    }
744:                    return r;
745:                }
746:            }
747:
748:            private class EntryIterator implements  Iterator {
749:                // These fields keep track of where we are in the table.
750:                int index;
751:                Entry entry;
752:                Entry previous;
753:
754:                // These Object fields provide hard references to the
755:                // current and next entry; this assures that if hasNext()
756:                // returns true, next() will actually return a valid element.
757:                Object nextKey, nextValue;
758:                Object currentKey, currentValue;
759:
760:                int expectedModCount;
761:
762:                public EntryIterator() {
763:                    index = (size() != 0 ? table.length : 0);
764:                    // have to do this here!  size() invocation above
765:                    // may have altered the modCount.
766:                    expectedModCount = modCount;
767:                }
768:
769:                public boolean hasNext() {
770:                    checkMod();
771:                    while (nextNull()) {
772:                        Entry e = entry;
773:                        int i = index;
774:                        while ((e == null) && (i > 0)) {
775:                            i--;
776:                            e = table[i];
777:                        }
778:                        entry = e;
779:                        index = i;
780:                        if (e == null) {
781:                            currentKey = null;
782:                            currentValue = null;
783:                            return false;
784:                        }
785:                        nextKey = e.getKey();
786:                        nextValue = e.getValue();
787:                        if (nextNull())
788:                            entry = entry.next;
789:                    }
790:                    return true;
791:                }
792:
793:                private void checkMod() {
794:                    if (modCount != expectedModCount) {
795:                        throw new ConcurrentModificationException();
796:                    }
797:                }
798:
799:                private boolean nextNull() {
800:                    return (nextKey == null) || (nextValue == null);
801:                }
802:
803:                protected Entry nextEntry() {
804:                    checkMod();
805:                    if (nextNull() && !hasNext())
806:                        throw new NoSuchElementException();
807:                    previous = entry;
808:                    entry = entry.next;
809:                    currentKey = nextKey;
810:                    currentValue = nextValue;
811:                    nextKey = null;
812:                    nextValue = null;
813:                    return previous;
814:                }
815:
816:                public Object next() {
817:                    return nextEntry();
818:                }
819:
820:                public void remove() {
821:                    checkMod();
822:                    if (previous == null)
823:                        throw new IllegalStateException();
824:                    ReferenceMap.this .remove(currentKey);
825:                    previous = null;
826:                    currentKey = null;
827:                    currentValue = null;
828:                    expectedModCount = modCount;
829:                }
830:
831:            }
832:
833:            private class ValueIterator extends EntryIterator {
834:                public Object next() {
835:                    return nextEntry().getValue();
836:                }
837:            }
838:
839:            private class KeyIterator extends EntryIterator {
840:                public Object next() {
841:                    return nextEntry().getKey();
842:                }
843:            }
844:
845:            // These two classes store the hashCode of the key of
846:            // of the mapping, so that after they're dequeued a quick
847:            // lookup of the bucket in the table can occur.
848:
849:            private static class SoftRef extends SoftReference {
850:                private int hash;
851:
852:                public SoftRef(int hash, Object r, ReferenceQueue q) {
853:                    super (r, q);
854:                    this .hash = hash;
855:                }
856:
857:                public int hashCode() {
858:                    return hash;
859:                }
860:            }
861:
862:            private static class WeakRef extends WeakReference {
863:                private int hash;
864:
865:                public WeakRef(int hash, Object r, ReferenceQueue q) {
866:                    super (r, q);
867:                    this .hash = hash;
868:                }
869:
870:                public int hashCode() {
871:                    return hash;
872:                }
873:            }
874:
875:            private int hashCode(Object obj) {
876:                return useSystemIdentity ? System.identityHashCode(obj) : obj
877:                        .hashCode(); // null keys|values are not supported
878:            }
879:
880:            private boolean equals(Object obj1, Object obj2) {
881:                return (obj1 == obj2)
882:                        || (!useSystemIdentity && obj1.equals(obj2)); // null keys|values are not supported
883:            }
884:
885:            //***********************************************
886:            // inner class
887:            //***********************************************
888:            /** A default implementation of {@link java.util.Map.Entry}
889:             *
890:             * @since 1.0
891:             * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
892:             * @author <a href="mailto:mas@apache.org">Michael A. Smith</a>
893:             */
894:
895:            public class DefaultMapEntry implements  Map.Entry {
896:
897:                private Object key;
898:                private Object value;
899:
900:                /**
901:                 *  Constructs a new <Code>DefaultMapEntry</Code> with a null key
902:                 *  and null value.
903:                 */
904:                public DefaultMapEntry() {
905:                }
906:
907:                /**
908:                 *  Constructs a new <Code>DefaultMapEntry</Code> with the given
909:                 *  key and given value.
910:                 *
911:                 *  @param key  the key for the entry, may be null
912:                 *  @param value  the value for the entyr, may be null
913:                 */
914:                public DefaultMapEntry(Object key, Object value) {
915:                    this .key = key;
916:                    this .value = value;
917:                }
918:
919:                /**
920:                 *  Implemented per API documentation of
921:                 *  {@link java.util.Map.Entry#equals(java.lang.Object)}
922:                 **/
923:                public boolean equals(Object o) {
924:                    if (o == null)
925:                        return false;
926:                    if (o == this )
927:                        return true;
928:
929:                    if (!(o instanceof  Map.Entry))
930:                        return false;
931:                    Map.Entry e2 = (Map.Entry) o;
932:                    return ((getKey() == null ? e2.getKey() == null : getKey()
933:                            .equals(e2.getKey())) && (getValue() == null ? e2
934:                            .getValue() == null : getValue().equals(
935:                            e2.getValue())));
936:                }
937:
938:                /**
939:                 *  Implemented per API documentation of
940:                 *  {@link java.util.Map.Entry#hashCode()}
941:                 **/
942:                public int hashCode() {
943:                    return ((getKey() == null ? 0 : getKey().hashCode()) ^ (getValue() == null ? 0
944:                            : getValue().hashCode()));
945:                }
946:
947:                // Map.Entry interface
948:                //-------------------------------------------------------------------------
949:
950:                /**
951:                 *  Returns the key.
952:                 *
953:                 *  @return the key
954:                 */
955:                public Object getKey() {
956:                    return key;
957:                }
958:
959:                /**
960:                 *  Returns the value.
961:                 *
962:                 *  @return the value
963:                 */
964:                public Object getValue() {
965:                    return value;
966:                }
967:
968:                // Properties
969:                //-------------------------------------------------------------------------
970:
971:                /**
972:                 *  Sets the key.  This method does not modify any map.
973:                 *
974:                 *  @param key  the new key
975:                 */
976:                public void setKey(Object key) {
977:                    this .key = key;
978:                }
979:
980:                /** Note that this method only sets the local reference inside this object and
981:                 * does not modify the original Map.
982:                 *
983:                 * @return the old value of the value
984:                 * @param value the new value
985:                 */
986:                public Object setValue(Object value) {
987:                    Object answer = this.value;
988:                    this.value = value;
989:                    return answer;
990:                }
991:
992:            }
993:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.