Author: drobiazko
Date: Thu Jan 7 07:13:49 2010
New Revision: 896767
URL: http://svn.apache.org/viewvc?rev=896767&view=rev
Log:
TAP5-895: Tracking issue for Tapestry/JSR-303 integration
Added:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ClientConstraintDescriptor.java
(with props)
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ClientConstraintDescriptorSource.java
(with props)
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/BeanFieldValidator.java
(with props)
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/ClientConstraintDescriptorImpl.java
(with props)
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/resources/
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/resources/org/
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/resources/org/apache/
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/resources/org/apache/tapestry5/
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/resources/org/apache/tapestry5/beanvalidator/
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/resources/org/apache/tapestry5/beanvalidator/tapestry-beanvalidator.js
(with props)
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/ClientValidationDemo.java
(with props)
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/test/webapp/ClientValidationDemo.tml
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/BeanValidationContextImpl.java
(with props)
Modified:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/BeanValidatorModule.java
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/BeanFieldValidatorDefaultSource.java
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/test/java/org/apache/tapestry5/beanvalidator/integration/TapestryBeanValidationIntegrationTests.java
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/test/webapp/Index.tml
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/BeanEditor.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/BeanValidationContext.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/components/BeanEditorTest.java
Modified:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/BeanValidatorModule.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/BeanValidatorModule.java?rev=896767&r1=896766&r2=896767&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/BeanValidatorModule.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/BeanValidatorModule.java
Thu Jan 7 07:13:49 2010
@@ -1,4 +1,4 @@
-// Copyright 2009 The Apache Software Foundation
+// Copyright 2009, 2010 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.
@@ -13,16 +13,19 @@
// limitations under the License.
package org.apache.tapestry5.beanvalidator;
-import java.util.Locale;
-
import javax.validation.MessageInterpolator;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
+import javax.validation.constraints.NotNull;
import javax.validation.groups.Default;
+import org.apache.tapestry5.Asset;
+import org.apache.tapestry5.MarkupWriter;
+import org.apache.tapestry5.RenderSupport;
import
org.apache.tapestry5.internal.beanvalidator.BeanFieldValidatorDefaultSource;
import
org.apache.tapestry5.internal.beanvalidator.BeanValidationGroupSourceImpl;
import org.apache.tapestry5.internal.beanvalidator.BeanValidatorSourceImpl;
+import
org.apache.tapestry5.internal.beanvalidator.ClientConstraintDescriptorImpl;
import org.apache.tapestry5.internal.beanvalidator.MessageInterpolatorImpl;
import org.apache.tapestry5.ioc.Configuration;
import org.apache.tapestry5.ioc.MappedConfiguration;
@@ -31,7 +34,11 @@
import org.apache.tapestry5.ioc.annotations.Local;
import org.apache.tapestry5.ioc.services.PropertyShadowBuilder;
import org.apache.tapestry5.ioc.services.ThreadLocale;
+import org.apache.tapestry5.services.AssetSource;
+import org.apache.tapestry5.services.Environment;
import org.apache.tapestry5.services.FieldValidatorDefaultSource;
+import org.apache.tapestry5.services.MarkupRenderer;
+import org.apache.tapestry5.services.MarkupRendererFilter;
/**
* Module for JSR-303 services.
@@ -46,6 +53,7 @@
.withId("BeanFieldValidatorDefaultSource");
binder.bind(BeanValidatorGroupSource.class,
BeanValidationGroupSourceImpl.class);
binder.bind(BeanValidatorSource.class,
BeanValidatorSourceImpl.class);
+ binder.bind(ClientConstraintDescriptorSource.class,
ClientConstraintDescriptorImpl.class);
}
public static void contributeServiceOverride(
@@ -85,5 +93,39 @@
}
});
}
+
+ public static void contributeClientConstraintDescriptorSource(
+ final Configuration<ClientConstraintDescriptor>
configuration)
+ {
+ configuration.add(new ClientConstraintDescriptor(NotNull.class,
"notnull"));
+ }
+
+ public void contributeMarkupRenderer(
+ OrderedConfiguration<MarkupRendererFilter>
configuration,
+
+ final AssetSource assetSource,
+
+ final ThreadLocale threadLocale,
+
+ final Environment environment)
+ {
+ MarkupRendererFilter injectBeanValidatorScript = new
MarkupRendererFilter()
+ {
+ public void renderMarkup(MarkupWriter writer, MarkupRenderer
renderer)
+ {
+ RenderSupport renderSupport =
environment.peek(RenderSupport.class);
+
+ Asset validators = assetSource.getAsset(null,
"org/apache/tapestry5/beanvalidator/tapestry-beanvalidator.js",
+ threadLocale.getLocale());
+
+ renderSupport.addScriptLink(validators);
+
+ renderer.renderMarkup(writer);
+ }
+ };
+
+
+ configuration.add("BeanValidatorScript", injectBeanValidatorScript,
"after:*");
+ }
}
Added:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ClientConstraintDescriptor.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ClientConstraintDescriptor.java?rev=896767&view=auto
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ClientConstraintDescriptor.java
(added)
+++
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ClientConstraintDescriptor.java
Thu Jan 7 07:13:49 2010
@@ -0,0 +1,64 @@
+// Copyright 2009 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package org.apache.tapestry5.beanvalidator;
+
+import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newSet;
+
+import java.util.Set;
+
+import org.apache.tapestry5.json.JSONObject;
+
+/**
+ * Describes a single client-side constraint.
+ *
+ */
+public final class ClientConstraintDescriptor
+{
+ private final Class annotationClass;
+ private final String validatorName;
+ private final Set<String> attributes;
+
+ public ClientConstraintDescriptor(final Class annotationClass,
+ final String validatorName, final String... attributes)
+ {
+ this.annotationClass = annotationClass;
+ this.validatorName = validatorName;
+ this.attributes = newSet(attributes);
+ }
+
+ /**
+ * Returns the annotation describing the constraint declaration.
+ */
+ public Class getAnnotationClass()
+ {
+ return this.annotationClass;
+ }
+
+ /**
+ * Returns the name of the client-side validator.
+ */
+ public String getValidatorName()
+ {
+ return this.validatorName;
+ }
+
+ /**
+ * Returns a map containing the annotation attribute names as keys and the
annotation attribute values as value.
+ * This map is passed to the client-side validator as a {...@link
JSONObject}.
+ */
+ public Set<String> getAttributes()
+ {
+ return this.attributes;
+ }
+}
\ No newline at end of file
Propchange:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ClientConstraintDescriptor.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ClientConstraintDescriptor.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ClientConstraintDescriptorSource.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ClientConstraintDescriptorSource.java?rev=896767&view=auto
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ClientConstraintDescriptorSource.java
(added)
+++
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ClientConstraintDescriptorSource.java
Thu Jan 7 07:13:49 2010
@@ -0,0 +1,31 @@
+// Copyright 2010 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package org.apache.tapestry5.beanvalidator;
+
+import org.apache.tapestry5.ioc.annotations.UsesConfiguration;
+
+/**
+ * Source for {...@link ClientConstraintDescriptor}.
+ *
+ */
+...@usesconfiguration(ClientConstraintDescriptor.class)
+public interface ClientConstraintDescriptorSource
+{
+ /**
+ * Return a {...@link ClientConstraintDescriptor} for a constraint
annotation or null.
+ *
+ * @param annotationClass type of the constraint annotation
+ */
+ ClientConstraintDescriptor getConstraintDescriptor(Class
annotationClass);
+}
Propchange:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ClientConstraintDescriptorSource.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ClientConstraintDescriptorSource.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/BeanFieldValidator.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/BeanFieldValidator.java?rev=896767&view=auto
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/BeanFieldValidator.java
(added)
+++
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/BeanFieldValidator.java
Thu Jan 7 07:13:49 2010
@@ -0,0 +1,177 @@
+// Copyright 2010 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package org.apache.tapestry5.internal.beanvalidator;
+
+import static java.lang.String.format;
+
+import java.lang.annotation.Annotation;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.MessageInterpolator;
+import javax.validation.Validator;
+import javax.validation.ValidatorFactory;
+import javax.validation.MessageInterpolator.Context;
+import javax.validation.metadata.BeanDescriptor;
+import javax.validation.metadata.ConstraintDescriptor;
+import javax.validation.metadata.PropertyDescriptor;
+
+import org.apache.tapestry5.Field;
+import org.apache.tapestry5.FieldValidator;
+import org.apache.tapestry5.MarkupWriter;
+import org.apache.tapestry5.ValidationException;
+import org.apache.tapestry5.beanvalidator.BeanValidatorGroupSource;
+import org.apache.tapestry5.beanvalidator.ClientConstraintDescriptor;
+import org.apache.tapestry5.beanvalidator.ClientConstraintDescriptorSource;
+import org.apache.tapestry5.json.JSONObject;
+import org.apache.tapestry5.services.BeanValidationContext;
+import org.apache.tapestry5.services.Environment;
+import org.apache.tapestry5.services.FormSupport;
+
+
+public class BeanFieldValidator implements FieldValidator
+{
+ private final Field field;
+ private final String propertyName;
+ private final ValidatorFactory validatorFactory;
+ private final BeanValidatorGroupSource beanValidationGroupSource;
+ private final ClientConstraintDescriptorSource clientValidatorSource;
+ private final FormSupport formSupport;
+ private final Environment environment;
+
+ public BeanFieldValidator(Field field, String propertyName,
+ ValidatorFactory validatorFactory,
+ BeanValidatorGroupSource beanValidationGroupSource,
+ ClientConstraintDescriptorSource clientValidatorSource,
+ FormSupport formSupport,
+ Environment environment)
+ {
+ this.field = field;
+ this.propertyName = propertyName;
+ this.validatorFactory = validatorFactory;
+ this.beanValidationGroupSource = beanValidationGroupSource;
+ this.clientValidatorSource = clientValidatorSource;
+ this.formSupport = formSupport;
+ this.environment = environment;
+ }
+
+ public boolean isRequired()
+ {
+ return false;
+ }
+
+ public void render(final MarkupWriter writer)
+ {
+ final BeanValidationContext beanValidationContext =
environment.peek(BeanValidationContext.class);
+
+ if (beanValidationContext == null)
+ {
+ return;
+ }
+
+ final Validator validator = validatorFactory.getValidator();
+
+ BeanDescriptor beanDescriptor =
validator.getConstraintsForClass(beanValidationContext.getBeanType());
+
+ PropertyDescriptor propertyDescriptor =
beanDescriptor.getConstraintsForProperty(propertyName);
+
+ for (final ConstraintDescriptor<?> descriptor
:propertyDescriptor.getConstraintDescriptors())
+ {
+ Class<? extends Annotation> annotationType =
descriptor.getAnnotation().annotationType();
+
+ ClientConstraintDescriptor clientConstraintDescriptor =
clientValidatorSource.getConstraintDescriptor(annotationType);
+
+ if(clientConstraintDescriptor != null)
+ {
+ String message = interpolateMessage(descriptor);
+
+ JSONObject specs = new JSONObject();
+
+ for (String attribute :
clientConstraintDescriptor.getAttributes())
+ {
+ Object object = descriptor.getAttributes().get(attribute);
+
+ if (object == null)
+ {
+ throw new RuntimeException("Expected attribute is null");
+ }
+ specs.put(attribute, object);
+ }
+
+ formSupport.addValidation(field,
clientConstraintDescriptor.getValidatorName(), message, specs);
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public void validate(final Object value) throws ValidationException
+ {
+
+ final BeanValidationContext beanValidationContext =
environment.peek(BeanValidationContext.class);
+
+ if (beanValidationContext == null)
+ {
+ return;
+ }
+
+ final Validator validator = validatorFactory.getValidator();
+
+ final Set<ConstraintViolation<Object>> violations =
validator.validateValue(
+ (Class<Object>)
beanValidationContext.getBeanType(), propertyName,
+ value,
beanValidationGroupSource.get());
+
+ if (violations.isEmpty())
+ {
+ return;
+ }
+
+ final StringBuilder builder = new StringBuilder();
+
+ for (Iterator iterator = violations.iterator();
iterator.hasNext();)
+ {
+ ConstraintViolation<?> violation =
(ConstraintViolation<Object>) iterator.next();
+
+ builder.append(format("%s %s", field.getLabel(),
violation.getMessage()));
+
+ if(iterator.hasNext())
+ builder.append(", ");
+
+ }
+
+ throw new ValidationException(builder.toString());
+
+ }
+
+ private String interpolateMessage(final ConstraintDescriptor<?>
descriptor)
+ {
+ String messageTemplate = (String)
descriptor.getAttributes().get("message");
+
+ MessageInterpolator messageInterpolator =
validatorFactory.getMessageInterpolator();
+
+ return messageInterpolator.interpolate(messageTemplate, new
Context()
+ {
+
+ public ConstraintDescriptor<?> getConstraintDescriptor()
+ {
+ return descriptor;
+ }
+
+ public Object getValidatedValue()
+ {
+ return null;
+ }
+ });
+ }
+}
Propchange:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/BeanFieldValidator.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/BeanFieldValidator.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/BeanFieldValidatorDefaultSource.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/BeanFieldValidatorDefaultSource.java?rev=896767&r1=896766&r2=896767&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/BeanFieldValidatorDefaultSource.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/BeanFieldValidatorDefaultSource.java
Thu Jan 7 07:13:49 2010
@@ -1,4 +1,4 @@
-// Copyright 2009 The Apache Software Foundation
+// Copyright 2009, 2010 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.
@@ -13,47 +13,46 @@
// limitations under the License.
package org.apache.tapestry5.internal.beanvalidator;
-import static java.lang.String.format;
-
import java.util.Arrays;
-import java.util.Iterator;
import java.util.Locale;
-import java.util.Set;
-import javax.validation.ConstraintViolation;
-import javax.validation.Validator;
+import javax.validation.ValidatorFactory;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.Field;
import org.apache.tapestry5.FieldValidator;
-import org.apache.tapestry5.MarkupWriter;
-import org.apache.tapestry5.ValidationException;
import org.apache.tapestry5.beanvalidator.BeanValidatorGroupSource;
-import org.apache.tapestry5.beanvalidator.BeanValidatorSource;
+import org.apache.tapestry5.beanvalidator.ClientConstraintDescriptorSource;
import org.apache.tapestry5.internal.services.CompositeFieldValidator;
import org.apache.tapestry5.ioc.AnnotationProvider;
import org.apache.tapestry5.ioc.Messages;
-import org.apache.tapestry5.services.BeanValidationContext;
import org.apache.tapestry5.services.Core;
import org.apache.tapestry5.services.Environment;
import org.apache.tapestry5.services.FieldValidatorDefaultSource;
+import org.apache.tapestry5.services.FormSupport;
public class BeanFieldValidatorDefaultSource implements
FieldValidatorDefaultSource
{
private final FieldValidatorDefaultSource fieldValidatorDefaultSource;
- private final BeanValidatorSource beanValidatorSource;
+ private final ValidatorFactory validatorFactory;
private final BeanValidatorGroupSource beanValidationGroupSource;
+ private final ClientConstraintDescriptorSource clientValidatorSource;
+ private final FormSupport formSupport;
private final Environment environment;
public BeanFieldValidatorDefaultSource(
@Core FieldValidatorDefaultSource
fieldValidatorDefaultSource,
- final BeanValidatorSource beanValidatorSource,
+ final ValidatorFactory validatorFactory,
final BeanValidatorGroupSource
beanValidationGroupSource,
+ final ClientConstraintDescriptorSource
clientValidatorSource,
+ final FormSupport formSupport,
final Environment environment)
{
this.fieldValidatorDefaultSource = fieldValidatorDefaultSource;
- this.beanValidatorSource = beanValidatorSource;
+ this.validatorFactory = validatorFactory;
this.beanValidationGroupSource = beanValidationGroupSource;
+ this.clientValidatorSource = clientValidatorSource;
+ this.formSupport = formSupport;
this.environment = environment;
}
@@ -66,57 +65,10 @@
FieldValidator validator =
fieldValidatorDefaultSource.createDefaultValidator(
field, overrideId, overrideMessages, locale,
propertyType, propertyAnnotations);
- FieldValidator beanValidator = new FieldValidator() {
-
- public boolean isRequired()
- {
- return false;
- }
-
- public void render(final MarkupWriter writer)
- {
- }
-
- public void validate(final Object value) throws
ValidationException
- {
-
- final BeanValidationContext
beanValidationContext = BeanFieldValidatorDefaultSource.this.environment
-
.peek(BeanValidationContext.class);
-
- if (beanValidationContext == null)
- {
- return;
- }
-
- final Validator validator =
BeanFieldValidatorDefaultSource.this.beanValidatorSource.create();
-
- final Set<ConstraintViolation<Object>>
violations = validator.validateValue(
- (Class<Object>)
beanValidationContext.getObject().getClass(), overrideId,
- value,
beanValidationGroupSource.get());
-
- if (violations.isEmpty())
- {
- return;
- }
-
- final StringBuilder builder = new
StringBuilder();
-
- for (Iterator iterator = violations.iterator();
iterator.hasNext();)
- {
- ConstraintViolation<?> violation =
(ConstraintViolation<Object>) iterator.next();
-
- builder.append(format("%s %s",
field.getLabel(), violation.getMessage()));
-
- if(iterator.hasNext())
- builder.append(", ");
-
- }
-
- throw new
ValidationException(builder.toString());
-
- }
-
- };
+
+ FieldValidator beanValidator
+ = new BeanFieldValidator(field, overrideId,
validatorFactory, beanValidationGroupSource,
+ clientValidatorSource, formSupport,
environment);
return new CompositeFieldValidator(Arrays.asList(validator,
beanValidator));
}
Added:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/ClientConstraintDescriptorImpl.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/ClientConstraintDescriptorImpl.java?rev=896767&view=auto
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/ClientConstraintDescriptorImpl.java
(added)
+++
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/ClientConstraintDescriptorImpl.java
Thu Jan 7 07:13:49 2010
@@ -0,0 +1,47 @@
+// Copyright 2010 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package org.apache.tapestry5.internal.beanvalidator;
+
+import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newList;
+
+import java.util.Collection;
+
+import org.apache.tapestry5.beanvalidator.ClientConstraintDescriptorSource;
+import org.apache.tapestry5.beanvalidator.ClientConstraintDescriptor;
+
+public class ClientConstraintDescriptorImpl implements
ClientConstraintDescriptorSource
+{
+
+ private Collection<ClientConstraintDescriptor> descriptors = newList();
+
+ public ClientConstraintDescriptorImpl(
+ final Collection<ClientConstraintDescriptor> configuration)
+ {
+ super();
+ this.descriptors = configuration;
+ }
+
+ public ClientConstraintDescriptor getConstraintDescriptor(final Class
annotationClass)
+ {
+ for (final ClientConstraintDescriptor desc : this.descriptors)
+ {
+ if (desc.getAnnotationClass().equals(annotationClass))
+ {
+ return desc;
+ }
+ }
+ return null;
+ }
+
+}
\ No newline at end of file
Propchange:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/ClientConstraintDescriptorImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/ClientConstraintDescriptorImpl.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/resources/org/apache/tapestry5/beanvalidator/tapestry-beanvalidator.js
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/resources/org/apache/tapestry5/beanvalidator/tapestry-beanvalidator.js?rev=896767&view=auto
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/resources/org/apache/tapestry5/beanvalidator/tapestry-beanvalidator.js
(added)
+++
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/resources/org/apache/tapestry5/beanvalidator/tapestry-beanvalidator.js
Thu Jan 7 07:13:49 2010
@@ -0,0 +1,18 @@
+// Copyright 2010 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.
+
+Tapestry.Validator.notnull = function(field, message, spec)
+{
+ Tapestry.Validator.required(field, message);
+};
\ No newline at end of file
Propchange:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/resources/org/apache/tapestry5/beanvalidator/tapestry-beanvalidator.js
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/main/resources/org/apache/tapestry5/beanvalidator/tapestry-beanvalidator.js
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/test/java/org/apache/tapestry5/beanvalidator/integration/TapestryBeanValidationIntegrationTests.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-beanvalidator/src/test/java/org/apache/tapestry5/beanvalidator/integration/TapestryBeanValidationIntegrationTests.java?rev=896767&r1=896766&r2=896767&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/test/java/org/apache/tapestry5/beanvalidator/integration/TapestryBeanValidationIntegrationTests.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/test/java/org/apache/tapestry5/beanvalidator/integration/TapestryBeanValidationIntegrationTests.java
Thu Jan 7 07:13:49 2010
@@ -1,4 +1,4 @@
-// Copyright 2009 The Apache Software Foundation
+// Copyright 2009, 2010 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.
@@ -70,4 +70,35 @@
assertTextPresent("User Name may not be null");
}
+
+ public void client_validaton() throws Exception
+ {
+ start("Client Validation Demo");
+
+ click(SUBMIT);
+
+ assertBubbleMessage("userName", "may not be null");
+
+ type("userName", "igor");
+
+ click(SUBMIT);
+
+ assertBubbleMessage("password", "may not be null");
+ }
+
+ protected final void assertBubbleMessage(String fieldId, String expected)
+ {
+ String popupId = fieldId + ":errorpopup";
+
+ waitForElementToAppear(popupId);
+
+ assertText(String.format("//d...@id='%s']/span", popupId), expected);
+ }
+
+ protected final void waitForElementToAppear(String elementId)
+ {
+ String condition = String.format("window.$(\"%s\")", elementId);
+
+ waitForCondition(condition, PAGE_LOAD_TIMEOUT);
+ }
}
\ No newline at end of file
Added:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/ClientValidationDemo.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/ClientValidationDemo.java?rev=896767&view=auto
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/ClientValidationDemo.java
(added)
+++
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/ClientValidationDemo.java
Thu Jan 7 07:13:49 2010
@@ -0,0 +1,26 @@
+// Copyright 2010 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.example.testapp.pages;
+
+import org.apache.tapestry5.annotations.Persist;
+import org.apache.tapestry5.annotations.Property;
+import org.example.testapp.entities.User;
+
+public class ClientValidationDemo
+{
+ @Property
+ @Persist
+ private User user;
+
+}
Propchange:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/ClientValidationDemo.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/test/java/org/example/testapp/pages/ClientValidationDemo.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/test/webapp/ClientValidationDemo.tml
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-beanvalidator/src/test/webapp/ClientValidationDemo.tml?rev=896767&view=auto
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/test/webapp/ClientValidationDemo.tml
(added)
+++
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/test/webapp/ClientValidationDemo.tml
Thu Jan 7 07:13:49 2010
@@ -0,0 +1,5 @@
+<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd">
+ <body>
+ <t:beaneditform object="user"/>
+ </body>
+</html>
\ No newline at end of file
Modified:
tapestry/tapestry5/trunk/tapestry-beanvalidator/src/test/webapp/Index.tml
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-beanvalidator/src/test/webapp/Index.tml?rev=896767&r1=896766&r2=896767&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-beanvalidator/src/test/webapp/Index.tml
(original)
+++ tapestry/tapestry5/trunk/tapestry-beanvalidator/src/test/webapp/Index.tml
Thu Jan 7 07:13:49 2010
@@ -15,6 +15,9 @@
<li>
<t:pagelink page="InjectValidatorDemo">Inject Validator
Demo</t:pagelink>
</li>
+ <li>
+ <t:pagelink page="ClientValidationDemo">Client Validation
Demo</t:pagelink>
+ </li>
</ul>
</body>
</html>
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/BeanEditor.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/BeanEditor.java?rev=896767&r1=896766&r2=896767&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/BeanEditor.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/BeanEditor.java
Thu Jan 7 07:13:49 2010
@@ -24,11 +24,13 @@
import org.apache.tapestry5.annotations.SupportsInformalParameters;
import org.apache.tapestry5.beaneditor.BeanModel;
import org.apache.tapestry5.corelib.internal.InternalMessages;
+import org.apache.tapestry5.internal.BeanValidationContextImpl;
import org.apache.tapestry5.internal.beaneditor.BeanModelUtils;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.internal.util.TapestryException;
import org.apache.tapestry5.services.BeanEditContext;
import org.apache.tapestry5.services.BeanModelSource;
+import org.apache.tapestry5.services.BeanValidationContext;
import org.apache.tapestry5.services.Environment;
import org.apache.tapestry5.services.FormSupport;
@@ -202,6 +204,11 @@
ex);
throw new TapestryException(message, resources.getLocation(),
ex);
}
+
+
+ //If 'object' parameter is bound to a null-value
BeanValidationContext is empty.
+ //This prevents JSR-303 javascript validators to be rendered
properly .
+ refreshBeanValidationContext();
}
BeanEditContext context = new BeanEditContext()
@@ -227,6 +234,16 @@
{
environment.pop(BeanEditContext.class);
}
+
+ private void refreshBeanValidationContext()
+ {
+ if(environment.peek(BeanValidationContext.class) != null)
+ {
+ environment.pop(BeanValidationContext.class);
+
+ environment.push(BeanValidationContext.class, new
BeanValidationContextImpl(object));
+ }
+ }
// For testing
void inject(ComponentResources resources, PropertyOverrides overrides,
BeanModelSource source,
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java?rev=896767&r1=896766&r2=896767&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
Thu Jan 7 07:13:49 2010
@@ -21,6 +21,7 @@
import org.apache.tapestry5.corelib.internal.InternalFormSupport;
import org.apache.tapestry5.corelib.mixins.RenderInformals;
import org.apache.tapestry5.dom.Element;
+import org.apache.tapestry5.internal.BeanValidationContextImpl;
import org.apache.tapestry5.internal.services.ComponentResultProcessorWrapper;
import org.apache.tapestry5.internal.services.HeartbeatImpl;
import org.apache.tapestry5.internal.util.AutofocusValidationDecorator;
@@ -310,6 +311,8 @@
environment.push(FormSupport.class, formSupport);
environment.push(ValidationTracker.class, tracker);
+ environment.push(BeanValidationContext.class, new
BeanValidationContextImpl(validate));
+
if (autofocus)
{
@@ -347,7 +350,7 @@
}
writer.end(); // div
-
+
environment.peek(Heartbeat.class).begin();
}
@@ -402,6 +405,8 @@
formSupport = null;
environment.pop(ValidationTracker.class);
+
+ environment.pop(BeanValidationContext.class);
}
@SuppressWarnings(
@@ -415,14 +420,7 @@
environment.push(ValidationTracker.class, tracker);
environment.push(FormSupport.class, formSupport);
- environment.push(BeanValidationContext.class, new
BeanValidationContext()
- {
-
- public Object getObject()
- {
- return validate;
- }
- });
+ environment.push(BeanValidationContext.class, new
BeanValidationContextImpl(validate));
Heartbeat heartbeat = new HeartbeatImpl();
Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/BeanValidationContextImpl.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/BeanValidationContextImpl.java?rev=896767&view=auto
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/BeanValidationContextImpl.java
(added)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/BeanValidationContextImpl.java
Thu Jan 7 07:13:49 2010
@@ -0,0 +1,37 @@
+// Copyright 2010 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package org.apache.tapestry5.internal;
+
+import org.apache.tapestry5.services.BeanValidationContext;
+
+public class BeanValidationContextImpl implements BeanValidationContext
+{
+ private Object bean;
+
+ public BeanValidationContextImpl(Object bean)
+ {
+ this.bean = bean;
+ }
+
+ public Class getBeanType()
+ {
+ return bean==null?null:bean.getClass();
+ }
+
+ public Object getBeanInstance()
+ {
+ return bean;
+ }
+
+}
Propchange:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/BeanValidationContextImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/BeanValidationContextImpl.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/BeanValidationContext.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/BeanValidationContext.java?rev=896767&r1=896766&r2=896767&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/BeanValidationContext.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/BeanValidationContext.java
Thu Jan 7 07:13:49 2010
@@ -1,4 +1,4 @@
-// Copyright 2009 The Apache Software Foundation
+// Copyright 2009, 2010 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.
@@ -21,7 +21,12 @@
public interface BeanValidationContext
{
/**
+ * Returns the type of the object to validate. This method is needed for
client side validation.
+ */
+ Class getBeanType();
+
+ /**
* Return the object to validate.
*/
- Object getObject();
+ Object getBeanInstance();
}
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/components/BeanEditorTest.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/components/BeanEditorTest.java?rev=896767&r1=896766&r2=896767&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/components/BeanEditorTest.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/components/BeanEditorTest.java
Thu Jan 7 07:13:49 2010
@@ -14,6 +14,10 @@
package org.apache.tapestry5.corelib.components;
+import static org.easymock.EasyMock.isA;
+
+import static org.easymock.EasyMock.eq;
+
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.PropertyOverrides;
import org.apache.tapestry5.beaneditor.BeanModel;
@@ -23,6 +27,7 @@
import org.apache.tapestry5.ioc.internal.util.TapestryException;
import org.apache.tapestry5.services.BeanEditContext;
import org.apache.tapestry5.services.BeanModelSource;
+import org.apache.tapestry5.services.BeanValidationContext;
import org.apache.tapestry5.services.Environment;
import org.apache.tapestry5.test.TapestryTestCase;
import org.easymock.EasyMock;
@@ -154,6 +159,62 @@
train_getOverrideMessages(overrides, messages);
expect(model.newInstance()).andReturn(data);
+
+ expect(env.peek(eq(BeanValidationContext.class))).andReturn(null);
+
+ expect(model.getBeanType()).andReturn(RegistrationData.class);
+
+ BeanEditContext ctxt = new BeanEditContext()
+ {
+ public Class<?> getBeanClass()
+ {
+ return RegistrationData.class;
+ }
+
+ public <T extends Annotation> T getAnnotation(Class<T> type)
+ {
+ return null;
+ }
+ };
+
+ expect(env.push(eq(BeanEditContext.class),
contextEq())).andReturn(ctxt);
+ replay();
+
+ BeanEditor component = new BeanEditor();
+
+ component.inject(resources, overrides, source, env);
+
+ component.doPrepare();
+
+ verify();
+ }
+
+ @Test
+ public void refresh_bean_validation_context()
+ {
+ ComponentResources resources = mockComponentResources();
+ BeanModelSource source = mockBeanModelSource();
+ BeanModel model = mockBeanModel();
+ Environment env = mockEnvironment();
+ RegistrationData data = new RegistrationData();
+ Messages messages = mockMessages();
+ PropertyOverrides overrides = mockPropertyOverrides();
+ BeanValidationContext beanValidationContext =
newMock(BeanValidationContext.class);
+
+ train_getBoundType(resources, "object", RegistrationData.class);
+
+ train_createEditModel(source, RegistrationData.class, messages, model);
+
+ train_getOverrideMessages(overrides, messages);
+
+ expect(model.newInstance()).andReturn(data);
+
+
expect(env.peek(eq(BeanValidationContext.class))).andReturn(beanValidationContext);
+
+
expect(env.pop(eq(BeanValidationContext.class))).andReturn(beanValidationContext);
+
+ expect(env.push(eq(BeanValidationContext.class),
isA(BeanValidationContext.class))).andReturn(beanValidationContext);
+
expect(model.getBeanType()).andReturn(RegistrationData.class);
BeanEditContext ctxt = new BeanEditContext()
@@ -169,7 +230,7 @@
}
};
- expect(env.push(EasyMock.eq(BeanEditContext.class),
contextEq())).andReturn(ctxt);
+ expect(env.push(eq(BeanEditContext.class),
contextEq())).andReturn(ctxt);
replay();
BeanEditor component = new BeanEditor();