[jboss-svn-commits] JBL Code SVN: r28937 - in labs/jbosstm/trunk/common: tests/com/arjuna/common/tests/simple and 1 other directory.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Fri Aug 14 10:48:51 EDT 2009


Author: jhalliday
Date: 2009-08-14 10:48:51 -0400 (Fri, 14 Aug 2009)
New Revision: 28937

Modified:
   labs/jbosstm/trunk/common/classes/com/arjuna/common/internal/util/propertyservice/BeanPopulator.java
   labs/jbosstm/trunk/common/tests/com/arjuna/common/tests/simple/DummyPropertyManager.java
Log:
Improvements to the propertyfile->bean copy handling. JBTM-596


Modified: labs/jbosstm/trunk/common/classes/com/arjuna/common/internal/util/propertyservice/BeanPopulator.java
===================================================================
--- labs/jbosstm/trunk/common/classes/com/arjuna/common/internal/util/propertyservice/BeanPopulator.java	2009-08-14 14:46:26 UTC (rev 28936)
+++ labs/jbosstm/trunk/common/classes/com/arjuna/common/internal/util/propertyservice/BeanPopulator.java	2009-08-14 14:48:51 UTC (rev 28937)
@@ -22,6 +22,10 @@
 
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
+import java.util.List;
+import java.util.LinkedList;
+import java.util.Enumeration;
+import java.util.Collections;
 
 import com.arjuna.common.util.propertyservice.PropertyManager;
 
