View Javadoc

1   // WARNING: This file was automatically generated. Do not edit it directly,
2   //          or you will lose your changes.
3   
4   /*
5    * Licensed to the Apache Software Foundation (ASF) under one
6    * or more contributor license agreements.  See the NOTICE file
7    * distributed with this work for additional information
8    * regarding copyright ownership.  The ASF licenses this file
9    * to you under the Apache License, Version 2.0 (the
10   * "License"); you may not use this file except in compliance
11   * with the License.  You may obtain a copy of the License at
12   *
13   *   http://www.apache.org/licenses/LICENSE-2.0
14   *
15   * Unless required by applicable law or agreed to in writing,
16   * software distributed under the License is distributed on an
17   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18   * KIND, either express or implied.  See the License for the
19   * specific language governing permissions and limitations
20   * under the License.
21  */
22  package org.apache.myfaces.trinidad.component;
23  
24  import java.lang.reflect.Array;
25  import java.util.ArrayList;
26  import java.util.Collection;
27  import java.util.List;
28  import javax.faces.context.FacesContext;
29  import org.apache.myfaces.trinidad.bean.FacesBean;
30  import org.apache.myfaces.trinidad.logging.TrinidadLogger;
31  
32  /**
33   *
34   * UIXSelectMany is a base abstraction for 
35   *           components that allow selection of multiple of a
36   *     series of selectItem controls, where order
37   *           is not relevant.
38   *           selectOne controls may contain any number of
39   *           <f:selectItem>, <f:selectItems>, or
40   *     <tr:selectItem> components.
41   *
42   * <h4>Events:</h4>
43   * <table border="1" width="100%" cellpadding="3" summary="">
44   * <tr bgcolor="#CCCCFF" class="TableHeadingColor">
45   * <th align="left">Type</th>
46   * <th align="left">Phases</th>
47   * <th align="left">Description</th>
48   * </tr>
49   * <tr class="TableRowColor">
50   * <td valign="top"><code>javax.faces.event.ValueChangeEvent</code></td>
51   * <td valign="top" nowrap>Process<br>Validations<br>Apply<br>Request<br>Values</td>
52   * <td valign="top">The valueChange event is delivered when the value
53                         attribute is changed.</td>
54   * </tr>
55   * <tr class="TableRowColor">
56   * <td valign="top"><code>org.apache.myfaces.trinidad.event.AttributeChangeEvent</code></td>
57   * <td valign="top" nowrap>Invoke<br>Application<br>Apply<br>Request<br>Values</td>
58   * <td valign="top">Event delivered to describe an attribute change.  Attribute change events are not delivered for any programmatic change to a property.  They are only delivered when a renderer changes a property without the application's specific request.  An example of an attribute change event might include the width of a column that supported client-side resizing.</td>
59   * </tr>
60   * </table>
61   */
62  public class UIXSelectMany extends UIXEditableValue
63  {
64    static public final FacesBean.Type TYPE = new FacesBean.Type(
65      UIXEditableValue.TYPE);
66  
67    static public final String COMPONENT_FAMILY =
68      "org.apache.myfaces.trinidad.SelectMany";
69    static public final String COMPONENT_TYPE =
70      "org.apache.myfaces.trinidad.SelectMany";
71  
72    /**
73     * Construct an instance of the UIXSelectMany.
74     */
75    public UIXSelectMany()
76    {
77      super("org.apache.myfaces.trinidad.Listbox");
78    }
79    
80  
81    static public final String REQUIRED_MESSAGE_ID =
82      "org.apache.myfaces.trinidad.UIXSelectMany.REQUIRED";
83    static public final String UNSUPPORTED_MODEL_TYPE_MESSAGE_ID =
84      "org.apache.myfaces.trinidad.UIXSelectMany.UNSUPPORTED_MODEL_TYPE";
85  
86  
87    /**
88     * Compares two values, disregarding the order of the elements.
89     */
90    // TODO walk through UIXSelectItem values to determine that new
91    //       values are permitted
92    @Override
93    protected void validateValue(FacesContext context, Object newValue)
94    {
95      super.validateValue(context, newValue);
96    }
97  
98    @Override
99    protected boolean isEmpty(Object value)
100   {
101     if (value == null)
102       return true;
103 
104     if (value instanceof Collection)
105       return ((Collection) value).isEmpty();
106 
107     if (value.getClass().isArray())
108       return Array.getLength(value) == 0;
109 
110     return false;
111   }
112 
113   @Override
114   protected String getRequiredMessageKey()
115   {
116     return REQUIRED_MESSAGE_ID;
117   }
118 
119   /**
120    * @return true if the values are different
121    */
122   // TODO improve efficiency
123   @Override
124   protected boolean compareValues(Object previous, Object value)
125   {
126     int prevSize = __getSize(previous);
127     int newSize = __getSize(value);
128 
129     // If the sizes are different, no need to bother with further work
130     if (prevSize != newSize)
131       return true;
132 
133     // If the sizes are the same, and they're empty, we're also done.
134     if (prevSize == 0)
135       return false;
136 
137     List<Object> prevList = __toList(previous);
138     List<Object> newList = __toList(value);
139     return _destructiveCompareOutOfOrderLists(prevList, newList);
140   }
141 
142   //
143   // Return the size of each list
144   //
145   static int __getSize(Object o)
146   {
147     if (o == null)
148       return 0;
149 
150     if (o instanceof Collection)
151       return ((Collection) o).size();
152 
153     if (o.getClass().isArray())
154       return Array.getLength(o);
155 
156     if (_LOG.isFine())
157       _LOG.fine("Type " + o.getClass() +
158                 " is not a supported List model type");
159     return 0;
160   }
161 
162   //
163   // Compare two Lists in an order-independent fashion, possibly
164   // mutating one or the other list.
165   //
166   static private boolean _destructiveCompareOutOfOrderLists(
167     List<Object> one,
168     List<Object> two)
169   {
170     int size = one.size();
171 
172     // Assert the two sizes are the same, since we should
173     // have eliminated that possibility earlier
174     assert(one.size() == two.size());
175 
176     for (int i = 0; i < size; i++)
177     {
178       Object o = one.get(i);
179       int indexOf = two.indexOf(o);
180       if (indexOf < 0)
181         return true;
182 
183       two.remove(indexOf);
184     }
185 
186     return false;
187   }
188 
189   //
190   // Convert an Object to a mutable, copied List;  copied
191   // because our compare routine is destructive.
192   //
193   @SuppressWarnings("unchecked")
194   static List<Object> __toList(Object o)
195   {
196     if (o == null)
197       return null;
198 
199     ArrayList<Object> listCopy = new ArrayList<Object>();
200     if (o instanceof Collection)
201     {
202       listCopy.addAll((Collection<Object>) o);
203     }
204     // Use java.lang.reflect.Array, etc. to support primitive Object arrays
205     else if (o.getClass().isArray())
206     {
207       int length = Array.getLength(o);
208       listCopy.ensureCapacity(length);
209       for (int i = 0; i < length; i++)
210       {
211         listCopy.add(Array.get(o, i));
212       }
213     }
214     else
215     {
216       // Already logged in __getSize(), so let it slide here
217       ;
218     }
219 
220     return listCopy;
221   }
222 
223   static private final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(UIXSelectMany.class);
224 
225   @Override
226   public String getFamily()
227   {
228     return COMPONENT_FAMILY;
229   }
230 
231   @Override
232   protected FacesBean.Type getBeanType()
233   {
234     return TYPE;
235   }
236 
237   /**
238    * Construct an instance of the UIXSelectMany.
239    */
240   protected UIXSelectMany(
241     String rendererType
242     )
243   {
244     super(rendererType);
245   }
246 
247   static
248   {
249     TYPE.lockAndRegister("org.apache.myfaces.trinidad.SelectMany","org.apache.myfaces.trinidad.Listbox");
250   }
251 }