View Javadoc

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.myfaces.util;
17  
18  import java.util.ArrayList;
19  import java.util.Arrays;
20  import java.util.Collection;
21  import java.util.Iterator;
22  import java.util.Map;
23  import java.util.NoSuchElementException;
24  
25  import javax.faces.component.UIComponent;
26  import javax.faces.component.UISelectItem;
27  import javax.faces.component.UISelectItems;
28  import javax.faces.el.ValueBinding;
29  import javax.faces.model.SelectItem;
30  
31  import org.apache.myfaces.renderkit.RendererUtils;
32  
33  /***
34   * @author Mathias Broekelmann (latest modification by $Author$)
35   * @version $Revision$ $Date$
36   */
37  public class SelectItemsIterator implements Iterator
38  {
39      private final Iterator _childs;
40      private Iterator _nestedItems;
41      private Object _nextItem;
42      private String _collectionLabel;
43      private UISelectItems _currentUISelectItems;
44  
45      public SelectItemsIterator(UIComponent selectItemsParent)
46      {
47          _childs = selectItemsParent.getChildren().iterator();
48      }
49  
50      public boolean hasNext()
51      {
52          if(_nextItem != null)
53          {
54              return true;
55          }
56          if(_nestedItems != null)
57          {
58              if(_nestedItems.hasNext())
59              {
60                  return true;
61              }
62              _nestedItems = null;
63          }            
64          if (_childs.hasNext())
65          {
66              UIComponent child = (UIComponent) _childs.next();
67              if (child instanceof UISelectItem)
68              {
69                  UISelectItem uiSelectItem = (UISelectItem) child;
70                  Object item = uiSelectItem.getValue();
71                  if (item == null)
72                  {
73                      Object itemValue = ((UISelectItem) child).getItemValue();
74                      String label = ((UISelectItem) child).getItemLabel();
75                      String description = ((UISelectItem) child)
76                                      .getItemDescription();
77                      boolean disabled = ((UISelectItem) child).isItemDisabled();
78                      if (label == null)
79                      {
80                          label = itemValue.toString();
81                      }
82                      item = new SelectItem(itemValue, label, description,
83                                      disabled);
84                  }
85                  else if (!(item instanceof SelectItem))
86                  {
87                      ValueBinding binding = ((UISelectItem) child)
88                                      .getValueBinding("value");
89                      throw new IllegalArgumentException(
90                                      "Value binding '"
91                                      + (binding == null ? null : binding.getExpressionString())
92                                      + "' of UISelectItem : "
93                                      + RendererUtils.getPathToComponent(child)
94                                      + " does not reference an Object of type SelectItem");
95                  }
96                  _nextItem = item;
97                  return true;
98              }
99              else if (child instanceof UISelectItems)
100             {
101                 _currentUISelectItems = ((UISelectItems) child);
102                 Object value = _currentUISelectItems.getValue();
103 
104                 if (value instanceof SelectItem)
105                 {
106                     _nextItem = value;
107                     return true;
108                 }
109                 else if (value instanceof SelectItem[])
110                 {
111                     _nestedItems = Arrays.asList((SelectItem[]) value)
112                                     .iterator();
113                     _collectionLabel = "Array";
114                     return hasNext();
115                 }
116                 else if (value instanceof Collection)
117                 {
118                     _nestedItems = ((Collection)value).iterator();
119                     _collectionLabel = "Collection";
120                     return hasNext();
121                 }
122                 else if (value instanceof Map)
123                 {
124                     Map map = ((Map) value);
125                     Collection items = new ArrayList(map.size()); 
126                     for (Iterator it = map.entrySet().iterator(); it
127                                     .hasNext();)
128                     {
129                         Map.Entry entry = (Map.Entry) it.next();
130                         items.add(new SelectItem(entry.getValue(), entry
131                                         .getKey().toString()));
132                     }
133                     _nestedItems = items.iterator();
134                     _collectionLabel = "Map";
135                     return hasNext();
136                 }
137                 else
138                 {
139                     ValueBinding binding = _currentUISelectItems.getValueBinding("value");
140 
141                     throw new IllegalArgumentException(
142                         "Value binding '"
143                         + (binding == null ? null : binding
144                                         .getExpressionString())
145                         + "'of UISelectItems with component-path "
146                         + RendererUtils.getPathToComponent(child)
147                         + " does not reference an Object of type SelectItem, SelectItem[], Collection or Map but of type : "
148                         + ((value == null) ? null : value
149                                         .getClass()
150                                         .getName()));
151                 }
152             }
153             else
154             {
155                 //todo: may other objects than selectItems be nested or not?
156                 //log.error("Invalid component : " + getPathToComponent(child) + " : must be UISelectItem or UISelectItems, is of type : "+((child==null)?"null":child.getClass().getName()));
157             }
158         }
159         return false;
160     }
161 
162     public Object next()
163     {
164         if (!hasNext())
165         {
166             throw new NoSuchElementException();
167         }
168         if(_nextItem != null)
169         {
170             Object value = _nextItem;
171             _nextItem = null;
172             return value;
173         }        
174         if (_nestedItems != null)
175         {
176             Object item = _nestedItems.next();
177             if (!(item instanceof SelectItem))
178             {
179                 ValueBinding binding = _currentUISelectItems
180                                 .getValueBinding("value");
181                 throw new IllegalArgumentException(
182                 _collectionLabel + " referenced by UISelectItems with binding '"
183                 + binding.getExpressionString()
184                 + "' and Component-Path : " + RendererUtils.getPathToComponent(_currentUISelectItems)
185                 + " does not contain Objects of type SelectItem");
186             }
187             return item;
188         }
189         throw new NoSuchElementException();
190     }
191 
192     public void remove()
193     {
194         throw new UnsupportedOperationException();
195     }
196 }