Author: knopp Date: Tue Jun 5 14:41:04 2007 New Revision: 544645 URL: http://svn.apache.org/viewvc?view=rev&rev=544645 Log: WICKET-619 - Models that can should be able to provide information about field/getter/setter
Added: incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/model/IPropertyReflectionAwareModel.java Modified: incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/model/AbstractPropertyModel.java incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/util/lang/PropertyResolver.java incubator/wicket/trunk/jdk-1.4/wicket/src/test/java/org/apache/wicket/util/lang/PropertyResolverTest.java Modified: incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/model/AbstractPropertyModel.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/model/AbstractPropertyModel.java?view=diff&rev=544645&r1=544644&r2=544645 ============================================================================== --- incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/model/AbstractPropertyModel.java (original) +++ incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/model/AbstractPropertyModel.java Tue Jun 5 14:41:04 2007 @@ -16,6 +16,9 @@ */ package org.apache.wicket.model; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + import org.apache.wicket.Application; import org.apache.wicket.Component; import org.apache.wicket.Session; @@ -32,7 +35,11 @@ * @author Eelco Hillenius * @author Jonathan Locke */ -public abstract class AbstractPropertyModel implements IChainingModel, IObjectClassAwareModel +public abstract class AbstractPropertyModel + implements + IChainingModel, + IObjectClassAwareModel, + IPropertyReflectionAwareModel { /** Any model object (which may or may not implement IModel) */ private Object target; @@ -194,6 +201,57 @@ return null; } + /** + * @see org.apache.wicket.model.IPropertyReflectionAwareModel#getPropertyField() + */ + public Field getPropertyField() + { + String expression = propertyExpression(); + if (Strings.isEmpty(expression) == false) + { + Object target = getTarget(); + if (target != null) + { + return PropertyResolver.getPropertyField(expression, target); + } + } + return null; + } + + /** + * @see org.apache.wicket.model.IPropertyReflectionAwareModel#getPropertyGetter() + */ + public Method getPropertyGetter() + { + String expression = propertyExpression(); + if (Strings.isEmpty(expression) == false) + { + Object target = getTarget(); + if (target != null) + { + return PropertyResolver.getPropertyGetter(expression, target); + } + } + return null; + } + + /** + * @see org.apache.wicket.model.IPropertyReflectionAwareModel#getPropertySetter() + */ + public Method getPropertySetter() + { + String expression = propertyExpression(); + if (Strings.isEmpty(expression) == false) + { + Object target = getTarget(); + if (target != null) + { + return PropertyResolver.getPropertySetter(expression, target); + } + } + return null; + } + /** * @return The property expression for the component */ Added: incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/model/IPropertyReflectionAwareModel.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/model/IPropertyReflectionAwareModel.java?view=auto&rev=544645 ============================================================================== --- incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/model/IPropertyReflectionAwareModel.java (added) +++ incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/model/IPropertyReflectionAwareModel.java Tue Jun 5 14:41:04 2007 @@ -0,0 +1,53 @@ +/* + * 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. + */ +package org.apache.wicket.model; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +/** + * Optional interface implemented by models that are able to provide + * reflection information about object property they interact with. + * + * The model doesn't have to support all propery information in this + * interface. It is valid to return null for any method. + * + * @author Matej Knopp + */ +public interface IPropertyReflectionAwareModel +{ + /** + * Returns the field of model property or null if the field doesn't exist. + * @return Field or null + */ + public Field getPropertyField(); + + /** + * Returns the getter method of model property or null if the method + * doesn't exist. + * @return Method or null + */ + public Method getPropertyGetter(); + + + /** + * Returns the setter metod of model property or null if the method doesn't + * exist. + * @return Method or null + */ + public Method getPropertySetter(); +} Modified: incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/util/lang/PropertyResolver.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/util/lang/PropertyResolver.java?view=diff&rev=544645&r1=544644&r2=544645 ============================================================================== --- incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/util/lang/PropertyResolver.java (original) +++ incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/util/lang/PropertyResolver.java Tue Jun 5 14:41:04 2007 @@ -138,7 +138,7 @@ /** * @param expression * @param object - * @return + * @return class of the target property object */ public final static Class getPropertyClass(String expression, Object object) { @@ -151,6 +151,57 @@ return setter.getTargetClass(); } + /** + * @param expression + * @param object + * @return Field for the property expression or null if such field doesn't + * exist (only getters and setters) + */ + public final static Field getPropertyField(String expression, Object object) + { + ObjectAndGetSetter setter = getObjectAndGetSetter(expression, object, true); + if (setter == null) + { + throw new WicketRuntimeException("Null object returned for expression: " + expression + + " for getting the target classs of: " + object); + } + return setter.getField(); + } + + /** + * @param expression + * @param object + * @return Getter method for the property expression or null if such getter + * doesn't exist (only field) + */ + public final static Method getPropertyGetter(String expression, Object object) + { + ObjectAndGetSetter setter = getObjectAndGetSetter(expression, object, true); + if (setter == null) + { + throw new WicketRuntimeException("Null object returned for expression: " + expression + + " for getting the target classs of: " + object); + } + return setter.getGetter(); + } + + /** + * @param expression + * @param object + * @return Setter method for the property expression or null if such setter + * doesn't exist (only field) + */ + public final static Method getPropertySetter(String expression, Object object) + { + ObjectAndGetSetter setter = getObjectAndGetSetter(expression, object, true); + if (setter == null) + { + throw new WicketRuntimeException("Null object returned for expression: " + expression + + " for getting the target classs of: " + object); + } + return setter.getSetter(); + } + private static ObjectAndGetSetter getObjectAndGetSetter(final String expression, final Object object, boolean tryToCreateNull) { @@ -264,7 +315,7 @@ method = findMethod(clz, exp); if (method != null) { - getAndSetter = new MethodGetAndSet(method); + getAndSetter = new MethodGetAndSet(method, null); } else { @@ -344,7 +395,7 @@ } else { - getAndSetter = new MethodGetAndSet(method); + getAndSetter = new MethodGetAndSet(method, field); } } else @@ -355,7 +406,8 @@ } else { - getAndSetter = new MethodGetAndSet(method); + field = findField(clz, exp); + getAndSetter = new MethodGetAndSet(method, field); } getAndSetters.put(exp, getAndSetter); } @@ -488,11 +540,38 @@ return getAndSetter.getValue(value); } + /** + * @return class of property value + */ public Class getTargetClass() { return getAndSetter.getTargetClass(this.value); } + /** + * @return Field or null if no field exists for expression + */ + public Field getField() + { + return getAndSetter.getField(); + } + + /** + * @return Getter method or null if no getter exists for expression + */ + public Method getGetter() + { + return getAndSetter.getGetter(); + } + + /** + * @return Setter method or null if no setter exists for expression + */ + public Method getSetter() + { + return getAndSetter.getSetter(); + } + } @@ -528,9 +607,58 @@ public void setValue(final Object object, final Object value, PropertyResolverConverter converter); + /** + * @return Field or null if there is no field + */ + public Field getField(); + + /** + * @return Getter method or null if there is no getter + */ + public Method getGetter(); + + /** + * @return Setter of null if there is no setter + */ + public Method getSetter(); + } + + private static abstract class AbstractGetAndSet implements IGetAndSet + { + /** + * @see org.apache.wicket.util.lang.PropertyResolver.IGetAndSet#getField() + */ + public Field getField() + { + return null; + } + + /** + * @see org.apache.wicket.util.lang.PropertyResolver.IGetAndSet#getGetter() + */ + public Method getGetter() + { + return null; + } + + /** + * @see org.apache.wicket.util.lang.PropertyResolver.IGetAndSet#getSetter() + */ + public Method getSetter() + { + return null; + } + + /** + * @see org.apache.wicket.util.lang.PropertyResolver.IGetAndSet#getTargetClass(java.lang.Object) + */ + public Class getTargetClass(Object object) + { + return null; + } } - private static final class MapGetSet implements IGetAndSet + private static final class MapGetSet extends AbstractGetAndSet { final private String key; @@ -565,17 +693,9 @@ // map and try to make one of the class if finds? return null; } - - /** - * @see org.apache.wicket.util.lang.PropertyResolver.IGetAndSet#getTargetClass(Object) - */ - public Class getTargetClass(Object object) - { - return null; - } } - private static final class ListGetSet implements IGetAndSet + private static final class ListGetSet extends AbstractGetAndSet { final private int index; @@ -627,17 +747,9 @@ // list and try to make one of the class if finds? return null; } - - /** - * @see org.apache.wicket.util.lang.PropertyResolver.IGetAndSet#getTargetClass(Object) - */ - public Class getTargetClass(Object object) - { - return null; - } } - private static final class ArrayGetSet implements IGetAndSet + private static final class ArrayGetSet extends AbstractGetAndSet { final private int index; @@ -693,7 +805,7 @@ } } - private static final class ArrayLengthGetSet implements IGetAndSet + private static final class ArrayLengthGetSet extends AbstractGetAndSet { ArrayLengthGetSet() { @@ -733,7 +845,7 @@ } } - private static final class ArrayPropertyGetSet implements IGetAndSet + private static final class ArrayPropertyGetSet extends AbstractGetAndSet { final private Integer index; final private Method getMethod; @@ -862,15 +974,17 @@ } } - private static final class MethodGetAndSet implements IGetAndSet + private static final class MethodGetAndSet extends AbstractGetAndSet { private Method getMethod; private Method setMethod; + private Field field; - MethodGetAndSet(Method getMethod) + MethodGetAndSet(Method getMethod, Field field) { this.getMethod = getMethod; this.getMethod.setAccessible(true); + this.field = field; } /** @@ -1013,12 +1127,36 @@ { return getMethod.getReturnType(); } + + /** + * @see org.apache.wicket.util.lang.PropertyResolver.AbstractGetAndSet#getGetter() + */ + public Method getGetter() + { + return getMethod; + } + + /** + * @see org.apache.wicket.util.lang.PropertyResolver.AbstractGetAndSet#getSetter() + */ + public Method getSetter() + { + return setMethod; + } + + /** + * @see org.apache.wicket.util.lang.PropertyResolver.AbstractGetAndSet#getField() + */ + public Field getField() + { + return field; + } } /** * @author jcompagner */ - private static class FieldGetAndSetter implements IGetAndSet + private static class FieldGetAndSetter extends AbstractGetAndSet { private Field field; @@ -1094,6 +1232,11 @@ public Class getTargetClass(Object object) { return field.getType(); + } + + public Field getField() + { + return field; } } } Modified: incubator/wicket/trunk/jdk-1.4/wicket/src/test/java/org/apache/wicket/util/lang/PropertyResolverTest.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/jdk-1.4/wicket/src/test/java/org/apache/wicket/util/lang/PropertyResolverTest.java?view=diff&rev=544645&r1=544644&r2=544645 ============================================================================== --- incubator/wicket/trunk/jdk-1.4/wicket/src/test/java/org/apache/wicket/util/lang/PropertyResolverTest.java (original) +++ incubator/wicket/trunk/jdk-1.4/wicket/src/test/java/org/apache/wicket/util/lang/PropertyResolverTest.java Tue Jun 5 14:41:04 2007 @@ -16,6 +16,8 @@ */ package org.apache.wicket.util.lang; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -355,5 +357,71 @@ clazz = PropertyResolver.getPropertyClass("addressArray[0].number", person); assertEquals(int.class, clazz); + } + + /** + * + */ + public void testGetTargetField() { + Address address = new Address(); + + Field field = PropertyResolver.getPropertyField("number", address); + assertEquals(field.getName(), "number"); + assertEquals(field.getType(), int.class); + + Person person = new Person(); + person.setAddress(new Address()); + + field = PropertyResolver.getPropertyField("address.number", person); + assertEquals(field.getName(), "number"); + assertEquals(field.getType(), int.class); + + person.setAddressArray(new Address[] { new Address(), new Address() }); + field = PropertyResolver.getPropertyField("addressArray[0].number", person); + assertEquals(field.getName(), "number"); + assertEquals(field.getType(), int.class); + } + + /** + * + */ + public void testGetTargetGetter() { + Address address = new Address(); + + Method method = PropertyResolver.getPropertyGetter("number", address); + assertEquals(method.getName(), "getNumber"); + assertEquals(method.getReturnType(), int.class); + + Person person = new Person(); + person.setAddress(new Address()); + + method = PropertyResolver.getPropertyGetter("address.number", person); + assertEquals(method.getName(), "getNumber"); + assertEquals(method.getReturnType(), int.class); + + person.setAddressArray(new Address[] { new Address(), new Address() }); + method = PropertyResolver.getPropertyGetter("addressArray[0].number", person); + assertEquals(method.getName(), "getNumber"); + assertEquals(method.getReturnType(), int.class); + } + + /** + * + */ + public void testGetTargetSetter() { + Address address = new Address(); + + Method method = PropertyResolver.getPropertySetter("number", address); + assertEquals(method.getName(), "setNumber"); + + Person person = new Person(); + person.setAddress(new Address()); + + method = PropertyResolver.getPropertySetter("address.number", person); + assertEquals(method.getName(), "setNumber"); + + person.setAddressArray(new Address[] { new Address(), new Address() }); + method = PropertyResolver.getPropertySetter("addressArray[0].number", person); + assertEquals(method.getName(), "setNumber"); } }