[seam-commits] Seam SVN: r9191 - in trunk: src/main/org/jboss/seam and 2 other directories.

seam-commits at lists.jboss.org seam-commits at lists.jboss.org
Sat Oct 4 11:23:25 EDT 2008


Author: pete.muir at jboss.org
Date: 2008-10-04 11:23:25 -0400 (Sat, 04 Oct 2008)
New Revision: 9191

Modified:
   trunk/doc/Seam_Reference_Guide/en-US/Xml.xml
   trunk/src/main/org/jboss/seam/Component.java
   trunk/src/main/org/jboss/seam/components-2.1.xsd
   trunk/src/main/org/jboss/seam/init/Initialization.java
   trunk/src/main/org/jboss/seam/util/Conversions.java
Log:
JBSEAM-3460

Modified: trunk/doc/Seam_Reference_Guide/en-US/Xml.xml
===================================================================
--- trunk/doc/Seam_Reference_Guide/en-US/Xml.xml	2008-10-04 14:46:32 UTC (rev 9190)
+++ trunk/doc/Seam_Reference_Guide/en-US/Xml.xml	2008-10-04 15:23:25 UTC (rev 9191)
@@ -333,6 +333,24 @@
 </component>]]></programlisting>
 
             <para> 
+                When configuring multi-valued properties, by default, Seam will preserve the order in which you place the attributes
+                in <literal>components.xml</literal> (unless you use a <literal>SortedSet</literal>/<literal>SortedMap</literal>
+                then Seam will use <literal>TreeMap</literal>/<literal>TreeSet</literal>). If the property has a concrete type (for 
+                example <literal>LinkedList</literal> Seam will use that type.
+            </para>
+            <para> 
+                You can also override the type by specifying a fully qualified class name:
+            </para>
+
+            <programlisting role="XML"><![CDATA[<component name="issueEditor">
+   <property name="issueStatusOptions" type="java.util.LinkedHashMap">
+      <key>open</key> <value>open issue</value>
+      <key>resolved</key> <value>issue resolved by developer</value>
+      <key>closed</key> <value>resolution accepted by user</value>
+   </property>
+</component>]]></programlisting>
+
+            <para> 
                 Finally, you may wire together components using a value-binding expression. Note that this is quite
                 different to injection using <literal>@In</literal>, since it happens at component instantiation time
                 instead of invocation time. It is therefore much more similar to the dependency injection facilities

Modified: trunk/src/main/org/jboss/seam/Component.java
===================================================================
--- trunk/src/main/org/jboss/seam/Component.java	2008-10-04 14:46:32 UTC (rev 9190)
+++ trunk/src/main/org/jboss/seam/Component.java	2008-10-04 15:23:25 UTC (rev 9191)
@@ -41,9 +41,15 @@
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.TreeSet;
 
 import javassist.util.proxy.MethodFilter;
 import javassist.util.proxy.MethodHandler;
@@ -2450,7 +2456,7 @@
          }
          else if (converter!=null && value instanceof String[])
          {
-            return converter.toObject( new Conversions.MultiPropertyValue( (String[]) value ), parameterType );
+            return converter.toObject( new Conversions.MultiPropertyValue( (String[]) value, null), parameterType );
          }
          else
          {
@@ -2480,12 +2486,21 @@
    {
       private InitialValue[] initialValues;
       private Class elementType;
-
+      private Class collectionClass;
+      
       public SetInitialValue(PropertyValue propertyValue, Class collectionClass, Type collectionType)
       {
          String[] expressions = propertyValue.getMultiValues();
          initialValues = new InitialValue[expressions.length];
          elementType = Reflections.getCollectionElementType(collectionType);
+         if (propertyValue.getType() != null)
+         {
+            this.collectionClass = propertyValue.getType();
+         }
+         else
+         {
+            this.collectionClass = collectionClass;
+         }
          for ( int i=0; i<expressions.length; i++ )
          {
             PropertyValue elementValue = new Conversions.FlatPropertyValue( expressions[i] );
@@ -2495,10 +2510,43 @@
 
       public Object getValue(Class type)
       {
-          Set set = new HashSet(initialValues.length);
-          for (InitialValue iv: initialValues) {
-              set.add( iv.getValue(elementType) );
+          Set set;
+          //if no configuration has been specified then we first see if
+          //the property is an abstract type, if so we create it using newInstance
+          if (Modifier.isAbstract(collectionClass.getModifiers()) || Modifier.isInterface(collectionClass.getModifiers()))
+          {
+             if(collectionClass == SortedSet.class)
+             {
+                set = new TreeSet();
+             }
+             else
+             {
+                set = new LinkedHashSet(initialValues.length);
+             }
           }
+          else
+          {
+             try
+             {
+                set = (Set) collectionClass.newInstance();
+             }
+             catch (IllegalAccessException e)
+             {
+                throw new IllegalArgumentException("Cannot instantiate a set of type " + collectionClass + "; try specifying type type in components.xml");
+             }
+             catch (ClassCastException e)
+             {
+                throw new IllegalArgumentException("Cannot cast " + collectionClass + " to java.util.Set");
+             }
+             catch (java.lang.InstantiationException e)
+             {
+                throw new IllegalArgumentException("Cannot instantiate a set of type " + collectionClass + "; try specifying type type in components.xml");
+             }
+          }
+          for (InitialValue iv: initialValues) 
+          {
+             set.add( iv.getValue(elementType) );
+          }
           return set;
       }
       
@@ -2514,6 +2562,7 @@
       private InitialValue[] initialValues;
       private Class elementType;
       private boolean isArray;
+      private Class collectionClass;
 
       public ListInitialValue(PropertyValue propertyValue, Class collectionClass, Type collectionType)
       {
@@ -2523,6 +2572,14 @@
          elementType = isArray ? 
                   collectionClass.getComponentType() : 
                   Reflections.getCollectionElementType(collectionType);
+         if (propertyValue.getType() != null)
+         {
+            this.collectionClass = propertyValue.getType();
+         }
+         else
+         {
+            this.collectionClass = collectionClass;
+         }
          for ( int i=0; i<expressions.length; i++ )
          {
             PropertyValue elementValue = new Conversions.FlatPropertyValue( expressions[i] );
@@ -2543,7 +2600,32 @@
          }
          else
          {
-            List list = new ArrayList(initialValues.length);
+            List list;
+            //if no configuration has been specified then we first see if
+            //the property is an abstract type, if so we create it using newInstance
+            if (Modifier.isAbstract(collectionClass.getModifiers()) || Modifier.isInterface(collectionClass.getModifiers()))
+            {
+               list = new ArrayList(initialValues.length);
+            }
+            else
+            {
+               try
+               {
+                  list = (List) collectionClass.newInstance();
+               }
+               catch (IllegalAccessException e)
+               {
+                  throw new IllegalArgumentException("Cannot instantiate a list of type " + collectionClass + "; try specifying type type in components.xml");
+               }
+               catch (ClassCastException e)
+               {
+                  throw new IllegalArgumentException("Cannot cast " + collectionClass + " to java.util.List");
+               }
+               catch (java.lang.InstantiationException e)
+               {
+                  throw new IllegalArgumentException("Cannot instantiate a list of type " + collectionClass + "; try specifying type type in components.xml");
+               }
+            }
             for (InitialValue iv: initialValues)
             {
                list.add( iv.getValue(elementType) );
@@ -2565,13 +2647,22 @@
       private Map<InitialValue, InitialValue> initialValues;
       private Class elementType;
       private Class keyType;
-
+      private Class collectionClass;
+      
       public MapInitialValue(PropertyValue propertyValue, Class collectionClass, Type collectionType)
       {
          Map<String, String> expressions = propertyValue.getKeyedValues();
-         initialValues = new HashMap<InitialValue, InitialValue>(expressions.size());
+         initialValues = new LinkedHashMap<InitialValue, InitialValue>(expressions.size());      
          elementType = Reflections.getCollectionElementType(collectionType);
          keyType = Reflections.getMapKeyType(collectionType);
+         if (propertyValue.getType() != null )
+         {
+            this.collectionClass = propertyValue.getType();
+         }
+         else
+         {
+            this.collectionClass = collectionClass;
+         }
          for ( Map.Entry<String, String> me: expressions.entrySet() )
          {
             PropertyValue keyValue = new Conversions.FlatPropertyValue( me.getKey() );
@@ -2582,7 +2673,38 @@
 
       public Object getValue(Class type)
       {
-         Map result = new HashMap(initialValues.size());
+         Map result;
+         if (Modifier.isAbstract(collectionClass.getModifiers()) || Modifier.isInterface(collectionClass.getModifiers()))
+         {
+            if (collectionClass == SortedMap.class)
+            {
+               result = new TreeMap();
+            }
+            else
+            {
+               result = new LinkedHashMap(initialValues.size());
+            }
+         }
+         else
+         {
+            try
+            {
+               result = (Map) collectionClass.newInstance();
+            }
+            catch (IllegalAccessException e)
+            {
+               throw new IllegalArgumentException("Cannot instantiate a map of type " + collectionClass + "; try specifying type type in components.xml");
+            }
+            catch (ClassCastException e)
+            {
+               throw new IllegalArgumentException("Cannot cast " + collectionClass + " to java.util.Map");
+            }
+            catch (java.lang.InstantiationException e)
+            {
+               throw new IllegalArgumentException("Cannot instantiate a map of type " + collectionClass + "; try specifying type type in components.xml");
+            }
+         }
+        
          for ( Map.Entry<InitialValue, InitialValue> me : initialValues.entrySet() )
          {
             result.put( me.getKey().getValue(keyType), me.getValue().getValue(elementType) );

Modified: trunk/src/main/org/jboss/seam/components-2.1.xsd
===================================================================
--- trunk/src/main/org/jboss/seam/components-2.1.xsd	2008-10-04 14:46:32 UTC (rev 9190)
+++ trunk/src/main/org/jboss/seam/components-2.1.xsd	2008-10-04 15:23:25 UTC (rev 9191)
@@ -219,6 +219,11 @@
                 <xs:documentation>The property name</xs:documentation>
             </xs:annotation>
         </xs:attribute>
+	<xs:attribute name="type" type="components:string" >
+            <xs:annotation>
+                <xs:documentation>Concrete type to use if the property is multi-valued</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
     </xs:attributeGroup>
     
 
@@ -344,7 +349,16 @@
             <xs:enumeration value="APPLICATION"/>
         </xs:restriction>
     </xs:simpleType>
-      
+    <xs:simpleType name="implementationType">
+        <xs:restriction base="xs:token">
+            <xs:enumeration value="hash"/>
+            <xs:enumeration value="linked"/>
+            <xs:enumeration value="tree"/>
+            <xs:enumeration value="HASH"/>
+            <xs:enumeration value="LINKED"/>
+            <xs:enumeration value="TREE"/>
+        </xs:restriction>
+    </xs:simpleType>
     <xs:simpleType name="precedenceType">
         <xs:restriction base="xs:int">
             <xs:enumeration value="0"/>

Modified: trunk/src/main/org/jboss/seam/init/Initialization.java
===================================================================
--- trunk/src/main/org/jboss/seam/init/Initialization.java	2008-10-04 14:46:32 UTC (rev 9190)
+++ trunk/src/main/org/jboss/seam/init/Initialization.java	2008-10-04 15:23:25 UTC (rev 9191)
@@ -15,6 +15,7 @@
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
@@ -594,6 +595,21 @@
    private Conversions.PropertyValue getPropertyValue(Element prop, String propName,
             Properties replacements)
    {
+      String typeName = prop.attributeValue("type");
+      Class type = null;
+      try
+      {
+         if(typeName != null )
+         {
+            type = Class.forName(typeName);
+         }
+      }
+      catch(ClassNotFoundException e)
+      {
+         throw new RuntimeException("Cannot find class " + typeName + " when setting up property " + propName);
+      }
+      
+      
       List<Element> keyElements = prop.elements("key");
       List<Element> valueElements = prop.elements("value");
 
@@ -611,7 +627,7 @@
          {
             values[i] = trimmedText(valueElements.get(i), propName, replacements);
          }
-         return new Conversions.MultiPropertyValue(values);
+         return new Conversions.MultiPropertyValue(values, type);
       }
       else
       {
@@ -621,14 +637,14 @@
             throw new IllegalArgumentException("value elements must match key elements: "
                      + propName);
          }
-         Map<String, String> keyedValues = new HashMap<String, String>();
+         Map<String, String> keyedValues = new LinkedHashMap<String, String>();
          for (int i = 0; i < keyElements.size(); i++)
          {
             String key = trimmedText(keyElements.get(i), propName, replacements);
             String value = trimmedText(valueElements.get(i), propName, replacements);
             keyedValues.put(key, value);
          }
-         return new Conversions.AssociativePropertyValue(keyedValues);
+         return new Conversions.AssociativePropertyValue(keyedValues, type);
       }
    }
 

Modified: trunk/src/main/org/jboss/seam/util/Conversions.java
===================================================================
--- trunk/src/main/org/jboss/seam/util/Conversions.java	2008-10-04 14:46:32 UTC (rev 9190)
+++ trunk/src/main/org/jboss/seam/util/Conversions.java	2008-10-04 15:23:25 UTC (rev 9191)
@@ -277,6 +277,7 @@
       boolean isExpression();
       boolean isMultiValued();
       boolean isAssociativeValued();
+      Class getType();
    }
    
    public static class FlatPropertyValue implements PropertyValue
@@ -342,16 +343,24 @@
          return string;
       }
       
+      public Class getType()
+      {
+         return null;
+      }
+      
    }
    
    public static class MultiPropertyValue implements PropertyValue
    {     
       private String[] strings;
       
-      public MultiPropertyValue(String[] strings)
+      private Class type;
+      
+      public MultiPropertyValue(String[] strings, Class type)
       {
          if (strings==null) throw new IllegalArgumentException();
          this.strings = strings;
+         this.type = type;
       }
       
       public String[] getMultiValues()
@@ -390,16 +399,23 @@
          return Strings.toString( ", ", (Object[]) strings );
       }
       
+      public Class getType()
+      {
+         return type;
+      }
    }
    
    public static class AssociativePropertyValue implements PropertyValue
    {      
       private Map<String, String> keyedValues;
       
-      public AssociativePropertyValue(Map<String, String> keyedValues)
+      private Class type;
+      
+      public AssociativePropertyValue(Map<String, String> keyedValues, Class type)
       {
          if (keyedValues==null) throw new IllegalArgumentException();
          this.keyedValues = keyedValues;
+         this.type = type;
       }
       
       public String[] getMultiValues()
@@ -438,6 +454,12 @@
          return keyedValues.toString();
       }
       
+      
+      public Class getType()
+      {
+         return type;
+      }
+      
    }
    
 }




More information about the seam-commits mailing list