You are viewing a plain text version of this content. The canonical link for it is here.
Posted to torque-dev@db.apache.org by tf...@apache.org on 2013/03/29 14:32:49 UTC

svn commit: r1462477 - in /db/torque/torque4/trunk/torque-generator/src: main/java/org/apache/torque/generator/source/model/ test/java/org/apache/torque/generator/source/model/

Author: tfischer
Date: Fri Mar 29 13:32:49 2013
New Revision: 1462477

URL: http://svn.apache.org/r1462477
Log:
TORQUE-273 start utility class for setting properties by reflection 

Added:
    db/torque/torque4/trunk/torque-generator/src/main/java/org/apache/torque/generator/source/model/
    db/torque/torque4/trunk/torque-generator/src/main/java/org/apache/torque/generator/source/model/NoSuchPropertyException.java
    db/torque/torque4/trunk/torque-generator/src/main/java/org/apache/torque/generator/source/model/PropertyAccess.java
    db/torque/torque4/trunk/torque-generator/src/test/java/org/apache/torque/generator/source/model/
    db/torque/torque4/trunk/torque-generator/src/test/java/org/apache/torque/generator/source/model/PropertyAccessTest.java

Added: db/torque/torque4/trunk/torque-generator/src/main/java/org/apache/torque/generator/source/model/NoSuchPropertyException.java
URL: http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-generator/src/main/java/org/apache/torque/generator/source/model/NoSuchPropertyException.java?rev=1462477&view=auto
==============================================================================
--- db/torque/torque4/trunk/torque-generator/src/main/java/org/apache/torque/generator/source/model/NoSuchPropertyException.java (added)
+++ db/torque/torque4/trunk/torque-generator/src/main/java/org/apache/torque/generator/source/model/NoSuchPropertyException.java Fri Mar 29 13:32:49 2013
@@ -0,0 +1,33 @@
+package org.apache.torque.generator.source.model;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.torque.generator.source.SourceException;
+
+public class NoSuchPropertyException extends SourceException
+{
+    public NoSuchPropertyException(Object target, String name)
+    {
+        super("Neither public field nor public setter exists for property "
+                + name
+                + " of class "
+                + target.getClass().getName());
+    }
+}

