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/11/17 20:37:21 UTC
svn commit: r595993 - in /tapestry/tapestry5/trunk:
tapestry-core/src/main/java/org/apache/tapestry/corelib/base/
tapestry-core/src/main/java/org/apache/tapestry/corelib/components/
tapestry-core/src/main/java/org/apache/tapestry/corelib/internal/ tape...
Author: hlship
Date: Sat Nov 17 11:37:20 2007
New Revision: 595993
URL: http://svn.apache.org/viewvc?rev=595993&view=rev
Log:
TAPESTRY-1476: Component events for input translation and validation
Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/FieldValidationSupportImpl.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/FieldValidationSupport.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/FieldValidationSupportImplTest.java
Removed:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/internal/ComponentTranslatorWrapper.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/internal/ComponentValidatorWrapper.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/corelib/internal/ComponentTranslatorWrapperTest.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/corelib/internal/ComponentValidatorWrapperTest.java
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/base/AbstractTextField.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Select.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
tapestry/tapestry5/trunk/tapestry-upload/src/main/java/org/apache/tapestry/upload/components/Upload.java
tapestry/tapestry5/trunk/tapestry-upload/src/test/java/org/apache/tapestry/upload/components/UploadTest.java
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/base/AbstractTextField.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/base/AbstractTextField.java?rev=595993&r1=595992&r2=595993&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/base/AbstractTextField.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/base/AbstractTextField.java Sat Nov 17 11:37:20 2007
@@ -19,9 +19,6 @@
import org.apache.tapestry.annotations.BeginRender;
import org.apache.tapestry.annotations.Environmental;
import org.apache.tapestry.annotations.Parameter;
-import org.apache.tapestry.corelib.internal.ComponentTranslatorWrapper;
-import org.apache.tapestry.corelib.internal.ComponentValidatorWrapper;
-import org.apache.tapestry.ioc.Messages;
import org.apache.tapestry.ioc.annotations.Inject;
import org.apache.tapestry.services.*;
@@ -75,9 +72,6 @@
private ValidationTracker _tracker;
@Inject
- private ValidationMessagesSource _messagesSource;
-
- @Inject
private TranslatorDefaultSource _translatorDefaultSource;
@Inject
@@ -92,6 +86,9 @@
@Inject
private Request _request;
+ @Inject
+ private FieldValidationSupport _fieldValidationSupport;
+
/**
* Computes a default value for the "translate" parameter using {@link TranslatorDefaultSource}.
*/
@@ -137,13 +134,7 @@
{
String value = _tracker.getInput(this);
- if (value == null)
- {
-
- Translator wrapper = new ComponentTranslatorWrapper(_resources, _translate);
-
- value = wrapper.toClient(_value);
- }
+ if (value == null) value = _fieldValidationSupport.toClient(_value, _resources, _translate);
writeFieldTag(writer, value);
@@ -178,17 +169,11 @@
_tracker.recordInput(this, rawValue);
- Messages messages = _messagesSource.getValidationMessages(_locale);
-
try
{
- Translator translatorWrapper = new ComponentTranslatorWrapper(_resources, _translate);
-
- Object translated = translatorWrapper.parseClient(rawValue, messages);
-
- FieldValidator validatorWrapper = new ComponentValidatorWrapper(_resources, _validate);
+ Object translated = _fieldValidationSupport.parseClient(rawValue, _resources, _translate);
- validatorWrapper.validate(translated);
+ _fieldValidationSupport.validate(translated, _resources, _validate);
_value = translated;
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Select.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Select.java?rev=595993&r1=595992&r2=595993&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Select.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Select.java Sat Nov 17 11:37:20 2007
@@ -19,7 +19,6 @@
import org.apache.tapestry.annotations.Environmental;
import org.apache.tapestry.annotations.Parameter;
import org.apache.tapestry.corelib.base.AbstractField;
-import org.apache.tapestry.corelib.internal.ComponentValidatorWrapper;
import org.apache.tapestry.internal.util.SelectModelRenderer;
import org.apache.tapestry.ioc.annotations.Inject;
import org.apache.tapestry.services.*;
@@ -105,6 +104,9 @@
@Inject
private ValueEncoderSource _valueEncoderSource;
+ @Inject
+ private FieldValidationSupport _fieldValidationSupport;
+
@SuppressWarnings({"unchecked"})
@Override
protected void processSubmission(FormSupport formSupport, String elementName)
@@ -113,11 +115,9 @@
Object selectedValue = _encoder.toValue(primaryKey);
- FieldValidator wrappedValidator = new ComponentValidatorWrapper(_resources, _validate);
-
try
{
- wrappedValidator.validate(selectedValue);
+ _fieldValidationSupport.validate(selectedValue, _resources, _validate);
_value = selectedValue;
}
Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/FieldValidationSupportImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/FieldValidationSupportImpl.java?rev=595993&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/FieldValidationSupportImpl.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/FieldValidationSupportImpl.java Sat Nov 17 11:37:20 2007
@@ -0,0 +1,108 @@
+package org.apache.tapestry.internal.services;
+
+import org.apache.tapestry.*;
+import org.apache.tapestry.corelib.internal.InternalMessages;
+import org.apache.tapestry.internal.util.Holder;
+import org.apache.tapestry.ioc.Messages;
+import org.apache.tapestry.runtime.Component;
+import org.apache.tapestry.runtime.ComponentEventException;
+import org.apache.tapestry.services.FieldValidationSupport;
+import org.apache.tapestry.services.ValidationMessagesSource;
+
+public class FieldValidationSupportImpl implements FieldValidationSupport
+{
+ static final String PARSE_CLIENT_EVENT = "parseClient";
+ static final String TO_CLIENT_EVENT = "toClient";
+ static final String VALIDATE_EVENT = "validate";
+
+ private final ValidationMessagesSource _messagesSource;
+
+ public FieldValidationSupportImpl(ValidationMessagesSource messagesSource)
+ {
+ _messagesSource = messagesSource;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public String toClient(Object value, ComponentResources componentResources, Translator translator)
+ {
+ final Holder<String> resultHolder = Holder.create();
+
+ ComponentEventHandler handler = new ComponentEventHandler()
+ {
+ public boolean handleResult(Object result, Component component, String methodDescription)
+ {
+ // What's nice is that the ComponentEventException will automatically identify
+ // the method description.
+
+ if (!(result instanceof String))
+ throw new RuntimeException(InternalMessages.toClientShouldReturnString());
+
+ resultHolder.put((String) result);
+
+ return true;
+ }
+ };
+
+ componentResources.triggerEvent(TO_CLIENT_EVENT, new Object[]{value}, handler);
+
+ if (resultHolder.hasValue()) return resultHolder.get();
+
+ return translator.toClient(value);
+
+ }
+
+ public Object parseClient(String clientValue, ComponentResources componentResources, Translator translator)
+ throws ValidationException
+ {
+ final Holder<Object> resultHolder = Holder.create();
+
+ ComponentEventHandler handler = new ComponentEventHandler()
+ {
+ public boolean handleResult(Object result, Component component, String methodDescription)
+ {
+ resultHolder.put(result);
+ return true;
+ }
+ };
+
+ try
+ {
+ componentResources.triggerEvent(PARSE_CLIENT_EVENT, new Object[]{clientValue}, handler);
+ }
+ catch (ComponentEventException ex)
+ {
+ ValidationException ve = ex.get(ValidationException.class);
+
+ if (ve != null) throw ve;
+
+ throw ex;
+ }
+
+ if (resultHolder.hasValue()) return resultHolder.get();
+
+ // Otherwise, let the normal translator do the job.
+
+ Messages messages = _messagesSource.getValidationMessages(componentResources.getLocale());
+
+ return translator.parseClient(clientValue, messages);
+ }
+
+ public void validate(Object value, ComponentResources componentResources, FieldValidator validator)
+ throws ValidationException
+ {
+ validator.validate(value);
+
+ try
+ {
+ componentResources.triggerEvent(VALIDATE_EVENT, new Object[]{value}, null);
+ }
+ catch (ComponentEventException ex)
+ {
+ ValidationException ve = ex.get(ValidationException.class);
+
+ if (ve != null) throw ve;
+
+ throw ex;
+ }
+ }
+}
Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/FieldValidationSupport.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/FieldValidationSupport.java?rev=595993&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/FieldValidationSupport.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/FieldValidationSupport.java Sat Nov 17 11:37:20 2007
@@ -0,0 +1,52 @@
+package org.apache.tapestry.services;
+
+import org.apache.tapestry.ComponentResources;
+import org.apache.tapestry.FieldValidator;
+import org.apache.tapestry.Translator;
+import org.apache.tapestry.ValidationException;
+
+/**
+ * Services to help with field {@linkplain org.apache.tapestry.Validator validation} and
+ * {@linkplain org.apache.tapestry.Translator translation}. This service encapsulates
+ * the logic that mixes normal configured/declared validation/translation with
+ * events triggered on the component.
+ */
+public interface FieldValidationSupport
+{
+ /**
+ * A wrapper around {@link org.apache.tapestry.Translator#toClient(Object)} that first
+ * fires a "toclient" event on the component to see if it can perform the conversion.
+ *
+ * @param value to be converted to a client-side string
+ * @param componentResources used to fire events on the component
+ * @param translator used if the component does not provide a non-null value
+ * @return the translated value
+ */
+ String toClient(Object value, ComponentResources componentResources, Translator translator);
+
+ /**
+ * A wrapper around {@link org.apache.tapestry.Translator#parseClient(String, org.apache.tapestry.ioc.Messages)}.
+ * First a "parseclient" event is fired; the translator is only invoked if that returns null.
+ *
+ * @param clientValue the value provided by the client (may be null)
+ * @param componentResources used to trigger events
+ * @param translator translator that will do the work if the component event returns null
+ * @return the input parsed to an object
+ * @throws org.apache.tapestry.ValidationException
+ * if the value can't be parsed
+ */
+ Object parseClient(String clientValue, ComponentResources componentResources, Translator translator)
+ throws ValidationException;
+
+ /**
+ * Performs validation on a parsed value from the client. Normal validations occur first,
+ * then a "validate" event is triggered on the component.
+ *
+ * @param value parsed value from the client
+ * @param componentResources used to trigger events
+ * @param validator performs normal validations
+ * @throws ValidationException if the value is not valid
+ */
+ void validate(Object value, ComponentResources componentResources, FieldValidator validator)
+ throws ValidationException;
+}
\ No newline at end of file
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java?rev=595993&r1=595992&r2=595993&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java Sat Nov 17 11:37:20 2007
@@ -91,7 +91,7 @@
binder.bind(BeanBlockSource.class, BeanBlockSourceImpl.class);
binder.bind(ComponentDefaultProvider.class, ComponentDefaultProviderImpl.class);
binder.bind(MarkupWriterFactory.class, MarkupWriterFactoryImpl.class);
-
+ binder.bind(FieldValidationSupport.class, FieldValidationSupportImpl.class);
binder.bind(TemplateParser.class, TemplateParserImpl.class);
binder.bind(PageResponseRenderer.class, PageResponseRendererImpl.class);
binder.bind(PageMarkupRenderer.class, PageMarkupRendererImpl.class);
@@ -107,7 +107,6 @@
binder.bind(ResourceStreamer.class, ResourceStreamerImpl.class);
binder.bind(ClientPersistentFieldStorage.class, ClientPersistentFieldStorageImpl.class);
binder.bind(RequestEncodingInitializer.class, RequestEncodingInitializerImpl.class);
-
}
public static Alias build(Logger logger,
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/test/TapestryTestCase.java?rev=595993&r1=595992&r2=595993&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/test/TapestryTestCase.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/test/TapestryTestCase.java Sat Nov 17 11:37:20 2007
@@ -949,4 +949,9 @@
return new MapMessages(Locale.ENGLISH, map);
}
+
+ protected final FieldValidationSupport mockFieldValidationSupport()
+ {
+ return newMock(FieldValidationSupport.class);
+ }
}
Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/FieldValidationSupportImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/FieldValidationSupportImplTest.java?rev=595993&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/FieldValidationSupportImplTest.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/FieldValidationSupportImplTest.java Sat Nov 17 11:37:20 2007
@@ -0,0 +1,349 @@
+package org.apache.tapestry.internal.services;
+
+import org.apache.tapestry.*;
+import org.apache.tapestry.corelib.internal.InternalMessages;
+import org.apache.tapestry.ioc.Messages;
+import org.apache.tapestry.runtime.ComponentEventException;
+import org.apache.tapestry.services.FieldValidationSupport;
+import org.apache.tapestry.services.ValidationMessagesSource;
+import org.apache.tapestry.test.TapestryTestCase;
+import org.easymock.EasyMock;
+import org.easymock.IAnswer;
+import org.testng.annotations.Test;
+
+import java.util.Locale;
+
+public class FieldValidationSupportImplTest extends TapestryTestCase
+{
+
+ @SuppressWarnings({"unchecked"})
+ @Test
+ public void parse_client_via_event() throws ValidationException
+ {
+ ComponentResources resources = mockComponentResources();
+ Translator translator = mockTranslator();
+ ValidationMessagesSource source = mockValidationMessagesSource();
+
+ String clientValue = "abracadabra";
+
+ IAnswer answer = new IAnswer()
+ {
+ @SuppressWarnings({"unchecked"})
+ public Object answer() throws Throwable
+ {
+ Object[] args = EasyMock.getCurrentArguments();
+ Object[] context = (Object[]) args[1];
+ ComponentEventHandler handler = (ComponentEventHandler) args[2];
+
+ // Pretend that the parser event handler converted it to upper case.
+
+ return handler.handleResult(context[0].toString().toUpperCase(), null, null);
+ }
+ };
+
+ EasyMock.expect(resources.triggerEvent(EasyMock.eq(FieldValidationSupportImpl.PARSE_CLIENT_EVENT),
+ EasyMock.isA(Object[].class),
+ EasyMock.isA(ComponentEventHandler.class))).andAnswer(answer);
+
+
+ replay();
+
+
+ FieldValidationSupport support = new FieldValidationSupportImpl(source);
+
+ Object actual = support.parseClient(clientValue, resources, translator);
+
+ assertEquals(actual, clientValue.toUpperCase());
+
+ verify();
+ }
+
+ @SuppressWarnings({"ThrowableInstanceNeverThrown"})
+ @Test
+ public void parse_client_event_handler_throws_validation_exception() throws Exception
+ {
+ ComponentResources resources = mockComponentResources();
+ Translator translator = mockTranslator();
+ ValidationException ve = new ValidationException("Just didn't feel right.");
+ ValidationMessagesSource source = mockValidationMessagesSource();
+
+ String clientValue = "abracadabra";
+
+
+ EasyMock.expect(resources.triggerEvent(EasyMock.eq(FieldValidationSupportImpl.PARSE_CLIENT_EVENT),
+ EasyMock.isA(Object[].class),
+ EasyMock.isA(ComponentEventHandler.class))).andThrow(
+ new ComponentEventException(ve.getMessage(), null, ve));
+
+
+ replay();
+
+ FieldValidationSupport support = new FieldValidationSupportImpl(source);
+
+ try
+ {
+ support.parseClient(clientValue, resources, translator);
+
+ unreachable();
+ }
+ catch (ValidationException ex)
+ {
+ assertSame(ex, ve);
+ }
+
+
+ verify();
+ }
+
+ @SuppressWarnings({"ThrowableInstanceNeverThrown"})
+ @Test
+ public void parse_client_event_handler_fails_with_other_exception() throws Exception
+ {
+ ComponentResources resources = mockComponentResources();
+ Translator translator = mockTranslator();
+ RuntimeException re = new RuntimeException("Just didn't feel right.");
+ ComponentEventException cee = new ComponentEventException(re.getMessage(), null, re);
+ ValidationMessagesSource source = mockValidationMessagesSource();
+
+ String clientValue = "abracadabra";
+
+
+ EasyMock.expect(resources.triggerEvent(EasyMock.eq(FieldValidationSupportImpl.PARSE_CLIENT_EVENT),
+ EasyMock.isA(Object[].class),
+ EasyMock.isA(ComponentEventHandler.class))).andThrow(cee);
+
+
+ replay();
+
+ FieldValidationSupport support = new FieldValidationSupportImpl(source);
+
+ try
+ {
+ support.parseClient(clientValue, resources, translator);
+
+ unreachable();
+ }
+ catch (ComponentEventException ex)
+ {
+ assertSame(ex, cee);
+ assertSame(ex.getCause(), re);
+ }
+
+
+ verify();
+ }
+
+ @Test
+ public void parse_client_via_translator() throws ValidationException
+ {
+ Messages messages = mockMessages();
+ ComponentResources resources = mockComponentResources();
+ Translator translator = mockTranslator();
+ ValidationMessagesSource source = mockValidationMessagesSource();
+ Locale locale = Locale.GERMAN;
+
+ String clientValue = "abracadabra";
+
+
+ EasyMock.expect(resources.triggerEvent(EasyMock.eq(FieldValidationSupportImpl.PARSE_CLIENT_EVENT),
+ EasyMock.isA(Object[].class),
+ EasyMock.isA(ComponentEventHandler.class))).andReturn(false);
+
+ train_getLocale(resources, locale);
+
+ train_getValidationMessages(source, locale, messages);
+
+ expect(translator.parseClient(clientValue, messages)).andReturn("foobar");
+
+ replay();
+
+ FieldValidationSupport support = new FieldValidationSupportImpl(source);
+
+ Object actual = support.parseClient(clientValue, resources, translator);
+
+ assertEquals(actual, "foobar");
+
+ verify();
+ }
+
+ @SuppressWarnings({"unchecked"})
+ @Test
+ public void to_client_via_translator()
+ {
+ Object value = new Object();
+ ComponentResources resources = mockComponentResources();
+ Translator translator = mockTranslator();
+ ValidationMessagesSource source = mockValidationMessagesSource();
+
+ String clientValue = "abracadabra";
+
+ EasyMock.expect(resources.triggerEvent(EasyMock.eq(FieldValidationSupportImpl.TO_CLIENT_EVENT),
+ EasyMock.aryEq(new Object[]{value}),
+ EasyMock.isA(ComponentEventHandler.class))).andReturn(false);
+
+ expect(translator.toClient(value)).andReturn(clientValue);
+
+ replay();
+
+ FieldValidationSupport support = new FieldValidationSupportImpl(source);
+
+ String actual = support.toClient(value, resources, translator);
+
+ assertEquals(actual, clientValue);
+
+ verify();
+ }
+
+ @SuppressWarnings({"unchecked"})
+ @Test
+ public void to_client_via_event_handler() throws Exception
+ {
+ Object value = new Object();
+ ComponentResources resources = mockComponentResources();
+ Translator translator = mockTranslator();
+ ValidationMessagesSource source = mockValidationMessagesSource();
+
+ final String clientValue = "abracadabra";
+
+ IAnswer answer = new IAnswer()
+ {
+ @SuppressWarnings({"unchecked"})
+ public Object answer() throws Throwable
+ {
+ Object[] args = EasyMock.getCurrentArguments();
+ ComponentEventHandler handler = (ComponentEventHandler) args[2];
+
+ return handler.handleResult(clientValue, null, null);
+ }
+ };
+
+ EasyMock.expect(resources.triggerEvent(EasyMock.eq(FieldValidationSupportImpl.TO_CLIENT_EVENT),
+ EasyMock.aryEq(new Object[]{value}),
+ EasyMock.isA(ComponentEventHandler.class))).andAnswer(answer);
+
+
+ replay();
+
+ FieldValidationSupport support = new FieldValidationSupportImpl(source);
+
+ String actual = support.toClient(value, resources, translator);
+
+ assertEquals(actual, clientValue);
+
+ verify();
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public void to_client_via_event_handler_returns_non_string() throws Exception
+ {
+ Object value = new Object();
+ ComponentResources resources = mockComponentResources();
+ Translator translator = mockTranslator();
+ ValidationMessagesSource source = mockValidationMessagesSource();
+
+ IAnswer answer = new IAnswer()
+ {
+ @SuppressWarnings({"unchecked"})
+ public Object answer() throws Throwable
+ {
+ Object[] args = EasyMock.getCurrentArguments();
+ ComponentEventHandler handler = (ComponentEventHandler) args[2];
+
+ // Return an innappropriate value.
+
+ return handler.handleResult(this, null, null);
+ }
+ };
+
+ EasyMock.expect(resources.triggerEvent(EasyMock.eq(FieldValidationSupportImpl.TO_CLIENT_EVENT),
+ EasyMock.aryEq(new Object[]{value}),
+ EasyMock.isA(ComponentEventHandler.class))).andAnswer(answer);
+
+
+ replay();
+
+ FieldValidationSupport support = new FieldValidationSupportImpl(source);
+
+ try
+ {
+
+ support.toClient(value, resources, translator);
+
+ unreachable();
+ }
+ catch (RuntimeException ex)
+ {
+ assertEquals(ex.getMessage(), InternalMessages.toClientShouldReturnString());
+ }
+
+ verify();
+ }
+
+ @SuppressWarnings({"unchecked"})
+ @Test
+ public void event_triggered_after_delegate_invoked() throws Exception
+ {
+ getMocksControl().checkOrder(true);
+
+ ComponentResources resources = mockComponentResources();
+ FieldValidator fv = mockFieldValidator();
+ ValidationMessagesSource source = mockValidationMessagesSource();
+
+ Object value = new Object();
+
+ fv.validate(value);
+
+ ComponentEventHandler handler = null;
+
+ expect(resources.triggerEvent(EasyMock.eq(FieldValidationSupportImpl.VALIDATE_EVENT),
+ EasyMock.aryEq(new Object[]{value}), EasyMock.eq(handler))).andReturn(true);
+
+
+ replay();
+
+ FieldValidationSupport support = new FieldValidationSupportImpl(source);
+
+ support.validate(value, resources, fv);
+
+ verify();
+ }
+
+ @SuppressWarnings({"unchecked", "ThrowableInstanceNeverThrown"})
+ @Test
+ public void event_trigger_throws_validation_exception() throws Exception
+ {
+ ComponentResources resources = mockComponentResources();
+ FieldValidator fv = mockFieldValidator();
+ ValidationMessagesSource source = mockValidationMessagesSource();
+
+ Object value = new Object();
+
+ ValidationException ve = new ValidationException("Bah!");
+ ComponentEventException cee = new ComponentEventException(ve.getMessage(), null, ve);
+
+ ComponentEventHandler handler = null;
+
+ fv.validate(value);
+
+ expect(resources.triggerEvent(EasyMock.eq(FieldValidationSupportImpl.VALIDATE_EVENT),
+ EasyMock.aryEq(new Object[]{value}), EasyMock.eq(handler))).andThrow(cee);
+
+
+ replay();
+
+ FieldValidationSupport support = new FieldValidationSupportImpl(source);
+
+
+ try
+ {
+ support.validate(value, resources, fv);
+ unreachable();
+ }
+ catch (ValidationException ex)
+ {
+ assertSame(ex, ve);
+ }
+
+ verify();
+ }
+}
Modified: tapestry/tapestry5/trunk/tapestry-upload/src/main/java/org/apache/tapestry/upload/components/Upload.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-upload/src/main/java/org/apache/tapestry/upload/components/Upload.java?rev=595993&r1=595992&r2=595993&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-upload/src/main/java/org/apache/tapestry/upload/components/Upload.java (original)
+++ tapestry/tapestry5/trunk/tapestry-upload/src/main/java/org/apache/tapestry/upload/components/Upload.java Sat Nov 17 11:37:20 2007
@@ -18,8 +18,8 @@
import org.apache.tapestry.annotations.Environmental;
import org.apache.tapestry.annotations.Parameter;
import org.apache.tapestry.corelib.base.AbstractField;
-import org.apache.tapestry.corelib.internal.ComponentValidatorWrapper;
import org.apache.tapestry.ioc.annotations.Inject;
+import org.apache.tapestry.services.FieldValidationSupport;
import org.apache.tapestry.services.FieldValidatorDefaultSource;
import org.apache.tapestry.services.FormSupport;
import org.apache.tapestry.upload.services.MultipartDecoder;
@@ -67,6 +67,9 @@
@Inject
private Locale _locale;
+ @Inject
+ private FieldValidationSupport _fieldValidationSupport;
+
/**
* Computes a default value for the "validate" parameter using
* {@link FieldValidatorDefaultSource}.
@@ -88,13 +91,14 @@
// For testing
Upload(UploadedFile value, FieldValidator<Object> validate, MultipartDecoder decoder, ValidationTracker tracker,
- ComponentResources resources)
+ ComponentResources resources, FieldValidationSupport fieldValidationSupport)
{
_value = value;
if (validate != null) _validate = validate;
_decoder = decoder;
_tracker = tracker;
_resources = resources;
+ _fieldValidationSupport = fieldValidationSupport;
}
@SuppressWarnings({"unchecked"})
@@ -108,11 +112,9 @@
if (uploaded.getFileName() == null || uploaded.getFileName().length() == 0) uploaded = null;
}
- FieldValidator wrappedValidator = new ComponentValidatorWrapper(_resources, _validate);
-
try
{
- wrappedValidator.validate(uploaded);
+ _fieldValidationSupport.validate(uploaded, _resources, _validate);
}
catch (ValidationException ex)
{
Modified: tapestry/tapestry5/trunk/tapestry-upload/src/test/java/org/apache/tapestry/upload/components/UploadTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-upload/src/test/java/org/apache/tapestry/upload/components/UploadTest.java?rev=595993&r1=595992&r2=595993&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-upload/src/test/java/org/apache/tapestry/upload/components/UploadTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-upload/src/test/java/org/apache/tapestry/upload/components/UploadTest.java Sat Nov 17 11:37:20 2007
@@ -16,11 +16,12 @@
import org.apache.tapestry.*;
import org.apache.tapestry.dom.Element;
+import org.apache.tapestry.services.FieldValidationSupport;
import org.apache.tapestry.services.FormSupport;
import org.apache.tapestry.test.TapestryTestCase;
import org.apache.tapestry.upload.services.MultipartDecoder;
import org.apache.tapestry.upload.services.UploadedFile;
-import static org.easymock.EasyMock.*;
+import static org.easymock.EasyMock.expectLastCall;
import org.testng.annotations.Test;
public class UploadTest extends TapestryTestCase
@@ -46,7 +47,7 @@
replay();
- Upload component = new Upload(null, null, null, null, resources);
+ Upload component = new Upload(null, null, null, null, resources, null);
component.injectDecorator(new StubValidationDecorator());
component.injectFormSupport(formSupport);
@@ -70,7 +71,7 @@
getMocksControl().checkOrder(true);
ComponentResources resources = mockComponentResources();
- Upload component = new Upload(null, null, null, null, resources);
+ Upload component = new Upload(null, null, null, null, resources, null);
MarkupWriter writer = createMarkupWriter();
writer.element("form");
@@ -106,7 +107,7 @@
FieldValidator<Object> validate = mockFieldValidator();
ComponentResources resources = mockComponentResources();
- Upload component = new Upload(null, validate, null, null, resources);
+ Upload component = new Upload(null, validate, null, null, resources, null);
MarkupWriter writer = createMarkupWriter();
writer.element("form");
@@ -145,6 +146,7 @@
}
+ @SuppressWarnings({"unchecked"})
@Test
public void process_submission_extracts_value_from_decoder() throws Exception
{
@@ -152,13 +154,15 @@
MultipartDecoder decoder = mockMultipartDecoder();
UploadedFile uploadedFile = mockUploadedFile();
ComponentResources resources = mockComponentResources();
+ FieldValidationSupport support = mockFieldValidationSupport();
+ FieldValidator validate = mockFieldValidator();
- Upload component = new Upload(null, null, decoder, null, resources);
+ Upload component = new Upload(null, validate, decoder, null, resources, support);
expect(decoder.getFileUpload("test")).andReturn(uploadedFile);
expect(uploadedFile.getFileName()).andReturn("foo").anyTimes();
- train_validate(resources, uploadedFile);
+ support.validate(uploadedFile, resources, validate);
replay();
@@ -169,12 +173,7 @@
assertSame(component.getValue(), uploadedFile);
}
- protected final void train_validate(ComponentResources resources, Object... context)
- {
- ComponentEventHandler handler = null;
- expect(resources.triggerEvent(eq("validate"), aryEq(context), eq(handler))).andReturn(false);
- }
-
+ @SuppressWarnings({"unchecked"})
@Test
public void process_submission_ignores_null_value() throws Exception
{
@@ -182,14 +181,16 @@
MultipartDecoder decoder = mockMultipartDecoder();
UploadedFile uploadedFile = mockUploadedFile();
ComponentResources resources = mockComponentResources();
+ FieldValidationSupport support = mockFieldValidationSupport();
+ FieldValidator validate = mockFieldValidator();
- Upload component = new Upload(null, null, decoder, null, resources);
+ Upload component = new Upload(null, validate, decoder, null, resources, support);
expect(decoder.getFileUpload("test")).andReturn(uploadedFile);
expect(uploadedFile.getFileName()).andReturn("").atLeastOnce();
+ support.validate(null, resources, validate);
- train_validate(resources, new Object[]{null});
replay();
@@ -209,15 +210,14 @@
UploadedFile uploadedFile = mockUploadedFile();
FieldValidator<Object> validate = mockFieldValidator();
ComponentResources resources = mockComponentResources();
+ FieldValidationSupport support = mockFieldValidationSupport();
- Upload component = new Upload(null, validate, decoder, null, resources);
+ Upload component = new Upload(null, validate, decoder, null, resources, support);
expect(decoder.getFileUpload("test")).andReturn(uploadedFile);
expect(uploadedFile.getFileName()).andReturn("test").atLeastOnce();
- train_validate(resources, uploadedFile);
-
- validate.validate(uploadedFile);
+ support.validate(uploadedFile, resources, validate);
replay();
@@ -226,7 +226,7 @@
verify();
}
- @SuppressWarnings("unchecked")
+ @SuppressWarnings({"unchecked", "ThrowableInstanceNeverThrown"})
@Test
public void process_submission_tracks_validator_errors() throws Exception
{
@@ -236,14 +236,14 @@
FieldValidator<Object> validate = mockFieldValidator();
ValidationTracker tracker = mockValidationTracker();
ComponentResources resources = mockComponentResources();
+ FieldValidationSupport support = mockFieldValidationSupport();
- Upload component = new Upload(null, validate, decoder, tracker, resources);
+ Upload component = new Upload(null, validate, decoder, tracker, resources, support);
expect(decoder.getFileUpload("test")).andReturn(uploadedFile);
expect(uploadedFile.getFileName()).andReturn("test").atLeastOnce();
- validate.validate(uploadedFile);
-
+ support.validate(uploadedFile, resources, validate);
expectLastCall().andThrow(new ValidationException("an error"));
tracker.recordError(component, "an error");