WICKET-6318 adding ParsedPropertyExpressionResolver, a resolver that uses parsed property expressions; moving DefaultPropertyLocator, IPropertyResolver, CachingPropertyLocator back to OGNLPropertyExpressionResolverOGNLPropertyExpressionResolver; restoring IPropertyResolver name back to IPropertyLocator
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/7fd219c3 Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/7fd219c3 Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/7fd219c3 Branch: refs/heads/WICKET-6318-configurable-property-expression-resolver Commit: 7fd219c3b764f844665c3cff8d5cc719e77c6a99 Parents: 6a895f0 Author: Pedro Henrique Oliveira dos Santos <[email protected]> Authored: Mon Feb 27 03:13:43 2017 -0300 Committer: Pedro Henrique Oliveira dos Santos <[email protected]> Committed: Mon Feb 27 03:15:27 2017 -0300 ---------------------------------------------------------------------- .../validation/DefaultPropertyResolver.java | 2 +- .../core/util/lang/DefaultPropertyLocator.java | 160 ---- .../util/lang/IPropertyExpressionResolver.java | 22 +- .../core/util/lang/IPropertyResolver.java | 18 - .../lang/OGNLPropertyExpressionResolver.java | 393 +++++--- .../wicket/core/util/lang/PropertyResolver.java | 97 +- .../ParsedPropertyExpressionResolver.java | 173 ++++ .../core/util/parser/PropertyExpression.java | 25 + .../util/parser/PropertyExpressionResolver.java | 21 - .../util/reflection/CachingPropertyLocator.java | 70 -- .../reflection/IndexedPropertyGetAndSet.java | 2 +- .../core/util/reflection/MethodGetAndSet.java | 51 +- .../util/reflection/ObjectWithGetAndSet.java | 8 +- .../core/util/reflection/ReflectionUtility.java | 78 +- .../wicket/model/AbstractPropertyModel.java | 2 +- .../ParsedPropertyExpressionResolverTest.java | 103 +++ .../parser/PropertyExpressionParserTest.java | 16 + .../OGNLPropertyExpressionResolverTest.java | 916 +------------------ .../lang/PropertyExpressionResolverTest.java | 852 +++++++++++++++++ .../org/apache/wicket/util/lang/WeirdList.java | 48 + .../org/apache/wicket/util/lang/WeirdMap.java | 48 + 21 files changed, 1721 insertions(+), 1384 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/7fd219c3/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/DefaultPropertyResolver.java ---------------------------------------------------------------------- diff --git a/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/DefaultPropertyResolver.java b/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/DefaultPropertyResolver.java index 174598a..e6a4985 100644 --- a/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/DefaultPropertyResolver.java +++ b/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/DefaultPropertyResolver.java @@ -35,7 +35,7 @@ public class DefaultPropertyResolver implements IPropertyResolver String expression = delegate.getPropertyExpression(); IPropertyExpressionResolver propertyExpressionResolver = Application.get().getApplicationSettings().getPropertyExpressionResolver(); - ObjectWithGetAndSet objectWithGetAndSet = propertyExpressionResolver.resolve(expression, target, target.getClass()); + ObjectWithGetAndSet objectWithGetAndSet = propertyExpressionResolver.resolve(expression, target, target.getClass(), IPropertyExpressionResolver.RESOLVE_CLASS); Method getter = objectWithGetAndSet.getGetter(); if (getter != null) http://git-wip-us.apache.org/repos/asf/wicket/blob/7fd219c3/wicket-core/src/main/java/org/apache/wicket/core/util/lang/DefaultPropertyLocator.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/core/util/lang/DefaultPropertyLocator.java b/wicket-core/src/main/java/org/apache/wicket/core/util/lang/DefaultPropertyLocator.java deleted file mode 100644 index c8803c7..0000000 --- a/wicket-core/src/main/java/org/apache/wicket/core/util/lang/DefaultPropertyLocator.java +++ /dev/null @@ -1,160 +0,0 @@ -package org.apache.wicket.core.util.lang; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.List; -import java.util.Map; - -import org.apache.wicket.WicketRuntimeException; -import org.apache.wicket.core.util.reflection.ArrayGetAndSet; -import org.apache.wicket.core.util.reflection.ArrayLengthGetAndSet; -import org.apache.wicket.core.util.reflection.FieldGetAndSet; -import org.apache.wicket.core.util.reflection.IGetAndSet; -import org.apache.wicket.core.util.reflection.IndexedPropertyGetAndSet; -import org.apache.wicket.core.util.reflection.ListGetAndSet; -import org.apache.wicket.core.util.reflection.MapGetAndSet; -import org.apache.wicket.core.util.reflection.MethodGetAndSet; -import org.apache.wicket.core.util.reflection.ReflectionUtility; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Default locator supporting <em>Java Beans</em> properties, maps, lists and method invocations. - */ -public class DefaultPropertyLocator implements IPropertyResolver -{ - public static final Logger log = LoggerFactory.getLogger(DefaultPropertyLocator.class); - - public IGetAndSet get(Class<?> clz, String exp) - { - IGetAndSet getAndSet = null; - - Method method = null; - Field field; - if (exp.startsWith("[")) - { - // if expression begins with [ skip method finding and use it as - // a key/index lookup on a map. - exp = exp.substring(1, exp.length() - 1); - } - else if (exp.endsWith("()")) - { - // if expression ends with (), don't test for setters just skip - // directly to method finding. - method = ReflectionUtility.findMethod(clz, exp); - } - else - { - method = ReflectionUtility.findGetter(clz, exp); - } - if (method == null) - { - if (List.class.isAssignableFrom(clz)) - { - try - { - int index = Integer.parseInt(exp); - getAndSet = new ListGetAndSet(index); - } - catch (NumberFormatException ex) - { - // can't parse the exp as an index, maybe the exp was a - // method. - method = ReflectionUtility.findMethod(clz, exp); - if (method != null) - { - getAndSet = new MethodGetAndSet(method, - MethodGetAndSet.findSetter(method, clz), null); - } - else - { - field = ReflectionUtility.findField(clz, exp); - if (field != null) - { - getAndSet = new FieldGetAndSet(field); - } - else - { - throw new WicketRuntimeException("The expression '" + exp - + "' is neither an index nor is it a method or field for the list " - + clz); - } - } - } - } - else if (Map.class.isAssignableFrom(clz)) - { - getAndSet = new MapGetAndSet(exp); - } - else if (clz.isArray()) - { - try - { - int index = Integer.parseInt(exp); - getAndSet = new ArrayGetAndSet(clz.getComponentType(), index); - } - catch (NumberFormatException ex) - { - if (exp.equals("length") || exp.equals("size")) - { - getAndSet = new ArrayLengthGetAndSet(); - } - else - { - throw new WicketRuntimeException("Can't parse the expression '" + exp - + "' as an index for an array lookup"); - } - } - } - else - { - field = ReflectionUtility.findField(clz, exp); - if (field == null) - { - method = ReflectionUtility.findMethod(clz, exp); - if (method == null) - { - int index = exp.indexOf('.'); - if (index != -1) - { - String propertyName = exp.substring(0, index); - String propertyIndex = exp.substring(index + 1); - try - { - int parsedIndex = Integer.parseInt(propertyIndex); - // if so then it could be a getPropertyIndex(int) - // and setPropertyIndex(int, object) - String name = Character.toUpperCase(propertyName.charAt(0)) - + propertyName.substring(1); - method = clz.getMethod(MethodGetAndSet.GET + name, - new Class[] { int.class }); - getAndSet = new IndexedPropertyGetAndSet(method, parsedIndex); - } - catch (Exception e) - { - throw new WicketRuntimeException("No get method defined for class: " - + clz + " expression: " + propertyName); - } - } - } - else - { - getAndSet = new MethodGetAndSet(method, - MethodGetAndSet.findSetter(method, clz), null); - } - } - else - { - getAndSet = new FieldGetAndSet(field); - } - } - } - else - { - field = ReflectionUtility.findField(clz, exp); - getAndSet = new MethodGetAndSet(method, MethodGetAndSet.findSetter(method, clz), field); - } - - return getAndSet; - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/wicket/blob/7fd219c3/wicket-core/src/main/java/org/apache/wicket/core/util/lang/IPropertyExpressionResolver.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/core/util/lang/IPropertyExpressionResolver.java b/wicket-core/src/main/java/org/apache/wicket/core/util/lang/IPropertyExpressionResolver.java index 4574be2..526d40c 100644 --- a/wicket-core/src/main/java/org/apache/wicket/core/util/lang/IPropertyExpressionResolver.java +++ b/wicket-core/src/main/java/org/apache/wicket/core/util/lang/IPropertyExpressionResolver.java @@ -10,6 +10,10 @@ import org.apache.wicket.core.util.reflection.ObjectWithGetAndSet; public interface IPropertyExpressionResolver { + int RETURN_NULL = 0; + int CREATE_NEW_VALUE = 1; + int RESOLVE_CLASS = 2; + /** * @param expression * @param object @@ -17,21 +21,7 @@ public interface IPropertyExpressionResolver * @param clz * @return {@link ObjectWithGetAndSet} */ - ObjectWithGetAndSet resolve(String expression, Object object, Class<? extends Object> clz); - - /** - * Creates a new value to each null property in the way to the expressed property. So the - * property expression: "attr1.attr2.attr3" would have "attr1" and "attr2" tested for null, in - * which case they would get new constructed values to guarantee a place to set the new value at - * "attr3" - * - * @param expression - * @param object - * @param value - * @param prc - */ - // TODO find a better name, multiple values are being setting here - // TODO if possible, to move to PropertyExpression - void setValue(String expression, Object object, Object value, PropertyResolverConverter prc); + ObjectWithGetAndSet resolve(String expression, Object object, Class<? extends Object> clz, + int tryToCreateNull); } http://git-wip-us.apache.org/repos/asf/wicket/blob/7fd219c3/wicket-core/src/main/java/org/apache/wicket/core/util/lang/IPropertyResolver.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/core/util/lang/IPropertyResolver.java b/wicket-core/src/main/java/org/apache/wicket/core/util/lang/IPropertyResolver.java deleted file mode 100644 index 65b7cdb..0000000 --- a/wicket-core/src/main/java/org/apache/wicket/core/util/lang/IPropertyResolver.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.apache.wicket.core.util.lang; - -import org.apache.wicket.core.util.reflection.IGetAndSet; - -/** - * Resolves a property string to an {@link IGetAndSet}. - * - * @see {@link IPropertyExpressionResolver} Property expression are resolved by - * {@link IPropertyExpressionResolver} implementations instead - * - * @author pedro - */ -public interface IPropertyResolver -{ - - IGetAndSet get(Class<?> clz, String exp); - -} http://git-wip-us.apache.org/repos/asf/wicket/blob/7fd219c3/wicket-core/src/main/java/org/apache/wicket/core/util/lang/OGNLPropertyExpressionResolver.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/core/util/lang/OGNLPropertyExpressionResolver.java b/wicket-core/src/main/java/org/apache/wicket/core/util/lang/OGNLPropertyExpressionResolver.java index 085adb3..1c74173 100644 --- a/wicket-core/src/main/java/org/apache/wicket/core/util/lang/OGNLPropertyExpressionResolver.java +++ b/wicket-core/src/main/java/org/apache/wicket/core/util/lang/OGNLPropertyExpressionResolver.java @@ -18,13 +18,23 @@ package org.apache.wicket.core.util.lang; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; -import org.apache.wicket.Application; -import org.apache.wicket.Session; import org.apache.wicket.WicketRuntimeException; -import org.apache.wicket.core.util.reflection.CachingPropertyLocator; +import org.apache.wicket.core.util.reflection.AbstractGetAndSet; +import org.apache.wicket.core.util.reflection.ArrayGetAndSet; +import org.apache.wicket.core.util.reflection.ArrayLengthGetAndSet; +import org.apache.wicket.core.util.reflection.FieldGetAndSet; import org.apache.wicket.core.util.reflection.IGetAndSet; +import org.apache.wicket.core.util.reflection.IndexedPropertyGetAndSet; +import org.apache.wicket.core.util.reflection.ListGetAndSet; +import org.apache.wicket.core.util.reflection.MapGetAndSet; +import org.apache.wicket.core.util.reflection.MethodGetAndSet; import org.apache.wicket.core.util.reflection.ObjectWithGetAndSet; +import org.apache.wicket.core.util.reflection.ReflectionUtility; +import org.apache.wicket.util.lang.Generics; import org.apache.wicket.util.string.Strings; /** @@ -63,147 +73,25 @@ import org.apache.wicket.util.string.Strings; public class OGNLPropertyExpressionResolver implements IPropertyExpressionResolver { - private final static int RETURN_NULL = 0; - private final static int CREATE_NEW_VALUE = 1; - private final static int RESOLVE_CLASS = 2; - private IPropertyResolver locator = new CachingPropertyLocator( new DefaultPropertyLocator()); - - - /** - * Looks up the value from the object with the given expression. If the expression, the object - * itself or one property evaluates to null then a null will be returned. - * - * @param expression - * The expression string with the property to be lookup. - * @param object - * The object which is evaluated. - * @return The value that is evaluated. Null something in the expression evaluated to null. - */ - //TODO remove, only being used in tests - public Object getValue(final String expression, final Object object) + private IPropertyLocator locator; + + public OGNLPropertyExpressionResolver() { - ObjectWithGetAndSet objectWithGetAndSet = getObjectWithGetAndSet(expression, object, - RETURN_NULL); - if (objectWithGetAndSet == null) - { - return null; - } - - return objectWithGetAndSet.getValue(); + this(new CachingPropertyLocator(new DefaultPropertyLocator())); } - /** - * Set the value on the object with the given expression. If the expression can't be evaluated - * then a WicketRuntimeException will be thrown. If a null object is encountered then it will - * try to generate it by calling the default constructor and set it on the object. - * - * The value will be tried to convert to the right type with the given converter. - * - * @param expression - * The expression string with the property to be set. - * @param object - * The object which is evaluated to set the value on. - * @param value - * The value to set. - * @param converter - * The converter to convert the value if needed to the right type. - * @throws WicketRuntimeException - */ - @Override - public void setValue(final String expression, final Object object, final Object value, - final PropertyResolverConverter converter) + public OGNLPropertyExpressionResolver(IPropertyLocator locator) { - if (Strings.isEmpty(expression)) - { - throw new WicketRuntimeException( - "Empty expression setting value: " + value + " on object: " + object); - } - if (object == null) - { - throw new WicketRuntimeException( - "Attempted to set property value on a null object. Property expression: " - + expression + " Value: " + value); - } - - ObjectWithGetAndSet objectWithGetAndSet = getObjectWithGetAndSet(expression, object, - CREATE_NEW_VALUE); - if (objectWithGetAndSet == null) - { - throw new WicketRuntimeException("Null object returned for expression: " + expression - + " for setting value: " + value + " on: " + object); - } - objectWithGetAndSet.setValue(value, - converter == null - ? new PropertyResolverConverter(Application.get().getConverterLocator(), - Session.get().getLocale()) - : converter); - } - - /** - /** - * @param expression - * @param object - * @return Field for the property expression - * @throws WicketRuntimeException - * if there is no such field - */ - public Field getPropertyField(final String expression, final Object object) - { - ObjectWithGetAndSet objectWithGetAndSet = getObjectWithGetAndSet(expression, object, - RESOLVE_CLASS); - if (objectWithGetAndSet == null) - { - throw new WicketRuntimeException("Null object returned for expression: " + expression - + " for getting the target class of: " + object); - } - return objectWithGetAndSet.getField(); - } - - /** - * @param expression - * @param object - * @return Getter method for the property expression - * @throws WicketRuntimeException - * if there is no getter method - */ - public Method getPropertyGetter(final String expression, final Object object) - { - ObjectWithGetAndSet objectWithGetAndSet = getObjectWithGetAndSet(expression, object, - RESOLVE_CLASS); - if (objectWithGetAndSet == null) - { - throw new WicketRuntimeException("Null object returned for expression: " + expression - + " for getting the target class of: " + object); - } - return objectWithGetAndSet.getGetter(); - } - - /** - * @param expression - * @param object - * @return Setter method for the property expression - * @throws WicketRuntimeException - * if there is no setter method - */ - public Method getPropertySetter(final String expression, final Object object) - { - ObjectWithGetAndSet objectWithGetAndSet = getObjectWithGetAndSet(expression, object, - RESOLVE_CLASS); - if (objectWithGetAndSet == null) - { - throw new WicketRuntimeException("Null object returned for expression: " + expression - + " for getting the target class of: " + object); - } - return objectWithGetAndSet.getSetter(); + this.locator = locator; } @Override - public ObjectWithGetAndSet resolve(String expression, Object object, Class<? extends Object> clz) + public ObjectWithGetAndSet resolve(String expression, Object object, Class<? extends Object> clz, int tryToCreateNull) { ObjectWithGetAndSet objectWithGetAndSet = getObjectWithGetAndSet(expression, object, - RESOLVE_CLASS, clz); - if (objectWithGetAndSet == null) + tryToCreateNull, clz); + if (objectWithGetAndSet == null && tryToCreateNull != RETURN_NULL) { throw new WicketRuntimeException("Null object returned for expression: " + expression + " for getting the target class of: " + clz); @@ -212,21 +100,6 @@ public class OGNLPropertyExpressionResolver implements IPropertyExpressionResolv } /** - * Just delegating the call to the original getObjectAndGetSetter passing the object type as - * parameter. - * - * @param expression - * @param object - * @param tryToCreateNull - * @return {@link ObjectWithGetAndSet} - */ - private ObjectWithGetAndSet getObjectWithGetAndSet(final String expression, - final Object object, int tryToCreateNull) - { - return getObjectWithGetAndSet(expression, object, tryToCreateNull, object.getClass()); - } - - /** * Receives the class parameter also, since this method can resolve the type for some * expression, only knowing the target class. * @@ -293,7 +166,7 @@ public class OGNLPropertyExpressionResolver implements IPropertyExpressionResolv } if (nextValue == null) { - if (tryToCreateNull == CREATE_NEW_VALUE) + if (tryToCreateNull == IPropertyExpressionResolver.CREATE_NEW_VALUE) { nextValue = getAndSet.newValue(value); if (nextValue == null) @@ -301,7 +174,7 @@ public class OGNLPropertyExpressionResolver implements IPropertyExpressionResolv return null; } } - else if (tryToCreateNull == RESOLVE_CLASS) + else if (tryToCreateNull == IPropertyExpressionResolver.RESOLVE_CLASS) { clz = getAndSet.getTargetClass(); } @@ -370,5 +243,223 @@ public class OGNLPropertyExpressionResolver implements IPropertyExpressionResolv return getAndSet; } + /** + * A locator of properties. + * + * @see https://issues.apache.org/jira/browse/WICKET-5623 + */ + public static interface IPropertyLocator + { + /** + * Get {@link IGetAndSet} for a property. + * + * @param clz owning class + * @param exp identifying the property + * @return getAndSet or {@code null} if non located + */ + IGetAndSet get(Class<?> clz, String exp); + } + + /** + * A wrapper for another {@link IPropertyLocator} that caches results of + * {@link #get(Class, String)}. + */ + public static class CachingPropertyLocator implements IPropertyLocator + { + private final ConcurrentHashMap<String, IGetAndSet> map = Generics.newConcurrentHashMap(16); + + /** + * Special token to put into the cache representing no located {@link IGetAndSet}. + */ + private IGetAndSet NONE = new AbstractGetAndSet() + { + + @Override + public Object getValue(Object object) + { + return null; + } + + @Override + public Object newValue(Object object) + { + return null; + } + + @Override + public void setValue(Object object, Object value, PropertyResolverConverter converter) + { + } + }; + + private IPropertyLocator resolver; + + public CachingPropertyLocator(IPropertyLocator locator) + { + this.resolver = locator; + } + + public IGetAndSet get(Class<?> clz, String exp) + { + String key = clz.getName() + "#" + exp; + + IGetAndSet located = map.get(key); + if (located == null) + { + located = resolver.get(clz, exp); + if (located == null) + { + located = NONE; + } + map.put(key, located); + } + + if (located == NONE) + { + located = null; + } + + return located; + } + } + + /** + * Default locator supporting <em>Java Beans</em> properties, maps, lists and method invocations. + */ + public static class DefaultPropertyLocator implements IPropertyLocator + { + + public IGetAndSet get(Class<?> clz, String exp) + { + IGetAndSet getAndSet = null; + Method method = null; + Field field; + if (exp.startsWith("[")) + { + // if expression begins with [ skip method finding and use it as + // a key/index lookup on a map. + exp = exp.substring(1, exp.length() - 1); + } + else if (exp.endsWith("()")) + { + // if expression ends with (), don't test for setters just skip + // directly to method finding. + method = ReflectionUtility.findMethod(clz, exp); + } + else + { + method = ReflectionUtility.findGetter(clz, exp); + } + if (method == null) + { + if (List.class.isAssignableFrom(clz)) + { + try + { + int index = Integer.parseInt(exp); + getAndSet = new ListGetAndSet(index); + } + catch (NumberFormatException ex) + { + // can't parse the exp as an index, maybe the exp was a + // method. + method = ReflectionUtility.findMethod(clz, exp); + if (method != null) + { + getAndSet = new MethodGetAndSet(method, + ReflectionUtility.findSetter(method, clz), null); + } + else + { + field = ReflectionUtility.findField(clz, exp); + if (field != null) + { + getAndSet = new FieldGetAndSet(field); + } + else + { + throw new WicketRuntimeException("The expression '" + exp + + "' is neither an index nor is it a method or field for the list " + + clz); + } + } + } + } + else if (Map.class.isAssignableFrom(clz)) + { + getAndSet = new MapGetAndSet(exp); + } + else if (clz.isArray()) + { + try + { + int index = Integer.parseInt(exp); + getAndSet = new ArrayGetAndSet(clz.getComponentType(), index); + } + catch (NumberFormatException ex) + { + if (exp.equals("length") || exp.equals("size")) + { + getAndSet = new ArrayLengthGetAndSet(); + } + else + { + throw new WicketRuntimeException("Can't parse the expression '" + exp + + "' as an index for an array lookup"); + } + } + } + else + { + field = ReflectionUtility.findField(clz, exp); + if (field == null) + { + method = ReflectionUtility.findMethod(clz, exp); + if (method == null) + { + int index = exp.indexOf('.'); + if (index != -1) + { + String propertyName = exp.substring(0, index); + String propertyIndex = exp.substring(index + 1); + try + { + int parsedIndex = Integer.parseInt(propertyIndex); + // if so then it could be a getPropertyIndex(int) + // and setPropertyIndex(int, object) + String name = Character.toUpperCase(propertyName.charAt(0)) + + propertyName.substring(1); + method = clz.getMethod(ReflectionUtility.GET + name, + new Class[] { int.class }); + getAndSet = new IndexedPropertyGetAndSet(method, parsedIndex); + } + catch (Exception e) + { + throw new WicketRuntimeException("No get method defined for class: " + + clz + " expression: " + propertyName); + } + } + } + else + { + getAndSet = new MethodGetAndSet(method, + ReflectionUtility.findSetter(method, clz), null); + } + } + else + { + getAndSet = new FieldGetAndSet(field); + } + } + } + else + { + field = ReflectionUtility.findField(clz, exp); + getAndSet = new MethodGetAndSet(method, ReflectionUtility.findSetter(method, clz), field); + } + + return getAndSet; + } + } } http://git-wip-us.apache.org/repos/asf/wicket/blob/7fd219c3/wicket-core/src/main/java/org/apache/wicket/core/util/lang/PropertyResolver.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/core/util/lang/PropertyResolver.java b/wicket-core/src/main/java/org/apache/wicket/core/util/lang/PropertyResolver.java index b7f87dc..ccbc0a9 100644 --- a/wicket-core/src/main/java/org/apache/wicket/core/util/lang/PropertyResolver.java +++ b/wicket-core/src/main/java/org/apache/wicket/core/util/lang/PropertyResolver.java @@ -16,37 +16,110 @@ */ package org.apache.wicket.core.util.lang; +import static org.apache.wicket.core.util.lang.IPropertyExpressionResolver.CREATE_NEW_VALUE; +import static org.apache.wicket.core.util.lang.IPropertyExpressionResolver.RESOLVE_CLASS; +import static org.apache.wicket.core.util.lang.IPropertyExpressionResolver.RETURN_NULL; + import org.apache.wicket.Application; +import org.apache.wicket.Session; +import org.apache.wicket.WicketRuntimeException; +import org.apache.wicket.core.util.reflection.ObjectWithGetAndSet; +import org.apache.wicket.util.string.Strings; /** - * Old {@link PropertyResolver} kept just as a facade for the current implementation + * Facade with common usages of the {@link ObjectWithGetAndSet} resolved by {@link Application}'s + * {@link IPropertyExpressionResolver} */ -@Deprecated public final class PropertyResolver { - - public static <T> T getValue(String expression, T object) + /** + * Looks up the value from the object with the given expression. If the expression, the object + * itself or one property evaluates to null then a null will be returned. + * + * @param expression + * The expression string with the property to be lookup. + * @param object + * The object which is evaluated. + * @return The value that is evaluated. Null something in the expression evaluated to null. + */ + public static Object getValue(String expression, Object object) { if (expression == null || expression.equals("") || object == null) { return object; } - IPropertyExpressionResolver propertyExpressionResolver = Application.get().getApplicationSettings().getPropertyExpressionResolver(); - return (T)propertyExpressionResolver.resolve(expression, object, object.getClass()).getValue(); + IPropertyExpressionResolver propertyExpressionResolver = Application.get() + .getApplicationSettings().getPropertyExpressionResolver(); + ObjectWithGetAndSet property = propertyExpressionResolver.resolve(expression, object, + object.getClass(), RETURN_NULL); + return property == null ? null : property.getValue(false); } - public static <T> Class<T> getPropertyClass(String expression, Object object, - Class<?> targetClass) + /** + * @param expression + * @param object + * @param targetClass + * @return class of the target property object + * @throws WicketRuntimeException + * if the cannot be resolved + */ + public static Class<?> getPropertyClass(String expression, Object object, Class<?> targetClass) { - IPropertyExpressionResolver propertyExpressionResolver = Application.get().getApplicationSettings().getPropertyExpressionResolver(); - return (Class<T>)propertyExpressionResolver.resolve(expression, object, targetClass).getTargetClass(); + IPropertyExpressionResolver propertyExpressionResolver = Application.get() + .getApplicationSettings().getPropertyExpressionResolver(); + ObjectWithGetAndSet objectWithGetAndSet = propertyExpressionResolver.resolve(expression, + object, targetClass, RESOLVE_CLASS); + if (objectWithGetAndSet == null) + { + throw new WicketRuntimeException("No Class returned for expression: " + expression + + " for getting the target class of: " + targetClass); + } + return objectWithGetAndSet.getTargetClass(); } + /** + * Set the value on the object with the given expression. If the expression can't be evaluated + * then a WicketRuntimeException will be thrown. If a null object is encountered then it will + * try to generate it by calling the default constructor and set it on the object. + * + * The value will be tried to convert to the right type with the given converter. + * + * @param expression + * The expression string with the property to be set. + * @param object + * The object which is evaluated to set the value on. + * @param value + * The value to set. + * @param converter + * The converter to convert the value if needed to the right type. + * @throws WicketRuntimeException + */ public static void setValue(String expression, Object object, Object value, PropertyResolverConverter prc) { - Application.get().getApplicationSettings().getPropertyExpressionResolver() - .setValue(expression, object, value, prc); + IPropertyExpressionResolver propertyExpressionResolver = Application.get() + .getApplicationSettings().getPropertyExpressionResolver(); + + if (Strings.isEmpty(expression)) + { + throw new WicketRuntimeException( + "Empty expression setting value: " + value + " on object: " + object); + } + if (object == null) + { + throw new WicketRuntimeException( + "Attempted to set property value on a null object. Property expression: " + + expression + " Value: " + value); + } + + ObjectWithGetAndSet objectWithGetAndSet = propertyExpressionResolver.resolve(expression, + object, object.getClass(), CREATE_NEW_VALUE); + + objectWithGetAndSet.setValue(value, + prc == null + ? new PropertyResolverConverter(Application.get().getConverterLocator(), + Session.get().getLocale()) + : prc); } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/wicket/blob/7fd219c3/wicket-core/src/main/java/org/apache/wicket/core/util/parser/ParsedPropertyExpressionResolver.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/core/util/parser/ParsedPropertyExpressionResolver.java b/wicket-core/src/main/java/org/apache/wicket/core/util/parser/ParsedPropertyExpressionResolver.java new file mode 100644 index 0000000..34847e4 --- /dev/null +++ b/wicket-core/src/main/java/org/apache/wicket/core/util/parser/ParsedPropertyExpressionResolver.java @@ -0,0 +1,173 @@ +package org.apache.wicket.core.util.parser; + +import static java.lang.Integer.parseInt; +import static org.apache.wicket.core.util.reflection.ReflectionUtility.findField; +import static org.apache.wicket.core.util.reflection.ReflectionUtility.findGetter; +import static org.apache.wicket.core.util.reflection.ReflectionUtility.findMethod; +import static org.apache.wicket.core.util.reflection.ReflectionUtility.findPositionGetter; +import static org.apache.wicket.core.util.reflection.ReflectionUtility.findSetter; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.List; +import java.util.Map; + +import org.apache.wicket.WicketRuntimeException; +import org.apache.wicket.core.util.lang.IPropertyExpressionResolver; +import org.apache.wicket.core.util.reflection.ArrayGetAndSet; +import org.apache.wicket.core.util.reflection.ArrayLengthGetAndSet; +import org.apache.wicket.core.util.reflection.FieldGetAndSet; +import org.apache.wicket.core.util.reflection.IGetAndSet; +import org.apache.wicket.core.util.reflection.IndexedPropertyGetAndSet; +import org.apache.wicket.core.util.reflection.ListGetAndSet; +import org.apache.wicket.core.util.reflection.MapGetAndSet; +import org.apache.wicket.core.util.reflection.MethodGetAndSet; +import org.apache.wicket.core.util.reflection.ObjectWithGetAndSet; + +public class ParsedPropertyExpressionResolver implements IPropertyExpressionResolver +{ + @Override + public ObjectWithGetAndSet resolve(String expression, Object object, + Class<? extends Object> clz, int tryToCreateNull) + { + PropertyExpression ast = new PropertyExpressionParser().parse(expression); + return resolveExpression(ast, object, clz, tryToCreateNull); + } + + public ObjectWithGetAndSet resolveExpression(PropertyExpression ast, Object object, + Class<?> clz, int tryToCreateNull) + { + + IGetAndSet getAndSet = resolveProperty(clz, ast); + + if (getAndSet == null + && (ast.index != null || ast.next != null && ast.next.canDefaultToIndex())) + { + getAndSet = resolvePropertyAtPosition(clz, ast.getPropertyToken(), + ast.index != null ? ast.index : ast.next.toIndex()); + + if (getAndSet != null && ast.index == null) + ast = ast.next; + } + + if (getAndSet == null && ast.canDefaultToIndex()) + getAndSet = resolveIndex(clz, ast.toIndex()); + + if (getAndSet == null)// ok, finally give up + throw new WicketRuntimeException("Can't parse the expression '" + ast); + + ObjectWithGetAndSet resolved = new ObjectWithGetAndSet(getAndSet, object); + + if (ast.javaProperty != null && ast.javaProperty.index != null) + { + getAndSet = resolveIndex(getAndSet.getTargetClass(), ast.javaProperty.index); + resolved = new ObjectWithGetAndSet(getAndSet, + resolved.getValue(tryToCreateNull == CREATE_NEW_VALUE)); + } + if (ast.beanProperty != null && ast.beanProperty.index != null) + { + getAndSet = resolveIndex(getAndSet.getTargetClass(), ast.beanProperty.index); + resolved = new ObjectWithGetAndSet(getAndSet, + resolved.getValue(tryToCreateNull == CREATE_NEW_VALUE)); + } + + if (ast.next == null) + return resolved; + + Object nextValue = resolved.getValue(tryToCreateNull == CREATE_NEW_VALUE); + Class<?> nextClass = nextValue != null ? nextValue.getClass() : resolved.getTargetClass(); + + if (nextValue == null && tryToCreateNull == RETURN_NULL) + return null; + + return resolveExpression(ast.next, nextValue, nextClass, tryToCreateNull); + + } + + private IGetAndSet resolveProperty(Class<?> clz, PropertyExpression ast) + { + if (ast.javaProperty != null) + return resolveJavaProperty(clz, ast); + else if (ast.beanProperty != null) + return resolveBeanProperty(clz, ast); + else if (ast.index != null) + return resolveIndex(clz, ast.index); + else + throw new WicketRuntimeException("Resolver failed to find a property to resolve"); + } + + private IGetAndSet resolveJavaProperty(Class<?> clz, PropertyExpression ast) + { + if (ast.javaProperty.hasMethodSign) + { + Method method = findMethod(clz, ast.javaProperty.javaIdentifier); + return new MethodGetAndSet(method, findSetter(method, clz), null); + } + else + { + Method method = findGetter(clz, ast.javaProperty.javaIdentifier); + Field field = findField(clz, ast.javaProperty.javaIdentifier); + + if (method == null && field == null) + return null; + else if (method == null) + return new FieldGetAndSet(field); + else + return new MethodGetAndSet(method, findSetter(method, clz), field); + } + } + + private IGetAndSet resolveBeanProperty(Class<?> clz, PropertyExpression ast) + { + Method method = findGetter(clz, ast.beanProperty.propertyName); + + return method == null ? null : new MethodGetAndSet(method, findSetter(method, clz), null); + } + + private IGetAndSet resolveIndex(Class<?> clz, String index) + { + if (List.class.isAssignableFrom(clz)) + { + int position = Integer.parseInt(index); + return new ListGetAndSet(position); + } + else if (Map.class.isAssignableFrom(clz)) + { + return new MapGetAndSet(index); + } + else if (clz.isArray()) + { + try + { + int position = Integer.parseInt(index); + return new ArrayGetAndSet(clz.getComponentType(), position); + } + catch (NumberFormatException ex) + { + if (index.equals("length") || index.equals("size")) + { + return new ArrayLengthGetAndSet(); + } + throw new WicketRuntimeException( + "Can't parse the expression '" + index + "' as an index for an array lookup"); + } + } + return null; + } + + private IGetAndSet resolvePropertyAtPosition(Class<?> clz, String property, String position) + { + Method method = findPositionGetter(clz, property); + if (method == null) + return null; + try + { + return new IndexedPropertyGetAndSet(method, parseInt(position)); + } + catch (NumberFormatException e) + { + return null; + } + } + +} http://git-wip-us.apache.org/repos/asf/wicket/blob/7fd219c3/wicket-core/src/main/java/org/apache/wicket/core/util/parser/PropertyExpression.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/core/util/parser/PropertyExpression.java b/wicket-core/src/main/java/org/apache/wicket/core/util/parser/PropertyExpression.java index 2cd5e6d..1030b26 100644 --- a/wicket-core/src/main/java/org/apache/wicket/core/util/parser/PropertyExpression.java +++ b/wicket-core/src/main/java/org/apache/wicket/core/util/parser/PropertyExpression.java @@ -28,6 +28,31 @@ public class PropertyExpression String index; PropertyExpression next; + public String getPropertyToken() + { + if (javaProperty != null) + return javaProperty.javaIdentifier; + else if (beanProperty != null) + return beanProperty.propertyName; + return null; + } + + public boolean canDefaultToIndex() + { + return (javaProperty != null && (javaProperty.index == null && !javaProperty.hasMethodSign)) + || (beanProperty != null && beanProperty.index == null); + } + + public String toIndex() + { + if (index != null) + return index; + else if (javaProperty != null) + return javaProperty.javaIdentifier; + else + return beanProperty.propertyName; + } + static class BeanProperty { String propertyName; http://git-wip-us.apache.org/repos/asf/wicket/blob/7fd219c3/wicket-core/src/main/java/org/apache/wicket/core/util/parser/PropertyExpressionResolver.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/core/util/parser/PropertyExpressionResolver.java b/wicket-core/src/main/java/org/apache/wicket/core/util/parser/PropertyExpressionResolver.java deleted file mode 100644 index fd976aa..0000000 --- a/wicket-core/src/main/java/org/apache/wicket/core/util/parser/PropertyExpressionResolver.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.apache.wicket.core.util.parser; - -import org.apache.wicket.core.util.lang.IPropertyExpressionResolver; -import org.apache.wicket.core.util.lang.PropertyResolverConverter; -import org.apache.wicket.core.util.reflection.ObjectWithGetAndSet; - -public class PropertyExpressionResolver implements IPropertyExpressionResolver -{ - @Override - public ObjectWithGetAndSet resolve(String expression, Object object, Class<? extends Object> clz) - { - return null; - } - - @Override - public void setValue(String expression, Object object, Object value, PropertyResolverConverter prc) - { - - } - -} http://git-wip-us.apache.org/repos/asf/wicket/blob/7fd219c3/wicket-core/src/main/java/org/apache/wicket/core/util/reflection/CachingPropertyLocator.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/core/util/reflection/CachingPropertyLocator.java b/wicket-core/src/main/java/org/apache/wicket/core/util/reflection/CachingPropertyLocator.java deleted file mode 100644 index 78fafc1..0000000 --- a/wicket-core/src/main/java/org/apache/wicket/core/util/reflection/CachingPropertyLocator.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.apache.wicket.core.util.reflection; - -import java.util.concurrent.ConcurrentHashMap; - -import org.apache.wicket.core.util.lang.IPropertyResolver; -import org.apache.wicket.core.util.lang.PropertyResolverConverter; -import org.apache.wicket.util.lang.Generics; - -/** - * A wrapper for another {@link IPropertyLocator} that caches results of - * {@link #get(Class, String)}. - */ -public class CachingPropertyLocator implements IPropertyResolver -{ - private final ConcurrentHashMap<String, IGetAndSet> map = Generics.newConcurrentHashMap(16); - - /** - * Special token to put into the cache representing no located {@link IGetAndSet}. - */ - private IGetAndSet NONE = new AbstractGetAndSet() - { - - @Override - public Object getValue(Object object) - { - return null; - } - - @Override - public Object newValue(Object object) - { - return null; - } - - @Override - public void setValue(Object object, Object value, PropertyResolverConverter converter) - { - } - }; - - private IPropertyResolver resolver; - - public CachingPropertyLocator(IPropertyResolver locator) - { - this.resolver = locator; - } - - public IGetAndSet get(Class<?> clz, String exp) - { - String key = clz.getName() + "#" + exp; - - IGetAndSet located = map.get(key); - if (located == null) - { - located = resolver.get(clz, exp); - if (located == null) - { - located = NONE; - } - map.put(key, located); - } - - if (located == NONE) - { - located = null; - } - - return located; - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/wicket/blob/7fd219c3/wicket-core/src/main/java/org/apache/wicket/core/util/reflection/IndexedPropertyGetAndSet.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/core/util/reflection/IndexedPropertyGetAndSet.java b/wicket-core/src/main/java/org/apache/wicket/core/util/reflection/IndexedPropertyGetAndSet.java index 1eac5af..96fdceb 100644 --- a/wicket-core/src/main/java/org/apache/wicket/core/util/reflection/IndexedPropertyGetAndSet.java +++ b/wicket-core/src/main/java/org/apache/wicket/core/util/reflection/IndexedPropertyGetAndSet.java @@ -26,7 +26,7 @@ public final class IndexedPropertyGetAndSet extends AbstractGetAndSet private static Method findSetter(final Method getMethod, final Class<?> clz) { String name = getMethod.getName(); - name = MethodGetAndSet.SET + name.substring(3); + name = ReflectionUtility.SET + name.substring(3); try { return clz.getMethod(name, new Class[] { int.class, getMethod.getReturnType() }); http://git-wip-us.apache.org/repos/asf/wicket/blob/7fd219c3/wicket-core/src/main/java/org/apache/wicket/core/util/reflection/MethodGetAndSet.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/core/util/reflection/MethodGetAndSet.java b/wicket-core/src/main/java/org/apache/wicket/core/util/reflection/MethodGetAndSet.java index 6765dbf..c7fc13a 100644 --- a/wicket-core/src/main/java/org/apache/wicket/core/util/reflection/MethodGetAndSet.java +++ b/wicket-core/src/main/java/org/apache/wicket/core/util/reflection/MethodGetAndSet.java @@ -12,10 +12,7 @@ import org.slf4j.LoggerFactory; public final class MethodGetAndSet extends AbstractGetAndSet { - private static final Logger log = LoggerFactory.getLogger(MethodGetAndSet.class); - public static final String GET = "get"; - public static final String IS = "is"; - public static final String SET = "set"; + static final Logger log = LoggerFactory.getLogger(MethodGetAndSet.class); private final Method getMethod; private final Method setMethod; @@ -133,52 +130,6 @@ public final class MethodGetAndSet extends AbstractGetAndSet } } - public static Method findSetter(Method getMethod, Class<?> clz) - { - String name = getMethod.getName(); - if (name.startsWith(GET)) - { - name = SET + name.substring(3); - } - else - { - name = SET + name.substring(2); - } - try - { - Method method = clz.getMethod(name, new Class[] { getMethod.getReturnType() }); - if (method != null) - { - method.setAccessible(true); - } - return method; - } - catch (NoSuchMethodException e) - { - Method[] methods = clz.getMethods(); - for (Method method : methods) - { - if (method.getName().equals(name)) - { - Class<?>[] parameterTypes = method.getParameterTypes(); - if (parameterTypes.length == 1) - { - if (parameterTypes[0].isAssignableFrom(getMethod.getReturnType())) - { - return method; - } - } - } - } - log.debug("Cannot find setter corresponding to " + getMethod); - } - catch (Exception e) - { - log.debug("Cannot find setter corresponding to " + getMethod); - } - return null; - } - /** * {@inheritDoc} */ http://git-wip-us.apache.org/repos/asf/wicket/blob/7fd219c3/wicket-core/src/main/java/org/apache/wicket/core/util/reflection/ObjectWithGetAndSet.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/core/util/reflection/ObjectWithGetAndSet.java b/wicket-core/src/main/java/org/apache/wicket/core/util/reflection/ObjectWithGetAndSet.java index 4dec997..f6b1aa5 100644 --- a/wicket-core/src/main/java/org/apache/wicket/core/util/reflection/ObjectWithGetAndSet.java +++ b/wicket-core/src/main/java/org/apache/wicket/core/util/reflection/ObjectWithGetAndSet.java @@ -34,11 +34,15 @@ public class ObjectWithGetAndSet } /** + * @param createIfNull if the value should be created in case the property is null * @return The value */ - public Object getValue() + public Object getValue(boolean createIfNull) { - return getAndSet.getValue(value); + Object propertyValue = getAndSet.getValue(value); + if(propertyValue == null && createIfNull) + propertyValue = getAndSet.newValue(value); + return propertyValue; } /** http://git-wip-us.apache.org/repos/asf/wicket/blob/7fd219c3/wicket-core/src/main/java/org/apache/wicket/core/util/reflection/ReflectionUtility.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/core/util/reflection/ReflectionUtility.java b/wicket-core/src/main/java/org/apache/wicket/core/util/reflection/ReflectionUtility.java index caa0fed..e035d4b 100644 --- a/wicket-core/src/main/java/org/apache/wicket/core/util/reflection/ReflectionUtility.java +++ b/wicket-core/src/main/java/org/apache/wicket/core/util/reflection/ReflectionUtility.java @@ -3,11 +3,17 @@ package org.apache.wicket.core.util.reflection; import java.lang.reflect.Field; import java.lang.reflect.Method; -import org.apache.wicket.core.util.lang.DefaultPropertyLocator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class ReflectionUtility { + private static final Logger log = LoggerFactory.getLogger(ReflectionUtility.class); + public static final String GET = "get"; + private static final String IS = "is"; + public static final String SET = "set"; + /** * @param clz * @param expression @@ -36,7 +42,7 @@ public class ReflectionUtility } tmp = tmp.getSuperclass(); } - DefaultPropertyLocator.log.debug("Cannot find field " + clz + "." + expression); + log.debug("Cannot find field " + clz + "." + expression); } return field; } @@ -52,7 +58,7 @@ public class ReflectionUtility Method method = null; try { - method = clz.getMethod(MethodGetAndSet.GET + name, (Class[])null); + method = clz.getMethod(GET + name, (Class[])null); } catch (Exception ignored) { @@ -61,11 +67,11 @@ public class ReflectionUtility { try { - method = clz.getMethod(MethodGetAndSet.IS + name, (Class[])null); + method = clz.getMethod(IS + name, (Class[])null); } catch (Exception e) { - DefaultPropertyLocator.log.debug("Cannot find getter " + clz + "." + expression); + log.debug("Cannot find getter " + clz + "." + expression); } } return method; @@ -84,9 +90,69 @@ public class ReflectionUtility } catch (Exception e) { - DefaultPropertyLocator.log.debug("Cannot find method " + clz + "." + expression); + log.debug("Cannot find method " + clz + "." + expression); } return method; } + public static Method findPositionGetter(Class<?> clz, String property) + { + String name = Character.toUpperCase(property.charAt(0)) + property.substring(1); + try + { + return clz.getMethod(GET + name, new Class[] { int.class }); + } + catch (Exception e) + { + log.debug("Cannot find method " + clz + "." + name + "(int)"); + return null; + } + } + + public static Method findSetter(Method getMethod, Class<?> clz) + { + String name = getMethod.getName(); + if (name.startsWith(GET)) + { + name = SET + name.substring(3); + } + else + { + name = SET + name.substring(2); + } + try + { + Method method = clz.getMethod(name, new Class[] { getMethod.getReturnType() }); + if (method != null) + { + method.setAccessible(true); + } + return method; + } + catch (NoSuchMethodException e) + { + Method[] methods = clz.getMethods(); + for (Method method : methods) + { + if (method.getName().equals(name)) + { + Class<?>[] parameterTypes = method.getParameterTypes(); + if (parameterTypes.length == 1) + { + if (parameterTypes[0].isAssignableFrom(getMethod.getReturnType())) + { + return method; + } + } + } + } + log.debug("Cannot find setter corresponding to " + getMethod); + } + catch (Exception e) + { + log.debug("Cannot find setter corresponding to " + getMethod); + } + return null; + } + } http://git-wip-us.apache.org/repos/asf/wicket/blob/7fd219c3/wicket-core/src/main/java/org/apache/wicket/model/AbstractPropertyModel.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/model/AbstractPropertyModel.java b/wicket-core/src/main/java/org/apache/wicket/model/AbstractPropertyModel.java index 4c48366..4db3ddc 100644 --- a/wicket-core/src/main/java/org/apache/wicket/model/AbstractPropertyModel.java +++ b/wicket-core/src/main/java/org/apache/wicket/model/AbstractPropertyModel.java @@ -159,7 +159,7 @@ public abstract class AbstractPropertyModel<T> extends ChainingModel<T> Class<?> targetClass = ((IObjectClassAwareModel<?>) getTarget()).getObjectClass(); if (targetClass != null) { - return PropertyResolver.getPropertyClass(expression, null, targetClass); + return (Class<T>)PropertyResolver.getPropertyClass(expression, null, targetClass); } } catch (WicketRuntimeException e) http://git-wip-us.apache.org/repos/asf/wicket/blob/7fd219c3/wicket-core/src/test/java/org/apache/wicket/core/util/parser/ParsedPropertyExpressionResolverTest.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/core/util/parser/ParsedPropertyExpressionResolverTest.java b/wicket-core/src/test/java/org/apache/wicket/core/util/parser/ParsedPropertyExpressionResolverTest.java new file mode 100644 index 0000000..aa00732 --- /dev/null +++ b/wicket-core/src/test/java/org/apache/wicket/core/util/parser/ParsedPropertyExpressionResolverTest.java @@ -0,0 +1,103 @@ +/* + * 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.core.util.parser; + +import static org.hamcrest.CoreMatchers.is; + +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import org.apache.wicket.ConverterLocator; +import org.apache.wicket.core.util.lang.IPropertyExpressionResolver; +import org.apache.wicket.core.util.lang.PropertyResolver; +import org.apache.wicket.core.util.lang.PropertyResolverConverter; +import org.apache.wicket.util.lang.Person; +import org.apache.wicket.util.lang.WeirdList; +import org.apache.wicket.util.lang.WeirdMap; +import org.apache.wicket.util.tester.WicketTestCase; +import org.junit.Before; +import org.junit.Test; + +public class ParsedPropertyExpressionResolverTest extends WicketTestCase +{ + + private static final Integer AN_INTEGER = 10; + private static final Integer ANOTHER_INTEGER = 11; + private static final PropertyResolverConverter CONVERTER = new PropertyResolverConverter( + new ConverterLocator(), Locale.US); + + private IPropertyExpressionResolver resolver = new ParsedPropertyExpressionResolver(); + private Person person = new Person(); + private Map<String, Integer> integerMap = new HashMap<String, Integer>(); + private WeirdMap map = new WeirdMap(); + private WeirdList list = new WeirdList(); + + @Before + public void before() + { + tester.getApplication().getApplicationSettings().setPropertyExpressionResolver(resolver); + } + + @Test + public void shouldAllowEmptySpacesInsideMethodCallBrackets() throws Exception + { + person.setName("bob"); + assertThat("bob", is(PropertyResolver.getValue("person.getName( )", this))); + } + + @Test + public void shouldAllowMapKeysWithSpecialCharactersIncludingOpenSquareBracket() throws Exception + { + String code = "!@#$%^&*()_+-=[{}|"; + String expression = "[" + code + "]"; + PropertyResolver.setValue(expression, integerMap, AN_INTEGER, CONVERTER); + assertThat(PropertyResolver.getValue(expression, integerMap), is(AN_INTEGER)); + assertThat(integerMap.get(code), is(AN_INTEGER)); + } + + @Test + public void shouldGetValueAtAListPosition() throws Exception + { + list.add(null); + PropertyResolver.setValue("valueAt.0", list, AN_INTEGER, CONVERTER); + assertThat(list.get(0), is(AN_INTEGER)); + } + + @Test + public void shouldGetValueAtAMapPosition() throws Exception + { + PropertyResolver.setValue("valueAt.0", map, AN_INTEGER, CONVERTER); + assertThat(map.getValueAt(0), is(AN_INTEGER)); + } + + /** + * https://issues.apache.org/jira/browse/WICKET-6327 + */ + @Test + public void shouldGetValueInAField() throws Exception + { + map.field = AN_INTEGER; + map.put("field", ANOTHER_INTEGER); + list.field = AN_INTEGER; + assertThat(PropertyResolver.getValue("map.field", this), is(AN_INTEGER)); + assertThat(PropertyResolver.getValue("map[field]", this), is(ANOTHER_INTEGER)); + assertThat(PropertyResolver.getValue("list.field", this), is(AN_INTEGER)); + + } + +} http://git-wip-us.apache.org/repos/asf/wicket/blob/7fd219c3/wicket-core/src/test/java/org/apache/wicket/core/util/parser/PropertyExpressionParserTest.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/core/util/parser/PropertyExpressionParserTest.java b/wicket-core/src/test/java/org/apache/wicket/core/util/parser/PropertyExpressionParserTest.java index da043f2..c0b6d9b 100644 --- a/wicket-core/src/test/java/org/apache/wicket/core/util/parser/PropertyExpressionParserTest.java +++ b/wicket-core/src/test/java/org/apache/wicket/core/util/parser/PropertyExpressionParserTest.java @@ -1,3 +1,19 @@ +/* + * 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.core.util.parser; import static org.hamcrest.CoreMatchers.is; http://git-wip-us.apache.org/repos/asf/wicket/blob/7fd219c3/wicket-core/src/test/java/org/apache/wicket/util/lang/OGNLPropertyExpressionResolverTest.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/util/lang/OGNLPropertyExpressionResolverTest.java b/wicket-core/src/test/java/org/apache/wicket/util/lang/OGNLPropertyExpressionResolverTest.java index af87541..7baf210 100644 --- a/wicket-core/src/test/java/org/apache/wicket/util/lang/OGNLPropertyExpressionResolverTest.java +++ b/wicket-core/src/test/java/org/apache/wicket/util/lang/OGNLPropertyExpressionResolverTest.java @@ -16,922 +16,88 @@ */ package org.apache.wicket.util.lang; -import static org.hamcrest.CoreMatchers.is; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Vector; - -import org.apache.wicket.ConverterLocator; -import org.apache.wicket.IConverterLocator; -import org.apache.wicket.WicketRuntimeException; -import org.apache.wicket.core.util.lang.DefaultPropertyLocator; import org.apache.wicket.core.util.lang.OGNLPropertyExpressionResolver; +import org.apache.wicket.core.util.lang.OGNLPropertyExpressionResolver.DefaultPropertyLocator; +import org.apache.wicket.core.util.lang.OGNLPropertyExpressionResolver.IPropertyLocator; import org.apache.wicket.core.util.lang.PropertyResolver; import org.apache.wicket.core.util.lang.PropertyResolverConverter; import org.apache.wicket.core.util.reflection.AbstractGetAndSet; -import org.apache.wicket.core.util.reflection.CachingPropertyLocator; import org.apache.wicket.core.util.reflection.IGetAndSet; -import org.apache.wicket.util.convert.ConversionException; -import org.apache.wicket.util.convert.IConverter; -import org.apache.wicket.util.convert.converter.AbstractConverter; import org.apache.wicket.util.tester.WicketTestCase; -import org.junit.After; -import org.junit.Before; import org.junit.Test; -/** - * @author jcompagner - * - */ public class OGNLPropertyExpressionResolverTest extends WicketTestCase { - - private static final PropertyResolverConverter CONVERTER = new PropertyResolverConverter( - new ConverterLocator(), Locale.US); - OGNLPropertyExpressionResolver ognlResolver = new OGNLPropertyExpressionResolver(); - - private static final int AN_INTEGER = 10; - private Person person; - private Map<String, Integer> integerMap = new HashMap<String, Integer>(); - private WeirdList integerList = new WeirdList(); - - /** - * @throws Exception - */ - @Before - public void before() - { - person = new Person(); - } - - /** - * @throws Exception - */ - @After - public void after() - { -// ognlResolver.destroy(tester.getApplication()); - } + private OGNLPropertyExpressionResolver ognlResolver = new OGNLPropertyExpressionResolver( + new CustomGetAndSetLocator()); /** - * @throws Exception + * WICKET-5623 custom properties */ @Test - public void simpleExpression() throws Exception + public void custom() { - String name = (String)ognlResolver.getValue("name", person); - assertNull(name); - - ognlResolver.setValue("name", person, "wicket", CONVERTER); - name = (String)ognlResolver.getValue("name", person); - assertEquals(name, "wicket"); - } - - /** - * @throws Exception - */ - @Test(expected = ConversionException.class) - public void primitiveValue() throws Exception - { - Integer integer = (Integer)ognlResolver.getValue("age", person); - assertTrue(integer == 0); - - ognlResolver.setValue("age", person, 10, CONVERTER); - integer = (Integer)ognlResolver.getValue("age", person); - assertTrue(integer == 10); + tester.getApplication().getApplicationSettings() + .setPropertyExpressionResolver(ognlResolver); - ognlResolver.setValue("age", person, null, CONVERTER); - fail("primitive type can't be set to null"); + Document document = new Document(); + document.setType("type"); + document.setProperty("string", "string"); - } - - /** - * @throws Exception - */ - @Test - public void pathExpression() throws Exception - { - person.setAddress(new Address()); - ognlResolver.setValue("address.street", person, "wicket-street", - CONVERTER); - String street = (String)ognlResolver.getValue("address.street", person); - assertEquals(street, "wicket-street"); + Document nestedCustom = new Document(); + nestedCustom.setProperty("string", "string2"); + document.setProperty("nested", nestedCustom); + assertEquals("type", PropertyResolver.getValue("type", document)); + assertEquals("string", PropertyResolver.getValue("string", document)); + assertEquals("string2", PropertyResolver.getValue("nested.string", document)); } - /** - * @throws Exception - */ - @Test - public void testNull() throws Exception + class CustomGetAndSetLocator implements IPropertyLocator { - String street = (String)ognlResolver.getValue("address.street", person); - assertNull(street); - } - /** - * @throws Exception - */ - @Test - public void nullCreation() throws Exception - { - ognlResolver.setValue("address.street", person, "wicket-street", - CONVERTER); - String street = (String)ognlResolver.getValue("address.street", person); - assertEquals(street, "wicket-street"); + private IPropertyLocator locator = new DefaultPropertyLocator(); - try + @Override + public IGetAndSet get(Class<?> clz, String exp) { - ognlResolver.setValue("country.name", person, "US", CONVERTER); - fail("name can't be set on a country that doesn't have default constructor"); - } - catch (WicketRuntimeException ex) - { - } - } - - /** - * @throws Exception - */ - @Test - public void getterOnly() throws Exception - { - ognlResolver.setValue("country", person, new Country("US"), CONVERTER); - ognlResolver.getValue("country.name", person); - - try - { - ognlResolver.setValue("country.name", person, "NL", CONVERTER); - } - catch (WicketRuntimeException ex) - { - } - } - - /** - * @throws Exception - */ - @Test - public void pathExpressionWithConversion() throws Exception - { - person.setAddress(new Address()); - ognlResolver.setValue("address.number", person, "10", CONVERTER); - Integer number = (Integer)ognlResolver.getValue("address.number", person); - assertEquals(number, new Integer(10)); - - try - { - ognlResolver.setValue("address.number", person, "10a", CONVERTER); - throw new Exception("Conversion error should be thrown"); - } - catch (ConversionException ex) - { - } - - } - - /** - * @throws Exception - */ - @Test - public void mapLookup() throws Exception - { - Address address = new Address(); - ognlResolver.setValue("addressMap", person, - new HashMap<String, Address>(), CONVERTER); - ognlResolver.setValue("addressMap.address", person, address, CONVERTER); - ognlResolver.setValue("addressMap.address.street", person, - "wicket-street", CONVERTER); - String street = (String)ognlResolver.getValue("addressMap.address.street", - person); - assertEquals(street, "wicket-street"); - } - - /** - * @throws Exception - */ - @Test - public void mapWithDotLookup() throws Exception - { - Address address = new Address(); - HashMap<String, Address> hm = new HashMap<String, Address>(); - ognlResolver.setValue("addressMap", person, hm, CONVERTER); - ognlResolver.setValue("addressMap[address.test]", person, address, - CONVERTER); - assertNotNull(hm.get("address.test")); - ognlResolver.setValue("addressMap[address.test].street", person, - "wicket-street", CONVERTER); - String street = (String)ognlResolver - .getValue("addressMap[address.test].street", person); - assertEquals(street, "wicket-street"); - } - - /** - * @throws Exception - */ - @Test - public void listLookup() throws Exception - { - ognlResolver.setValue("addressList", person, new ArrayList<Address>(), - CONVERTER); - ognlResolver.setValue("addressList.0", person, new Address(), CONVERTER); - ognlResolver.setValue("addressList.10", person, new Address(), CONVERTER); - ognlResolver.setValue("addressList.1", person, new Address(), CONVERTER); - ognlResolver.setValue("addressList.1.street", person, "wicket-street", - CONVERTER); - - String street = (String)ognlResolver.getValue("addressList.0.street", - person); - assertNull(street); - street = (String)ognlResolver.getValue("addressList.1.street", person); - assertEquals(street, "wicket-street"); - } - - /** - * @throws Exception - */ - @Test - public void arrayLookup() throws Exception - { - ognlResolver.setValue("addressArray", person, - new Address[] { new Address(), null }, CONVERTER); - ognlResolver.setValue("addressArray.0.street", person, "wicket-street", - CONVERTER); - String street = (String)ognlResolver.getValue("addressArray.0.street", - person); - assertEquals(street, "wicket-street"); - - ognlResolver.setValue("addressArray.1.street", person, "wicket-street", - CONVERTER); - street = (String)ognlResolver.getValue("addressArray.1.street", person); - assertEquals(street, "wicket-street"); - } - - /** - * @throws Exception - */ - @Test - public void arrayLookupByBrackets() throws Exception - { - ognlResolver.setValue("addressArray", person, - new Address[] { new Address(), null }, CONVERTER); - ognlResolver.setValue("addressArray[0].street", person, "wicket-street", - CONVERTER); - String street = (String)ognlResolver.getValue("addressArray[0].street", - person); - assertEquals(street, "wicket-street"); - - ognlResolver.setValue("addressArray[1].street", person, "wicket-street", - CONVERTER); - street = (String)ognlResolver.getValue("addressArray[1].street", person); - assertEquals(street, "wicket-street"); - } - - /** - * @throws Exception - */ - @Test - public void propertyByIndexLookup() throws Exception - { - ognlResolver.setValue("addressAt.0", person, new Address(), CONVERTER); - ognlResolver.setValue("addressAt.0.street", person, "wicket-street", - CONVERTER); - String street = (String)ognlResolver.getValue("addressAt.0.street", - person); - assertEquals(street, "wicket-street"); - } - - /** - * @throws Exception - */ - @Test - public void getPropertyByNotExistingIndexArrayLookup() throws Exception - { - ognlResolver.setValue("addressArray", person, new Address[] { }, - CONVERTER); - String street = (String)ognlResolver.getValue("addressArray.0.street", - person); - assertNull(street); - street = (String)ognlResolver.getValue("addressArray[0].street", person); - assertNull(street); - } - - /** - * @throws Exception - */ - @Test - public void getPropertyByNotExistingIndexListLookup() throws Exception - { - ognlResolver.setValue("addressList", person, new ArrayList<Address>(), - CONVERTER); - String street = (String)ognlResolver.getValue("addressList.0.street", - person); - assertNull(street); - street = (String)ognlResolver.getValue("addressList[0].street", person); - assertNull(street); - } - - /** - * @throws Exception - */ - @Test - public void getIndexPropertyDirectly() throws Exception - { - Address address = new Address(); - Address[] addresses = new Address[] { address }; - - Address address2 = (Address)ognlResolver.getValue("[0]", addresses); - assertSame(address, address2); - } - - /** - * @throws Exception - */ - @Test - public void listSizeLookup() throws Exception - { - List<Address> addresses = new ArrayList<Address>(); - addresses.add(new Address()); - addresses.add(new Address()); - person.setAddressList(addresses); - Object size = ognlResolver.getValue("addressList.size", person); - assertEquals(size, 2); - size = ognlResolver.getValue("addressList.size()", person); - assertEquals(size, 2); - } - - - /** - * @throws Exception - */ - @Test - public void mapSizeLookup() throws Exception - { - Map<String, Address> addresses = new HashMap<String, Address>(); - Address address = new Address(); - addresses.put("size", address); - addresses.put("test", new Address()); - person.setAddressMap(addresses); - Object addressFromMap = ognlResolver.getValue("addressMap.size", person); - assertEquals(addressFromMap, address); - Object size = ognlResolver.getValue("addressMap.size()", person); - assertEquals(size, 2); - } - - /** - * @throws Exception - */ - @Test - public void arraySizeLookup() throws Exception - { - person.setAddressArray(new Address[] { new Address(), new Address() }); - Object size = ognlResolver.getValue("addressArray.length", person); - assertEquals(size, 2); - size = ognlResolver.getValue("addressArray.size", person); - assertEquals(size, 2); - } - - /** - * @throws Exception - */ - @Test - public void methodLookup() throws Exception - { - Address[] addresses = new Address[] { new Address(), new Address() }; - person.setAddressArray(addresses); - Object value = ognlResolver.getValue("getAddressArray()", person); - assertEquals(value, addresses); - } - - /** - * @throws Exception - */ - @Test - public void field() throws Exception - { - Address address = new Address(); - ognlResolver.setValue("address2", person, address, CONVERTER); - Address address2 = (Address)ognlResolver.getValue("address2", person); - assertEquals(address, address2); - - try - { - ognlResolver.setValue("address3", person, address, CONVERTER); - fail("Shoudln't come here"); - } - catch (RuntimeException ex) - { - + // first try default properties + IGetAndSet getAndSet = locator.get(clz, exp); + if (getAndSet == null && Document.class.isAssignableFrom(clz)) + { + // fall back to document properties + getAndSet = new DocumentPropertyGetAndSet(exp); + } + return getAndSet; } - } - - /** - * @throws Exception - */ - @Test - public void testPrivateField() throws Exception - { - Address address = new Address(); - ognlResolver.setValue("privateAddress", person, address, CONVERTER); - Address address2 = (Address)ognlResolver.getValue("privateAddress", - person); - assertEquals(address, address2); - } - - /** - * @throws Exception - */ - @Test - public void privateFieldOfSuperClass() throws Exception - { - Person2 person2 = new Person2(); - Address address = new Address(); - ognlResolver.setValue("privateAddress", person2, address, CONVERTER); - Address address2 = (Address)ognlResolver.getValue("privateAddress", - person2); - assertEquals(address, address2); - } - - /** - * - */ - @Test - public void getTargetClass() - { - Address address = new Address(); - - Class<?> clazz = ognlResolver.resolve("number", address, address.getClass()).getTargetClass(); - assertEquals(int.class, clazz); - - Person person = new Person(); - person.setAddress(new Address()); - - clazz = ognlResolver.resolve("address.number", person, person.getClass()).getTargetClass(); - assertEquals(int.class, clazz); - - person.setAddressArray(new Address[] { new Address(), new Address() }); - clazz = ognlResolver.resolve("addressArray[0]", person, person.getClass()).getTargetClass(); - assertEquals(Address.class, clazz); - - clazz = ognlResolver.resolve("addressArray[0].number", person, person.getClass()).getTargetClass(); - assertEquals(int.class, clazz); - } - - /** - * - */ - @Test - public void getTargetField() - { - Address address = new Address(); - - Field field = ognlResolver.getPropertyField("number", address); - assertEquals(field.getName(), "number"); - assertEquals(field.getType(), int.class); - - Person person = new Person(); - person.setAddress(new Address()); - - field = ognlResolver.getPropertyField("address.number", person); - assertEquals(field.getName(), "number"); - assertEquals(field.getType(), int.class); - - person.setAddressArray(new Address[] { new Address(), new Address() }); - field = ognlResolver.getPropertyField("addressArray[0].number", person); - assertEquals(field.getName(), "number"); - assertEquals(field.getType(), int.class); - } - - /** - * - */ - @Test - public void getTargetGetter() - { - Address address = new Address(); - - Method method = ognlResolver.getPropertyGetter("number", address); - assertEquals(method.getName(), "getNumber"); - assertEquals(method.getReturnType(), int.class); - - Person person = new Person(); - person.setAddress(new Address()); - - method = ognlResolver.getPropertyGetter("address.number", person); - assertEquals(method.getName(), "getNumber"); - assertEquals(method.getReturnType(), int.class); - - person.setAddressArray(new Address[] { new Address(), new Address() }); - method = ognlResolver.getPropertyGetter("addressArray[0].number", person); - assertEquals(method.getName(), "getNumber"); - assertEquals(method.getReturnType(), int.class); - } - - /** - * @throws Exception - */ - @Test - public void onlyPrimitiveGetter() throws Exception - { - Person person = new Person(); - - ognlResolver.setValue("onlyGetterPrimitive", person, 1, CONVERTER); - - assertEquals(person.getOnlyGetterPrimitive(), 1); - assertEquals(ognlResolver.getValue("onlyGetterPrimitive", person), 1); - - } - - /** - * @throws Exception - */ - @Test - public void onlyStringGetter() throws Exception - { - Person person = new Person(); - - ognlResolver.setValue("onlyGetterString", person, "onlygetter", - CONVERTER); - assertEquals(person.getOnlyGetterString(), "onlygetter"); - assertEquals(ognlResolver.getValue("onlyGetterString", person), - "onlygetter"); - - } - - /** - * - */ - @Test - public void getTargetSetter() - { - Address address = new Address(); - - Method method = ognlResolver.getPropertySetter("number", address); - assertEquals(method.getName(), "setNumber"); - - Person person = new Person(); - person.setAddress(new Address()); - - method = ognlResolver.getPropertySetter("address.number", person); - assertEquals(method.getName(), "setNumber"); - - person.setAddressArray(new Address[] { new Address(), new Address() }); - method = ognlResolver.getPropertySetter("addressArray[0].number", person); - assertEquals(method.getName(), "setNumber"); - } - - /** - * @throws Exception - */ - @Test - public void overriddenGetter() throws Exception - { - Person2 person = new Person2(); - person.setName("foo"); - - String name = (String)ognlResolver.getValue("name", person); - assertEquals("foo", name); - - ognlResolver.setValue("name", person, "bar", CONVERTER); - - name = (String)ognlResolver.getValue("name", person); - assertEquals("bar", name); - - } - - /** - * @throws Exception - */ - @Test - public void propertyClassWithSubType() throws Exception - { - Person person = new Person(); - assertEquals(String.class, - ognlResolver.resolve("country.name", person, person.getClass()).getTargetClass()); - try - { - ognlResolver.resolve("country.subCountry.name", person, person.getClass()).getTargetClass(); - fail("country.subCountry shouldnt be found"); - } - catch (Exception e) + public class DocumentPropertyGetAndSet extends AbstractGetAndSet { - } - person.setCountry(new Country2("test", new Country("test"))); - ognlResolver.resolve("country.subCountry.name", person, person.getClass()).getTargetClass(); - } - - /** - * Used for models in testing. - */ - private static class InnerVectorPOJO extends Vector<Void> - { - private static final long serialVersionUID = 1L; - - /** - */ - @SuppressWarnings("unused") - public String testValue = "vector"; - } - - /** - * Tests the PropertyModel with vector. - */ - @Test - public void propertyModel() - { - String value = (String)ognlResolver.getValue("testValue", - new InnerVectorPOJO()); - assertEquals("vector", value); - } + private String name; - /** - * - */ - @Test - public void directFieldSetWithDifferentTypeThanGetter() - { - final DirectFieldSetWithDifferentTypeThanGetter obj = new DirectFieldSetWithDifferentTypeThanGetter(); - ognlResolver.setValue("value", obj, 1, null); - assertEquals(1, obj.value); - } - - private static class DirectFieldSetWithDifferentTypeThanGetter - { - private int value; - - @SuppressWarnings("unused") - public String getValue() - { - return String.valueOf(value); - } - } - - /** - * @see <a href="https://issues.apache.org/jira/browse/WICKET-1802">WICKET-1802</a> - */ - @Test - public void conversionExceptionMessageContainsTheObjectPropertyBeingSet() - { - try - { - PropertyResolverConverter convertToNull = new PropertyResolverConverter(null, null) + public DocumentPropertyGetAndSet(String name) { - private static final long serialVersionUID = 1L; - - @Override - public <T> T convert(Object object, java.lang.Class<T> clz) - { - return null; - } - }; - ognlResolver.setValue("name", person, "", convertToNull); - fail("Should have thrown an ConversionException"); - } - catch (ConversionException e) - { - assertTrue(e.getMessage().toLowerCase().contains("name")); - } - } - - /** - * WICKET-3441 - */ - @Test - public void dateToStringConverting() - { - IConverterLocator converterLocator = new ConverterLocator(); - Locale locale = Locale.GERMAN; - PropertyResolverConverter converter = new PropertyResolverConverter(converterLocator, - locale); - - Calendar calDate = Calendar.getInstance(); - calDate.clear(); - calDate.set(2011, Calendar.APRIL, 17); - Date date = calDate.getTime(); - - Object actual = converter.convert(date, String.class); - String expected = converterLocator.getConverter(Date.class).convertToString(date, locale); - assertEquals(expected, actual); - } - - /** - * WICKET-3441 - */ - @Test - public void dateToLongConverting() - { - ConverterLocator converterLocator = new ConverterLocator(); - final IConverter<Date> dateConverter = converterLocator.get(Date.class); - IConverter<Long> customLongConverter = new AbstractConverter<Long>() - { - private static final long serialVersionUID = 1L; + this.name = name; + } @Override - public Long convertToObject(String value, Locale locale) + public Object getValue(Object object) { - Date date = dateConverter.convertToObject(value, locale); - return date != null ? date.getTime() : null; + return ((Document)object).getProperty(name); } @Override - public String convertToString(Long value, Locale locale) + public Object newValue(Object object) { - Date date; - if (value != null) - { - date = new Date(); - date.setTime(value); - } - else - { - date = null; - } - - return dateConverter.convertToString(date, locale); + return new Document(); } @Override - protected Class<Long> getTargetType() + public void setValue(Object object, Object value, PropertyResolverConverter converter) { - return Long.class; + ((Document)object).setProperty(name, value); } - }; - converterLocator.set(Long.class, customLongConverter); - converterLocator.set(Long.TYPE, customLongConverter); - - PropertyResolverConverter converter = new PropertyResolverConverter(converterLocator, - Locale.ENGLISH); - - Calendar calDate = Calendar.getInstance(); - calDate.clear(); - calDate.set(2011, Calendar.APRIL, 17); - Date date = calDate.getTime(); - - Object actual = converter.convert(date, Long.class); - assertEquals(date.getTime(), actual); - } - -// /** -// * WICKET-5623 custom properties -// */ -// @Test -// public void custom() -// { -// Document document = new Document(); -// document.setType("type"); -// document.setProperty("string", "string"); -// -// Document nestedCustom = new Document(); -// nestedCustom.setProperty("string", "string2"); -// document.setProperty("nested", nestedCustom); -// -// ognlResolver.setLocator(tester.getApplication(), -// new CachingPropertyLocator(new CustomGetAndSetLocator())); -// -// assertEquals("type", ognlResolver.getValue("type", document)); -// assertEquals("string", ognlResolver.getValue("string", document)); -// assertEquals("string2", ognlResolver.getValue("nested.string", document)); -// } - -// class CustomGetAndSetLocator implements IPropertyLocator -// { -// -// private IPropertyLocator locator = new DefaultPropertyLocator(); -// -// @Override -// public IGetAndSet get(Class<?> clz, String exp) -// { -// // first try default properties -// IGetAndSet getAndSet = locator.get(clz, exp); -// if (getAndSet == null && Document.class.isAssignableFrom(clz)) -// { -// // fall back to document properties -// getAndSet = new DocumentPropertyGetAndSet(exp); -// } -// return getAndSet; -// } -// -// public class DocumentPropertyGetAndSet extends AbstractGetAndSet -// { -// -// private String name; -// -// public DocumentPropertyGetAndSet(String name) -// { -// this.name = name; -// } -// -// @Override -// public Object getValue(Object object) -// { -// return ((Document)object).getProperty(name); -// } -// -// @Override -// public Object newValue(Object object) -// { -// return new Document(); -// } -// -// @Override -// public void setValue(Object object, Object value, PropertyResolverConverter converter) -// { -// ((Document)object).setProperty(name, value); -// } -// } -// } - - - // EDGE CASES - @Test - public void shouldAllowEmptySpacesInsideMethodCallBrackets() throws Exception - { - person.setName("bob"); - assertThat("bob", is(PropertyResolver.getValue("person.getName( )", this))); - } - - @Test - public void shouldAllowMapKeysWithSpecialCharactersIncludingOpenSquareBracket() throws Exception - { - String code = "!@#$%^&*()_+-=[{}|"; - String expression = "[" + code + "]"; - PropertyResolver.setValue(expression, integerMap, AN_INTEGER, CONVERTER); - assertThat(PropertyResolver.getValue(expression, integerMap), is(AN_INTEGER)); - assertThat(integerMap.get(code), is(AN_INTEGER)); - } - - @Test - public void shouldAllowMapKeysWithDot() throws Exception - { - String code = "code-1.0"; - String expression = "[" + code + "]"; - PropertyResolver.setValue(expression, integerMap, AN_INTEGER, CONVERTER); - assertThat(PropertyResolver.getValue(expression, integerMap), is(AN_INTEGER)); - assertThat(integerMap.get(code), is(AN_INTEGER)); - } - - @Test - public void shouldAllowMapKeysHavingQuotes() throws Exception - { - String code = "the\"key\""; - String expression = "[" + code + "]"; - PropertyResolver.setValue(expression, integerMap, AN_INTEGER, CONVERTER); - assertThat(PropertyResolver.getValue(expression, integerMap), is(AN_INTEGER)); - assertThat(integerMap.get(code), is(AN_INTEGER)); - } - - @Test - public void shouldPriorityzeListIndex() throws Exception - { - integerList.set0(AN_INTEGER); - assertThat(PropertyResolver.getValue("integerList.0", this), is(AN_INTEGER)); - } - - @Test - public void shouldPriorityzeMapKeyInSquareBrakets() throws Exception - { - PropertyResolver.setValue("[class]", integerMap, AN_INTEGER, CONVERTER); - assertThat(PropertyResolver.getValue("[class]", integerMap), is(AN_INTEGER)); - } - - @Test - public void shouldPriorityzeMapKeyInSquareBraketsAfterAnExpresison() throws Exception - { - PropertyResolver.setValue("integerMap[class]", this, AN_INTEGER, CONVERTER); - assertThat(PropertyResolver.getValue("integerMap[class]", this), is(AN_INTEGER)); - } - - @Test - public void shouldPriorityzeMethodCallWhenEndedByParentises() throws Exception - { - assertThat(PropertyResolver.getValue("integerMap.getClass()", this), is(HashMap.class)); - } - - - static class WeirdList extends ArrayList<Integer> - { - private static final long serialVersionUID = 1L; - private Integer integer; - - public void set0(Integer integer) - { - this.integer = integer; - - } - - public Integer get0() - { - return integer; } } -} \ No newline at end of file +}
