001: /*
002: * Copyright 2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package javax.faces.component;
017:
018: import javax.el.ValueExpression;
019: import javax.faces.FacesException;
020: import javax.faces.context.FacesContext;
021: import javax.faces.convert.Converter;
022: import javax.faces.convert.ConverterException;
023: import java.lang.reflect.Array;
024: import java.util.ArrayList;
025: import java.util.List;
026:
027: /**
028: * The util methods in this class are shared between the javax.faces.component package and
029: * the org.apache.myfaces.renderkit package.
030: * Please note: Any changes here must also apply to the class in the other package!
031: *
032: * @author Manfred Geiler (latest modification by $Author: baranda $)
033: * @version $Revision: 540250 $ $Date: 2007-05-21 21:38:49 +0200 (Mo, 21 Mai 2007) $
034: */
035: class _SharedRendererUtils {
036: static Converter findUIOutputConverter(FacesContext facesContext,
037: UIOutput component) {
038: // Attention!
039: // This code is duplicated in jsfapi component package.
040: // If you change something here please do the same in the other class!
041:
042: Converter converter = component.getConverter();
043: if (converter != null)
044: return converter;
045:
046: //Try to find out by value expression
047: ValueExpression expression = component
048: .getValueExpression("value");
049: if (expression == null)
050: return null;
051:
052: Class valueType = expression.getType(facesContext
053: .getELContext());
054: if (valueType == null)
055: return null;
056:
057: if (Object.class.equals(valueType))
058: return null; //There is no converter for Object class
059:
060: try {
061: return facesContext.getApplication().createConverter(
062: valueType);
063: } catch (FacesException e) {
064: log(facesContext, "No Converter for type "
065: + valueType.getName() + " found", e);
066: return null;
067: }
068: }
069:
070: static Object getConvertedUISelectManyValue(
071: FacesContext facesContext, UISelectMany component,
072: String[] submittedValue) throws ConverterException {
073: // Attention!
074: // This code is duplicated in jsfapi component package.
075: // If you change something here please do the same in the other class!
076:
077: if (submittedValue == null)
078: throw new NullPointerException("submittedValue");
079:
080: ValueExpression expression = component
081: .getValueExpression("value");
082: Class valueType = null;
083: Class arrayComponentType = null;
084: if (expression != null) {
085: valueType = expression.getType(facesContext.getELContext());
086: if (valueType != null && valueType.isArray()) {
087: arrayComponentType = valueType.getComponentType();
088: }
089: }
090:
091: Converter converter = component.getConverter();
092: if (converter == null) {
093: if (valueType == null) {
094: // No converter, and no idea of expected type
095: // --> return the submitted String array
096: return submittedValue;
097: }
098:
099: if (List.class.isAssignableFrom(valueType)) {
100: // expected type is a List
101: // --> according to javadoc of UISelectMany we assume that the element type
102: // is java.lang.String, and copy the String array to a new List
103: int len = submittedValue.length;
104: List lst = new ArrayList(len);
105: for (int i = 0; i < len; i++) {
106: lst.add(submittedValue[i]);
107: }
108: return lst;
109: }
110:
111: if (arrayComponentType == null) {
112: throw new IllegalArgumentException(
113: "ValueBinding for UISelectMany must be of type List or Array");
114: }
115:
116: if (Object.class.equals(arrayComponentType))
117: return submittedValue; //No conversion for Object class
118:
119: converter = facesContext.getApplication().createConverter(
120: arrayComponentType);
121:
122: if (converter == null) {
123: return submittedValue;
124: }
125: }
126:
127: // Now, we have a converter...
128: // We determine the type of the component array after converting one of it's elements
129: if (expression != null) {
130: valueType = expression.getType(facesContext.getELContext());
131: if (valueType != null && valueType.isArray()) {
132: if (submittedValue.length > 0) {
133: arrayComponentType = converter.getAsObject(
134: facesContext, component, submittedValue[0])
135: .getClass();
136: }
137: }
138: }
139:
140: if (valueType == null) {
141: // ...but have no idea of expected type
142: // --> so let's convert it to an Object array
143: int len = submittedValue.length;
144: Object[] convertedValues = (Object[]) Array.newInstance(
145: arrayComponentType == null ? Object.class
146: : arrayComponentType, len);
147: for (int i = 0; i < len; i++) {
148: convertedValues[i] = converter.getAsObject(
149: facesContext, component, submittedValue[i]);
150: }
151: return convertedValues;
152: }
153:
154: if (List.class.isAssignableFrom(valueType)) {
155: // Curious case: According to specs we should assume, that the element type
156: // of this List is java.lang.String. But there is a Converter set for this
157: // component. Because the user must know what he is doing, we will convert the values.
158: int len = submittedValue.length;
159: List lst = new ArrayList(len);
160: for (int i = 0; i < len; i++) {
161: lst.add(converter.getAsObject(facesContext, component,
162: submittedValue[i]));
163: }
164: return lst;
165: }
166:
167: if (arrayComponentType == null) {
168: throw new IllegalArgumentException(
169: "ValueBinding for UISelectMany must be of type List or Array");
170: }
171:
172: if (arrayComponentType.isPrimitive()) {
173: //primitive array
174: int len = submittedValue.length;
175: Object convertedValues = Array.newInstance(
176: arrayComponentType, len);
177: for (int i = 0; i < len; i++) {
178: Array.set(convertedValues, i, converter.getAsObject(
179: facesContext, component, submittedValue[i]));
180: }
181: return convertedValues;
182: }
183:
184: //Object array
185: int len = submittedValue.length;
186: ArrayList convertedValues = new ArrayList(len);
187: for (int i = 0; i < len; i++) {
188: convertedValues.add(i, converter.getAsObject(facesContext,
189: component, submittedValue[i]));
190: }
191: return convertedValues.toArray((Object[]) Array.newInstance(
192: arrayComponentType, len));
193: }
194:
195: /**
196: * This method is different in the two versions of _SharedRendererUtils.
197: */
198: private static void log(FacesContext context, String msg,
199: Exception e) {
200: context.getExternalContext().log(msg, e);
201: }
202: }
|