docs: static Object getConvertedUISelectManyValue(FacesContext facesContext, UISelectMany component,  
              String[] submittedValue, boolean considerValueType) throws ConverterException
      {
          // Attention!
          // This code is duplicated in shared renderkit package (except for considerValueType).
          // If you change something here please do the same in the other class!
  
          if (submittedValue == null)
          {
              throw new NullPointerException("submittedValue");
          }
  
          ValueExpression expression = component.getValueExpression("value");
          Object targetForConvertedValues = null;
          
          // if the component has an attached converter, use it
          Converter converter = component.getConverter();
          // at this point the valueType attribute is handled in shared.
          if (converter == null && considerValueType)
          {
              // try to get a converter from the valueType attribute
              converter = getValueTypeConverter(facesContext, component);
          }
          
          if (expression != null)
          {
              Class<?> modelType = expression
                      .getType(facesContext.getELContext());
              if (modelType == null)
              {
                  // FIXME temporal workaround for MYFACES-2552
                  return submittedValue;
              }
              else if (modelType.isArray())
              {
                  // the target should be an array
                  Class<?> componentType = modelType.getComponentType();
                  // check for optimization if the target is
                  // a string array --> no conversion needed
                  if (String.class.equals(componentType))
                  {
                      return submittedValue;
                  }
                  if (converter == null)
                  {
                      // the compononent does not have an attached converter
                      // --> try to get a registered-by-class converter
                      converter = facesContext.getApplication().createConverter(
                              componentType);
  
                      if (converter == null && !Object.class.equals(componentType))
                      {
                          // could not obtain a Converter
                          // --> check if we maybe do not really have to convert
  
                          // target is not an Object array
                          // and not a String array (checked some lines above)
                          // and we do not have a Converter
                          throw new ConverterException(
                                  "Could not obtain a Converter for "
                                          + componentType.getName());
                      }
                  }
                  // instantiate the array
                  targetForConvertedValues = Array.newInstance(componentType,
                          submittedValue.length);
              }
              else if (Collection.class.isAssignableFrom(modelType) || Object.class.equals(modelType))
              {
                  if (converter == null)
                  {
                      // try to get the by-type-converter from the type of the SelectItems
                      _SelectItemsIterator iterator = new _SelectItemsIterator(component, facesContext);
                      converter = getSelectItemsValueConverter(iterator, facesContext);
                  }
  
                  Object collectionTypeAttr = component.getAttributes().get(
                          COLLECTION_TYPE_KEY);
                  if (collectionTypeAttr != null)
                  {
                      Class<?> collectionType = getClassFromAttribute(facesContext, collectionTypeAttr);
                      if (collectionType == null)
                      {
                          throw new FacesException(
                                  "The attribute "
                                          + COLLECTION_TYPE_KEY
                                          + " of component "
                                          + component.getClientId(facesContext)
                                          + " does not evaluate to a "
                                          + "String, a Class object or a ValueExpression pointing "
                                          + "to a String or a Class object.");
                      }
                      // now we have a collectionType --> but is it really some kind of Collection
                      if (!Collection.class.isAssignableFrom(collectionType))
                      {
                          throw new FacesException("The attribute "
                                  + COLLECTION_TYPE_KEY + " of component "
                                  + component.getClientId(facesContext)
                                  + " does not point to a valid type of Collection.");
                      }
                      // now we have a real collectionType --> try to instantiate it
                      try
                      {
                          targetForConvertedValues = collectionType.newInstance();
                      }
                      catch (Exception e)
                      {
                          throw new FacesException("The Collection "
                                  + collectionType.getName()
                                  + "can not be instantiated.", e);
                      }
                  }
                  else if (Collection.class.isAssignableFrom(modelType))
                  {
                      // component.getValue() will implement Collection at this point
                      Collection<?> componentValue = (Collection<?>) component
                              .getValue();
                      // can we clone the Collection
                      if (componentValue instanceof Cloneable)
                      {
                          // clone method of Object is protected --> use reflection
                          try
                          {
                              Method cloneMethod = componentValue.getClass()
                                      .getMethod("clone");
                              Collection<?> clone = (Collection<?>) cloneMethod
                                      .invoke(componentValue);
                              clone.clear();
                              targetForConvertedValues = clone;
                          }
                          catch (Exception e)
                          {
                              log(facesContext, "Could not clone "
                                      + componentValue.getClass().getName(), e);
                          }
                      }
  
                      // if clone did not work
                      if (targetForConvertedValues == null)
                      {
                          // try to create the (concrete) collection from modelType 
                          // or with the class object of componentValue (if any)
                          try
                          {
                              targetForConvertedValues = (componentValue != null 
                                      ? componentValue.getClass()
                                      : modelType).newInstance();
                          }
                          catch (Exception e)
                          {
                              // this did not work either
                              // use the standard concrete type
                              if (SortedSet.class.isAssignableFrom(modelType))
                              {
                                  targetForConvertedValues = new TreeSet();
                              }
                              else if (Queue.class.isAssignableFrom(modelType))
                              {
                                  targetForConvertedValues = new LinkedList();
                              }
                              else if (Set.class.isAssignableFrom(modelType))
                              {
                                  targetForConvertedValues = new HashSet(
                                          submittedValue.length);
                              }
                              else
                              {
                                  targetForConvertedValues = new ArrayList(
                                          submittedValue.length);
                              }
                          }
                      }
                  }
                  else /* if (Object.class.equals(modelType)) */
                  {
                      // a modelType of Object is also permitted, in order to support
                      // managed bean properties of type Object
                      
                      // optimization: if we don't have a converter, we can return the submittedValue
                      if (converter == null)
                      {
                          return submittedValue;
                      }
                      
                      targetForConvertedValues = new Object[submittedValue.length];
                  }
              }
              else
              {
                  // the expression does neither point to an array nor to a collection
                  throw new ConverterException(
                          "ValueExpression for UISelectMany must be of type Collection or Array.");
              }
          }
          else
          {
              targetForConvertedValues = new Object[submittedValue.length];
          }
  
          // convert the values with the selected converter (if any)
          // and store them in targetForConvertedValues
          boolean isArray = (targetForConvertedValues.getClass().isArray());
          for (int i = 0; i < submittedValue.length; i++)
          {
              // get the value
              Object value;
              if (converter != null)
              {
                  value = converter.getAsObject(facesContext, component,
                          submittedValue[i]);
              }
              else
              {
                  value = submittedValue[i];
              }
              // store it in targetForConvertedValues
              if (isArray)
              {
                  Array.set(targetForConvertedValues, i, value);
              }
              else
              {
                  ((Collection) targetForConvertedValues).add(value);
              }
          }
  
          return targetForConvertedValues;
      }