View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.shared_orchestra.util;
20  
21  import java.util.ArrayList;
22  import java.util.Arrays;
23  import java.util.Collection;
24  import java.util.Iterator;
25  import java.util.Map;
26  import java.util.NoSuchElementException;
27  
28  import javax.faces.component.UIComponent;
29  import javax.faces.component.UISelectItem;
30  import javax.faces.component.UISelectItems;
31  import javax.faces.el.ValueBinding;
32  import javax.faces.model.SelectItem;
33  
34  import org.apache.myfaces.shared_orchestra.renderkit.RendererUtils;
35  
36  /**
37   * @author Mathias Broekelmann (latest modification by $Author$)
38   * @version $Revision$ $Date$
39   */
40  public class SelectItemsIterator implements Iterator
41  {
42      private final Iterator _childs;
43      private Iterator _nestedItems;
44      private Object _nextItem;
45      private String _collectionLabel;
46      private UISelectItems _currentUISelectItems;
47  
48      public SelectItemsIterator(UIComponent selectItemsParent)
49      {
50          _childs = selectItemsParent.getChildren().iterator();
51      }
52  
53      public boolean hasNext()
54      {
55          if(_nextItem != null)
56          {
57              return true;
58          }
59          if(_nestedItems != null)
60          {
61              if(_nestedItems.hasNext())
62              {
63                  return true;
64              }
65              _nestedItems = null;
66          }            
67          if (_childs.hasNext())
68          {
69              UIComponent child = (UIComponent) _childs.next();
70              // When there is other components nested that does
71              // not extends from UISelectItem or UISelectItems
72              // the behavior for this iterator is just skip this
73              // element(s) until an element that extends from these
74              // classes are found. If there is no more elements
75              // that conform this condition, just return false.
76              while (!(child instanceof UISelectItem)
77                      && !(child instanceof UISelectItems))
78              {
79                  //Try to skip it
80                  if (_childs.hasNext())
81                  {
82                      //Skip and do the same check
83                      child = (UIComponent) _childs.next();
84                  }
85                  else
86                  {
87                      //End loop, so the final result is return false,
88                      //since there are no more components to iterate.
89                      return false;
90                  }
91              }
92              if (child instanceof UISelectItem)
93              {
94                  UISelectItem uiSelectItem = (UISelectItem) child;
95                  Object item = uiSelectItem.getValue();
96                  if (item == null)
97                  {
98                      Object itemValue = ((UISelectItem) child).getItemValue();
99                      String label = ((UISelectItem) child).getItemLabel();
100                     String description = ((UISelectItem) child)
101                                     .getItemDescription();
102                     boolean disabled = ((UISelectItem) child).isItemDisabled();
103                     if (label == null)
104                     {
105                         label = itemValue.toString();
106                     }
107                     item = new SelectItem(itemValue, label, description,
108                                     disabled);
109                 }
110                 else if (!(item instanceof SelectItem))
111                 {
112                     ValueBinding binding = ((UISelectItem) child)
113                                     .getValueBinding("value");
114                     throw new IllegalArgumentException(
115                                     "Value binding '"
116                                     + (binding == null ? null : binding.getExpressionString())
117                                     + "' of UISelectItem : "
118                                     + RendererUtils.getPathToComponent(child)
119                                     + " does not reference an Object of type SelectItem");
120                 }
121                 _nextItem = item;
122                 return true;
123             }
124             else if (child instanceof UISelectItems)
125             {
126                 _currentUISelectItems = ((UISelectItems) child);
127                 Object value = _currentUISelectItems.getValue();
128 
129                 if (value instanceof SelectItem)
130                 {
131                     _nextItem = value;
132                     return true;
133                 }
134                 else if (value instanceof SelectItem[])
135                 {
136                     _nestedItems = Arrays.asList((SelectItem[]) value)
137                                     .iterator();
138                     _collectionLabel = "Array";
139                     return hasNext();
140                 }
141                 else if (value instanceof Collection)
142                 {
143                     _nestedItems = ((Collection)value).iterator();
144                     _collectionLabel = "Collection";
145                     return hasNext();
146                 }
147                 else if (value instanceof Map)
148                 {
149                     Map map = ((Map) value);
150                     Collection items = new ArrayList(map.size()); 
151                     for (Iterator it = map.entrySet().iterator(); it
152                                     .hasNext();)
153                     {
154                         Map.Entry entry = (Map.Entry) it.next();
155                         items.add(new SelectItem(entry.getValue(), entry
156                                         .getKey().toString()));
157                     }
158                     _nestedItems = items.iterator();
159                     _collectionLabel = "Map";
160                     return hasNext();
161                 }
162                 else
163                 {
164                     ValueBinding binding = _currentUISelectItems.getValueBinding("value");
165 
166                     throw new IllegalArgumentException(
167                         "Value binding '"
168                         + (binding == null ? null : binding
169                                         .getExpressionString())
170                         + "'of UISelectItems with component-path "
171                         + RendererUtils.getPathToComponent(child)
172                         + " does not reference an Object of type SelectItem, SelectItem[], Collection or Map but of type : "
173                         + ((value == null) ? null : value
174                                         .getClass()
175                                         .getName()));
176                 }
177             }
178         }
179         return false;
180     }
181 
182     public Object next()
183     {
184         if (!hasNext())
185         {
186             throw new NoSuchElementException();
187         }
188         if(_nextItem != null)
189         {
190             Object value = _nextItem;
191             _nextItem = null;
192             return value;
193         }        
194         if (_nestedItems != null)
195         {
196             Object item = _nestedItems.next();
197             if (!(item instanceof SelectItem))
198             {
199                 ValueBinding binding = _currentUISelectItems
200                                 .getValueBinding("value");
201                 throw new IllegalArgumentException(
202                 _collectionLabel + " referenced by UISelectItems with binding '"
203                 + binding.getExpressionString()
204                 + "' and Component-Path : " + RendererUtils.getPathToComponent(_currentUISelectItems)
205                 + " does not contain Objects of type SelectItem");
206             }
207             return item;
208         }
209         throw new NoSuchElementException();
210     }
211 
212     public void remove()
213     {
214         throw new UnsupportedOperationException();
215     }
216 }