You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2008/05/22 18:57:46 UTC
svn commit: r659159 - in /tapestry/tapestry5/trunk:
tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/
tapestry-core/src/main/java/org/apache/tapestry5/internal/
tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ tapes...
Author: hlship
Date: Thu May 22 09:57:45 2008
New Revision: 659159
URL: http://svn.apache.org/viewvc?rev=659159&view=rev
Log:
TAPESTRY-2425: Tapestry annotations such as @Validate, @DataType, etc. should be applicable to fields as well as accessor methods
Added:
tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/ReorderProperties.java
Removed:
tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/OrderAfter.java
tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/OrderBefore.java
Modified:
tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/DataType.java
tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/NonVisual.java
tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/Validate.java
tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/Width.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/TapestryInternalUtils.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/BeanModelSourceImpl.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/BeanModelSource.java
tapestry/tapestry5/trunk/tapestry-core/src/site/apt/upgrade.apt
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/RegistrationData.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/SimpleTrack.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/PropertyOrderBean.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/TapestryInternalUtilsTest.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/bindings/PropBindingFactoryTest.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/bindings/TargetBean.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/BeanModelSourceImplTest.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/StoogeBean.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassPropertyAdapterImpl.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PropertyAdapterImpl.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/PropertyAdapter.java
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/PropertyAccessImplTest.java
Modified: tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/DataType.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/DataType.java?rev=659159&r1=659158&r2=659159&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/DataType.java (original)
+++ tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/DataType.java Thu May 22 09:57:45 2008
@@ -1,4 +1,4 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2008 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -18,10 +18,10 @@
/**
* Used to explicitly set the data type used to select an editor (or display) block. Normally, the data type is
- * determined from the type of the property (for example, property type java.lang.String would map to data type
- * "text").
+ * determined from the type of the property (for example, property type java.lang.String would map to data type "text").
+ * This annotation may be attached to a getter or setter method, or the matching field.
*/
-@Target(ElementType.METHOD)
+@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataType
Modified: tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/NonVisual.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/NonVisual.java?rev=659159&r1=659158&r2=659159&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/NonVisual.java (original)
+++ tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/NonVisual.java Thu May 22 09:57:45 2008
@@ -1,4 +1,4 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2008 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -15,16 +15,16 @@
package org.apache.tapestry5.beaneditor;
import java.lang.annotation.Documented;
-import static java.lang.annotation.ElementType.METHOD;
+import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Target;
/**
* Marker annotation for properties which are non-visual, and so should not appear (by default) inside a {@link
- * BeanModel}. The annotation may be placed on either the getter or the setter method.
+ * BeanModel}. The annotation may be placed on either the getter or the setter method or on the field.
*/
-@Target(METHOD)
+@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RUNTIME)
@Documented
public @interface NonVisual
Added: tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/ReorderProperties.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/ReorderProperties.java?rev=659159&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/ReorderProperties.java (added)
+++ tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/ReorderProperties.java Thu May 22 09:57:45 2008
@@ -0,0 +1,33 @@
+// Copyright 2008 The Apache Software Foundation
+//
+// Licensed 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.tapestry5.beaneditor;
+
+import java.lang.annotation.*;
+
+
+/**
+ * An annotation that may be placed on a JavaBean to re-order the properties.
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface ReorderProperties
+{
+ /**
+ * A comma-separated list of property names. Properties will be re-ordered as specified, with any unmentioned
+ * property names ordered to the end of the list.
+ */
+ String value();
+}
Modified: tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/Validate.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/Validate.java?rev=659159&r1=659158&r2=659159&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/Validate.java (original)
+++ tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/Validate.java Thu May 22 09:57:45 2008
@@ -1,4 +1,4 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2008 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
package org.apache.tapestry5.beaneditor;
import java.lang.annotation.Documented;
-import static java.lang.annotation.ElementType.METHOD;
+import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Target;
@@ -25,8 +25,10 @@
* value is a comma separated list of <em>validation constraints</em>, each one identifying a validator type (such as
* "required", "minlength") and optionally, a constraint value. Most validators need a constraint value, which is
* separated from the type by an equals size (i.e., "maxlength=30").
+ * <p/>
+ * May be placed on an getter or setter method, or on the matching field.
*/
-@Target(METHOD)
+@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RUNTIME)
@Documented
public @interface Validate
Modified: tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/Width.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/Width.java?rev=659159&r1=659158&r2=659159&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/Width.java (original)
+++ tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/Width.java Thu May 22 09:57:45 2008
@@ -1,4 +1,4 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2008 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,18 +14,17 @@
package org.apache.tapestry5.beaneditor;
-import java.lang.annotation.Documented;
-import static java.lang.annotation.ElementType.METHOD;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
+import java.lang.annotation.*;
/**
* Defines the desired width of the field used to edit the property. Note that width (generally equivalent to the size
* attribute of an HTML <input> element) is only used for presentation; validation must be used to actually
* enforce a maximum input length.
+ * <p/>
+ * <p/>
+ * May be placed on an getter or setter method, or on the matching field.
*/
-@Target(METHOD)
+@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Width
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/TapestryInternalUtils.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/TapestryInternalUtils.java?rev=659159&r1=659158&r2=659159&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/TapestryInternalUtils.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/TapestryInternalUtils.java Thu May 22 09:57:45 2008
@@ -18,24 +18,14 @@
import org.apache.commons.codec.net.URLCodec;
import org.apache.tapestry5.OptionModel;
import org.apache.tapestry5.SelectModel;
-import org.apache.tapestry5.beaneditor.OrderAfter;
-import org.apache.tapestry5.beaneditor.OrderBefore;
-import org.apache.tapestry5.ioc.Location;
import org.apache.tapestry5.ioc.Messages;
import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newList;
import org.apache.tapestry5.ioc.internal.util.Defense;
import static org.apache.tapestry5.ioc.internal.util.Defense.notNull;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
-import org.apache.tapestry5.ioc.internal.util.Orderer;
-import org.apache.tapestry5.ioc.services.ClassFactory;
-import org.apache.tapestry5.ioc.services.ClassPropertyAdapter;
-import org.apache.tapestry5.ioc.services.PropertyAdapter;
-import org.slf4j.Logger;
-import java.lang.reflect.Method;
import java.util.BitSet;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
@@ -342,124 +332,6 @@
return InternalUtils.join(classes, " ");
}
- private static class PropertyOrder implements Comparable<PropertyOrder>
- {
- final String propertyName;
-
- final int classDepth;
-
- final int sortKey;
-
- public PropertyOrder(final String propertyName, int classDepth, int sortKey)
- {
- this.propertyName = propertyName;
- this.classDepth = classDepth;
- this.sortKey = sortKey;
- }
-
- public int compareTo(PropertyOrder o)
- {
- int result = classDepth - o.classDepth;
-
- if (result == 0) result = sortKey - o.sortKey;
-
- if (result == 0) result = propertyName.compareTo(o.propertyName);
-
- return result;
- }
- }
-
- /**
- * Sorts the property names into presentation order. Filters out any properties that have an explicit {@link
- * OrderBefore}, leaving the remainder. Estimates each propertie's position based on the relative position of the
- * property's getter. The code assumes that all methods are readable (have a getter method).
- *
- * @param classAdapter defines the bean that contains the properties
- * @param classFactory used to access method line number information
- * @param propertyNames the initial set of property names
- * @return propertyNames filtered and sorted
- */
- public static List<String> orderProperties(Logger logger, ClassPropertyAdapter classAdapter,
- ClassFactory classFactory, List<String> propertyNames)
- {
-
- // Property name to a list of constraints.
- Map<String, List<String>> constraints = CollectionFactory.newMap();
-
- List<PropertyOrder> properties = newList();
-
- for (String name : propertyNames)
- {
-
- PropertyAdapter pa = classAdapter.getPropertyAdapter(name);
- List<String> propertyConstraints = CollectionFactory.newList();
-
- OrderBefore beforeAnnotation = pa.getAnnotation(OrderBefore.class);
-
- if (beforeAnnotation != null) propertyConstraints.add("before:" + beforeAnnotation.value());
-
- OrderAfter afterAnnotation = pa.getAnnotation(OrderAfter.class);
-
- if (afterAnnotation != null) propertyConstraints.add("after:" + afterAnnotation.value());
-
- if (!propertyConstraints.isEmpty()) constraints.put(name, propertyConstraints);
-
- Method readMethod = pa.getReadMethod();
-
- Location location = classFactory.getMethodLocation(readMethod);
-
- properties.add(new PropertyOrder(name, computeDepth(readMethod), location.getLine()));
- }
-
- Collections.sort(properties);
-
- Orderer<String> orderer = new Orderer<String>(logger);
- String prev = null;
-
- for (PropertyOrder po : properties)
- {
- String name = po.propertyName;
-
- List<String> propertyConstraints = constraints.get(name);
-
- if (propertyConstraints != null)
- {
-
- String[] asArray = propertyConstraints.toArray(new String[propertyConstraints
- .size()]);
-
- orderer.add(name, name, asArray);
-
- prev = name;
-
- continue;
- }
-
- if (prev == null) orderer.add(name, name);
- else orderer.add(name, name, "after:" + prev);
-
- prev = name;
- }
-
- return orderer.getOrdered();
-
- }
-
- private static int computeDepth(Method method)
- {
- int depth = 0;
- Class c = method.getDeclaringClass();
-
- // When the method originates in an interface, the parent may be null, not Object.
-
- while (c != null && c != Object.class)
- {
- depth++;
- c = c.getSuperclass();
- }
-
- return depth;
- }
/**
* Converts an enum to a label string, allowing for overrides from a message catalog.
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/BeanModelSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/BeanModelSourceImpl.java?rev=659159&r1=659158&r2=659159&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/BeanModelSourceImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/BeanModelSourceImpl.java Thu May 22 09:57:45 2008
@@ -17,8 +17,10 @@
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.beaneditor.BeanModel;
import org.apache.tapestry5.beaneditor.NonVisual;
-import org.apache.tapestry5.internal.TapestryInternalUtils;
+import org.apache.tapestry5.beaneditor.ReorderProperties;
import org.apache.tapestry5.internal.beaneditor.BeanModelImpl;
+import org.apache.tapestry5.internal.beaneditor.BeanModelUtils;
+import org.apache.tapestry5.ioc.Location;
import org.apache.tapestry5.ioc.LoggerSource;
import org.apache.tapestry5.ioc.Messages;
import org.apache.tapestry5.ioc.ObjectLocator;
@@ -31,8 +33,9 @@
import org.apache.tapestry5.services.DataTypeAnalyzer;
import org.apache.tapestry5.services.PropertyConduitSource;
+import java.lang.reflect.Method;
+import java.util.Collections;
import java.util.List;
-import java.util.Map;
public class BeanModelSourceImpl implements BeanModelSource
{
@@ -50,6 +53,81 @@
private final ObjectLocator locator;
+
+ private static class PropertyOrder implements Comparable<PropertyOrder>
+ {
+ final String propertyName;
+
+ final int classDepth;
+
+ final int sortKey;
+
+ public PropertyOrder(final String propertyName, int classDepth, int sortKey)
+ {
+ this.propertyName = propertyName;
+ this.classDepth = classDepth;
+ this.sortKey = sortKey;
+ }
+
+ public int compareTo(PropertyOrder o)
+ {
+ int result = classDepth - o.classDepth;
+
+ if (result == 0) result = sortKey - o.sortKey;
+
+ if (result == 0) result = propertyName.compareTo(o.propertyName);
+
+ return result;
+ }
+ }
+
+ /**
+ * @param classAdapter defines the bean that contains the properties
+ * @param propertyNames the initial set of property names, which will be rebuilt in the correct order
+ */
+ private void orderProperties(ClassPropertyAdapter classAdapter, List<String> propertyNames)
+ {
+ List<PropertyOrder> properties = CollectionFactory.newList();
+
+ for (String name : propertyNames)
+ {
+ PropertyAdapter pa = classAdapter.getPropertyAdapter(name);
+ List<String> propertyConstraints = CollectionFactory.newList();
+
+ Method readMethod = pa.getReadMethod();
+
+ Location location = classFactory.getMethodLocation(readMethod);
+
+ properties.add(new PropertyOrder(name, computeDepth(readMethod), location.getLine()));
+ }
+
+ Collections.sort(properties);
+
+ propertyNames.clear();
+
+ for (PropertyOrder po : properties)
+ {
+ propertyNames.add(po.propertyName);
+ }
+
+ }
+
+ private static int computeDepth(Method method)
+ {
+ int depth = 0;
+ Class c = method.getDeclaringClass();
+
+ // When the method originates in an interface, the parent may be null, not Object.
+
+ while (c != null && c != Object.class)
+ {
+ depth++;
+ c = c.getSuperclass();
+ }
+
+ return depth;
+ }
+
public BeanModelSourceImpl(LoggerSource loggerSource, TypeCoercer typeCoercer, PropertyAccess propertyAccess,
PropertyConduitSource propertyConduitSource, @ComponentLayer ClassFactory classFactory,
@Primary DataTypeAnalyzer dataTypeAnalyzer, ObjectLocator locator)
@@ -72,12 +150,8 @@
ClassPropertyAdapter adapter = propertyAccess.getAdapter(beanClass);
- final BeanModel<T> model = new BeanModelImpl<T>(beanClass, propertyConduitSource, typeCoercer, messages,
- locator);
-
- List<String> propertyNames = CollectionFactory.newList();
-
- Map<String, Runnable> worksheet = CollectionFactory.newMap();
+ BeanModel<T> model = new BeanModelImpl<T>(beanClass, propertyConduitSource, typeCoercer, messages,
+ locator);
for (final String propertyName : adapter.getPropertyNames())
{
@@ -95,38 +169,28 @@
if (dataType == null) continue;
- propertyNames.add(propertyName);
-
- // We need to defer execution of this; we want to add them in proper order, not
- // alphabetical order.
+ model.add(propertyName).dataType(dataType);
+ }
- Runnable worker = new Runnable()
- {
- public void run()
- {
- model.add(propertyName).dataType(dataType);
- }
- };
+ // First, order the properties based on the location of the getter method
+ // within the class.
- worksheet.put(propertyName, worker);
- }
+ List<String> propertyNames = model.getPropertyNames();
- // Determine the correct order to add the properties.
+ orderProperties(adapter, propertyNames);
- List<String> orderedNames = TapestryInternalUtils.orderProperties(loggerSource
- .getLogger(beanClass), adapter, classFactory, propertyNames);
+ model.reorder(propertyNames.toArray(new String[propertyNames.size()]));
- for (String propertyName : orderedNames)
- {
- Runnable r = worksheet.get(propertyName);
+ // Next, check for an annotation with specific ordering information.
- // This actually adds the property to the model, but we're doing it
- // in orderedNames order, not propertyNames order (which is alphabetical).
- // The default ordering comes from method ordering within the class.
+ ReorderProperties reorderAnnotation = beanClass.getAnnotation(ReorderProperties.class);
- r.run();
+ if (reorderAnnotation != null)
+ {
+ BeanModelUtils.reorder(model, reorderAnnotation.value());
}
+
return model;
}
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/BeanModelSource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/BeanModelSource.java?rev=659159&r1=659158&r2=659159&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/BeanModelSource.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/BeanModelSource.java Thu May 22 09:57:45 2008
@@ -16,11 +16,10 @@
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.beaneditor.BeanModel;
-import org.apache.tapestry5.beaneditor.OrderBefore;
/**
- * Used by a component to create a default {@link BeanModel} for a particular bean class. Also provides support to the
- * model by generating validation information for individual fields.
+ * Used by a component to create a default {@link org.apache.tapestry5.beaneditor.BeanModel} for a particular bean
+ * class. Also provides support to the model by generating validation information for individual fields.
* <p/>
* BeanModels are the basis for the {@link org.apache.tapestry5.corelib.components.BeanEditor} and {@link
* org.apache.tapestry5.corelib.components.Grid} comopnents.
@@ -31,9 +30,10 @@
{
/**
* Creates a new model used for editing the indicated bean class. The model will represent all read/write properties
- * of the bean. The order of the properties is defined by the {@link OrderBefore} annotation on the getter or setter
- * methods. The labels for the properties are derived from the property names, but if the component's message
- * catalog has keys of the form <code>propertyName-label</code>, then those will be used instead.
+ * of the bean. The order of properties is determined from the order of the getter methods in the code, and can be
+ * overridden with the {@link org.apache.tapestry5.beaneditor.ReorderProperties} annotation. The labels for the
+ * properties are derived from the property names, but if the component's message catalog has keys of the form
+ * <code>propertyName-label</code>, then those will be used instead.
* <p/>
* Models are <em>mutable</em>, so they are not cached, a fresh instance is created each time.
*
Modified: tapestry/tapestry5/trunk/tapestry-core/src/site/apt/upgrade.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/site/apt/upgrade.apt?rev=659159&r1=659158&r2=659159&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/site/apt/upgrade.apt (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/site/apt/upgrade.apt Thu May 22 09:57:45 2008
@@ -14,6 +14,13 @@
Release 5.0.12
+* ReorderProperties annotation
+
+ A new annotation,
+ {{{../apidocs/org/apache/tapestry5/beaneditor/ReorderProperties.html}ReorderProperties}}
+ (which is placed on a type) has replaced the OrderAfter and OrderBefore annotations
+ (which were placed on accessor methods).
+
* {{{https://issues.apache.org/jira/browse/TAPESTRY-2421}TAPESTRY-2421}}
To enable deployment compatibility between Tapestry 4 and Tapestry 5, a
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/RegistrationData.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/RegistrationData.java?rev=659159&r1=659158&r2=659159&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/RegistrationData.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/RegistrationData.java Thu May 22 09:57:45 2008
@@ -14,8 +14,12 @@
package org.apache.tapestry5.integration.app1.data;
-import org.apache.tapestry5.beaneditor.*;
+import org.apache.tapestry5.beaneditor.DataType;
+import org.apache.tapestry5.beaneditor.ReorderProperties;
+import org.apache.tapestry5.beaneditor.Validate;
+import org.apache.tapestry5.beaneditor.Width;
+@ReorderProperties("firstname,lastname,birthyear,sex")
public class RegistrationData
{
private String lastName;
@@ -32,7 +36,6 @@
private String notes;
- @OrderAfter("lastName")
@Validate("min=1900,max=2007")
@Width(4)
public int getBirthYear()
@@ -40,13 +43,11 @@
return birthYear;
}
- @OrderAfter("lastname,birthyear")
public Sex getSex()
{
return sex;
}
- @OrderBefore("lastname")
public String getFirstName()
{
return firstName;
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/SimpleTrack.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/SimpleTrack.java?rev=659159&r1=659158&r2=659159&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/SimpleTrack.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/SimpleTrack.java Thu May 22 09:57:45 2008
@@ -1,4 +1,4 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2008 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,14 +14,13 @@
package org.apache.tapestry5.integration.app1.data;
-import org.apache.tapestry5.beaneditor.OrderBefore;
+import org.apache.tapestry5.beaneditor.ReorderProperties;
+@ReorderProperties("title,album")
public interface SimpleTrack
{
- @OrderBefore("album")
String getTitle();
- @OrderBefore("rating")
String getAlbum();
int getRating();
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/PropertyOrderBean.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/PropertyOrderBean.java?rev=659159&r1=659158&r2=659159&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/PropertyOrderBean.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/PropertyOrderBean.java Thu May 22 09:57:45 2008
@@ -1,4 +1,4 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2008 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,8 +14,9 @@
package org.apache.tapestry5.internal;
-import org.apache.tapestry5.beaneditor.OrderBefore;
+import org.apache.tapestry5.beaneditor.ReorderProperties;
+@ReorderProperties("third")
public class PropertyOrderBean
{
private String first;
@@ -34,7 +35,6 @@
return second;
}
- @OrderBefore("first")
public String getThird()
{
return third;
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/TapestryInternalUtilsTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/TapestryInternalUtilsTest.java?rev=659159&r1=659158&r2=659159&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/TapestryInternalUtilsTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/TapestryInternalUtilsTest.java Thu May 22 09:57:45 2008
@@ -21,10 +21,10 @@
import org.apache.tapestry5.ioc.Messages;
import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
import org.apache.tapestry5.ioc.services.ClassFactory;
-import org.apache.tapestry5.ioc.services.ClassPropertyAdapter;
import org.apache.tapestry5.ioc.services.PropertyAccess;
import org.apache.tapestry5.ioc.services.TypeCoercer;
import org.apache.tapestry5.runtime.ComponentResourcesAware;
+import org.apache.tapestry5.services.BeanModelSource;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
@@ -39,11 +39,14 @@
private PropertyAccess access;
+ private BeanModelSource beanModelSource;
+
@BeforeClass
public void setup()
{
classFactory = getService("ClassFactory", ClassFactory.class);
access = getService("PropertyAccess", PropertyAccess.class);
+ beanModelSource = getService(BeanModelSource.class);
}
@AfterClass
@@ -51,6 +54,7 @@
{
access = null;
classFactory = null;
+ beanModelSource = null;
}
@@ -295,52 +299,6 @@
}
@Test
- public void property_order_basic()
- {
- ClassPropertyAdapter adapter = access.getAdapter(DataBean.class);
-
- List<String> names = adapter.getPropertyNames();
-
- names.remove("class");
-
- List<String> sorted = TapestryInternalUtils.orderProperties(null, adapter, classFactory, names);
-
- assertEquals(sorted, Arrays.asList("firstName", "lastName", "age"));
- }
-
- @Test
- public void property_order_on_subclass()
- {
- ClassPropertyAdapter adapter = access.getAdapter(DataBeanSubclass.class);
-
- List<String> names = adapter.getPropertyNames();
-
- names.remove("class");
-
- List<String> sorted = TapestryInternalUtils.orderProperties(null, adapter, classFactory, names);
-
- // Subclass properties listed after superclass properties, as desired.
-
- assertEquals(sorted, Arrays.asList("firstName", "lastName", "age", "street", "city", "state", "zip"));
- }
-
- @Test
- public void properties_with_order_annotation_filtered()
- {
- ClassPropertyAdapter adapter = access.getAdapter(PropertyOrderBean.class);
-
- List<String> names = adapter.getPropertyNames();
-
- names.remove("class");
-
- List<String> sorted = TapestryInternalUtils.orderProperties(null, adapter, classFactory, names);
-
- // Property third has an explicit @OrderBefore
-
- assertEquals(sorted, Arrays.asList("third", "first", "second"));
- }
-
- @Test
public void null_equals_null()
{
assertTrue(TapestryInternalUtils.isEqual(null, null));
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/bindings/PropBindingFactoryTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/bindings/PropBindingFactoryTest.java?rev=659159&r1=659158&r2=659159&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/bindings/PropBindingFactoryTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/bindings/PropBindingFactoryTest.java Thu May 22 09:57:45 2008
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// Copyright 2006, 2007, 2008 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -17,8 +17,7 @@
import org.apache.tapestry5.Binding;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.annotations.BeforeRenderBody;
-import org.apache.tapestry5.beaneditor.OrderAfter;
-import org.apache.tapestry5.beaneditor.OrderBefore;
+import org.apache.tapestry5.beaneditor.Validate;
import org.apache.tapestry5.internal.test.InternalBaseTestCase;
import org.apache.tapestry5.internal.util.IntegerRange;
import org.apache.tapestry5.ioc.Location;
@@ -95,7 +94,7 @@
Binding binding = factory.newBinding("test binding", resources, null, "readOnly", l);
- assertEquals(binding.getAnnotation(OrderBefore.class).value(), "writeOnly");
+ assertEquals(binding.getAnnotation(Validate.class).value(), "readonly");
verify();
}
@@ -111,7 +110,7 @@
Binding binding = factory.newBinding("test binding", resources, null, "writeOnly", l);
- assertEquals(binding.getAnnotation(OrderAfter.class).value(), "foobar");
+ assertEquals(binding.getAnnotation(Validate.class).value(), "writeonly");
verify();
}
@@ -127,7 +126,7 @@
Binding binding = factory.newBinding("test binding", resources, null, "intValue", l);
- assertNull(binding.getAnnotation(OrderBefore.class));
+ assertNull(binding.getAnnotation(Validate.class));
verify();
}
@@ -164,7 +163,7 @@
Binding binding = factory.newBinding("test binding", resources, null, "objectValue", l);
- assertEquals(binding.getAnnotation(OrderAfter.class).value(), "readOnly");
+ assertEquals(binding.getAnnotation(Validate.class).value(), "getObjectValue");
verify();
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/bindings/TargetBean.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/bindings/TargetBean.java?rev=659159&r1=659158&r2=659159&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/bindings/TargetBean.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/bindings/TargetBean.java Thu May 22 09:57:45 2008
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// Copyright 2006, 2007, 2008 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -15,9 +15,10 @@
package org.apache.tapestry5.internal.bindings;
import org.apache.tapestry5.annotations.BeforeRenderBody;
-import org.apache.tapestry5.beaneditor.OrderAfter;
-import org.apache.tapestry5.beaneditor.OrderBefore;
+import org.apache.tapestry5.beaneditor.ReorderProperties;
+import org.apache.tapestry5.beaneditor.Validate;
+@ReorderProperties("readonly,foobar,writeonly,objectvalue")
public class TargetBean extends DefaultComponent
{
private String objectValue;
@@ -54,25 +55,25 @@
this.intValue = intValue;
}
- @OrderAfter("readOnly")
+ @Validate("getObjectValue")
public String getObjectValue()
{
return objectValue;
}
- @OrderAfter("writeOnly")
+ @Validate("setObjectValue")
public void setObjectValue(String objectValue)
{
this.objectValue = objectValue;
}
- @OrderAfter("foobar")
+ @Validate("writeonly")
public void setWriteOnly(String value)
{
writeOnly = value;
}
- @OrderBefore("writeOnly")
+ @Validate("readonly")
public String getReadOnly()
{
return "ReadOnly";
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/BeanModelSourceImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/BeanModelSourceImplTest.java?rev=659159&r1=659158&r2=659159&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/BeanModelSourceImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/BeanModelSourceImplTest.java Thu May 22 09:57:45 2008
@@ -19,6 +19,7 @@
import org.apache.tapestry5.beaneditor.BeanModel;
import org.apache.tapestry5.beaneditor.PropertyModel;
import org.apache.tapestry5.beaneditor.RelativePosition;
+import org.apache.tapestry5.internal.PropertyOrderBean;
import org.apache.tapestry5.internal.test.InternalBaseTestCase;
import org.apache.tapestry5.internal.transform.pages.ReadOnlyBean;
import org.apache.tapestry5.ioc.Messages;
@@ -680,4 +681,22 @@
verify();
}
+
+ @Test
+ public void reoder_from_annotation()
+ {
+ ComponentResources resources = mockComponentResources();
+ Messages messages = mockMessages();
+
+ train_getMessages(resources, messages);
+ stub_contains(messages, false);
+
+ replay();
+
+ BeanModel model = source.create(PropertyOrderBean.class, true, resources);
+
+ assertEquals(model.getPropertyNames(), Arrays.asList("third", "first", "second"));
+
+ verify();
+ }
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/StoogeBean.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/StoogeBean.java?rev=659159&r1=659158&r2=659159&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/StoogeBean.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/StoogeBean.java Thu May 22 09:57:45 2008
@@ -1,4 +1,4 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2008 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,9 +14,9 @@
package org.apache.tapestry5.internal.services;
-import org.apache.tapestry5.beaneditor.OrderAfter;
-import org.apache.tapestry5.beaneditor.OrderBefore;
+import org.apache.tapestry5.beaneditor.ReorderProperties;
+@ReorderProperties("larry,moe,shemp,curly")
public class StoogeBean
{
private int moe, larry, curly, shemp;
@@ -26,13 +26,11 @@
return moe;
}
- @OrderAfter("shemp")
public int getCurly()
{
return curly;
}
- @OrderBefore("moe")
public int getLarry()
{
return larry;
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassPropertyAdapterImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassPropertyAdapterImpl.java?rev=659159&r1=659158&r2=659159&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassPropertyAdapterImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClassPropertyAdapterImpl.java Thu May 22 09:57:45 2008
@@ -47,7 +47,8 @@
Class propertyType = readMethod == null ? pd.getPropertyType() : GenericsUtils.extractGenericReturnType(
beanType, readMethod);
- PropertyAdapter pa = new PropertyAdapterImpl(pd.getName(), propertyType, readMethod, pd.getWriteMethod());
+ PropertyAdapter pa = new PropertyAdapterImpl(beanType, pd.getName(), propertyType, readMethod,
+ pd.getWriteMethod());
adapters.put(pa.getName(), pa);
}
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PropertyAdapterImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PropertyAdapterImpl.java?rev=659159&r1=659158&r2=659159&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PropertyAdapterImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PropertyAdapterImpl.java Thu May 22 09:57:45 2008
@@ -19,11 +19,14 @@
import org.apache.tapestry5.ioc.services.PropertyAdapter;
import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class PropertyAdapterImpl implements PropertyAdapter
{
+ private final Class beanType;
+
private final String name;
private final Method readMethod;
@@ -34,8 +37,19 @@
private final boolean castRequired;
- public PropertyAdapterImpl(String name, Class type, Method readMethod, Method writeMethod)
+ /**
+ * Have we tried to resolve from the property name to the field yet?
+ */
+ private boolean fieldCheckedFor;
+ /**
+ * The field from the containing type that matches this property name (may be null if not found, or not checked for
+ * yet).
+ */
+ private Field field;
+
+ public PropertyAdapterImpl(Class beanType, String name, Class type, Method readMethod, Method writeMethod)
{
+ this.beanType = notNull(beanType, "beanType");
this.name = notBlank(name, "name");
this.type = notNull(type, "type");
@@ -129,9 +143,43 @@
if (result == null && writeMethod != null) result = writeMethod.getAnnotation(annotationClass);
+ if (result == null) result = getAnnotationFromField(annotationClass);
+
return result;
}
+ private <T extends Annotation> T getAnnotationFromField(Class<T> annotationClass)
+ {
+ Field field = getField();
+
+ return field == null ? null : field.getAnnotation(annotationClass);
+ }
+
+
+ private synchronized Field getField()
+ {
+ if (!fieldCheckedFor)
+ {
+ // There's an assumption here, that the fields match the property name (we ignore case
+ // which leads to a manageable ambiguity) and that the field and the getter/setter
+ // are in the same class (i.e., that we don't have a getter exposing a protected field inherted
+ // from a base class, or some other oddity).
+
+ for (Field f : beanType.getDeclaredFields())
+ {
+ if (f.getName().equalsIgnoreCase(name))
+ {
+ field = f;
+ break;
+ }
+ }
+
+ fieldCheckedFor = true;
+ }
+
+ return field;
+ }
+
public boolean isCastRequired()
{
return castRequired;
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/PropertyAdapter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/PropertyAdapter.java?rev=659159&r1=659158&r2=659159&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/PropertyAdapter.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/PropertyAdapter.java Thu May 22 09:57:45 2008
@@ -19,8 +19,9 @@
import java.lang.reflect.Method;
/**
- * Provides access to a single property within a class. Acts as an {@link AnnotationProvider}; when searching for
- * annotations, the read method (if present) is checked first, followed by the write method.
+ * Provides access to a single property within a class. Acts as an {@link org.apache.tapestry5.ioc.AnnotationProvider};
+ * when searching for annotations, the read method (if present) is checked first, followed by the write method, followed
+ * by the underlying field (when the property name matches the field name).
*
* @see org.apache.tapestry5.ioc.services.ClassPropertyAdapter
*/
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/PropertyAccessImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/PropertyAccessImplTest.java?rev=659159&r1=659158&r2=659159&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/PropertyAccessImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/PropertyAccessImplTest.java Thu May 22 09:57:45 2008
@@ -14,6 +14,8 @@
package org.apache.tapestry5.ioc.internal.services;
+import org.apache.tapestry5.beaneditor.DataType;
+import org.apache.tapestry5.beaneditor.Validate;
import org.apache.tapestry5.ioc.Registry;
import org.apache.tapestry5.ioc.annotations.Scope;
import org.apache.tapestry5.ioc.internal.IOCInternalTestCase;
@@ -39,8 +41,11 @@
public static class Bean
{
+ @DataType("fred")
+ @Validate("field-value-overridden")
private int value;
+ @Validate("getter-value-overrides")
public int getValue()
{
return value;
@@ -453,6 +458,25 @@
}
@Test
+ public void get_annotation_will_read_field()
+ {
+ PropertyAdapter pa = access.getAdapter(Bean.class).getPropertyAdapter("value");
+
+ DataType dt = pa.getAnnotation(DataType.class);
+
+ assertNotNull(dt);
+ assertEquals(dt.value(), "fred");
+ }
+
+ @Test
+ public void field_annotation_overridden_by_getter_annotation()
+ {
+ PropertyAdapter pa = access.getAdapter(Bean.class).getPropertyAdapter("value");
+
+ assertEquals(pa.getAnnotation(Validate.class).value(), "getter-value-overrides");
+ }
+
+ @Test
public void using_generics()
{
ClassPropertyAdapter cpa1 = access.getAdapter(StringLongPair.class);