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 2007/12/22 05:55:59 UTC

svn commit: r606396 - in /tapestry/tapestry5/trunk: tapestry-annotations/src/main/java/org/apache/tapestry/beaneditor/ tapestry-core/src/main/java/org/apache/tapestry/corelib/components/ tapestry-core/src/main/java/org/apache/tapestry/internal/services...

Author: hlship
Date: Fri Dec 21 20:55:58 2007
New Revision: 606396

URL: http://svn.apache.org/viewvc?rev=606396&view=rev
Log:
TAPESTRY-1931: Add an annotation to allow explicit setting of property types

Added:
    tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry/beaneditor/DataType.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AnnotationDataTypeAnalyzer.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/AnnotationDataTypeAnalyzerTest.java
Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Form.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/RenderObject.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/BeanModelSourceImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderRequestHandlerImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PropertyConduitSourceImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Localization.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/PropertyAdapter.java

Added: tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry/beaneditor/DataType.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry/beaneditor/DataType.java?rev=606396&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry/beaneditor/DataType.java (added)
+++ tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry/beaneditor/DataType.java Fri Dec 21 20:55:58 2007
@@ -0,0 +1,30 @@
+// Copyright 2007 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.tapestry.beaneditor;
+
+import java.lang.annotation.*;
+
+/**
+ * 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").
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface DataType
+{
+    String value();
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Form.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Form.java?rev=606396&r1=606395&r2=606396&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Form.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Form.java Fri Dec 21 20:55:58 2007
@@ -161,6 +161,7 @@
     private RenderInformals _renderInformals;
 
     @Inject
+    @Traditional
     private ComponentEventResultProcessor _eventResultProcessor;
 
     private String _name;

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/RenderObject.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/RenderObject.java?rev=606396&r1=606395&r2=606396&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/RenderObject.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/RenderObject.java Fri Dec 21 20:55:58 2007
@@ -18,6 +18,7 @@
 import org.apache.tapestry.annotations.Parameter;
 import org.apache.tapestry.corelib.pages.ExceptionReport;
 import org.apache.tapestry.ioc.annotations.Inject;
+import org.apache.tapestry.ioc.annotations.Primary;
 import org.apache.tapestry.services.ObjectRenderer;
 
 /**
@@ -32,6 +33,7 @@
     private Object _object;
 
     @Inject
+    @Primary
     private ObjectRenderer<Object> _renderer;
 
     boolean beginRender(MarkupWriter writer)

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AnnotationDataTypeAnalyzer.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AnnotationDataTypeAnalyzer.java?rev=606396&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AnnotationDataTypeAnalyzer.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AnnotationDataTypeAnalyzer.java Fri Dec 21 20:55:58 2007
@@ -0,0 +1,32 @@
+// Copyright 2007 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.tapestry.internal.services;
+
+import org.apache.tapestry.beaneditor.DataType;
+import org.apache.tapestry.ioc.services.PropertyAdapter;
+import org.apache.tapestry.services.DataTypeAnalyzer;
+
+/**
+ * Checks for the {@link DataType} annotation, returning its value if present.
+ */
+public class AnnotationDataTypeAnalyzer implements DataTypeAnalyzer
+{
+    public String identifyDataType(PropertyAdapter adapter)
+    {
+        DataType annotation = adapter.getAnnotation(DataType.class);
+
+        return annotation == null ? null : annotation.value();
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/BeanModelSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/BeanModelSourceImpl.java?rev=606396&r1=606395&r2=606396&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/BeanModelSourceImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/BeanModelSourceImpl.java Fri Dec 21 20:55:58 2007
@@ -21,11 +21,13 @@
 import org.apache.tapestry.internal.beaneditor.BeanModelImpl;
 import org.apache.tapestry.ioc.LoggerSource;
 import org.apache.tapestry.ioc.Messages;
+import org.apache.tapestry.ioc.annotations.Primary;
 import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
 import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newMap;
 import static org.apache.tapestry.ioc.internal.util.Defense.notNull;
 import org.apache.tapestry.ioc.services.*;
 import org.apache.tapestry.services.BeanModelSource;
+import org.apache.tapestry.services.ComponentLayer;
 import org.apache.tapestry.services.DataTypeAnalyzer;
 import org.apache.tapestry.services.PropertyConduitSource;
 
@@ -46,9 +48,9 @@
 
     private final DataTypeAnalyzer _dataTypeAnalyzer;
 
-    public BeanModelSourceImpl(LoggerSource loggerSource, TypeCoercer typeCoercer,
-                               PropertyAccess propertyAccess, PropertyConduitSource propertyConduitSource,
-                               ClassFactory classFactory, DataTypeAnalyzer dataTypeAnalyzer)
+    public BeanModelSourceImpl(LoggerSource loggerSource, TypeCoercer typeCoercer, PropertyAccess propertyAccess,
+                               PropertyConduitSource propertyConduitSource, @ComponentLayer ClassFactory classFactory,
+                               @Primary DataTypeAnalyzer dataTypeAnalyzer)
     {
         _loggerSource = loggerSource;
         _typeCoercer = typeCoercer;
@@ -58,8 +60,7 @@
         _dataTypeAnalyzer = dataTypeAnalyzer;
     }
 
-    public BeanModel create(Class beanClass, boolean filterReadOnlyProperties,
-                            ComponentResources resources)
+    public BeanModel create(Class beanClass, boolean filterReadOnlyProperties, ComponentResources resources)
     {
         notNull(beanClass, "beanClass");
         notNull(resources, "resources");
@@ -68,8 +69,7 @@
 
         ClassPropertyAdapter adapter = _propertyAccess.getAdapter(beanClass);
 
-        final BeanModel model = new BeanModelImpl(beanClass, _propertyConduitSource, _typeCoercer,
-                                                  messages);
+        final BeanModel model = new BeanModelImpl(beanClass, _propertyConduitSource, _typeCoercer, messages);
 
         List<String> propertyNames = newList();
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderRequestHandlerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderRequestHandlerImpl.java?rev=606396&r1=606395&r2=606396&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderRequestHandlerImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderRequestHandlerImpl.java Fri Dec 21 20:55:58 2007
@@ -22,6 +22,7 @@
 import org.apache.tapestry.services.ComponentEventResultProcessor;
 import org.apache.tapestry.services.PageRenderRequestHandler;
 import org.apache.tapestry.services.Response;
+import org.apache.tapestry.services.Traditional;
 
 import java.io.IOException;
 
@@ -39,7 +40,8 @@
 
     private final Response _response;
 
-    public PageRenderRequestHandlerImpl(RequestPageCache cache, ComponentEventResultProcessor resultProcessor,
+    public PageRenderRequestHandlerImpl(RequestPageCache cache,
+                                        @Traditional ComponentEventResultProcessor resultProcessor,
                                         PageResponseRenderer pageResponseRenderer, Response response)
     {
         _cache = cache;

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PropertyConduitSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PropertyConduitSourceImpl.java?rev=606396&r1=606395&r2=606396&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PropertyConduitSourceImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PropertyConduitSourceImpl.java Fri Dec 21 20:55:58 2007
@@ -23,6 +23,7 @@
 import static org.apache.tapestry.ioc.internal.util.Defense.notNull;
 import org.apache.tapestry.ioc.services.*;
 import org.apache.tapestry.ioc.util.BodyBuilder;
+import org.apache.tapestry.services.ComponentLayer;
 import org.apache.tapestry.services.PropertyConduitSource;
 
 import java.lang.annotation.Annotation;
@@ -46,15 +47,13 @@
     private final Map<MultiKey, PropertyConduit> _cache = newConcurrentMap();
 
     private static final MethodSignature GET_SIGNATURE = new MethodSignature(Object.class, "get",
-                                                                             new Class[]
-                                                                                     {Object.class}, null);
+                                                                             new Class[]{Object.class}, null);
 
     private static final MethodSignature SET_SIGNATURE = new MethodSignature(void.class, "set",
-                                                                             new Class[]
-                                                                                     {Object.class, Object.class},
+                                                                             new Class[]{Object.class, Object.class},
                                                                              null);
 
-    public PropertyConduitSourceImpl(final PropertyAccess access, final ClassFactory classFactory)
+    public PropertyConduitSourceImpl(PropertyAccess access, @ComponentLayer ClassFactory classFactory)
     {
         _access = access;
         _classFactory = classFactory;
@@ -122,8 +121,7 @@
 
         ClassFab classFab = _classFactory.newClass(name, BasePropertyConduit.class);
 
-        classFab.addConstructor(new Class[]
-                {Class.class, AnnotationProvider.class, String.class}, null, "super($$);");
+        classFab.addConstructor(new Class[]{Class.class, AnnotationProvider.class, String.class}, null, "super($$);");
 
         String[] terms = expression.split("\\.");
 
@@ -136,10 +134,7 @@
         Class propertyType = readMethod != null ? readMethod.getReturnType() : writeMethod
                 .getParameterTypes()[0];
 
-        String description = String.format(
-                "PropertyConduit[%s %s]",
-                rootClass.getName(),
-                expression);
+        String description = String.format("PropertyConduit[%s %s]", rootClass.getName(), expression);
 
         Class conduitClass = classFab.createClass();
 
@@ -150,8 +145,7 @@
             {
                 T result = readMethod == null ? null : readMethod.getAnnotation(annotationClass);
 
-                if (result == null && writeMethod != null)
-                    result = writeMethod.getAnnotation(annotationClass);
+                if (result == null && writeMethod != null) result = writeMethod.getAnnotation(annotationClass);
 
                 return result;
             }
@@ -160,10 +154,7 @@
 
         try
         {
-            return (PropertyConduit) conduitClass.getConstructors()[0].newInstance(
-                    propertyType,
-                    provider,
-                    description);
+            return (PropertyConduit) conduitClass.getConstructors()[0].newInstance(propertyType, provider, description);
         }
         catch (Exception ex)
         {
@@ -192,11 +183,7 @@
             boolean nullable = term.endsWith("?");
             if (nullable) term = term.substring(0, term.length() - 1);
 
-            Method readMethod = readMethodForTerm(
-                    activeType,
-                    expression,
-                    term,
-                    (i < terms.length - 1));
+            Method readMethod = readMethodForTerm(activeType, expression, term, (i < terms.length - 1));
 
             if (readMethod == null)
             {
@@ -210,12 +197,8 @@
 
             // $w is harmless for non-wrapper types.
 
-            builder.addln(
-                    "%s %s = ($w) %s.%s();",
-                    ClassFabUtils.toJavaClassName(termType),
-                    thisStep,
-                    previousStep,
-                    readMethod.getName());
+            builder.addln("%s %s = ($w) %s.%s();", ClassFabUtils.toJavaClassName(termType), thisStep, previousStep,
+                          readMethod.getName());
 
             if (nullable) builder.addln("if (%s == null) return null;", thisStep);
 
@@ -232,10 +215,8 @@
         {
             builder.clear();
             builder
-                    .addln(
-                            "throw new java.lang.RuntimeException(\"Expression %s for class %s is write-only.\");",
-                            expression,
-                            rootClass.getName());
+                    .addln("throw new java.lang.RuntimeException(\"Expression %s for class %s is write-only.\");",
+                           expression, rootClass.getName());
         }
 
         classFab.addMethod(Modifier.PUBLIC, GET_SIGNATURE, builder.toString());
@@ -269,12 +250,8 @@
 
             // $w is harmless for non-wrapper types.
 
-            builder.addln(
-                    "%s %s = ($w) %s.%s();",
-                    ClassFabUtils.toJavaClassName(termType),
-                    thisStep,
-                    previousStep,
-                    readMethod.getName());
+            builder.addln("%s %s = ($w) %s.%s();", ClassFabUtils.toJavaClassName(termType), thisStep, previousStep,
+                          readMethod.getName());
 
             if (nullable) builder.addln("if (%s == null) return;", thisStep);
 
@@ -290,10 +267,8 @@
         {
             builder.clear();
             builder
-                    .addln(
-                            "throw new java.lang.RuntimeException(\"Expression %s for class %s is read-only.\");",
-                            expression,
-                            rootClass.getName());
+                    .addln("throw new java.lang.RuntimeException(\"Expression %s for class %s is read-only.\");",
+                           expression, rootClass.getName());
             classFab.addMethod(Modifier.PUBLIC, SET_SIGNATURE, builder.toString());
 
             return null;
@@ -326,18 +301,13 @@
         ClassPropertyAdapter classAdapter = _access.getAdapter(activeType);
         PropertyAdapter adapter = classAdapter.getPropertyAdapter(term);
 
-        if (adapter == null)
-            throw new RuntimeException(ServicesMessages.noSuchProperty(
-                    activeType,
-                    term,
-                    expression,
-                    classAdapter.getPropertyNames()));
+        if (adapter == null) throw new RuntimeException(
+                ServicesMessages.noSuchProperty(activeType, term, expression, classAdapter.getPropertyNames()));
 
         return adapter.getWriteMethod();
     }
 
-    private Method readMethodForTerm(Class activeType, String expression, String term,
-                                     boolean mustExist)
+    private Method readMethodForTerm(Class activeType, String expression, String term, boolean mustExist)
     {
         if (term.endsWith(PARENS))
         {
@@ -350,17 +320,11 @@
             }
             catch (NoSuchMethodException ex)
             {
-                throw new RuntimeException(ServicesMessages.methodNotFound(
-                        term,
-                        activeType,
-                        expression), ex);
+                throw new RuntimeException(ServicesMessages.methodNotFound(term, activeType, expression), ex);
             }
 
             if (method.getReturnType().equals(void.class))
-                throw new RuntimeException(ServicesMessages.methodIsVoid(
-                        term,
-                        activeType,
-                        expression));
+                throw new RuntimeException(ServicesMessages.methodIsVoid(term, activeType, expression));
 
             return method;
         }
@@ -368,20 +332,13 @@
         ClassPropertyAdapter classAdapter = _access.getAdapter(activeType);
         PropertyAdapter adapter = classAdapter.getPropertyAdapter(term);
 
-        if (adapter == null)
-            throw new RuntimeException(ServicesMessages.noSuchProperty(
-                    activeType,
-                    term,
-                    expression,
-                    classAdapter.getPropertyNames()));
+        if (adapter == null) throw new RuntimeException(
+                ServicesMessages.noSuchProperty(activeType, term, expression, classAdapter.getPropertyNames()));
 
         Method m = adapter.getReadMethod();
 
         if (m == null && mustExist)
-            throw new RuntimeException(ServicesMessages.writeOnlyProperty(
-                    term,
-                    activeType,
-                    expression));
+            throw new RuntimeException(ServicesMessages.writeOnlyProperty(term, activeType, expression));
 
         return m;
     }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java?rev=606396&r1=606395&r2=606396&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java Fri Dec 21 20:55:58 2007
@@ -35,7 +35,6 @@
 import org.apache.tapestry.ioc.annotations.*;
 import org.apache.tapestry.ioc.internal.util.CollectionFactory;
 import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newCaseInsensitiveMap;
-import org.apache.tapestry.ioc.internal.util.InternalUtils;
 import org.apache.tapestry.ioc.services.*;
 import org.apache.tapestry.ioc.util.StrategyRegistry;
 import org.apache.tapestry.ioc.util.TimePeriod;
@@ -133,53 +132,6 @@
     }
 
     /**
-     * A few of the built in services overlap in terms of service interface so we make contributions
-     * to the Alias service to disambiguate. This ensures that a bare parameter (without an
-     * InjectService annotation) will chose the correct value without being further qualified.
-     * <dl>
-     * <dt>{@link ComponentEventResultProcessor}
-     * <dd> the master ComponentEventResultProcessor service (rather than one of the other services
-     * that exist to handle a specific type of result)</li>
-     * <dt>{@link ObjectRenderer}
-     * <dd> the master ObjectRenderer service (rather than the one of the other services that
-     * renders a specific type of object)</li>
-     * <dt>{@link ClassFactory}
-     * <dd> the <em>ComponentClassFactory</em> (which will be recreated if the component class
-     * loader is recreated, on a change to a component class)
-     * <dt>{@link DataTypeAnalyzer}
-     * <dd> the <em>DefaultDataTypeAnalyzer</em> service
-     * </dl>
-     */
-    public static void contributeAlias(Configuration<AliasContribution> configuration, ObjectLocator locator,
-
-                                       @ComponentLayer ClassFactory componentClassFactory,
-
-                                       @InjectService("DefaultDataTypeAnalyzer")
-                                       DataTypeAnalyzer dataTypeAnalyzer)
-    {
-        add(configuration, locator, ComponentEventResultProcessor.class, ObjectRenderer.class);
-
-        configuration.add(AliasContribution.create(ClassFactory.class, componentClassFactory));
-        configuration.add(AliasContribution.create(DataTypeAnalyzer.class, dataTypeAnalyzer));
-    }
-
-    @SuppressWarnings("unchecked")
-    private static void add(Configuration<AliasContribution> configuration, ObjectLocator locator,
-                            Class... serviceInterfaces)
-    {
-        for (Class serviceInterface : serviceInterfaces)
-        {
-            String name = serviceInterface.getName();
-            String serviceId = InternalUtils.lastTerm(name);
-
-            AliasContribution contribution = AliasContribution.create(serviceInterface, locator
-                    .getService(serviceId, serviceInterface));
-
-            configuration.add(contribution);
-        }
-    }
-
-    /**
      * A companion service to {@linkplain #build(org.slf4j.Logger, String, AliasManager, java.util.Collection)}  the Alias service}
      * whose configuration contribution define spot overrides to specific services.
      */
@@ -339,18 +291,23 @@
     }
 
     /**
-     * Adds the {@link #build(java.util.List)}  DefaultDatatTypeAnalyzer} to the
-     * configuration, ordered explicitly last.
+     * <dl>
+     * <dt>Annotation</dt>
+     * <dd>Checks for {@link org.apache.tapestry.beaneditor.DataType} annotation</dd>
+     * <dt>Default  (ordered last)</dt>
+     * <dd>{@link org.apache.tapestry.internal.services.DefaultDataTypeAnalyzer} service ({@link #contributeDefaultDataTypeAnalyzer(org.apache.tapestry.ioc.MappedConfiguration)} })</dd>
+     * </dl>
      */
     public static void contributeDataTypeAnalyzer(OrderedConfiguration<DataTypeAnalyzer> configuration,
                                                   @InjectService("DefaultDataTypeAnalyzer")
                                                   DataTypeAnalyzer defaultDataTypeAnalyzer)
     {
+        configuration.add("Annotation", new AnnotationDataTypeAnalyzer());
         configuration.add("Default", defaultDataTypeAnalyzer, "after:*");
     }
 
     /**
-     * Maps property types to data type names
+     * Maps property types to data type names:
      * <ul>
      * <li>String --&gt; text
      * <li>Number --&gt; text
@@ -876,6 +833,13 @@
         return _chainBuilder.build(ComponentClassTransformWorker.class, configuration);
     }
 
+    /**
+     * Analyzes properties to determine the data types, used to
+     * {@linkplain #contributeBeanBlockSource(org.apache.tapestry.ioc.Configuration)} locale display and edit blocks}
+     * for properties.  The default behaviors look for a {@link org.apache.tapestry.beaneditor.DataType} annotation before
+     * deriving the data type from the property type.
+     */
+    @Marker(Primary.class)
     public DataTypeAnalyzer build(List<DataTypeAnalyzer> configuration)
     {
         return _chainBuilder.build(DataTypeAnalyzer.class, configuration);
@@ -1025,6 +989,7 @@
         return service;
     }
 
+    @Marker(Primary.class)
     public ObjectRenderer build(Map<Class, ObjectRenderer> configuration)
     {
         StrategyRegistry<ObjectRenderer> registry = StrategyRegistry.newInstance(ObjectRenderer.class, configuration);

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Localization.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Localization.java?rev=606396&r1=606395&r2=606396&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Localization.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Localization.java Fri Dec 21 20:55:58 2007
@@ -14,10 +14,11 @@
 
 package org.apache.tapestry.integration.app1.pages;
 
-import org.apache.tapestry.annotations.Service;
 import org.apache.tapestry.ioc.Messages;
 import org.apache.tapestry.ioc.annotations.Inject;
+import org.apache.tapestry.ioc.services.Builtin;
 import org.apache.tapestry.ioc.services.ClassFactory;
+import org.apache.tapestry.services.ComponentLayer;
 import org.apache.tapestry.services.PersistentLocale;
 import org.apache.tapestry.services.Request;
 
@@ -29,11 +30,11 @@
     private Messages _messages;
 
     @Inject
-    @Service("ClassFactory")
+    @Builtin
     private ClassFactory _iocClassFactory;
 
     @Inject
-    @Service("ComponentClassFactory")
+    @ComponentLayer
     private ClassFactory _componentClassFactory;
 
     @Inject

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/AnnotationDataTypeAnalyzerTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/AnnotationDataTypeAnalyzerTest.java?rev=606396&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/AnnotationDataTypeAnalyzerTest.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/AnnotationDataTypeAnalyzerTest.java Fri Dec 21 20:55:58 2007
@@ -0,0 +1,72 @@
+// Copyright 2007 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.tapestry.internal.services;
+
+import org.apache.tapestry.beaneditor.DataType;
+import org.apache.tapestry.ioc.services.PropertyAdapter;
+import org.apache.tapestry.services.DataTypeAnalyzer;
+import org.apache.tapestry.test.TapestryTestCase;
+import org.testng.annotations.Test;
+
+public class AnnotationDataTypeAnalyzerTest extends TapestryTestCase
+{
+    private DataType mockDataType(String annotationValue)
+    {
+        DataType annotation = newMock(DataType.class);
+
+        expect(annotation.value()).andReturn(annotationValue).atLeastOnce();
+
+        return annotation;
+    }
+
+    @Test
+    public void annotation_absent()
+    {
+        PropertyAdapter adapter = mockPropertyAdapter();
+
+        train_getAnnotation(adapter, DataType.class, null);
+
+        replay();
+
+        DataTypeAnalyzer analyzer = new AnnotationDataTypeAnalyzer();
+
+        assertNull(analyzer.identifyDataType(adapter));
+
+        verify();
+    }
+
+    @Test
+    public void value_from_annotation()
+    {
+        String value = "password";
+        PropertyAdapter adapter = mockPropertyAdapter();
+
+        train_getAnnotation(adapter, DataType.class, mockDataType(value));
+
+        replay();
+
+        DataTypeAnalyzer analyzer = new AnnotationDataTypeAnalyzer();
+
+        assertEquals(analyzer.identifyDataType(adapter), value);
+
+        verify();
+
+    }
+
+    private PropertyAdapter mockPropertyAdapter()
+    {
+        return newMock(PropertyAdapter.class);
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/PropertyAdapter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/PropertyAdapter.java?rev=606396&r1=606395&r2=606396&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/PropertyAdapter.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/PropertyAdapter.java Fri Dec 21 20:55:58 2007
@@ -14,15 +14,17 @@
 
 package org.apache.tapestry.ioc.services;
 
-import java.lang.annotation.Annotation;
+import org.apache.tapestry.ioc.AnnotationProvider;
+
 import java.lang.reflect.Method;
 
 /**
- * Provides access to a single property within a class.
+ * 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.
  *
  * @see org.apache.tapestry.ioc.services.ClassPropertyAdapter
  */
-public interface PropertyAdapter
+public interface PropertyAdapter extends AnnotationProvider
 {
     /**
      * Returns the name of the property.
@@ -71,14 +73,4 @@
      * Returns the type of the property.
      */
     Class getType();
-
-    /**
-     * Returns an annotation on the property. The read method (if present) is checked first,
-     * followed by the write method.
-     *
-     * @param <T>
-     * @param annotationClass the annotation to retrieve
-     * @return the annotation on the read or write method, or null if not present on either method
-     */
-    <T extends Annotation> T getAnnotation(Class<T> annotationClass);
 }