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 org.apache.myfaces.shared_orchestra.renderkit;
    20
    21  import org.apache.commons.logging.Log;
    22  import org.apache.commons.logging.LogFactory;
    23
    24  import javax.faces.FacesException;
    25  import javax.faces.component.UIOutput;
    26  import javax.faces.component.UISelectMany;
    27  import javax.faces.context.FacesContext;
    28  import javax.faces.convert.Converter;
    29  import javax.faces.convert.ConverterException;
    30  import javax.faces.el.ValueBinding;
    31  import java.lang.reflect.Array;
    32  import java.util.ArrayList;
    33  import java.util.List;
    34
    35  /**
    36   * The util methods in this class are shared between the javax.faces.component package and
    37   * the org.apache.myfaces.renderkit package.
    38   * Please note: Any changes here must also apply to the class in the other package!
    39   *
    40   * @author Manfred Geiler (latest modification by $Author: grantsmith $)
    41   * @version $Revision: 472618 $ $Date: 2006-11-08 15:06:54 -0500 (Wed, 08 Nov 2006) $
    42   */
    43  class _SharedRendererUtils
    44  {
    45      static Converter findUIOutputConverter(FacesContext facesContext, UIOutput component)
    46      {
    47          // Attention!
    48          // This code is duplicated in jsfapi component package.
    49          // If you change something here please do the same in the other class!
    50
    51          Converter converter = component.getConverter();
    52          if (converter != null) return converter;
    53
    54          //Try to find out by value binding
    55          ValueBinding vb = component.getValueBinding("value");
    56          if (vb == null) return null;
    57
    58          Class valueType = vb.getType(facesContext);
    59          if (valueType == null) return null;
    60
    61          if (String.class.equals(valueType)) return null;    //No converter needed for String type
    62          if (Object.class.equals(valueType)) return null;    //There is no converter for Object class
    63
    64          try
    65          {
    66              return facesContext.getApplication().createConverter(valueType);
    67          }
    68          catch (FacesException e)
    69          {
    70              log(facesContext, "No Converter for type " + valueType.getName() + " found", e);
    71              return null;
    72          }
    73      }
    74
    75      static Object getConvertedUISelectManyValue(FacesContext facesContext,
    76                                                  UISelectMany component,
    77                                                  String[] submittedValue)
    78              throws ConverterException
    79      {
    80          // Attention!
    81          // This code is duplicated in jsfapi component package.
    82          // If you change something here please do the same in the other class!
    83
    84          if (submittedValue == null) throw new NullPointerException("submittedValue");
    85
    86          ValueBinding vb = component.getValueBinding("value");
    87          Class valueType = null;
    88          Class arrayComponentType = null;
    89          if (vb != null)
    90          {
    91              valueType = vb.getType(facesContext);
    92              if (valueType != null && valueType.isArray())
    93              {
    94                  arrayComponentType = valueType.getComponentType();
    95              }
    96          }
    97
    98          Converter converter = component.getConverter();
    99          if (converter == null)
    100         {
    101             if (valueType == null)
    102             {
    103                 // No converter, and no idea of expected type
    104                 // --> return the submitted String array
    105                 return submittedValue;
    106             }
    107
    108             if (List.class.isAssignableFrom(valueType))
    109             {
    110                 // expected type is a List
    111                 // --> according to javadoc of UISelectMany we assume that the element type
    112                 //     is java.lang.String, and copy the String array to a new List
    113                 int len = submittedValue.length;
    114                 List lst = new ArrayList(len);
    115                 for (int i = 0; i < len; i++)
    116                 {
    117                     lst.add(submittedValue[i]);
    118                 }
    119                 return lst;
    120             }
    121
    122             if (arrayComponentType == null)
    123             {
    124                 throw new IllegalArgumentException("ValueBinding for UISelectMany must be of type List or Array");
    125             }
    126
    127             if (String.class.equals(arrayComponentType)) return submittedValue; //No conversion needed for String type
    128             if (Object.class.equals(arrayComponentType)) return submittedValue; //No conversion for Object class
    129
    130             try
    131             {
    132                 converter = facesContext.getApplication().createConverter(arrayComponentType);
    133             }
    134             catch (FacesException e)
    135             {
    136                 log(facesContext, "No Converter for type " + arrayComponentType.getName() + " found", e);
    137                 return submittedValue;
    138             }
    139             if(converter==null)
    140             {
    141                 log(facesContext, "No Converter for type " + arrayComponentType.getName() + " found.",null);
    142                 return submittedValue;
    143             }
    144         }
    145
    146         // Now, we have a converter...
    147         // We determine the type of the component array after converting one of it's elements
    148         if (vb != null)
    149         {
    150             valueType = vb.getType(facesContext);
    151             if (valueType != null && valueType.isArray())
    152             {
    153                 if (submittedValue.length > 0)
    154                 {
    155                     arrayComponentType = converter.getAsObject(facesContext, component, submittedValue[0]).getClass();
    156                 }
    157             }
    158         }
    159
    160         if (valueType == null)
    161         {
    162             // ...but have no idea of expected type
    163             // --> so let's convert it to an Object array
    164             int len = submittedValue.length;
    165             Object [] convertedValues = (Object []) Array.newInstance(
    166                     arrayComponentType==null?Object.class:arrayComponentType,len);
    167             for (int i = 0; i < len; i++)
    168             {
    169                 convertedValues[i]
    170                     = converter.getAsObject(facesContext, component, submittedValue[i]);
    171             }
    172             return convertedValues;
    173         }
    174
    175         if (List.class.isAssignableFrom(valueType))
    176         {
    177             // Curious case: According to specs we should assume, that the element type
    178             // of this List is java.lang.String. But there is a Converter set for this
    179             // component. Because the user must know what he is doing, we will convert the values.
    180             int len = submittedValue.length;
    181             List lst = new ArrayList(len);
    182             for (int i = 0; i < len; i++)
    183             {
    184                 lst.add(converter.getAsObject(facesContext, component, submittedValue[i]));
    185             }
    186             return lst;
    187         }
    188
    189         if (arrayComponentType == null)
    190         {
    191             throw new IllegalArgumentException("ValueBinding for UISelectMany must be of type List or Array");
    192         }
    193
    194         if (arrayComponentType.isPrimitive())
    195         {
    196             //primitive array
    197             int len = submittedValue.length;
    198             Object convertedValues = Array.newInstance(arrayComponentType, len);
    199             for (int i = 0; i < len; i++)
    200             {
    201                 Array.set(convertedValues, i,
    202                           converter.getAsObject(facesContext, component, submittedValue[i]));
    203             }
    204             return convertedValues;
    205         }
    206         else
    207         {
    208             //Object array
    209             int len = submittedValue.length;
    210             ArrayList convertedValues = new ArrayList(len);
    211             for (int i = 0; i < len; i++)
    212             {
    213                 convertedValues.add(i, converter.getAsObject(facesContext, component, submittedValue[i]));
    214             }
    215             return convertedValues.toArray((Object[]) Array.newInstance(arrayComponentType, len));
    216         }
    217     }
    218
    219
    220
    221     private static final Log log = LogFactory.getLog(_SharedRendererUtils.class);
    222
    223     /**
    224      * This method is different in the two versions of _SharedRendererUtils.
    225      */
    226     private static void log(FacesContext context, String msg, Exception e)
    227     {
    228         if(e!=null)
    229         {
    230             log.error(msg, e);
    231         }
    232         else
    233         {
    234             log.error(msg);
    235         }
    236     }
    237 }