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 }