KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ofbiz > base > util > collections > MapStack


1 /*
2  * $Id: MapStack.java 5462 2005-08-05 18:35:48Z jonesde $
3  *
4  * Copyright (c) 2004-2005 The Open For Business Project - www.ofbiz.org
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
21  * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */

24 package org.ofbiz.base.util.collections;
25
26 import java.util.Collection JavaDoc;
27 import java.util.Collections JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.Map JavaDoc;
31 import java.util.Set JavaDoc;
32
33 import javolution.lang.Reusable;
34 import javolution.realtime.ObjectFactory;
35 import javolution.util.FastList;
36 import javolution.util.FastMap;
37 import javolution.util.FastSet;
38
39 import org.ofbiz.base.util.Debug;
40
41
42 /**
43  * Map Stack
44  *
45  * @author <a HREF="mailto:jonesde@ofbiz.org">David E. Jones</a>
46  * @version $Rev: 5462 $
47  * @since 3.1
48  */

49 public class MapStack implements Map JavaDoc, Reusable {
50
51     public static final String JavaDoc module = MapStack.class.getName();
52
53     protected static final ObjectFactory mapStackFactory = new ObjectFactory() {
54         protected Object JavaDoc create() {
55             return new MapStack();
56         }
57     };
58     
59     public static MapStack create() {
60         MapStack newValue = (MapStack) mapStackFactory.object();
61         // initialize with a single entry
62
newValue.push();
63         return newValue;
64     }
65
66     public static MapStack create(Map JavaDoc baseMap) {
67         MapStack newValue = (MapStack) mapStackFactory.object();
68         newValue.stackList.add(0, baseMap);
69         return newValue;
70     }
71
72     /** Does a shallow copy of the internal stack of the passed MapStack; enables simultaneous stacks that share common parent Maps */
73     public static MapStack create(MapStack source) {
74         MapStack newValue = (MapStack) mapStackFactory.object();
75         newValue.stackList.addAll(source.stackList);
76         return newValue;
77     }
78
79     protected MapStack() {
80         super();
81     }
82     
83     protected List JavaDoc stackList = FastList.newInstance();
84     
85     public void reset() {
86         stackList = FastList.newInstance();
87     }
88     
89     /** Puts a new Map on the top of the stack */
90     public void push() {
91         this.stackList.add(0, FastMap.newInstance());
92     }
93     
94     /** Puts an existing Map on the top of the stack (top meaning will override lower layers on the stack) */
95     public void push(Map JavaDoc existingMap) {
96         if (existingMap == null) {
97             throw new IllegalArgumentException JavaDoc("Error: cannot push null existing Map onto a MapStack");
98         }
99         this.stackList.add(0, existingMap);
100     }
101     
102     /** Puts an existing Map on the BOTTOM of the stack (bottom meaning will be overriden by lower layers on the stack, ie everything else already there) */
103     public void addToBottom(Map JavaDoc existingMap) {
104         if (existingMap == null) {
105             throw new IllegalArgumentException JavaDoc("Error: cannot add null existing Map to bottom of a MapStack");
106         }
107         this.stackList.add(existingMap);
108     }
109     
110     /** Remove and returns the Map from the top of the stack; if there is only one Map on the stack it returns null and does not remove it */
111     public Map JavaDoc pop() {
112         // always leave at least one Map in the List, ie never pop off the last Map
113
if (this.stackList.size() > 1) {
114             return (Map JavaDoc) stackList.remove(0);
115         } else {
116             return null;
117         }
118     }
119     
120     /**
121      * Creates a MapStack object that has the same Map objects on its stack;
122      * meant to be used to enable a
123      * situation where a parent and child context are operating simultaneously
124      * using two different MapStack objects, but sharing the Maps in common
125      */

126     public MapStack standAloneStack() {
127         MapStack standAlone = MapStack.create(this);
128         return standAlone;
129     }
130
131     /**
132      * Creates a MapStack object that has the same Map objects on its stack,
133      * but with a new Map pushed on the top; meant to be used to enable a
134      * situation where a parent and child context are operating simultaneously
135      * using two different MapStack objects, but sharing the Maps in common
136      */

137     public MapStack standAloneChildStack() {
138         MapStack standAloneChild = MapStack.create(this);
139         standAloneChild.push();
140         return standAloneChild;
141     }
142
143     /* (non-Javadoc)
144      * @see java.util.Map#size()
145      */

146     public int size() {
147         // a little bit tricky; to represent the apparent size we need to aggregate all keys and get a count of unique keys
148
// this is a bit of a slow way, but gets the best number possible
149
Set JavaDoc keys = this.keySet();
150         return keys.size();
151     }
152
153     /* (non-Javadoc)
154      * @see java.util.Map#isEmpty()
155      */

156     public boolean isEmpty() {
157         // walk the stackList and if any is not empty, return false; otherwise return true
158
Iterator JavaDoc stackIter = this.stackList.iterator();
159         while (stackIter.hasNext()) {
160             Map JavaDoc curMap = (Map JavaDoc) stackIter.next();
161             if (!curMap.isEmpty()) {
162                 return false;
163             }
164         }
165         return true;
166     }
167
168     /* (non-Javadoc)
169      * @see java.util.Map#containsKey(java.lang.Object)
170      */

171     public boolean containsKey(Object JavaDoc key) {
172         // walk the stackList and for the first place it is found return true; otherwise refurn false
173
Iterator JavaDoc stackIter = this.stackList.iterator();
174         while (stackIter.hasNext()) {
175             Map JavaDoc curMap = (Map JavaDoc) stackIter.next();
176             if (curMap.containsKey(key)) {
177                 return true;
178             }
179         }
180         return false;
181     }
182
183     /* (non-Javadoc)
184      * @see java.util.Map#containsValue(java.lang.Object)
185      */

186     public boolean containsValue(Object JavaDoc value) {
187         // walk the stackList and the entries for each Map and if nothing is in for the current key, consider it an option, otherwise ignore
188
Set JavaDoc resultKeySet = FastSet.newInstance();
189         Iterator JavaDoc stackIter = this.stackList.iterator();
190         while (stackIter.hasNext()) {
191             Map JavaDoc curMap = (Map JavaDoc) stackIter.next();
192             Iterator JavaDoc curEntrySetIter = curMap.entrySet().iterator();
193             while (curEntrySetIter.hasNext()) {
194                 Map.Entry JavaDoc curEntry = (Map.Entry JavaDoc) curEntrySetIter.next();
195                 if (!resultKeySet.contains(curEntry.getKey())) {
196                     resultKeySet.add(curEntry.getKey());
197                     if (value == null) {
198                         if (curEntry.getValue() == null) {
199                             return true;
200                         }
201                     } else {
202                         if (value.equals(curEntry.getValue())) {
203                             return true;
204                         }
205                     }
206                 }
207             }
208         }
209         return false;
210     }
211
212     /* (non-Javadoc)
213      * @see java.util.Map#get(java.lang.Object)
214      */

215     public Object JavaDoc get(Object JavaDoc key) {
216         if ("context".equals(key)) {
217             return this;
218         }
219         
220         // walk the stackList and for the first place it is found return true; otherwise refurn false
221
Iterator JavaDoc stackIter = this.stackList.iterator();
222         while (stackIter.hasNext()) {
223             Map JavaDoc curMap = (Map JavaDoc) stackIter.next();
224             // only return if the curMap contains the key, rather than checking for null; this allows a null at a lower level to override a value at a higher level
225
if (curMap.containsKey(key)) {
226                 return curMap.get(key);
227             }
228         }
229         return null;
230     }
231
232     /* (non-Javadoc)
233      * @see java.util.Map#put(java.lang.Object, java.lang.Object)
234      */

235     public Object JavaDoc put(Object JavaDoc key, Object JavaDoc value) {
236         if ("context".equals(key)) {
237             if (value == null || this != value) {
238                 Debug.logWarning("WARNING: Putting a value in a MapStack with key [context] that is not this MapStack, will be hidden by the current MapStack self-reference: " + value, module);
239             }
240         }
241             
242         // all write operations are local: only put in the Map on the top of the stack
243
Map JavaDoc currentMap = (Map JavaDoc) this.stackList.get(0);
244         return currentMap.put(key, value);
245     }
246
247     /* (non-Javadoc)
248      * @see java.util.Map#remove(java.lang.Object)
249      */

250     public Object JavaDoc remove(Object JavaDoc key) {
251         // all write operations are local: only remove from the Map on the top of the stack
252
Map JavaDoc currentMap = (Map JavaDoc) this.stackList.get(0);
253         return currentMap.remove(key);
254     }
255
256     /* (non-Javadoc)
257      * @see java.util.Map#putAll(java.util.Map)
258      */

259     public void putAll(Map JavaDoc arg0) {
260         // all write operations are local: only put in the Map on the top of the stack
261
Map JavaDoc currentMap = (Map JavaDoc) this.stackList.get(0);
262         currentMap.putAll(arg0);
263     }
264
265     /* (non-Javadoc)
266      * @see java.util.Map#clear()
267      */

268     public void clear() {
269         // all write operations are local: only clear the Map on the top of the stack
270
Map JavaDoc currentMap = (Map JavaDoc) this.stackList.get(0);
271         currentMap.clear();
272     }
273
274     /* (non-Javadoc)
275      * @see java.util.Map#keySet()
276      */

277     public Set JavaDoc keySet() {
278         // walk the stackList and aggregate all keys
279
Set JavaDoc resultSet = FastSet.newInstance();
280         Iterator JavaDoc stackIter = this.stackList.iterator();
281         while (stackIter.hasNext()) {
282             Map JavaDoc curMap = (Map JavaDoc) stackIter.next();
283             resultSet.addAll(curMap.keySet());
284         }
285         return Collections.unmodifiableSet(resultSet);
286     }
287
288     /* (non-Javadoc)
289      * @see java.util.Map#values()
290      */

291     public Collection JavaDoc values() {
292         // walk the stackList and the entries for each Map and if nothing is in for the current key, put it in
293
Set JavaDoc resultKeySet = FastSet.newInstance();
294         List JavaDoc resultValues = FastList.newInstance();
295         Iterator JavaDoc stackIter = this.stackList.iterator();
296         while (stackIter.hasNext()) {
297             Map JavaDoc curMap = (Map JavaDoc) stackIter.next();
298             Iterator JavaDoc curEntrySetIter = curMap.entrySet().iterator();
299             while (curEntrySetIter.hasNext()) {
300                 Map.Entry JavaDoc curEntry = (Map.Entry JavaDoc) curEntrySetIter.next();
301                 if (!resultKeySet.contains(curEntry.getKey())) {
302                     resultKeySet.add(curEntry.getKey());
303                     resultValues.add(curEntry.getValue());
304                 }
305             }
306         }
307         return Collections.unmodifiableCollection(resultValues);
308     }
309
310     /* (non-Javadoc)
311      * @see java.util.Map#entrySet()
312      */

313     public Set JavaDoc entrySet() {
314         // walk the stackList and the entries for each Map and if nothing is in for the current key, put it in
315
Set JavaDoc resultKeySet = FastSet.newInstance();
316         Set JavaDoc resultEntrySet = FastSet.newInstance();
317         Iterator JavaDoc stackIter = this.stackList.iterator();
318         while (stackIter.hasNext()) {
319             Map JavaDoc curMap = (Map JavaDoc) stackIter.next();
320             Iterator JavaDoc curEntrySetIter = curMap.entrySet().iterator();
321             while (curEntrySetIter.hasNext()) {
322                 Map.Entry JavaDoc curEntry = (Map.Entry JavaDoc) curEntrySetIter.next();
323                 if (!resultKeySet.contains(curEntry.getKey())) {
324                     resultKeySet.add(curEntry.getKey());
325                     resultEntrySet.add(curEntry);
326                 }
327             }
328         }
329         return Collections.unmodifiableSet(resultEntrySet);
330     }
331     
332     public String JavaDoc toString() {
333         StringBuffer JavaDoc fullMapString = new StringBuffer JavaDoc();
334         int curLevel = 0;
335         Iterator JavaDoc stackIter = this.stackList.iterator();
336         while (stackIter.hasNext()) {
337             Map JavaDoc curMap = (Map JavaDoc) stackIter.next();
338             fullMapString.append("============================== Start stack level " + curLevel + "\n");
339             Iterator JavaDoc curEntrySetIter = curMap.entrySet().iterator();
340             while (curEntrySetIter.hasNext()) {
341                 Map.Entry JavaDoc curEntry = (Map.Entry JavaDoc) curEntrySetIter.next();
342                 
343                 fullMapString.append("==>[");
344                 fullMapString.append(curEntry.getKey());
345                 fullMapString.append("]:");
346                 // skip the instances of MapStack to avoid infinite loop
347
if (curEntry.getValue() instanceof MapStack) {
348                     fullMapString.append("<Instance of MapStack, not printing to avoid infinite recursion>");
349                 } else {
350                     fullMapString.append(curEntry.getValue());
351                 }
352                 fullMapString.append("\n");
353             }
354             fullMapString.append("============================== End stack level " + curLevel + "\n");
355             curLevel++;
356         }
357         return fullMapString.toString();
358     }
359 }
360
Popular Tags