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/01/31 21:18:52 UTC
svn commit: r501975 [1/2] - in /tapestry/tapestry5/tapestry-core/trunk/src:
main/java/org/apache/tapestry/ main/java/org/apache/tapestry/beaneditor/
main/java/org/apache/tapestry/corelib/components/
main/java/org/apache/tapestry/internal/beaneditor/ ma...
Author: hlship
Date: Wed Jan 31 12:18:49 2007
New Revision: 501975
URL: http://svn.apache.org/viewvc?view=rev&rev=501975
Log:
Add initial pass at BeanEditor component and surrounding infrastructure.
Added:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/BeanEditorModel.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/Order.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/PropertyConduit.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/PropertyEditModel.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/Validate.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/BeanEditor.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Delegate.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/BeanEditorMessages.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/BeanEditorModelImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/PrimitiveFieldConstraintGenerator.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/PropertyEditModelImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/ValidateAnnotationConstraintGenerator.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/BeanEditorModelSourceImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/CompositeFieldValidator.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ValidationConstraintGeneratorImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/NotificationEventHandler.java
- copied, changed from r499593, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/AcceptVoidEventHandler.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/BeanEditorModelSource.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ValidationConstraintGenerator.java
tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/corelib/components/BeanEditor.html
tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/beaneditor/
tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/beaneditor/BeanEditorStrings.properties
tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/BeanEditorDemo.html
tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/ViewRegistration.html
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/data/RegistrationData.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/BeanEditorDemo.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/ViewRegistration.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/beaneditor/
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/beaneditor/ValidateAnnotationConstraintGeneratorTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/BeanEditorModelSourceImplTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/SimpleBean.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/StoogeBean.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/util/NotificationEventHandlerTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/BeanEditorDemo.properties
Removed:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/AcceptVoidEventHandler.java
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResourcesCommon.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Validator.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Form.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FieldValidatorImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FieldValidatorSourceImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/FieldValidatorSource.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/Max.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/MaxLength.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/Min.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/MinLength.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/Required.java
tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/InternalStrings.properties
tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html
tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/FieldValidatorImplTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/FieldValidatorSourceImplTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/resources/log4j.properties
tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/ValidForm.properties
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResourcesCommon.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResourcesCommon.java?view=diff&rev=501975&r1=501974&r2=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResourcesCommon.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResourcesCommon.java Wed Jan 31 12:18:49 2007
@@ -89,7 +89,8 @@
* parameters (may be null)
* @param handler
* the handler to be informed of the result, or null if the event is a notification
- * that does not support return values from event handler methods
+ * that does not support return values from event handler methods (the value true is
+ * allowed even if the handler is null).
* @return true if any event handler was invoked (even if no event handler method returns a
* non-null value)
* @see OnEventWorker
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Validator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Validator.java?view=diff&rev=501975&r1=501974&r2=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Validator.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Validator.java Wed Jan 31 12:18:49 2007
@@ -70,8 +70,8 @@
throws ValidationException;
/**
- * Returns true if the validator should be skipped for null or blank (empty string) values. This
- * is generally true.
+ * Returns true if the validator should be invoked for null or blank (empty string) values. This
+ * is generally false.
*/
- boolean skipIfBlank();
+ boolean invokeIfBlank();
}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/BeanEditorModel.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/BeanEditorModel.java?view=auto&rev=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/BeanEditorModel.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/BeanEditorModel.java Wed Jan 31 12:18:49 2007
@@ -0,0 +1,55 @@
+// 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.util.List;
+
+/**
+ * Provides the information necessary to build a user interface to create or edit an instance of a
+ * particular type.
+ * <p>
+ * BeanEditorModels are not threadsafe, they are also not serializable.
+ */
+public interface BeanEditorModel
+{
+ /**
+ * Returns a list of the editable properties of the bean, in <em>presentation</em> order.
+ *
+ * @return
+ */
+ List<String> getPropertyNames();
+
+ /**
+ * Returns the named model.
+ *
+ * @param propertyName
+ * name of property to retrieve model for
+ * @return the model for the property
+ * @throws RuntimeException
+ * if the bean editor model does not have a property model for the provided name
+ */
+ PropertyEditModel get(String propertyName);
+
+ /**
+ * Adds a new property to the model, returning its mutable model for further refinement.
+ *
+ * @param propertyName
+ * name of property to add
+ * @return the model for the property
+ * @throws RuntimeException
+ * if the property already exists
+ */
+ PropertyEditModel add(String propertyName);
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/Order.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/Order.java?view=auto&rev=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/Order.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/Order.java Wed Jan 31 12:18:49 2007
@@ -0,0 +1,36 @@
+// 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 static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Placed on either a property getter or a property setter method to control the order in which the
+ * properties are presented to the user. The properties will be sorted in ascending order by the
+ * value. Properties with no value will be treated as though they have the value 0. When multiple
+ * properties have the same order value, they will be sorted alphabetically.
+ */
+@Target(METHOD)
+@Retention(RUNTIME)
+@Documented
+public @interface Order {
+ /** The sort order for this property. */
+ int value();
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/PropertyConduit.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/PropertyConduit.java?view=auto&rev=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/PropertyConduit.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/PropertyConduit.java Wed Jan 31 12:18:49 2007
@@ -0,0 +1,53 @@
+// 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.Annotation;
+
+/**
+ * Used to read or update the value associated with a property.
+ */
+public interface PropertyConduit
+{
+ /**
+ * Reads the property from the instance.
+ *
+ * @param instance
+ * object containing the property
+ * @return the current value of the property
+ */
+ Object read(Object instance);
+
+ /**
+ * Changes the current value of the property.
+ *
+ * @param instance
+ * object containing the property
+ * @param value
+ * to change the property to
+ */
+ void write(Object instance, Object value);
+
+ /**
+ * Returns an annotation if present on the property. The annotation is checked for on both the
+ * getter method and the setter method.
+ *
+ * @param <T>
+ * @param annotationClass
+ * the type of annotation to return
+ * @return the annotation if present, or null if not available
+ */
+ <T extends Annotation> T getAnnotation(Class<T> annotationClass);
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/PropertyEditModel.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/PropertyEditModel.java?view=auto&rev=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/PropertyEditModel.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/PropertyEditModel.java Wed Jan 31 12:18:49 2007
@@ -0,0 +1,89 @@
+// 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;
+
+/**
+ * Part of a {@link BeanEditorModel} that defines the attributes of a single edittable property of a
+ * bean.
+ */
+public interface PropertyEditModel
+{
+ /** Returns the name of the property. */
+ String getPropertyName();
+
+ /** Returns a user-presentable label for the property. */
+ String getLabel();
+
+ /** Returns the order vlaue, used to sort the properties into presentation order. */
+ int getOrder();
+
+ /** Returns the type of the property. */
+ Class getPropertyType();
+
+ /**
+ * Returns an object used to read or update the property. For virtual properties (properties
+ * that do not actually exist on the bean), the conduit may be null until one is provided via
+ * {@link MutablePropertyEditModel#conduit(PropertyConduit)}.
+ */
+ PropertyConduit getConduit();
+
+ /**
+ * Changes the property type for the property.
+ *
+ * @param propertyType
+ * the new property type for the property.
+ * @return the property's model, for further changes
+ */
+ PropertyEditModel propertyType(Class propertyType);
+
+ /**
+ * Changes the label for the property to the provided value.
+ *
+ * @param label
+ * new label for property
+ * @return the property's model, for further changes
+ */
+ PropertyEditModel label(String label);
+
+ /**
+ * Changes the order for the property. The properties are sorted by order (and then by name for
+ * identical orders) when building the user interface.
+ */
+ PropertyEditModel order(int order);
+
+ /**
+ * Changes the conduit for the property to the provided value.
+ *
+ * @param conduit
+ * new conduit object (used to read or update the property value on an instance)
+ * @return the property's model, for further changes
+ */
+ PropertyEditModel conduit(PropertyConduit conduit);
+
+ // "Navigation" methods useful for the "fluent" style of configuration.
+
+ /**
+ * Delegates to {@link BeanEditorModel#get(String)}.
+ */
+ PropertyEditModel get(String propertyName);
+
+ /**
+ * Delegates to {@link BeanEditorModel#add(String)}.
+ */
+ PropertyEditModel add(String propertyName);
+
+ /** Returns the containing model. */
+ BeanEditorModel model();
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/Validate.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/Validate.java?view=auto&rev=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/Validate.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/beaneditor/Validate.java Wed Jan 31 12:18:49 2007
@@ -0,0 +1,36 @@
+// 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 static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Used to attach validation constraints directly to a property (either the getter or the setter
+ * method). The annotation value is a comma seperated 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 seperated from the type by an
+ * equals size (i.e., "maxlength=30").
+ */
+@Target(METHOD)
+@Retention(RUNTIME)
+@Documented
+public @interface Validate {
+ String value();
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/BeanEditor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/BeanEditor.java?view=auto&rev=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/BeanEditor.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/BeanEditor.java Wed Jan 31 12:18:49 2007
@@ -0,0 +1,196 @@
+// 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.corelib.components;
+
+import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
+
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.tapestry.Block;
+import org.apache.tapestry.ComponentResources;
+import org.apache.tapestry.Field;
+import org.apache.tapestry.FieldValidator;
+import org.apache.tapestry.Translator;
+import org.apache.tapestry.annotations.Component;
+import org.apache.tapestry.annotations.ComponentClass;
+import org.apache.tapestry.annotations.Inject;
+import org.apache.tapestry.annotations.Parameter;
+import org.apache.tapestry.beaneditor.BeanEditorModel;
+import org.apache.tapestry.beaneditor.PropertyEditModel;
+import org.apache.tapestry.internal.services.CompositeFieldValidator;
+import org.apache.tapestry.ioc.Messages;
+import org.apache.tapestry.services.BeanEditorModelSource;
+import org.apache.tapestry.services.FieldValidatorSource;
+import org.apache.tapestry.services.TranslatorDefaultSource;
+import org.apache.tapestry.services.ValidationConstraintGenerator;
+
+/**
+ * A component that creates an entire form editting the properties of a particular bean. Inspired by
+ * <a href="http://www.trailsframework.org/">Trails</a> and <a
+ * href="http://beanform.sourceforge.net/">BeanForm</a> (both for Tapestry 4). Generates a simple
+ * UI for editting the properties of a JavaBean, with the flavor of UI for each property (text
+ * field, checkbox, drop down list) determined from the property type, and the order and validation
+ * for the properties determined from annotations on the property's getter and setter methods.
+ * <p>
+ * This component is likely to change more than any other thing in Tapestry! What's available now is
+ * a very limited preview of its eventual functionality.
+ *
+ * @see BeanEditorModel
+ * @see BeanEditorModelSource
+ */
+@ComponentClass
+public class BeanEditor
+{
+ /** The object to be editted by the BeanEditor. */
+ @Parameter(required = true)
+ private Object _object;
+
+ @Inject
+ private ComponentResources _resources;
+
+ @Inject("infrastructure:BeanEditorModelSource")
+ private BeanEditorModelSource _modelSource;
+
+ @Inject("infrastructure:TranslatorDefaultSource")
+ private TranslatorDefaultSource _translatorDefaultSource;
+
+ @Inject("infrastructure:FieldValidatorSource")
+ private FieldValidatorSource _fieldValidatorSource;
+
+ @Inject("infrastructure:ValidationConstraintGenerator")
+ private ValidationConstraintGenerator _validationConstraintGenerator;
+
+ @Inject
+ private Block _text;
+
+ @Component(parameters =
+ { "value=valueForProperty", "label=prop:propertyEditModel.label",
+ "translate=prop:translateForProperty", "validate=prop:validateForProperty" })
+ private TextField _textField;
+
+ @Inject
+ private Locale _locale;
+
+ @Parameter
+ private BeanEditorModel _model;
+
+ // Values that change with each change to the current property:
+
+ private PropertyEditModel _propertyEditModel;
+
+ private Block _blockForProperty;
+
+ private Field _fieldForProperty;
+
+ public BeanEditorModel getModel()
+ {
+ return _model;
+ }
+
+ public void setPropertyName(String propertyName)
+ {
+ _propertyEditModel = _model.get(propertyName);
+
+ // Shortly, we'll do a bit more work to set these two values.
+
+ _blockForProperty = _text;
+ _fieldForProperty = _textField;
+ }
+
+ public String getPropertyName()
+ {
+ return _propertyEditModel.getPropertyName();
+ }
+
+ boolean onPrepareFromForm()
+ {
+ // Fire a new prepare event to be consumed by the container. This is the container's
+ // chance to ensure that there's an object to edit.
+
+ _resources.triggerEvent(Form.PREPARE, null, null);
+
+ if (_model == null)
+ {
+ Class beanType = _object.getClass();
+
+ _model = _modelSource.create(beanType, _resources.getContainerResources());
+ }
+
+ return true; // abort the form's prepare event
+ }
+
+ public Translator getTranslateForProperty()
+ {
+ return _translatorDefaultSource.find(_propertyEditModel.getPropertyType());
+ }
+
+ public FieldValidator getValidateForProperty()
+ {
+ List<FieldValidator> validators = newList();
+
+ // Use the property name, not the field id, when locating
+ // validation message overrides.
+ String overrideId = _propertyEditModel.getPropertyName();
+ // Pull override messages out of the BeanEditor's container
+ Messages overrideMessages = _resources.getContainerResources().getMessages();
+
+ for (String constraint : _validationConstraintGenerator
+ .buildConstraints(_propertyEditModel))
+ {
+ int equalsx = constraint.indexOf('=');
+
+ String validatorType = equalsx > 0 ? constraint.substring(0, equalsx) : constraint;
+ String constraintValue = equalsx > 0 ? constraint.substring(equalsx + 1) : null;
+
+ FieldValidator validator = _fieldValidatorSource.createValidator(
+ _fieldForProperty,
+ validatorType,
+ constraintValue,
+ overrideId,
+ overrideMessages,
+ _locale);
+
+ validators.add(validator);
+ }
+
+ return new CompositeFieldValidator(validators);
+ }
+
+ public PropertyEditModel getPropertyEditModel()
+ {
+ return _propertyEditModel;
+ }
+
+ public Block getBlockForProperty()
+ {
+ return _blockForProperty;
+ }
+
+ public Field getFieldForProperty()
+ {
+ return _fieldForProperty;
+ }
+
+ public Object getValueForProperty()
+ {
+ return _propertyEditModel.getConduit().read(_object);
+ }
+
+ public void setValueForProperty(Object value)
+ {
+ _propertyEditModel.getConduit().write(_object, value);
+ }
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Delegate.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Delegate.java?view=auto&rev=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Delegate.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Delegate.java Wed Jan 31 12:18:49 2007
@@ -0,0 +1,36 @@
+// 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.corelib.components;
+
+import org.apache.tapestry.Block;
+import org.apache.tapestry.annotations.ComponentClass;
+import org.apache.tapestry.annotations.Parameter;
+
+/**
+ * A component that does not do any rendering of its own, but will delegate to some other object
+ * that can do rendering. This other object may be a component or a {@link Block} (among other
+ * things).
+ */
+@ComponentClass
+public class Delegate
+{
+ @Parameter(required = true)
+ private Object _to;
+
+ Object beginRender()
+ {
+ return _to;
+ }
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Form.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Form.java?view=diff&rev=501975&r1=501974&r2=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Form.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Form.java Wed Jan 31 12:18:49 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 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.
@@ -58,9 +58,9 @@
/**
* An HTML form, which will enclose other components to render out the various types of fields.
* <p>
- * A Form emits several notification events; when it renders it sends a
- * {@link #PREPARE_EVENT prepare} notification event, to allow any listeners to set up the state of
- * the page prior to rendering out the form's content.
+ * A Form emits several notification events; when it renders it sends a {@link #PREPARE prepare}
+ * notification event, to allow any listeners to set up the state of the page prior to rendering out
+ * the form's content.
* <p>
* When the form is submitted, the component emits four notifications: first another prepare event
* to allow the page to update its state as necessary to prepare for the form submission, then
@@ -80,7 +80,7 @@
* Invoked to let the containing component(s) prepare for the form rendering or the form
* submission.
*/
- public static final String PREPARE_EVENT = "prepare";
+ public static final String PREPARE = "prepare";
/**
* Event type for a notification after the form has submitted. This event notification occurs on
@@ -199,7 +199,7 @@
Object[] contextArray = _context == null ? new Object[0] : _context.toArray();
- _resources.triggerEvent(PREPARE_EVENT, contextArray, null);
+ _resources.triggerEvent(PREPARE, contextArray, null);
String name = _pageRenderSupport.allocateClientId(_resources.getId());
@@ -289,6 +289,9 @@
public boolean handleResult(Object result, Component component,
String methodDescription)
{
+ if (result instanceof Boolean)
+ return ((Boolean) result);
+
holder.put(_eventResultProcessor.processComponentEvent(
result,
component,
@@ -298,7 +301,7 @@
}
};
- _resources.triggerEvent(PREPARE_EVENT, context, handler);
+ _resources.triggerEvent(PREPARE, context, handler);
if (holder.hasValue())
return holder.get();
@@ -355,7 +358,7 @@
// If the tracker has no errors, then clear it of any input values
// as well, so that the next page render will be "clean" and show
// true persistent data, not value from the previous form submission.
-
+
if (!_tracker.getHasErrors())
_tracker.clear();
@@ -379,7 +382,7 @@
}
/**
- * A convienience for invoking {@link ValidationTracker#recordError(String)}.
+ * A convienience for invoking {@link ValidationTracker#recordError(String)}.
*/
public void recordError(String errorMessage)
{
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/BeanEditorMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/BeanEditorMessages.java?view=auto&rev=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/BeanEditorMessages.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/BeanEditorMessages.java Wed Jan 31 12:18:49 2007
@@ -0,0 +1,38 @@
+// 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.beaneditor;
+
+import java.util.Collection;
+
+import org.apache.tapestry.ioc.Messages;
+import org.apache.tapestry.ioc.internal.util.InternalUtils;
+import org.apache.tapestry.ioc.internal.util.MessagesImpl;
+
+class BeanEditorMessages
+{
+ private static final Messages MESSAGES = MessagesImpl.forClass(BeanEditorMessages.class);
+
+ static String duplicatePropertyName(Class beanType, String propertyName)
+ {
+ return MESSAGES.format("duplicate-property-name", beanType.getName(), propertyName);
+ }
+
+ static String unknownProperty(Class beanType, String propertyName,
+ Collection<String> propertyNames)
+ {
+ return MESSAGES.format("unknown-property", beanType.getName(), propertyName, InternalUtils
+ .joinSorted(propertyNames));
+ }
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/BeanEditorModelImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/BeanEditorModelImpl.java?view=auto&rev=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/BeanEditorModelImpl.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/BeanEditorModelImpl.java Wed Jan 31 12:18:49 2007
@@ -0,0 +1,179 @@
+// 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.beaneditor;
+
+import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
+import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newMap;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tapestry.beaneditor.BeanEditorModel;
+import org.apache.tapestry.beaneditor.PropertyConduit;
+import org.apache.tapestry.beaneditor.PropertyEditModel;
+import org.apache.tapestry.internal.TapestryUtils;
+import org.apache.tapestry.ioc.Messages;
+import org.apache.tapestry.ioc.services.ClassPropertyAdapter;
+import org.apache.tapestry.ioc.services.PropertyAdapter;
+import org.apache.tapestry.ioc.services.TypeCoercer;
+
+public class BeanEditorModelImpl implements BeanEditorModel, Comparator<PropertyEditModel>
+{
+ private final Class _beanType;
+
+ private final ClassPropertyAdapter _classPropertyAdapter;
+
+ private final TypeCoercer _typeCoercer;
+
+ private final Messages _messages;
+
+ private final Map<String, PropertyEditModel> _properties = newMap();
+
+ public BeanEditorModelImpl(Class beanType, ClassPropertyAdapter classPropertyAdapter,
+ TypeCoercer typeCoercer, Messages messages)
+ {
+ _beanType = beanType;
+ _classPropertyAdapter = classPropertyAdapter;
+ _typeCoercer = typeCoercer;
+ _messages = messages;
+ }
+
+ public PropertyEditModel add(String propertyName)
+ {
+ if (_properties.containsKey(propertyName))
+ throw new RuntimeException(BeanEditorMessages.duplicatePropertyName(
+ _beanType,
+ propertyName));
+
+ String label = defaultLabel(propertyName);
+
+ final PropertyAdapter adapter = _classPropertyAdapter.getPropertyAdapter(propertyName);
+
+ PropertyConduit conduit = defaultConduit(adapter);
+
+ PropertyEditModel propertyModel = new PropertyEditModelImpl(this, propertyName)
+ .label(label).conduit(conduit);
+
+ if (adapter != null)
+ propertyModel.propertyType(adapter.getType());
+
+ _properties.put(propertyName, propertyModel);
+
+ return propertyModel;
+ }
+
+ private PropertyConduit defaultConduit(final PropertyAdapter adapter)
+ {
+ if (adapter == null)
+ return null;
+
+ final Class propertyType = adapter.getType();
+
+ // Eventually, we'll find a way to replace this with something that does not
+ // use reflection.
+
+ return new PropertyConduit()
+ {
+ public Object read(Object instance)
+ {
+ return adapter.get(instance);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void write(Object instance, Object value)
+ {
+ // TODO: Wrap this to provide a more useful error if the coercion
+ // fails.
+
+ Object coerced = _typeCoercer.coerce(value, propertyType);
+
+ adapter.set(instance, coerced);
+ }
+
+ public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
+ {
+ T result = getAnnotation(adapter.getWriteMethod(), annotationClass);
+
+ if (result == null)
+ result = getAnnotation(adapter.getReadMethod(), annotationClass);
+
+ return result;
+ }
+
+ private <T extends Annotation> T getAnnotation(Method method, Class<T> annotationClass)
+ {
+ return method == null ? null : method.getAnnotation(annotationClass);
+ }
+
+ };
+ }
+
+ public PropertyEditModel edit(String propertyName)
+ {
+ PropertyEditModel propertyModel = _properties.get(propertyName);
+
+ if (propertyModel == null)
+ throw new RuntimeException(BeanEditorMessages.unknownProperty(
+ _beanType,
+ propertyName,
+ _properties.keySet()));
+
+ return propertyModel;
+ }
+
+ public PropertyEditModel get(String propertyName)
+ {
+ return edit(propertyName);
+ }
+
+ public List<String> getPropertyNames()
+ {
+ List<PropertyEditModel> propertyModels = newList(_properties.values());
+
+ Collections.sort(propertyModels, this);
+
+ List<String> result = newList();
+
+ for (PropertyEditModel propertyModel : propertyModels)
+ result.add(propertyModel.getPropertyName());
+
+ return result;
+ }
+
+ public int compare(PropertyEditModel o1, PropertyEditModel o2)
+ {
+ int result = o1.getOrder() - o2.getOrder();
+
+ if (result == 0)
+ result = o1.getPropertyName().compareTo(o2.getPropertyName());
+
+ return result;
+ }
+
+ private String defaultLabel(String propertyName)
+ {
+ String key = propertyName + "-label";
+
+ if (_messages.contains(key))
+ return _messages.get(key);
+
+ return TapestryUtils.toUserPresentable(propertyName);
+ }
+
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/PrimitiveFieldConstraintGenerator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/PrimitiveFieldConstraintGenerator.java?view=auto&rev=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/PrimitiveFieldConstraintGenerator.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/PrimitiveFieldConstraintGenerator.java Wed Jan 31 12:18:49 2007
@@ -0,0 +1,38 @@
+// 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.beaneditor;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.tapestry.beaneditor.PropertyEditModel;
+import org.apache.tapestry.services.ValidationConstraintGenerator;
+
+/**
+ * Adds a "required" constraint for any property of whose type is a primitive (not a wrapper or
+ * reference) type.
+ */
+public class PrimitiveFieldConstraintGenerator implements ValidationConstraintGenerator
+{
+ private final List<String> REQUIRED = Arrays.asList("required");
+
+ public List<String> buildConstraints(PropertyEditModel propertyModel)
+ {
+ Class type = propertyModel.getPropertyType();
+
+ return type.isPrimitive() ? REQUIRED : null;
+ }
+
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/PropertyEditModelImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/PropertyEditModelImpl.java?view=auto&rev=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/PropertyEditModelImpl.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/PropertyEditModelImpl.java Wed Jan 31 12:18:49 2007
@@ -0,0 +1,114 @@
+// 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.beaneditor;
+
+import static org.apache.tapestry.ioc.internal.util.Defense.notBlank;
+
+import org.apache.tapestry.beaneditor.BeanEditorModel;
+import org.apache.tapestry.beaneditor.PropertyConduit;
+import org.apache.tapestry.beaneditor.PropertyEditModel;
+import org.apache.tapestry.ioc.internal.util.Defense;
+
+public class PropertyEditModelImpl implements PropertyEditModel
+{
+ private final BeanEditorModel _model;
+
+ private final String _name;
+
+ private String _label;
+
+ private PropertyConduit _conduit;
+
+ private int _order;
+
+ private Class _propertyType = Object.class;
+
+ public PropertyEditModelImpl(BeanEditorModel model, final String name)
+ {
+ _model = model;
+ _name = name;
+ }
+
+ public Class getPropertyType()
+ {
+ return _propertyType;
+ }
+
+ public PropertyEditModel propertyType(Class propertyType)
+ {
+ Defense.notNull(propertyType, "propertyType");
+
+ _propertyType = propertyType;
+
+ return this;
+ }
+
+ public PropertyConduit getConduit()
+ {
+ return _conduit;
+ }
+
+ public PropertyEditModel conduit(PropertyConduit conduit)
+ {
+ _conduit = conduit;
+
+ return this;
+ }
+
+ public PropertyEditModel label(String label)
+ {
+ notBlank(label, "label");
+
+ _label = label;
+
+ return this;
+ }
+
+ public String getLabel()
+ {
+ return _label;
+ }
+
+ public String getPropertyName()
+ {
+ return _name;
+ }
+
+ public int getOrder()
+ {
+ return _order;
+ }
+
+ public PropertyEditModel order(int order)
+ {
+ _order = order;
+ return this;
+ }
+
+ public PropertyEditModel add(String propertyName)
+ {
+ return _model.add(propertyName);
+ }
+
+ public PropertyEditModel get(String propertyName)
+ {
+ return _model.get(propertyName);
+ }
+
+ public BeanEditorModel model()
+ {
+ return _model;
+ }
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/ValidateAnnotationConstraintGenerator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/ValidateAnnotationConstraintGenerator.java?view=auto&rev=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/ValidateAnnotationConstraintGenerator.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/ValidateAnnotationConstraintGenerator.java Wed Jan 31 12:18:49 2007
@@ -0,0 +1,40 @@
+// 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.beaneditor;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.tapestry.beaneditor.PropertyEditModel;
+import org.apache.tapestry.beaneditor.Validate;
+import org.apache.tapestry.services.ValidationConstraintGenerator;
+
+/**
+ * Checks for the {@link Validate} annotation, and extracts its value to form the result.
+ */
+public class ValidateAnnotationConstraintGenerator implements ValidationConstraintGenerator
+{
+
+ public List<String> buildConstraints(PropertyEditModel propertyModel)
+ {
+ Validate annotation = propertyModel.getConduit().getAnnotation(Validate.class);
+
+ if (annotation == null)
+ return null;
+
+ return Arrays.asList(annotation.value().split(","));
+ }
+
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/BeanEditorModelSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/BeanEditorModelSourceImpl.java?view=auto&rev=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/BeanEditorModelSourceImpl.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/BeanEditorModelSourceImpl.java Wed Jan 31 12:18:49 2007
@@ -0,0 +1,80 @@
+// 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 java.util.Collections;
+import java.util.List;
+
+import org.apache.tapestry.ComponentResources;
+import org.apache.tapestry.beaneditor.BeanEditorModel;
+import org.apache.tapestry.beaneditor.Order;
+import org.apache.tapestry.beaneditor.PropertyEditModel;
+import org.apache.tapestry.internal.beaneditor.BeanEditorModelImpl;
+import org.apache.tapestry.ioc.Messages;
+import org.apache.tapestry.ioc.internal.util.Defense;
+import org.apache.tapestry.ioc.services.ClassPropertyAdapter;
+import org.apache.tapestry.ioc.services.PropertyAccess;
+import org.apache.tapestry.ioc.services.PropertyAdapter;
+import org.apache.tapestry.ioc.services.TypeCoercer;
+import org.apache.tapestry.services.BeanEditorModelSource;
+
+public class BeanEditorModelSourceImpl implements BeanEditorModelSource
+{
+ private final TypeCoercer _typeCoercer;
+
+ private final PropertyAccess _propertyAccess;
+
+ public BeanEditorModelSourceImpl(final TypeCoercer typeCoercer,
+ final PropertyAccess propertyAccess)
+ {
+ _typeCoercer = typeCoercer;
+ _propertyAccess = propertyAccess;
+ }
+
+ public BeanEditorModel create(Class beanClass, ComponentResources resources)
+ {
+ Defense.notNull(beanClass, "beanClass");
+ Defense.notNull(resources, "resources");
+
+ Messages messages = resources.getMessages();
+
+ ClassPropertyAdapter adapter = _propertyAccess.getAdapter(beanClass);
+
+ BeanEditorModel model = new BeanEditorModelImpl(beanClass, adapter, _typeCoercer, messages);
+
+ for (String propertyName : adapter.getPropertyNames())
+ {
+ PropertyAdapter pa = adapter.getPropertyAdapter(propertyName);
+
+ if (pa.isRead() && pa.isUpdate())
+ {
+ PropertyEditModel propertyModel = model.add(propertyName);
+
+ Order annotation = propertyModel.getConduit().getAnnotation(Order.class);
+
+ if (annotation != null)
+ propertyModel.order(annotation.value());
+ }
+ }
+
+ return model;
+ }
+
+ public List<String> buildConstraints(PropertyEditModel propertyModel)
+ {
+ return Collections.emptyList();
+ }
+
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/CompositeFieldValidator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/CompositeFieldValidator.java?view=auto&rev=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/CompositeFieldValidator.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/CompositeFieldValidator.java Wed Jan 31 12:18:49 2007
@@ -0,0 +1,38 @@
+// 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 java.util.List;
+
+import org.apache.tapestry.FieldValidator;
+import org.apache.tapestry.ValidationException;
+
+/** Aggregates together a number of field validator instances as a single unit. */
+public final class CompositeFieldValidator implements FieldValidator
+{
+ private final FieldValidator[] _validators;
+
+ public CompositeFieldValidator(List<FieldValidator> validators)
+ {
+ _validators = validators.toArray(new FieldValidator[validators.size()]);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void validate(Object value) throws ValidationException
+ {
+ for (FieldValidator fv : _validators)
+ fv.validate(value);
+ }
+}
\ No newline at end of file
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FieldValidatorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FieldValidatorImpl.java?view=diff&rev=501975&r1=501974&r2=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FieldValidatorImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FieldValidatorImpl.java Wed Jan 31 12:18:49 2007
@@ -42,7 +42,7 @@
@SuppressWarnings("unchecked")
public void validate(Object value) throws ValidationException
{
- if (_validator.skipIfBlank() && isBlank(value))
+ if (! _validator.invokeIfBlank() && isBlank(value))
return;
if (value != null && !_validator.getValueType().isInstance(value))
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FieldValidatorSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FieldValidatorSourceImpl.java?view=diff&rev=501975&r1=501974&r2=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FieldValidatorSourceImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FieldValidatorSourceImpl.java Wed Jan 31 12:18:49 2007
@@ -25,7 +25,6 @@
import org.apache.tapestry.ComponentResources;
import org.apache.tapestry.Field;
import org.apache.tapestry.FieldValidator;
-import org.apache.tapestry.ValidationException;
import org.apache.tapestry.Validator;
import org.apache.tapestry.ioc.MessageFormatter;
import org.apache.tapestry.ioc.Messages;
@@ -56,42 +55,61 @@
Component component = cast(field, Component.class, "field");
notBlank(validatorType, "validatorType");
+ ComponentResources componentResources = component.getComponentResources();
+ String overrideId = componentResources.getId();
+ Locale locale = componentResources.getLocale();
+
+ ComponentResources containerResources = componentResources.getContainerResources();
+
+ // So, if you use a TextField on your EditUser page, we want to search the messages
+ // of the EditUser page (the container), not the TextField (which will always be the same).
+
+ Messages overrideMessages = containerResources.getMessages();
+
+ return createValidator(
+ field,
+ validatorType,
+ constraintValue,
+ overrideId,
+ overrideMessages,
+ locale);
+ }
+
+ public FieldValidator createValidator(Field field, String validatorType,
+ String constraintValue, String overrideId, Messages overrideMessages, Locale locale)
+ {
+ notBlank(validatorType, "validatorType");
+
Validator validator = _validators.get(validatorType);
if (validator == null)
- {
- String message = ServicesMessages.unknownValidatorType(validatorType, InternalUtils
- .sortedKeys(_validators));
-
- throw new IllegalArgumentException(message);
- }
+ throw new IllegalArgumentException(ServicesMessages.unknownValidatorType(
+ validatorType,
+ InternalUtils.sortedKeys(_validators)));
Object coercedConstraintValue = coerceConstraintValue(constraintValue, validator
.getConstraintType());
- MessageFormatter formatter = findMessageFormatter(component, validatorType, validator);
+ MessageFormatter formatter = findMessageFormatter(
+ overrideId,
+ overrideMessages,
+ locale,
+ validatorType,
+ validator);
return new FieldValidatorImpl(field, coercedConstraintValue, formatter, validator);
}
- private MessageFormatter findMessageFormatter(Component component, String validatorType,
- Validator validator)
+ private MessageFormatter findMessageFormatter(String overrideId, Messages overrideMessages,
+ Locale locale, String validatorType, Validator validator)
{
- ComponentResources resources = component.getComponentResources();
-
- String overrideKey = resources.getId() + "-" + validatorType;
-
- // So, if you use a TextField on your EditUser page, we want to search the messages
- // of the EditUser page (the container), not the TextField (which will always be the same).
-
- Messages messages = resources.getContainerResources().getMessages();
- if (messages.contains(overrideKey))
- return messages.getFormatter(overrideKey);
+ String overrideKey = overrideId + "-" + validatorType;
- Locale locale = resources.getLocale();
+ if (overrideMessages.contains(overrideKey))
+ return overrideMessages.getFormatter(overrideKey);
- messages = _messagesSource.getValidationMessages(locale);
+ Messages messages = _messagesSource.getValidationMessages(locale);
String key = validator.getMessageKey();
@@ -113,17 +131,7 @@
if (fieldValidators.size() == 1)
return fieldValidators.get(0);
- final FieldValidator[] array = fieldValidators.toArray(new FieldValidator[0]);
-
- return new FieldValidator()
- {
- @SuppressWarnings("unchecked")
- public void validate(Object value) throws ValidationException
- {
- for (FieldValidator fv : array)
- fv.validate(value);
- }
- };
+ return new CompositeFieldValidator(fieldValidators);
}
@SuppressWarnings("unchecked")
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ValidationConstraintGeneratorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ValidationConstraintGeneratorImpl.java?view=auto&rev=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ValidationConstraintGeneratorImpl.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ValidationConstraintGeneratorImpl.java Wed Jan 31 12:18:49 2007
@@ -0,0 +1,48 @@
+// 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 java.util.List;
+
+import org.apache.tapestry.beaneditor.PropertyEditModel;
+import org.apache.tapestry.ioc.internal.util.CollectionFactory;
+import org.apache.tapestry.services.ValidationConstraintGenerator;
+
+public class ValidationConstraintGeneratorImpl implements ValidationConstraintGenerator
+{
+ private final List<ValidationConstraintGenerator> _configuration;
+
+ public ValidationConstraintGeneratorImpl(final List<ValidationConstraintGenerator> configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public List<String> buildConstraints(PropertyEditModel propertyModel)
+ {
+ List<String> result = CollectionFactory.newList();
+
+ for (ValidationConstraintGenerator g : _configuration)
+ {
+ List<String> constraints = g.buildConstraints(propertyModel);
+
+ if (constraints != null)
+ result.addAll(constraints);
+ }
+
+ // TODO: How to handle duplicate or conflicting constraints from different generators?
+
+ return result;
+ }
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java?view=diff&rev=501975&r1=501974&r2=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java Wed Jan 31 12:18:49 2007
@@ -36,7 +36,7 @@
import org.apache.tapestry.internal.services.ComponentEventImpl;
import org.apache.tapestry.internal.services.EventImpl;
import org.apache.tapestry.internal.services.Instantiator;
-import org.apache.tapestry.internal.util.AcceptVoidEventHandler;
+import org.apache.tapestry.internal.util.NotificationEventHandler;
import org.apache.tapestry.ioc.BaseLocatable;
import org.apache.tapestry.ioc.IOCUtilities;
import org.apache.tapestry.ioc.Location;
@@ -997,7 +997,7 @@
// Provide a default handler for when the provided handler is null.
if (handler == null)
- handler = new AcceptVoidEventHandler(eventType, _completeId);
+ handler = new NotificationEventHandler(eventType, _completeId);
ComponentEvent event = new ComponentEventImpl(eventType, _id, context, handler,
_typeCoercer);
Copied: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/NotificationEventHandler.java (from r499593, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/AcceptVoidEventHandler.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/NotificationEventHandler.java?view=diff&rev=501975&p1=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/AcceptVoidEventHandler.java&r1=499593&p2=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/NotificationEventHandler.java&r2=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/AcceptVoidEventHandler.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/NotificationEventHandler.java Wed Jan 31 12:18:49 2007
@@ -12,36 +12,38 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.tapestry.internal.util;
-
-import org.apache.tapestry.ComponentEventHandler;
-import org.apache.tapestry.runtime.Component;
-
-/**
- * A {@link ComponentEventHandler} that does not accept any value. This is used when an event is
- * dispatched as a notification. Event handlers should not return a value.
- */
-public class AcceptVoidEventHandler implements ComponentEventHandler
-{
- private final String _eventType;
-
- private final String _completeId;
-
- public AcceptVoidEventHandler(final String eventType, final String completeId)
- {
- _eventType = eventType;
- _completeId = completeId;
- }
-
- public boolean handleResult(Object result, Component component, String methodDescription)
- {
- // Don't even need a null check because this is only invoked if a method returns non-null.
-
- throw new IllegalArgumentException(UtilMessages.noReturnValueAccepted(
- _eventType,
- _completeId,
- result,
- methodDescription));
- }
-
-}
+package org.apache.tapestry.internal.util;
+
+import org.apache.tapestry.ComponentEventHandler;
+import org.apache.tapestry.runtime.Component;
+
+/**
+ * A {@link ComponentEventHandler} used for notification events. Event handler methods may return
+ * true (to abort the event) or false (to allow the event to continue bubbling up), but all other
+ * values are forbidden.
+ */
+public class NotificationEventHandler implements ComponentEventHandler
+{
+ private final String _eventType;
+
+ private final String _completeId;
+
+ public NotificationEventHandler(String eventType, String completeId)
+ {
+ _eventType = eventType;
+ _completeId = completeId;
+ }
+
+ public boolean handleResult(Object result, Component component, String methodDescription)
+ {
+ if (result instanceof Boolean)
+ return ((Boolean) result);
+
+ throw new IllegalArgumentException(UtilMessages.noReturnValueAccepted(
+ _eventType,
+ _completeId,
+ result,
+ methodDescription));
+ }
+
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/BeanEditorModelSource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/BeanEditorModelSource.java?view=auto&rev=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/BeanEditorModelSource.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/BeanEditorModelSource.java Wed Jan 31 12:18:49 2007
@@ -0,0 +1,42 @@
+// 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.services;
+
+import org.apache.tapestry.ComponentResources;
+import org.apache.tapestry.beaneditor.BeanEditorModel;
+import org.apache.tapestry.beaneditor.Order;
+
+/**
+ * Used by a component to create a default {@link BeanEditorModel} for a particular bean class. Also
+ * provides support to the model by generating validation information for individual fields.
+ */
+public interface BeanEditorModelSource
+{
+ /**
+ * Creates a new model used for editting 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 Order} 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.
+ *
+ * @param beanClass
+ * class of object to be editted
+ * @param resources
+ * used when resolving resources, especially component messages (used to access
+ * labels)
+ * @return a model
+ */
+ BeanEditorModel create(Class beanClass, ComponentResources resources);
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/FieldValidatorSource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/FieldValidatorSource.java?view=diff&rev=501975&r1=501974&r2=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/FieldValidatorSource.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/FieldValidatorSource.java Wed Jan 31 12:18:49 2007
@@ -14,9 +14,13 @@
package org.apache.tapestry.services;
+import java.util.Locale;
+
import org.apache.tapestry.Field;
import org.apache.tapestry.FieldValidator;
import org.apache.tapestry.Validator;
+import org.apache.tapestry.corelib.components.BeanEditor;
+import org.apache.tapestry.ioc.Messages;
/**
* Used to create {@link FieldValidator}s for a particular {@link Field} component.
@@ -24,7 +28,12 @@
public interface FieldValidatorSource
{
/**
- * Creates the validator.
+ * Creates the validator. The error message associated with the field validator usually comes
+ * from the {@link ValidationMessagesSource} (using the validator's
+ * {@link Validator#getMessageKey() message key}). However, if the container component of the
+ * field defines a message key <code><i>id</i>-<i>validator</i>
+ * (where id is the simple id of the field component, and validator is the validatorType), then that
+ * message is used instead. This allows you to override the message for a particular validation of a particular field.
*
* @param field
* the field for which a validator is to be created
@@ -37,6 +46,34 @@
* @return the field validator for the field
*/
FieldValidator createValidator(Field field, String validatorType, String constraintValue);
+
+ /**
+ * Full featured version of {@link #createValidator(Field, String, String)} used in situations
+ * where the container of the field is not necesarrilly the place to look for override messages,
+ * and the id of the field is not the key to use when checking. The {@link BeanEditor} is an
+ * example of this.
+ *
+ * @param field
+ * the field for which a validator is to be created
+ * @param validatorType
+ * used to select the {@link Validator} that forms the core of the
+ * {@link FieldValidator}
+ * @param constraintValue
+ * a value used to configure the validator, or null if the validator is not
+ * configurable
+ * @param overrideId
+ * the base id used when searching for validator message overrides (this would
+ * normally be the field component's simple id)
+ * @param overrideMessages
+ * the message catalog to search for override messages (this would normally be the
+ * catalog for the container of the field component)
+ * @param locale
+ * locale used when retrieving default validation messages from the
+ * {@link ValidationMessagesSource}
+ * @return the field validator for the field
+ */
+ FieldValidator createValidator(Field field, String validatorType, String constraintValue,
+ String overrideId, Messages overrideMessages, Locale locale);
/**
* Creates a set of validators. The specification is a string used to identify and configure the
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java?view=diff&rev=501975&r1=501974&r2=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java Wed Jan 31 12:18:49 2007
@@ -40,10 +40,13 @@
import org.apache.tapestry.annotations.CleanupRender;
import org.apache.tapestry.annotations.InjectPage;
import org.apache.tapestry.annotations.SetupRender;
+import org.apache.tapestry.beaneditor.Validate;
import org.apache.tapestry.dom.DefaultMarkupModel;
import org.apache.tapestry.dom.Document;
import org.apache.tapestry.internal.InternalConstants;
import org.apache.tapestry.internal.TapestryUtils;
+import org.apache.tapestry.internal.beaneditor.PrimitiveFieldConstraintGenerator;
+import org.apache.tapestry.internal.beaneditor.ValidateAnnotationConstraintGenerator;
import org.apache.tapestry.internal.bindings.ComponentBindingFactory;
import org.apache.tapestry.internal.bindings.LiteralBindingFactory;
import org.apache.tapestry.internal.bindings.MessageBindingFactory;
@@ -57,6 +60,7 @@
import org.apache.tapestry.internal.services.ApplicationStateWorker;
import org.apache.tapestry.internal.services.AssetDispatcher;
import org.apache.tapestry.internal.services.AssetSourceImpl;
+import org.apache.tapestry.internal.services.BeanEditorModelSourceImpl;
import org.apache.tapestry.internal.services.BindingSourceImpl;
import org.apache.tapestry.internal.services.ClasspathAssetAliasManagerImpl;
import org.apache.tapestry.internal.services.CommonResourcesInjectionProvider;
@@ -128,6 +132,7 @@
import org.apache.tapestry.internal.services.TranslatorSourceImpl;
import org.apache.tapestry.internal.services.UnclaimedFieldWorker;
import org.apache.tapestry.internal.services.UpdateListenerHub;
+import org.apache.tapestry.internal.services.ValidationConstraintGeneratorImpl;
import org.apache.tapestry.internal.services.ValidationMessagesSourceImpl;
import org.apache.tapestry.ioc.Configuration;
import org.apache.tapestry.ioc.IOCUtilities;
@@ -474,6 +479,8 @@
locator,
ApplicationGlobals.class,
ApplicationStateManager.class,
+ ApplicationStatePersistenceStrategySource.class,
+ BeanEditorModelSource.class,
RequestGlobals.class,
MarkupWriterFactory.class,
PersistentFieldManager.class,
@@ -491,7 +498,8 @@
ValidationMessagesSource.class,
TranslatorSource.class,
TranslatorDefaultSource.class,
- FieldValidatorSource.class);
+ FieldValidatorSource.class,
+ ValidationConstraintGenerator.class);
configuration.add(new InfrastructureContribution("TypeCoercer", typeCoercer));
configuration.add(new InfrastructureContribution("PropertyAccess", propertyAccess));
@@ -1119,9 +1127,37 @@
public static ApplicationStateManager buildApplicationStateManager(
Map<Class, ApplicationStateContribution> configuration,
- @Inject("ApplicationStatePersistenceStrategySource")
+ @Inject("infrastructure:ApplicationStatePersistenceStrategySource")
ApplicationStatePersistenceStrategySource source)
{
return new ApplicationStateManagerImpl(configuration, source);
+ }
+
+ public static BeanEditorModelSource buildBeanEditorModelSource(
+ @Inject("infrastructure:TypeCoercer")
+ TypeCoercer typeCoercer, @Inject("infrastructure:PropertyAccess")
+ PropertyAccess propertyAccess)
+ {
+ return new BeanEditorModelSourceImpl(typeCoercer, propertyAccess);
+ }
+
+ public static ValidationConstraintGenerator buildValidationConstraintGenerator(
+ List<ValidationConstraintGenerator> configuration)
+ {
+ return new ValidationConstraintGeneratorImpl(configuration);
+ }
+
+ /**
+ * Adds built-in constraint generators:
+ * <ul>
+ * <li>PrimtiveField -- primitive fields are always required
+ * <li>ValidateAnnotation -- adds constraints from a {@link Validate} annotation
+ * </ul>
+ */
+ public static void contributeValidationConstraintGenerator(
+ OrderedConfiguration<ValidationConstraintGenerator> configuration)
+ {
+ configuration.add("PrimitiveField", new PrimitiveFieldConstraintGenerator());
+ configuration.add("ValidateAnnotation", new ValidateAnnotationConstraintGenerator());
}
}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ValidationConstraintGenerator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ValidationConstraintGenerator.java?view=auto&rev=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ValidationConstraintGenerator.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ValidationConstraintGenerator.java Wed Jan 31 12:18:49 2007
@@ -0,0 +1,43 @@
+// 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.services;
+
+import java.util.List;
+
+import org.apache.tapestry.FieldValidator;
+import org.apache.tapestry.beaneditor.PropertyEditModel;
+
+/**
+ * Invoked to generate a list of validation constraint strings for a property. This typically
+ * involves scanning the property for annotations or naming conventions that confer the desired
+ * validation. The constraint strings are ultimately handed to
+ * {@link FieldValidatorSource#createValidator(org.apache.tapestry.Field, String, String, String, org.apache.tapestry.ioc.Messages, java.util.Locale)}.
+ */
+public interface ValidationConstraintGenerator
+{
+ /**
+ * For a given property, identify all the approprite validation constraints. Each returned value
+ * is the name of a validator (i.e., "required") or a validator name and configuration (i.e.,
+ * "minlength=5"). These contraints are exactly the individual terms in a
+ * {@link FieldValidatorSource#createValidators(org.apache.tapestry.Field, String) validate specification}.
+ * These will ultimately be used to create {@link FieldValidator}s for the field that edits the
+ * property.
+ *
+ * @param propertyModel
+ * @return
+ * @see FieldValidatorSource
+ */
+ List<String> buildConstraints(PropertyEditModel propertyModel);
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java?view=diff&rev=501975&r1=501974&r2=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java Wed Jan 31 12:18:49 2007
@@ -18,6 +18,7 @@
import static org.apache.tapestry.internal.test.CodeEq.codeEq;
import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.isA;
import java.io.File;
import java.io.FileOutputStream;
@@ -47,6 +48,8 @@
import org.apache.tapestry.Validator;
import org.apache.tapestry.annotations.Inject;
import org.apache.tapestry.annotations.Parameter;
+import org.apache.tapestry.beaneditor.PropertyConduit;
+import org.apache.tapestry.beaneditor.PropertyEditModel;
import org.apache.tapestry.ioc.Location;
import org.apache.tapestry.ioc.Messages;
import org.apache.tapestry.ioc.Resource;
@@ -717,9 +720,9 @@
expect(validator.getValueType()).andReturn(valueType).atLeastOnce();
}
- protected final void train_skipIfBlank(Validator validator, boolean skipIfBlank)
+ protected final void train_invokeIfBlank(Validator validator, boolean invokeIfBlank)
{
- expect(validator.skipIfBlank()).andReturn(skipIfBlank).atLeastOnce();
+ expect(validator.invokeIfBlank()).andReturn(invokeIfBlank).atLeastOnce();
}
protected final void train_getFieldPersistenceStrategy(ComponentModel model, String fieldName,
@@ -758,5 +761,35 @@
String strategyName, ApplicationStatePersistenceStrategy strategy)
{
expect(source.get(strategyName)).andReturn(strategy).atLeastOnce();
+ }
+
+ protected final void train_get(Messages messages, String key, String message)
+ {
+ expect(messages.get(key)).andReturn(message).atLeastOnce();
+ }
+
+ protected final void stub_contains(Messages messages, boolean contained)
+ {
+ expect(messages.contains(isA(String.class))).andStubReturn(contained);
+ }
+
+ protected final <T extends Annotation> void train_getAnnotation(PropertyConduit conduit, Class<T> annotationClass, T annotation)
+ {
+ expect(conduit.getAnnotation(annotationClass)).andReturn(annotation).atLeastOnce();
+ }
+
+ protected final void train_getConduit(PropertyEditModel model, PropertyConduit conduit)
+ {
+ expect(model.getConduit()).andReturn(conduit).atLeastOnce();
+ }
+
+ protected final PropertyConduit newPropertyConduit()
+ {
+ return newMock(PropertyConduit.class);
+ }
+
+ protected final PropertyEditModel newPropertyEditModel()
+ {
+ return newMock(PropertyEditModel.class);
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/Max.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/Max.java?view=diff&rev=501975&r1=501974&r2=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/Max.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/Max.java Wed Jan 31 12:18:49 2007
@@ -37,9 +37,9 @@
return Number.class;
}
- public boolean skipIfBlank()
+ public boolean invokeIfBlank()
{
- return true;
+ return false;
}
public void validate(Field field, Long constraintValue, MessageFormatter formatter, Number value)
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/MaxLength.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/MaxLength.java?view=diff&rev=501975&r1=501974&r2=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/MaxLength.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/MaxLength.java Wed Jan 31 12:18:49 2007
@@ -36,9 +36,9 @@
return String.class;
}
- public boolean skipIfBlank()
+ public boolean invokeIfBlank()
{
- return true;
+ return false;
}
public void validate(Field field, Integer constraintValue, MessageFormatter formatter, String value)
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/Min.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/Min.java?view=diff&rev=501975&r1=501974&r2=501975
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/Min.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/Min.java Wed Jan 31 12:18:49 2007
@@ -37,9 +37,9 @@
return Number.class;
}
- public boolean skipIfBlank()
+ public boolean invokeIfBlank()
{
- return true;
+ return false;
}
public void validate(Field field, Long constraintValue, MessageFormatter formatter, Number value)