/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  }