Added: db/torque/torque4/trunk/torque-generator/src/main/java/org/apache/torque/generator/source/model/PropertyAccess.java
URL: http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-generator/src/main/java/org/apache/torque/generator/source/model/PropertyAccess.java?rev=1462477&view=auto
==============================================================================
--- db/torque/torque4/trunk/torque-generator/src/main/java/org/apache/torque/generator/source/model/PropertyAccess.java (added)
+++ db/torque/torque4/trunk/torque-generator/src/main/java/org/apache/torque/generator/source/model/PropertyAccess.java Fri Mar 29 13:32:49 2013
@@ -0,0 +1,250 @@
+package org.apache.torque.generator.source.model;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import org.apache.commons.beanutils.BeanUtils;
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.torque.generator.source.SourceException;
+
+/**
+ * Accesses properties of java classes by reflection.
+ *
+ * @version $Id: $
+ */
+public class PropertyAccess
+{
+    private Object target;
+
+    private String propertyName;
+
+    public PropertyAccess(Object target, String propertyName)
+    {
+        if (target == null)
+        {
+            throw new NullPointerException("target must not be null");
+        }
+        if (propertyName == null)
+        {
+            throw new NullPointerException("propertyName must not be null");
+        }
+        this.target = target;
+        this.propertyName = propertyName;
+    }
+
+    public void setSingleProperty(Object value)
+            throws SourceException
+    {
+        // try public field
+        try
+        {
+            Field field = target.getClass().getField(propertyName);
+            if (Modifier.isPublic(field.getModifiers()))
+            {
+                field.set(target, value);
+                return;
+            }
+        }
+        catch (SecurityException e)
+        {
+            throw createSetFieldException(
+                    null,
+                    " because access is denied to the field or package",
+                    e);
+        }
+        catch (NoSuchFieldException e)
+        {
+            // do nothing, field does not exist
+        }
+        catch (IllegalArgumentException e)
+        {
+            if (value == null) {
+                throw createSetFieldException(
+                        value,
+                        " because the value is null which is not allowed",
+                        e);
+
+            }
+            throw createSetFieldException(
+                    value,
+                    " because the argument has the wrong type "
+                            + value.getClass().getName() ,
+                    e);
+        } catch (IllegalAccessException e)
+        {
+            throw createSetFieldException(
+                    null,
+                    " because the field cannot be accessed",
+                    e);
+        }
+
+        // try setter
+        try
+        {
+            PropertyDescriptor propertyDescriptor
+                    = PropertyUtils.getPropertyDescriptor(target, propertyName);
+            if (propertyDescriptor == null)
+            {
+                throw new NoSuchPropertyException(target, propertyName);
+            }
+            Method writeMethod = propertyDescriptor.getWriteMethod();
+            if (writeMethod == null)
+            {
+                throw new NoSuchPropertyException(target, propertyName);
+            }
+            writeMethod.invoke(target, value);
+            return;
+        }
+        catch (NoSuchMethodException e)
+        {
+            throw new SourceException(e);
+        }
+        catch (IllegalAccessException e)
+        {
+            throw new SourceException(e);
+        }
+        catch (InvocationTargetException e)
+        {
+            throw new SourceException(e);
+        }
+        catch (IllegalArgumentException e)
+        {
+            if (value == null) {
+                throw createSetFieldException(
+                        value,
+                        " because the value is null which is not allowed",
+                        e);
+
+            }
+            throw createSetFieldException(
+                    value,
+                    " because the argument has the wrong type "
+                            + value.getClass().getName() ,
+                    e);
+        }
+    }
+
+    public void setProperty(Object value) throws SourceException
+    {
+        try
+        {
+            setSingleProperty(value);
+            return;
+        }
+        catch (NoSuchPropertyException e)
+        {
+
+        }
+
+        try
+        {
+            String propertyName = this.propertyName;
+            PropertyDescriptor propertyDescriptor
+                = PropertyUtils.getPropertyDescriptor(target, propertyName);
+            if (propertyDescriptor == null) {
+                propertyName = this.propertyName + "s";
+                propertyDescriptor
+                    = PropertyUtils.getPropertyDescriptor(target, propertyName);
+            }
+            if (propertyDescriptor == null) {
+                propertyName = this.propertyName + "Array";
+                propertyDescriptor
+                    = PropertyUtils.getPropertyDescriptor(target, propertyName);
+            }
+            if (propertyDescriptor == null) {
+                throw new SourceException("No property named "
+                        + this.propertyName + ", "
+                        + this.propertyName + "s, "
+                        + this.propertyName + "Array, "
+                        + "found on model element "
+                        + target.getClass().getName()
+                        + ". This property is needed because the source element"
+                        + " has a child element named "
+                        + this.propertyName);
+            }
+            Object childModelElement = null;
+            if (propertyDescriptor.getPropertyType().isArray())
+            {
+                Object[] oldChildModelElement = (Object[]) PropertyUtils.getProperty(target, propertyName);
+                int newIndex;
+                if (oldChildModelElement == null) {
+                    childModelElement = Array.newInstance(propertyDescriptor.getPropertyType().getComponentType(), 1);
+                    newIndex = 0;
+                }
+                else {
+                    childModelElement = Array.newInstance(propertyDescriptor.getPropertyType().getComponentType(), oldChildModelElement.length + 1);
+                    System.arraycopy(oldChildModelElement, 0, childModelElement, 0, oldChildModelElement.length);
+                    newIndex = oldChildModelElement.length;
+                }
+                ((Object[]) childModelElement)[newIndex] = value;
+            }
+            else
+            {
+                childModelElement = value;
+            }
+            try
+            {
+                BeanUtils.setProperty(target, propertyName, childModelElement);
+            }
+            catch (IllegalAccessException e)
+            {
+                throw new SourceException(e);
+            }
+            catch (InvocationTargetException e)
+            {
+                throw new SourceException(e);
+            }
+        } catch (IllegalAccessException e)
+        {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        } catch (InvocationTargetException e)
+        {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        } catch (NoSuchMethodException e)
+        {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+    }
+
+    private SourceException createSetFieldException(
+            Object value,
+            String reason,
+            Throwable cause)
+    {
+        StringBuilder message = new StringBuilder("The field ")
+            .append(propertyName)
+            .append(" of class ")
+            .append(target.getClass().getName());
+        if (value != null) {
+            message.append(" cannot be set to ").append(value);
+        }
+        message.append(reason);
+        return new SourceException(message.toString(), cause);
+    }
+}

Added: db/torque/torque4/trunk/torque-generator/src/test/java/org/apache/torque/generator/source/model/PropertyAccessTest.java
URL: http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-generator/src/test/java/org/apache/torque/generator/source/model/PropertyAccessTest.java?rev=1462477&view=auto
==============================================================================
--- db/torque/torque4/trunk/torque-generator/src/test/java/org/apache/torque/generator/source/model/PropertyAccessTest.java (added)
+++ db/torque/torque4/trunk/torque-generator/src/test/java/org/apache/torque/generator/source/model/PropertyAccessTest.java Fri Mar 29 13:32:49 2013
@@ -0,0 +1,442 @@
+package org.apache.torque.generator.source.model;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import org.apache.torque.generator.source.SourceException;
+import org.junit.Before;
+import org.junit.Test;
+
+public class PropertyAccessTest
+{
+    private TestClass testClass;
+
+    @Before
+    public void setUp()
+    {
+        testClass = new TestClass();
+    }
+
+    @Test
+    public void testPropertyAccessTargetNull() throws Exception
+    {
+        try
+        {
+            new PropertyAccess(null, "publicIntField");
+            fail("Exception expected");
+        }
+        catch (NullPointerException e)
+        {
+            assertEquals("target must not be null", e.getMessage());
+        }
+    }
+
+    @Test
+    public void testPropertyAccessPropertyNameNull() throws Exception
+    {
+        try
+        {
+            new PropertyAccess(testClass, null);
+            fail("Exception expected");
+        }
+        catch (NullPointerException e)
+        {
+            assertEquals("propertyName must not be null", e.getMessage());
+        }
+    }
+
+    @Test
+    public void testSetSinglePropertyNotExistentField() throws Exception
+    {
+        PropertyAccess propertyAccess
+                = new PropertyAccess(testClass, "fieldDoesNotExist");
+        try
+        {
+            propertyAccess.setSingleProperty(2);
+            fail("Exception expected");
+        }
+        catch (NoSuchPropertyException e)
+        {
+            assertEquals("Neither public field nor public setter exists "
+                    + "for property fieldDoesNotExist of class "
+                    + "org.apache.torque.generator.source.model"
+                    + ".PropertyAccessTest$TestClass",
+                e.getMessage());
+        }
+    }
+
+    @Test
+    public void testAccessPrivateField() throws Exception
+    {
+        PropertyAccess propertyAccess
+                = new PropertyAccess(testClass, "privateIntField");
+        try
+        {
+            propertyAccess.setSingleProperty(2);
+            fail("Exception expected");
+        }
+        catch (NoSuchPropertyException e)
+        {
+            assertEquals("Neither public field nor public setter exists "
+                    + "for property privateIntField of class "
+                    + "org.apache.torque.generator.source.model"
+                    + ".PropertyAccessTest$TestClass",
+                e.getMessage());
+        }
+    }
+
+    @Test
+    public void testAccessProtectedField() throws Exception
+    {
+        PropertyAccess propertyAccess
+                = new PropertyAccess(testClass, "protectedIntField");
+        try
+        {
+            propertyAccess.setSingleProperty(2);
+            fail("Exception expected");
+        }
+        catch (NoSuchPropertyException e)
+        {
+            assertEquals("Neither public field nor public setter exists "
+                    + "for property protectedIntField of class "
+                    + "org.apache.torque.generator.source.model"
+                    + ".PropertyAccessTest$TestClass",
+                e.getMessage());
+        }
+    }
+
+    @Test
+    public void testAccessField() throws Exception
+    {
+        PropertyAccess propertyAccess
+                = new PropertyAccess(testClass, "intField");
+        try
+        {
+            propertyAccess.setSingleProperty(2);
+            fail("Exception expected");
+        }
+        catch (NoSuchPropertyException e)
+        {
+            assertEquals("Neither public field nor public setter exists "
+                    + "for property intField of class "
+                    + "org.apache.torque.generator.source.model"
+                    + ".PropertyAccessTest$TestClass",
+                e.getMessage());
+        }
+    }
+
+    @Test
+    public void testAccessPublicField() throws Exception
+    {
+        PropertyAccess propertyAccess
+                = new PropertyAccess(testClass, "publicIntField");
+        propertyAccess.setSingleProperty(2);
+        assertEquals(2, testClass.publicIntField);
+    }
+
+    @Test
+    public void testAccessPublicFieldFromBaseClass() throws Exception
+    {
+        PropertyAccess propertyAccess
+                = new PropertyAccess(testClass, "publicIntFieldFromBaseClass");
+        propertyAccess.setSingleProperty(2);
+        assertEquals(2, testClass.publicIntFieldFromBaseClass);
+    }
+
+    @Test
+    public void testAccessPublicFieldWrongClass() throws Exception
+    {
+        PropertyAccess propertyAccess
+                = new PropertyAccess(testClass, "publicIntField");
+        try
+        {
+            propertyAccess.setProperty("abc");
+            fail("Exception expected");
+        }
+        catch (SourceException e)
+        {
+            assertEquals("The field publicIntField of class "
+                    + "org.apache.torque.generator.source.model"
+                    + ".PropertyAccessTest$TestClass cannot be set to abc "
+                    + "because the argument has the wrong type "
+                    + "java.lang.String",
+                e.getMessage());
+        }
+    }
+
+    @Test
+    public void testAccessIntFieldNull() throws Exception
+    {
+        PropertyAccess propertyAccess
+                = new PropertyAccess(testClass, "publicIntField");
+        try
+        {
+            propertyAccess.setSingleProperty(null);
+            fail("Exception expected");
+        }
+        catch (SourceException e)
+        {
+            assertEquals("The field publicIntField of class "
+                    + "org.apache.torque.generator.source.model"
+                    + ".PropertyAccessTest$TestClass because the value is null"
+                    + " which is not allowed",
+                e.getMessage());
+        }
+    }
+
+    @Test
+    public void testAccessPublicStringField() throws Exception
+    {
+        PropertyAccess propertyAccess
+                = new PropertyAccess(testClass, "publicStringField");
+        propertyAccess.setSingleProperty("abc");
+        assertEquals("abc", testClass.publicStringField);
+    }
+
+    @Test
+    public void testAccessPublicStringFieldNull() throws Exception
+    {
+        PropertyAccess propertyAccess
+                = new PropertyAccess(testClass, "publicStringField");
+        testClass.publicStringField = "abc";
+        propertyAccess.setSingleProperty(null);
+        assertEquals(null, testClass.publicStringField);
+    }
+
+    @Test
+    public void testSetSinglePropertyOnlyGetter() throws Exception
+    {
+        PropertyAccess propertyAccess
+                = new PropertyAccess(testClass, "onlyGetter");
+        try
+        {
+            propertyAccess.setSingleProperty(2);
+            fail("Exception expected");
+        }
+        catch (NoSuchPropertyException e)
+        {
+            assertEquals("Neither public field nor public setter exists "
+                    + "for property onlyGetter of class "
+                    + "org.apache.torque.generator.source.model"
+                    + ".PropertyAccessTest$TestClass",
+                e.getMessage());
+        }
+    }
+
+    @Test
+    public void testAccessPrivateSetter() throws Exception
+    {
+        PropertyAccess propertyAccess
+                = new PropertyAccess(testClass, "privateIntSetter");
+        try
+        {
+            propertyAccess.setSingleProperty(2);
+            fail("Exception expected");
+        }
+        catch (NoSuchPropertyException e)
+        {
+            assertEquals("Neither public field nor public setter exists "
+                    + "for property privateIntSetter of class "
+                    + "org.apache.torque.generator.source.model"
+                    + ".PropertyAccessTest$TestClass",
+                e.getMessage());
+        }
+    }
+
+    @Test
+    public void testAccessProtectedSetter() throws Exception
+    {
+        PropertyAccess propertyAccess
+                = new PropertyAccess(testClass, "protectedIntSetter");
+        try
+        {
+            propertyAccess.setSingleProperty(2);
+            fail("Exception expected");
+        }
+        catch (NoSuchPropertyException e)
+        {
+            assertEquals("Neither public field nor public setter exists "
+                    + "for property protectedIntSetter of class "
+                    + "org.apache.torque.generator.source.model"
+                    + ".PropertyAccessTest$TestClass",
+                e.getMessage());
+        }
+    }
+
+    @Test
+    public void testAccessSetter() throws Exception
+    {
+        PropertyAccess propertyAccess
+                = new PropertyAccess(testClass, "intSetter");
+        try
+        {
+            propertyAccess.setSingleProperty(2);
+            fail("Exception expected");
+        }
+        catch (NoSuchPropertyException e)
+        {
+            assertEquals("Neither public field nor public setter exists "
+                    + "for property intSetter of class "
+                    + "org.apache.torque.generator.source.model"
+                    + ".PropertyAccessTest$TestClass",
+                e.getMessage());
+        }
+    }
+
+    @Test
+    public void testAccessPublicSetter() throws Exception
+    {
+        PropertyAccess propertyAccess
+                = new PropertyAccess(testClass, "publicIntSetter");
+        propertyAccess.setSingleProperty(2);
+        assertEquals(2, testClass.publicIntField);
+    }
+
+    @Test
+    public void testAccessPublicSetterFromBaseClass() throws Exception
+    {
+        PropertyAccess propertyAccess
+                = new PropertyAccess(testClass, "publicIntSetterFromBaseClass");
+        propertyAccess.setSingleProperty(2);
+        assertEquals(2, testClass.publicIntFieldFromBaseClass);
+    }
+
+    @Test
+    public void testAccessPublicSetterWrongClass() throws Exception
+    {
+        PropertyAccess propertyAccess
+                = new PropertyAccess(testClass, "publicIntSetter");
+        try
+        {
+            propertyAccess.setProperty("abc");
+            fail("Exception expected");
+        }
+        catch (SourceException e)
+        {
+            assertEquals("The field publicIntSetter of class "
+                    + "org.apache.torque.generator.source.model"
+                    + ".PropertyAccessTest$TestClass cannot be set to abc "
+                    + "because the argument has the wrong type "
+                    + "java.lang.String",
+                e.getMessage());
+        }
+    }
+
+    @Test
+    public void testAccessIntSetterNull() throws Exception
+    {
+        PropertyAccess propertyAccess
+                = new PropertyAccess(testClass, "publicIntSetter");
+        try
+        {
+            propertyAccess.setSingleProperty(null);
+            fail("Exception expected");
+        }
+        catch (SourceException e)
+        {
+            assertEquals("The field publicIntSetter of class "
+                    + "org.apache.torque.generator.source.model"
+                    + ".PropertyAccessTest$TestClass because the value is null"
+                    + " which is not allowed",
+                e.getMessage());
+        }
+    }
+
+    @Test
+    public void testAccessPublicStringSetter() throws Exception
+    {
+        PropertyAccess propertyAccess
+                = new PropertyAccess(testClass, "publicStringSetter");
+        propertyAccess.setSingleProperty("abc");
+        assertEquals("abc", testClass.publicStringField);
+    }
+
+    @Test
+    public void testAccessPublicStringSetterNull() throws Exception
+    {
+        PropertyAccess propertyAccess
+                = new PropertyAccess(testClass, "publicStringSetter");
+        testClass.publicStringField = "abc";
+        propertyAccess.setSingleProperty(null);
+        assertEquals(null, testClass.publicStringField);
+    }
+
+    public static class TestClass extends TestBaseClass
+    {
+        private int privateIntField;
+
+        protected int protectedIntField;
+
+        int intField;
+
+        public int publicIntField;
+
+        public String publicStringField;
+
+        public int getOnlyGetter()
+        {
+            return 0;
+        }
+
+        private void setPrivateIntSetter(int value)
+        {
+            privateIntField = value;
+        }
+
+        protected void setProtectedIntSetter(int value)
+        {
+            protectedIntField = value;
+        }
+
+        void setIntSetter(int value)
+        {
+            intField = value;
+        }
+
+        public void setPublicIntSetter(int value)
+        {
+            publicIntField = value;
+        }
+
+        public void setPublicStringSetter(String value)
+        {
+            publicStringField = value;
+        }
+    }
+
+    public static class TestBaseClass
+    {
+        public int publicIntFieldFromBaseClass;
+
+        public int publicIntField; // to be overridden
+
+        public void setPublicIntSetterFromBaseClass(int value)
+        {
+            publicIntFieldFromBaseClass = value;
+        }
+
+        public void setPublicIntSetter(int value) // to be overridden
+        {
+            publicIntField = value;
+        }
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: torque-dev-unsubscribe@db.apache.org
For additional commands, e-mail: torque-dev-help@db.apache.org