KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > forms > util > CombiningMap


1 /*
2  * Copyright 2005 The Apache Software Foundation.
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 package org.apache.cocoon.forms.util;
17
18 import java.util.AbstractMap JavaDoc;
19 import java.util.AbstractSet JavaDoc;
20 import java.util.ArrayList JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.List JavaDoc;
23 import java.util.Map JavaDoc;
24 import java.util.NoSuchElementException JavaDoc;
25 import java.util.Set JavaDoc;
26
27 /**
28  * A read-only implementation of <code>Map</code> that combines several other maps.
29  *
30  * @version $Id: CombiningMap.java 327577 2005-10-21 20:59:14Z sylvain $
31  */

32 public class CombiningMap extends AbstractMap JavaDoc {
33
34     private List JavaDoc maps = new ArrayList JavaDoc();
35     private boolean locked = false;
36
37     /**
38      * Adds a <code>Map</code> in the combined map, with the lowest lookup priority.
39      * <p>
40      * New maps cannot be added if this object was already iterated.
41      *
42      * @param map the new map
43      * @return this object, as a convenience to write <code>combiner.add(map1).add(map2).add(map3)</code>
44      * @throw IllegalStateException if this object was already iterated.
45      */

46     public CombiningMap add(Map JavaDoc map) {
47         if (locked) {
48             throw new IllegalStateException JavaDoc("Cannot add new Maps to a CombiningMap once it has been iterated");
49         }
50         maps.add(map);
51         
52         return this;
53     }
54     
55     public Object JavaDoc get(Object JavaDoc key) {
56         // Faster implemetation than the default in AbstractMap
57
for (int i = 0; i < maps.size(); i++) {
58             Map JavaDoc map = (Map JavaDoc)maps.get(i);
59             Object JavaDoc result = map.get(key);
60
61             if (result != null) {
62                 return result;
63             }
64
65             if (map.containsKey(key)) {
66                 return null;
67             }
68         }
69         
70         return null;
71     }
72     
73     public boolean containsKey(Object JavaDoc key) {
74         // Faster implemetation than the default in AbstractMap
75
for (int i = 0; i < maps.size(); i++) {
76             Map JavaDoc map = (Map JavaDoc)maps.get(i);
77             if (map.containsKey(key)) {
78                 return true;
79             }
80         }
81         return false;
82     }
83
84     public Set JavaDoc entrySet() {
85         locked = true;
86         return new CombiningEntrySet();
87     }
88
89     private class CombiningEntrySet extends AbstractSet JavaDoc {
90
91         public Iterator JavaDoc iterator() {
92             return new CombiningIterator();
93         }
94
95         /**
96          * Super inefficient way, but this implementation is meant to be super-lightweight
97          * and efficient at iterations.
98          */

99         public int size() {
100            
101             int size = 0;
102             Iterator JavaDoc iter = iterator();
103             while (iter.hasNext()) {
104                 size++;
105                 iter.next();
106             }
107             return size;
108         }
109     }
110     
111     private class CombiningIterator implements Iterator JavaDoc {
112         
113         private int index;
114         private Iterator JavaDoc delegate;
115         private Map.Entry JavaDoc next;
116
117         public CombiningIterator() {
118             // Initialize the first result
119
if (!maps.isEmpty()) {
120                 delegate = ((Map JavaDoc)maps.get(0)).entrySet().iterator();
121                 if (delegate.hasNext()) {
122                     next = (Map.Entry JavaDoc)delegate.next();
123                 }
124             }
125             
126         }
127         public boolean hasNext() {
128             return next != null;
129         }
130
131         public Object JavaDoc next() {
132             if (next == null) {
133                 throw new NoSuchElementException JavaDoc();
134             }
135             Object JavaDoc result = next;
136             fetchNext();
137             return result;
138         }
139
140         public void remove() {
141             throw new UnsupportedOperationException JavaDoc();
142         }
143         
144         private void fetchNext() {
145             boolean skip;
146             do {
147                 // Get an iterator that has more values
148
while (delegate != null && !delegate.hasNext()) {
149                     // Ended iteration on the previous map
150
index++;
151                     if (index < maps.size()) {
152                         delegate = ((Map JavaDoc)maps.get(index)).entrySet().iterator();
153                     } else {
154                         // Iteration finished
155
next = null;
156                         delegate = null;
157                         return;
158                     }
159                 }
160                 
161                 // Get the next entry
162
next = (Map.Entry JavaDoc)delegate.next();
163                 
164                 // Skip it if its key doesn't exist in the previous Maps
165
Object JavaDoc key = next.getKey();
166                 skip = false;
167                 for (int i = 0; i < index-1; i++) {
168                     if (((Map JavaDoc)maps.get(i)).containsKey(key)) {
169                         skip = true;
170                         continue;
171                     }
172                 }
173             } while(skip);
174         }
175     }
176 }
177
Popular Tags