KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > util > CachingMapDecorator


1 /*
2  * Copyright 2002-2005 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.util;
18
19 import java.io.Serializable JavaDoc;
20 import java.util.Collection JavaDoc;
21 import java.util.Collections JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.util.Map JavaDoc;
24 import java.util.Set JavaDoc;
25 import java.util.WeakHashMap JavaDoc;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29
30 /**
31  * A simple decorator for a Map, encapsulating the workflow for caching
32  * expensive values in a target Map. Supports caching weak or strong keys.
33  *
34  * <p>This class is also an abstract template. Caching Map implementations
35  * should subclass and override the <code>create(key)</code> method which
36  * encapsulates expensive creation of a new object.
37  *
38  * @author Keith Donald
39  * @since 1.2.2
40  */

41 public abstract class CachingMapDecorator implements Map JavaDoc, Serializable JavaDoc {
42     
43     private static Object JavaDoc NULL_VALUE = new Object JavaDoc();
44
45
46     private static final Log logger = LogFactory.getLog(CachingMapDecorator.class);
47
48     private final Map JavaDoc targetMap;
49
50
51     /**
52      * Create a CachingMapDecorator with strong keys,
53      * using an underlying synchronized Map.
54      */

55     public CachingMapDecorator() {
56         this(false);
57     }
58
59     /**
60      * Create a CachingMapDecorator,
61      * using an underlying synchronized Map.
62      * @param weakKeys whether to use weak references for keys
63      */

64     public CachingMapDecorator(boolean weakKeys) {
65         Map JavaDoc internalMap = weakKeys ? (Map JavaDoc) new WeakHashMap JavaDoc() : new HashMap JavaDoc();
66         this.targetMap = Collections.synchronizedMap(internalMap);
67     }
68
69     /**
70      * Create a CachingMapDecorator with initial size,
71      * using an underlying synchronized Map.
72      * @param weakKeys whether to use weak references for keys
73      * @param size the initial cache size
74      */

75     public CachingMapDecorator(boolean weakKeys, int size) {
76         Map JavaDoc internalMap = weakKeys ? (Map JavaDoc) new WeakHashMap JavaDoc(size) : new HashMap JavaDoc(size);
77         this.targetMap = Collections.synchronizedMap(internalMap);
78     }
79
80     /**
81      * Create a CachingMapDecorator for the given Map.
82      * <p>The passed-in Map won't get synchronized explicitly,
83      * so make sure to pass in a properly synchronized Map, if desired.
84      * @param targetMap the Map to decorate
85      */

86     public CachingMapDecorator(Map JavaDoc targetMap) {
87         Assert.notNull(targetMap, "Target Map is required");
88         this.targetMap = targetMap;
89     }
90
91
92     public int size() {
93         return this.targetMap.size();
94     }
95
96     public boolean isEmpty() {
97         return this.targetMap.isEmpty();
98     }
99
100     public boolean containsKey(Object JavaDoc key) {
101         return this.targetMap.containsKey(key);
102     }
103
104     public boolean containsValue(Object JavaDoc value) {
105         return this.targetMap.containsValue(value);
106     }
107
108     public Object JavaDoc put(Object JavaDoc key, Object JavaDoc value) {
109         return this.targetMap.put(key, value);
110     }
111
112     public Object JavaDoc remove(Object JavaDoc key) {
113         return this.targetMap.remove(key);
114     }
115
116     public void putAll(Map JavaDoc t) {
117         this.targetMap.putAll(t);
118     }
119
120     public void clear() {
121         this.targetMap.clear();
122     }
123
124     public Set JavaDoc keySet() {
125         return this.targetMap.keySet();
126     }
127
128     public Collection JavaDoc values() {
129         return this.targetMap.values();
130     }
131
132     public Set JavaDoc entrySet() {
133         return this.targetMap.entrySet();
134     }
135
136
137     /**
138      * Get value for key.
139      * Creates and caches value if it doesn't already exist in the cache.
140      * <p>This implementation is <i>not</i> synchronized: This is highly
141      * concurrent but does not guarantee unique instances in the cache,
142      * as multiple values for the same key could get created in parallel.
143      * Consider overriding this method to synchronize it, if desired.
144      * @see #create(Object)
145      */

146     public Object JavaDoc get(Object JavaDoc key) {
147         Object JavaDoc value = this.targetMap.get(key);
148         if (value == null) {
149             if (logger.isDebugEnabled()) {
150                 logger.debug("Creating new expensive value for key '" + key + "'");
151             }
152             value = create(key);
153             if (value == null) {
154                 value = NULL_VALUE;
155             }
156             if (logger.isDebugEnabled()) {
157                 logger.debug("Caching expensive value: " + value);
158             }
159             put(key, value);
160         }
161         else {
162             if (logger.isDebugEnabled()) {
163                 logger.debug("For key '" + key + "', returning cached value: " + value);
164             }
165         }
166         return (value == NULL_VALUE) ? null : value;
167     }
168
169     /**
170      * Create a value to cache for the given key.
171      * Called by <code>get</code> if there is no value cached already.
172      * @param key the cache key
173      * @see #get(Object)
174      */

175     protected abstract Object JavaDoc create(Object JavaDoc key);
176
177
178     public String JavaDoc toString() {
179         return "CachingMapDecorator [" + getClass().getName() + "]:" + this.targetMap;
180     }
181
182 }
183
Popular Tags