@@ -36,19 +40,28 @@
     /**
      * Examine the properties of the provided bean and update them to match the values of the corresponding
      * properties in the PropertyManager.
-     * This will normally be used to configure a freshly created default bean to match the configuration
-     * read from a properties file.
+     * This will normally be used at startup to configure a freshly created default bean to match
+     * the configuration read from a properties file.
      *
      * The algorithm is as follows: for each field in the bean, which must have a getter and setter method
      * matching according to the JavaBeans naming conventions, determine the corresponding property key.
      *
-     * Several key names are tried, with the first match being used: The FQN of the bean followed by the field name,
-     * the short name of the bean followed by the field name, and finally the bean classes' PropertyPrefix annotation
-     * value followed by the name of the field, the last being except in cases where the field has a FullPropertyName
-     * annotation, in which case its value is used instead.
+     * Several key names are tried, with the first match being used:
+     * For scalar properties: The FQN of the bean followed by the field name,
+     *   the short name of the bean followed by the field name, and finally the bean classes' PropertyPrefix annotation
+     *   value followed by the name of the field, the last being except in cases where the field has a FullPropertyName
+     *   annotation, in which case its value is used instead.
+     * For vector (in the math sense - the type is actually normally List) properties, a single property key matched
+     *   according to the prior rules will be treated as having a compund vlaue which will be tokenized into list
+     *   elements based on whitespace and inserted into the list in token order.
+     * If no such key is found, the value of the field's ConcatenationPrefix annotation
+     * is treated as a name prefix and the list elements are assembled from the values of any properties having
+     * key values starting with the prefix. These are inserted into the list in order of the key's name sort position.
+     *
      * This allows for the convention that all properties in a given bean will share
      * the same prefix e.g. com.arjuna.ats.arjuna.foo. whilst still allowing for changing of the property
      * name in cases where this makes for more readable code.
+     *
      * Obtain the value of the property from the PropertyManager and if it's not null, type convert it to match
      * the bean's property field type.  Obtain the value of the property from the bean and if it's different
      * from the value read from the propertyManager, use the setter to update the bean.
@@ -63,10 +76,6 @@
             throw new Exception("no PropertyPrefix found on "+bean.getClass().getName());
         }
 
-        PropertyPrefix prefixAnnotation = bean.getClass().getAnnotation(PropertyPrefix.class);
-
-        String prefix = prefixAnnotation.prefix();
-
         for(Field field : bean.getClass().getDeclaredFields()) {
             Class type = field.getType();
 
@@ -87,76 +96,149 @@
                 getter = bean.getClass().getMethod(getterMethodName, new Class[] {});
             }
 
-            //////////////////
+            if(field.isAnnotationPresent(ConcatenationPrefix.class)) {
+                handleGroupProperty(bean, propertyManager, field, setter, getter);
+            } else {
+                handleSimpleProperty(bean, propertyManager, field, setter, getter);
+            }
+        }
+    }
 
-            String propertyFileKey = null;
-            String valueFromPropertyManager = null;
+    private static void handleGroupProperty(Object bean, PropertyManager propertyManager, Field field, Method setter, Method getter)
+        throws Exception
+    {
+        List<String> values = new LinkedList<String>();
 
-            if(valueFromPropertyManager == null) {
-                propertyFileKey = bean.getClass().getCanonicalName()+"."+field.getName();
-                valueFromPropertyManager = propertyManager.getProperty(propertyFileKey);
-            }
+        String valueFromPropertyManager = getValueFromPropertyManager(bean, propertyManager, field, bean.getClass().getSimpleName());
 
-            if(valueFromPropertyManager == null) {
-                propertyFileKey = bean.getClass().getSimpleName()+"."+field.getName();
-                valueFromPropertyManager = propertyManager.getProperty(propertyFileKey);
+        if(valueFromPropertyManager != null)
+        {
+            // it's a single value which needs parsing
+
+            String[] tokens = valueFromPropertyManager.split("\\s+");
+
+            // the order we want them is is the order they appear in the string, so we can just add in sequence:
+            for(String token : tokens) {
+                values.add(token);
             }
+        }
+        else
+        {
+            // it's set of values that need gathering together
+            // the order we want them in is the lex sort order of the keys, so we need to buffer and sort them:
 
-            if (valueFromPropertyManager == null) {
-                propertyFileKey = prefix+field.getName();
+            List<String> listOfMatchingPropertyNames = new LinkedList<String>();
+            Enumeration propertyNamesEnumeration = propertyManager.propertyNames();
 
-                if(field.isAnnotationPresent(FullPropertyName.class)) {
-                    FullPropertyName fullPropertyName = field.getAnnotation(FullPropertyName.class);
-                    propertyFileKey = fullPropertyName.name();
+            if (propertyNamesEnumeration != null)
+            {
+                String prefix = field.getAnnotation(ConcatenationPrefix.class).prefix();
+
+                while (propertyNamesEnumeration.hasMoreElements())
+                {
+                    String name = (String) propertyNamesEnumeration.nextElement();
+
+                    if (name.startsWith(prefix))
+                    {
+                        listOfMatchingPropertyNames.add(name);
+                    }
                 }
-
-                valueFromPropertyManager = propertyManager.getProperty(propertyFileKey);
             }
 
+            Collections.sort(listOfMatchingPropertyNames);
 
-            if(valueFromPropertyManager != null) {
+            for(String name : listOfMatchingPropertyNames) {
+                String value = propertyManager.getProperty(name);
+                values.add(value);
+            }            
+        }
+        
+        Object valueFromBean = getter.invoke(bean, new Object[] {});
 
-                Object valueFromBean = getter.invoke(bean, new Object[] {});
+        if(!valueFromBean.equals(values)) {
+            setter.invoke(bean, new Object[] {values});
+        }
+    }
 
-                if(field.getType().equals(Boolean.TYPE)) {
+    private static void handleSimpleProperty(Object bean, PropertyManager propertyManager, Field field, Method setter, Method getter)
+            throws Exception
+    {
+        PropertyPrefix prefixAnnotation = bean.getClass().getAnnotation(PropertyPrefix.class);
+        String prefix = prefixAnnotation.prefix();
 
-                    if(!((Boolean)valueFromBean).booleanValue() && isPositive(valueFromPropertyManager)) {
-                        setter.invoke(bean, new Object[]{ Boolean.TRUE });
-                    }
+        String valueFromPropertyManager = getValueFromPropertyManager(bean, propertyManager, field, prefix);
 
-                    if(((Boolean)valueFromBean).booleanValue() && isNegative(valueFromPropertyManager)) {
-                        setter.invoke(bean, new Object[] { Boolean.FALSE});
-                    }
+        if(valueFromPropertyManager != null) {
 
-                } else if(field.getType().equals(String.class)) {
+            Object valueFromBean = getter.invoke(bean, new Object[] {});
 
-                    if(!valueFromPropertyManager.equals(valueFromBean)) {
-                        setter.invoke(bean, new Object[] {valueFromPropertyManager});
-                    }
+            if(field.getType().equals(Boolean.TYPE)) {
 
-                } else if(field.getType().equals(Long.TYPE)) {
+                if(!((Boolean)valueFromBean).booleanValue() && isPositive(valueFromPropertyManager)) {
+                    setter.invoke(bean, new Object[]{ Boolean.TRUE });
+                }
 
-                    Long longValue = Long.valueOf(valueFromPropertyManager);
-                    if(!longValue.equals(valueFromBean)) {
-                        setter.invoke(bean, new Object[] {longValue});
-                    }
+                if(((Boolean)valueFromBean).booleanValue() && isNegative(valueFromPropertyManager)) {
+                    setter.invoke(bean, new Object[] { Boolean.FALSE});
+                }
 
-                } else if(field.getType().equals(Integer.TYPE)) {
+            } else if(field.getType().equals(String.class)) {
 
-                    Integer intValue = Integer.valueOf(valueFromPropertyManager);
-                    if(!intValue.equals(valueFromBean)) {
-                        setter.invoke(bean, new Object[] {intValue});
-                    }
+                if(!valueFromPropertyManager.equals(valueFromBean)) {
+                    setter.invoke(bean, new Object[] {valueFromPropertyManager});
+                }
 
-                } else {
+            } else if(field.getType().equals(Long.TYPE)) {
 
-                    throw new Exception("unknown field type "+field.getType());
+                Long longValue = Long.valueOf(valueFromPropertyManager);
+                if(!longValue.equals(valueFromBean)) {
+                    setter.invoke(bean, new Object[] {longValue});
+                }
 
+            } else if(field.getType().equals(Integer.TYPE)) {
+
+                Integer intValue = Integer.valueOf(valueFromPropertyManager);
+                if(!intValue.equals(valueFromBean)) {
+                    setter.invoke(bean, new Object[] {intValue});
                 }
+
+            } else {
+
+                throw new Exception("unknown field type "+field.getType());
+
             }
         }
     }
 
+    private static String getValueFromPropertyManager(Object bean, PropertyManager propertyManager, Field field, String prefix)
+    {
+        String propertyFileKey;
+        String valueFromPropertyManager = null;
+
+        if(valueFromPropertyManager == null) {
+            propertyFileKey = bean.getClass().getCanonicalName()+"."+field.getName();
+            valueFromPropertyManager = propertyManager.getProperty(propertyFileKey);
+        }
+
+        if(valueFromPropertyManager == null) {
+            propertyFileKey = bean.getClass().getSimpleName()+"."+field.getName();
+            valueFromPropertyManager = propertyManager.getProperty(propertyFileKey);
+        }
+
+        if (valueFromPropertyManager == null) {
+            propertyFileKey = prefix+field.getName();
+
+            if(field.isAnnotationPresent(FullPropertyName.class)) {
+                FullPropertyName fullPropertyName = field.getAnnotation(FullPropertyName.class);
+                propertyFileKey = fullPropertyName.name();
+            }
+
+            valueFromPropertyManager = propertyManager.getProperty(propertyFileKey);
+        }
+
+        return valueFromPropertyManager;
+    }
+
     private static String capitalizeFirstLetter(String string) {
         return (string.length()>0) ? (Character.toUpperCase(string.charAt(0))+string.substring(1)) : string;
     }

Modified: labs/jbosstm/trunk/common/tests/com/arjuna/common/tests/simple/DummyPropertyManager.java
===================================================================
--- labs/jbosstm/trunk/common/tests/com/arjuna/common/tests/simple/DummyPropertyManager.java	2009-08-14 14:46:26 UTC (rev 28936)
+++ labs/jbosstm/trunk/common/tests/com/arjuna/common/tests/simple/DummyPropertyManager.java	2009-08-14 14:48:51 UTC (rev 28937)
@@ -25,11 +25,9 @@
 import com.arjuna.common.util.exceptions.LoadPropertiesException;
 import com.arjuna.common.util.exceptions.SavePropertiesException;
 import com.arjuna.common.util.exceptions.ManagementPluginException;
+import com.arjuna.common.internal.util.propertyservice.ConcatenationPrefix;
 
-import java.util.Set;
-import java.util.HashSet;
-import java.util.Properties;
-import java.util.Enumeration;
+import java.util.*;
 import java.lang.reflect.Field;
 import java.io.IOException;
 
@@ -57,8 +55,20 @@
         return keys;
     }
 
+    public void addConcatenationKeys(Class environmentBean) {
+
+        for(Field field : environmentBean.getDeclaredFields()) {
+            if(field.isAnnotationPresent(ConcatenationPrefix.class)) {
+                String prefix = field.getAnnotation(ConcatenationPrefix.class).prefix();
+                concatenationKeys.add(prefix);
+                System.out.println("addConcat : "+prefix);
+            }
+        }
+    }
+
     public Set<String> usedKeys = new HashSet<String>();
     Properties properties = null;
+    public Set<String> concatenationKeys = new HashSet<String>();
 
     public DummyPropertyManager(Properties properties) {
         this.properties = properties;
@@ -66,6 +76,13 @@
 
     public String getProperty(String key)
     {
+        for(String prefix : concatenationKeys) {
+            if(key.startsWith(prefix) && !usedKeys.contains(prefix)) {
+                usedKeys.add(prefix);
+                break;
+            }
+        }
+
         usedKeys.add(key);
 
         if(properties != null) {
@@ -102,7 +119,12 @@
 
     public Enumeration propertyNames()
     {
-        throw new RuntimeException("this is not expected to be called during the test");
+        Vector<String> names = new Vector<String>();
+        for(String prefix : concatenationKeys) {
+            names.add(prefix+"_one");
+            names.add(prefix+"_two");
+        }
+        return names.elements();
     }
 
     public void load(String s, String s1) throws IOException, ClassNotFoundException, LoadPropertiesException



More information about the jboss-svn-commits mailing list