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-unsubscr...@db.apache.org For additional commands, e-mail: torque-dev-h...@db.apache.org