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 javax.faces.component;
20  
21  import java.util.*;
22  import javax.faces.el.ValueBinding;
23  import javax.faces.model.SelectItem;
24  
25  
26  /**
27   * @author Mathias Broekelmann (latest modification by $Author: lu4242 $)
28   * @version $Revision: 682489 $ $Date: 2008-08-04 15:22:15 -0500 (Mon, 04 Aug 2008) $
29   */
30  class _SelectItemsIterator implements Iterator
31  {
32      private final Iterator _childs;
33      private Iterator<SelectItem> _nestedItems;    
34      private Object _nextItem;
35      private String _collectionLabel;
36      private UISelectItems _currentUISelectItems;
37  
38      public _SelectItemsIterator(UIComponent selectItemsParent)
39      {
40          _childs = selectItemsParent.getChildren().iterator();
41      }
42  
43      public boolean hasNext()
44      {
45          if(_nextItem != null)
46          {
47              return true;
48          }
49          if(_nestedItems != null)
50          {
51              if(_nestedItems.hasNext())
52              {
53                  return true;
54              }
55              _nestedItems = null;
56          }            
57          if (_childs.hasNext())
58          {
59              UIComponent child = (UIComponent) _childs.next();
60              // When there is other components nested that does
61              // not extends from UISelectItem or UISelectItems
62              // the behavior for this iterator is just skip this
63              // element(s) until an element that extends from these
64              // classes are found. If there is no more elements
65              // that conform this condition, just return false.
66              while (!(child instanceof UISelectItem)
67                      && !(child instanceof UISelectItems))
68              {
69                  //Try to skip it
70                  if (_childs.hasNext())
71                  {
72                      //Skip and do the same check
73                      child = (UIComponent) _childs.next();
74                  }
75                  else
76                  {
77                      //End loop, so the final result is return false,
78                      //since there are no more components to iterate.
79                      return false;
80                  }
81              }
82              if (child instanceof UISelectItem)
83              {
84                  UISelectItem uiSelectItem = (UISelectItem) child;
85                  Object item = uiSelectItem.getValue();
86                  if (item == null)
87                  {
88                      Object itemValue = ((UISelectItem) child).getItemValue();
89                      String label = ((UISelectItem) child).getItemLabel();
90                      String description = ((UISelectItem) child)
91                                      .getItemDescription();
92                      boolean disabled = ((UISelectItem) child).isItemDisabled();
93                      if (label == null)
94                      {
95                          label = itemValue.toString();
96                      }
97                      item = new SelectItem(itemValue, label, description,
98                                      disabled);
99                  }
100                 else if (!(item instanceof SelectItem))
101                 {
102                     ValueBinding binding = ((UISelectItem) child)
103                                     .getValueBinding("value");
104                     throw new IllegalArgumentException(
105                                     "Value binding '"
106                                     + (binding == null ? null : binding.getExpressionString())
107                                     + "' of UISelectItem : "
108                                     + getPathToComponent(child)
109                                     + " does not reference an Object of type SelectItem");
110                 }
111                 _nextItem = item;
112                 return true;
113             }
114             else if (child instanceof UISelectItems)
115             {
116                 _currentUISelectItems = ((UISelectItems) child);
117                 Object value = _currentUISelectItems.getValue();
118 
119                 if (value instanceof SelectItem)
120                 {
121                     _nextItem = value;
122                     return true;
123                 }
124                 else if (value instanceof SelectItem[])
125                 {
126                     _nestedItems = Arrays.asList((SelectItem[]) value)
127                                     .iterator();
128                     _collectionLabel = "Array";
129                     return hasNext();
130                 }
131                 else if (value instanceof Collection)
132                 {
133                     _nestedItems = ((Collection<SelectItem>)value).iterator();
134                     _collectionLabel = "Collection";
135                     return hasNext();
136                 }
137                 else if (value instanceof Map)
138                 {
139                     Map map = ((Map) value);
140                     Collection<SelectItem> items = new ArrayList<SelectItem>(map.size()); 
141                     for (Iterator it = map.entrySet().iterator(); it
142                                     .hasNext();)
143                     {
144                         Map.Entry entry = (Map.Entry) it.next();
145                         items.add(new SelectItem(entry.getValue(), entry
146                                         .getKey().toString()));
147                     }
148                     _nestedItems = items.iterator();
149                     _collectionLabel = "Map";
150                     return hasNext();
151                 }
152                 else
153                 {
154                     ValueBinding binding = _currentUISelectItems.getValueBinding("value");
155 
156                     throw new IllegalArgumentException(
157                         "Value binding '"
158                         + (binding == null ? null : binding
159                                         .getExpressionString())
160                         + "'of UISelectItems with component-path "
161                         + getPathToComponent(child)
162                         + " does not reference an Object of type SelectItem, SelectItem[], Collection or Map but of type : "
163                         + ((value == null) ? null : value
164                                         .getClass()
165                                         .getName()));
166                 }
167             }
168         }
169         return false;
170     }
171 
172     public Object next()
173     {
174         if (!hasNext())
175         {
176             throw new NoSuchElementException();
177         }
178         if(_nextItem != null)
179         {
180             Object value = _nextItem;
181             _nextItem = null;
182             return value;
183         }        
184         if (_nestedItems != null)
185         {
186             Object item = _nestedItems.next();
187             if (!(item instanceof SelectItem))
188             {
189                 ValueBinding binding = _currentUISelectItems
190                                 .getValueBinding("value");
191                 throw new IllegalArgumentException(
192                 _collectionLabel + " referenced by UISelectItems with binding '"
193                 + binding.getExpressionString()
194                 + "' and Component-Path : " + getPathToComponent(_currentUISelectItems)
195                 + " does not contain Objects of type SelectItem");
196             }
197             return item;
198         }
199         throw new NoSuchElementException();
200     }
201 
202     public void remove()
203     {
204         throw new UnsupportedOperationException();
205     }
206 
207 
208     private String getPathToComponent(UIComponent component)
209     {
210         StringBuffer buf = new StringBuffer();
211 
212         if(component == null)
213         {
214             buf.append("{Component-Path : ");
215             buf.append("[null]}");
216             return buf.toString();
217         }
218 
219         getPathToComponent(component,buf);
220 
221         buf.insert(0,"{Component-Path : ");
222         buf.append("}");
223 
224         return buf.toString();
225     }
226 
227     private void getPathToComponent(UIComponent component, StringBuffer buf)
228     {
229         if(component == null)
230             return;
231 
232         StringBuffer intBuf = new StringBuffer();
233 
234         intBuf.append("[Class: ");
235         intBuf.append(component.getClass().getName());
236         if(component instanceof UIViewRoot)
237         {
238             intBuf.append(",ViewId: ");
239             intBuf.append(((UIViewRoot) component).getViewId());
240         }
241         else
242         {
243             intBuf.append(",Id: ");
244             intBuf.append(component.getId());
245         }
246         intBuf.append("]");
247 
248         buf.insert(0,intBuf);
249 
250         if(component!=null)
251         {
252             getPathToComponent(component.getParent(),buf);
253         }
254     }
255 }