/Users/lyon/j4p/src/classUtils/pack/util/ListMapIterator.java
|
1 package classUtils.pack.util;
2
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.HashMap;
6 import java.util.HashSet;
7 import java.util.Iterator;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.NoSuchElementException;
11 import java.util.Set;
12
13 /**
14 * An iterator to go thru a Map of Lists, using a specific key list for deciding
15 * how to access the sublists.
16 * <p>
17 * Given a {@link java.util.Map java.util.Map} binding each key K<sub>i</sub> to a
18 * {@link java.util.List java.util.List} L<sub>i</sub>, this Iterator allows to
19 * browse the set { L<sub>1</sub>, L<sub>2</sub>, ... , L<sub>n</sub>} , by
20 * specifying the order in which the lists should be picked.
21 * <p>
22 * Such order is specified by providing a key list at construction time; if no list
23 * is given, the order of iteration is the arbitrary order in which the keys are
24 * stored in the {@link java.util.Map java.util.Map}, as given by the iterator
25 * provided by the {@link java.util.Set#iterator() iterator()} method of the
26 * {@link java.util.Map java.util.Map}'s key set.
27 * <p>
28 * For example, if a Map is built by
29 * <pre>
30 * list1.add("Elem 1.1");
31 * list1.add("Elem 1.2");
32 * list2.add("Elem 2.1");
33 * list3.add("Elem 3.1");
34 * list3.add("Elem 3.2");
35 * list3.add("Elem 3.3");
36 * map.add("1", list1);
37 * map.add("2", list2);
38 * map.add("3", list3);
39 * </pre>
40 * a <code>ListMapIterator</code> built by
41 * <pre>
42 * ListMapIterator i = new ListMapIterator(map, new Arrays.asList(new String[] { "1", "2", "3")));
43 * </pre>
44 * will produce the iteration <code>Elem1.1, Elem1.2, Elem2.1, Elem3.1, Elem3.2, Elem3.3</code>.
45 *
46 * @version 1.0
47 * @author Cristiano Sadun
48 */
49 public class ListMapIterator implements Iterator {
50
51 Map map;
52 Iterator currentKeyIterator;
53 Iterator currentListIterator;
54 Object currentKey;
55
56 boolean failOnUnknownKeys;
57 boolean requireUniqueKeys;
58
59 private static List getDefaultOrderingList(Map map) {
60 Set s=map.keySet();
61 List l = new ArrayList();
62 for(Iterator i = s.iterator(); i.hasNext();) {
63 l.add(i.next());
64 }
65 return l;
66 }
67
68 /**
69 * Create a ListMapIterator which uses default ordering
70 * (as provided by the set of keys in the map).
71 *
72 * @param map the map of Lists to iterate
73 */
74 public ListMapIterator(Map map) {
75 this(map, getDefaultOrderingList(map));
76 }
77
78 /**
79 * Create a ListMapIterator which uses the key ordering
80 * defined in the given list.
81 *
82 * @param map the map of Lists to iterate.
83 * @param keyorder the order with which the map Lists must be iterated.
84 */
85 public ListMapIterator(Map map, List keyorder) {
86 this(map, keyorder, true, false);
87 }
88
89 /**
90 * Create a ListMapIterator which uses the key ordering defined in the given list.
91 *
92 * @param map the map of Lists to iterate.
93 * @param keyorder the order with which the map Lists must be iterated.
94 * @param failOnUnknownKeys if <b>true</b>, the iterator will fail with
95 * an IllegalArgumentException if one key in the
96 * ordering list is not defined in the map.
97 * Else, it will ignore the unknown key.
98 * @param requireUniqueKeys if <b>true</b>, the iterator will fail with
99 * an IllegalArgumentException if the keys in the
100 * ordering list are not unique.
101 */
102 public ListMapIterator(
103 Map map,
104 List keyorder,
105 boolean failOnUnknownKeys,
106 boolean requireUniqueKeys) {
107 this.map = map;
108 this.failOnUnknownKeys = failOnUnknownKeys;
109
110 if (requireUniqueKeys) {
111 Set s = new HashSet();
112 for (Iterator i = keyorder.iterator(); i.hasNext();) {
113 s.add(i.next());
114 }
115 if (s.size() != keyorder.size())
116 throw new IllegalArgumentException("ordering list must contain distinct keys");
117 }
118
119 this.currentKeyIterator = keyorder.iterator();
120 goToNextKey();
121 }
122
123 private boolean goToNextKey() {
124 if (currentKeyIterator.hasNext()) {
125 try {
126 currentKey = currentKeyIterator.next();
127 List l = ((List) map.get(currentKey));
128
129 // Ignore
130 if (l == null) {
131 if (failOnUnknownKeys)
132 throw new IllegalArgumentException(
133 "The key <"
134 + currentKey.toString()
135 + "> is not found in the map");
136 else
137 return goToNextKey();
138 }
139 currentListIterator = l.iterator();
140 return true;
141 } catch (ClassCastException e) {
142 throw new IllegalArgumentException("The passed map does not contain a List");
143 }
144 }
145 return false;
146 }
147
148 /**
149 * @see java.util.Iterator#hasNext()
150 */
151 public boolean hasNext() {
152 if (currentListIterator != null) {
153 if (currentListIterator.hasNext())
154 return true;
155 else {
156 if (!goToNextKey())
157 return false;
158 return hasNext();
159 }
160 }
161 return false;
162 }
163
164 /**
165 * @see java.util.Iterator#next()
166 */
167 public Object next() {
168 if (currentListIterator == null)
169 throw new NoSuchElementException();
170 return currentListIterator.next();
171 }
172
173 /**
174 * @see java.util.Iterator#remove()
175 */
176 public void remove() {
177 throw new UnsupportedOperationException("remove not supported");
178 }
179
180 public static void main(String args[]) throws Exception {
181 Map map = new HashMap();
182 List l1 = new ArrayList();
183 l1.add("hello");
184 List l2 = new ArrayList();
185 List l3 = new ArrayList();
186 l3.add("world");
187 l3.add(",");
188 l3.add("how");
189 List l4 = new ArrayList();
190 l4.add("is it?");
191 map.put("step1", l1);
192 map.put("step2", l2);
193 map.put("step3", l3);
194 map.put("step4", l4);
195 List order = new ArrayList();
196 order.add("step1");
197 order.add("step2");
198 order.add("step3");
199 order.add("step4");
200 ListMapIterator i = new ListMapIterator(map, order);
201 while (i.hasNext()) {
202 System.out.print(i.next());
203 System.out.print(" ");
204
205 }
206 }
207
208 public Object getCurrentKey() {
209 return currentKey;
210 }
211
212 }