You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2008/01/18 01:52:59 UTC
svn commit: r613029 - in /tapestry/tapestry5/trunk:
tapestry-core/src/main/java/org/apache/tapestry/
tapestry-core/src/main/java/org/apache/tapestry/corelib/base/
tapestry-core/src/main/java/org/apache/tapestry/internal/
tapestry-core/src/main/java/org...
Author: hlship
Date: Thu Jan 17 16:52:51 2008
New Revision: 613029
URL: http://svn.apache.org/viewvc?rev=613029&view=rev
Log:
TAPESTRY-2056: Add configurable null handling for text fields
Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/FieldValidationSupport.java
- copied, changed from r612958, tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/FieldValidationSupport.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/NullFieldStrategy.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/DefaultNullFieldStrategy.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/ZeroNullFieldStrategy.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/bindings/NullFieldStrategyBindingFactory.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/NullFieldStrategySourceImpl.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/NullFieldStrategySource.java
tapestry/tapestry5/trunk/tapestry-core/src/test/app1/NullStrategyDemo.tml
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/NullStrategyDemo.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/NullFieldStrategySourceImplTest.java
Removed:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/FieldValidationSupport.java
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/Translator.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/Validator.java
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/internal/services/FieldValidationSupportImpl.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties
tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/parameters.apt
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/FieldValidationSupportImplTest.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java
tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/coerce.apt
tapestry/tapestry5/trunk/tapestry-ioc/src/site/resources/images/type-coercer.png
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/TypeCoercerImplTest.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
Copied: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/FieldValidationSupport.java (from r612958, 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/FieldValidationSupport.java?p2=tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/FieldValidationSupport.java&p1=tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/FieldValidationSupport.java&r1=612958&r2=613029&rev=613029&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/FieldValidationSupport.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/FieldValidationSupport.java Thu Jan 17 16:52:51 2008
@@ -12,12 +12,7 @@
// 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.FieldValidator;
-import org.apache.tapestry.Translator;
-import org.apache.tapestry.ValidationException;
+package org.apache.tapestry;
/**
* Services to help with field {@linkplain org.apache.tapestry.Validator validation} and {@linkplain
@@ -35,6 +30,7 @@
* @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 or null if the value is null
+ * @see org.apache.tapestry.Translator#toClient(Object)
*/
String toClient(Object value, ComponentResources componentResources, Translator translator);
@@ -51,6 +47,7 @@
* @return the input parsed to an object
* @throws org.apache.tapestry.ValidationException
* if the value can't be parsed
+ * @see org.apache.tapestry.Translator#parseClient(String, org.apache.tapestry.ioc.Messages)
*/
Object parseClient(String clientValue, ComponentResources componentResources, Translator translator)
throws ValidationException;
@@ -63,6 +60,7 @@
* @param componentResources used to trigger events
* @param validator performs normal validations
* @throws ValidationException if the value is not valid
+ * @see org.apache.tapestry.Validator#validate(Field, Object, org.apache.tapestry.ioc.MessageFormatter, Object)
*/
void validate(Object value, ComponentResources componentResources, FieldValidator validator)
throws ValidationException;
Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/NullFieldStrategy.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/NullFieldStrategy.java?rev=613029&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/NullFieldStrategy.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/NullFieldStrategy.java Thu Jan 17 16:52:51 2008
@@ -0,0 +1,40 @@
+// Copyright 2008 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry;
+
+
+/**
+ * Defines a strategy, used by {@link Field} components such as {@link org.apache.tapestry.corelib.components.TextField},
+ * to handle the case where either the server-side value to be sent (as a string) to the client, or the client-side
+ * string passed back up to the server, is null or blank.
+ *
+ * @see org.apache.tapestry.services.NullFieldStrategySource
+ */
+public interface NullFieldStrategy
+{
+ /**
+ * Provides a replacement value for null, when converting the server-side object to a client-side string. The
+ * replacement value will be passed to {@link FieldValidationSupport#toClient(Object, ComponentResources,
+ * Translator)}.
+ */
+ Object replaceToClient();
+
+ /**
+ * Provides a replacement value for a null or blank string passed from the client to the server as part of a form
+ * submission. This replacement value will be passed to {@link FieldValidationSupport#parseClient(String,
+ * ComponentResources, Translator)} as if it were the value supplied by the user.
+ */
+ String replaceFromClient();
+}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/Translator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/Translator.java?rev=613029&r1=613028&r2=613029&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/Translator.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/Translator.java Thu Jan 17 16:52:51 2008
@@ -22,7 +22,7 @@
*
* @param <T>
* @see org.apache.tapestry.services.TranslatorDefaultSource
- * @see org.apache.tapestry.services.FieldValidationSupport
+ * @see FieldValidationSupport
*/
public interface Translator<T>
{
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/Validator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/Validator.java?rev=613029&r1=613028&r2=613029&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/Validator.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/Validator.java Thu Jan 17 16:52:51 2008
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// Copyright 2006, 2007, 2008 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -19,35 +19,33 @@
import org.apache.tapestry.services.ValidationMessagesSource;
/**
- * Used by a {@link Field} to enforce a <strong>constraint</strong> related to a form submission.
- * Validators themselves are stateless singletons.
+ * Used by a {@link Field} to enforce a <strong>constraint</strong> related to a form submission. Validators themselves
+ * are stateless singletons.
* <p/>
* Validators are usually encapsulated inside a {@link FieldValidator}.
*
- * @see org.apache.tapestry.services.FieldValidationSupport
+ * @see FieldValidationSupport
* @see org.apache.tapestry.services.FieldValidatorDefaultSource
*/
public interface Validator<C, T>
{
/**
- * Returns the type of constraint value used with this validator. Constraint values are used to
- * parameterize a validator, for example a "maxLength" validator will have a constraint value of
- * type int (the maximum length allowed). For constraints that do not have a constraint value,
- * this method returns null.
+ * Returns the type of constraint value used with this validator. Constraint values are used to parameterize a
+ * validator, for example a "maxLength" validator will have a constraint value of type int (the maximum length
+ * allowed). For constraints that do not have a constraint value, this method returns null.
*/
Class<C> getConstraintType();
/**
- * Returns the value type associated with this validator.
- * {@link #validate(Field, Object, MessageFormatter, Object)} will only be invoked when the
- * value is assignable to the validator's value type.
+ * Returns the value type associated with this validator. {@link #validate(Field, Object, MessageFormatter, Object)}
+ * will only be invoked when the value is assignable to the validator's value type.
*/
Class<T> getValueType();
/**
- * Returns the message key, within the validiation messages, normally used by this validator.
- * This is used to provide the {@link MessageFormatter} passed to
- * {@link #validate(Field, Object, MessageFormatter, Object)} (unless overridden).
+ * Returns the message key, within the validiation messages, normally used by this validator. This is used to
+ * provide the {@link MessageFormatter} passed to {@link #validate(Field, Object, MessageFormatter, Object)} (unless
+ * overridden).
*
* @return a message key
* @see ValidationMessagesSource
@@ -55,9 +53,9 @@
String getMessageKey();
/**
- * Invoked after the client-submitted value has been {@link Translator translated} to check that
- * the value conforms to expectations (often, in terms of minimum or maximum value). If and only
- * if the value is approved by all Validators is the value applied by the field.
+ * Invoked after the client-submitted value has been {@link Translator translated} to check that the value conforms
+ * to expectations (often, in terms of minimum or maximum value). If and only if the value is approved by all
+ * Validators is the value applied by the field.
*
* @param field the field for which a client submitted value is being validated
* @param constraintValue the value used to constrain
@@ -68,20 +66,19 @@
void validate(Field field, C constraintValue, MessageFormatter formatter, T value) throws ValidationException;
/**
- * Returns true if the validator should be invoked for null or blank (empty string) values. This
- * is generally false.
+ * Returns true if the validator should be invoked for null or blank (empty string) values. This is generally
+ * false.
*/
boolean invokeIfBlank();
/**
- * Hook used by components to allow the validator to contribute additional attribute or (more
- * often) client-side JavaScript (via the {@link PageRenderSupport}).
+ * Hook used by components to allow the validator to contribute additional attribute or (more often) client-side
+ * JavaScript (via the {@link PageRenderSupport}).
*
* @param field the field which is currently being rendered
* @param constraintValue the value used to constrain input
* @param formatter validation message, in the appropriate locale
- * @param writer markup writer, allowing additional attributes to be written into the active
- * element
+ * @param writer markup writer, allowing additional attributes to be written into the active element
* @param formSupport
*/
void render(Field field, C constraintValue, MessageFormatter formatter, MarkupWriter writer,
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=613029&r1=613028&r2=613029&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 Thu Jan 17 16:52:51 2008
@@ -18,7 +18,7 @@
import org.apache.tapestry.annotations.*;
import org.apache.tapestry.corelib.mixins.RenderDisabled;
import org.apache.tapestry.ioc.annotations.Inject;
-import org.apache.tapestry.services.FieldValidationSupport;
+import org.apache.tapestry.ioc.internal.util.InternalUtils;
import org.apache.tapestry.services.FieldValidatorDefaultSource;
import org.apache.tapestry.services.Request;
import org.apache.tapestry.services.TranslatorDefaultSource;
@@ -35,7 +35,7 @@
* <p/>
* If the component container (i.e., the page) provides an event handler method for the "toclient" event, and that
* handler returns a non-null string, that will be the string value sent to the client. The context passed to the event
- * handler method is the current value of the value parameter.
+ * handler method is t he current value of the value parameter.
* <p/>
* Likewise, on a form submit, the "parseclient" event handler method will be passed the string provided by the client,
* and may provide a non-null value as the parsed value. Returning null allows the normal translator to operate. The
@@ -67,6 +67,14 @@
@SuppressWarnings("unchecked")
private FieldValidator<Object> _validate = NOOP_VALIDATOR;
+ /**
+ * Defines how nulls on the server side, or sent from the client side, are treated. The selected strategy may
+ * replace the nulls with some other value. The default strategy leaves nulls alone. Another built-in strategy,
+ * zero, replaces nulls with the value 0.
+ */
+ @Parameter(defaultPrefix = "nullfieldstrategy", value = "default")
+ private NullFieldStrategy _nulls;
+
@Environmental
private ValidationTracker _tracker;
@@ -136,7 +144,25 @@
{
String value = _tracker.getInput(this);
- if (value == null) value = _fieldValidationSupport.toClient(_value, _resources, _translate);
+ // If this is a response to a form submission, and the user provided a value.
+ // then send that exact value back at them.
+
+ if (value == null)
+ {
+ // Otherwise, get the value from the parameter ...
+
+ Object untranslated = _value;
+
+ // Substitute an alternative for null values.
+ // TODO: May want to coerce untranslated to the bound parameter type, to ensure it is compatible with the translator.
+
+ if (untranslated == null) untranslated = _nulls.replaceToClient();
+
+ // Then let the translator and or various triggered events get it into
+ // a format ready to be sent to the client.
+
+ value = _fieldValidationSupport.toClient(untranslated, _resources, _translate);
+ }
writeFieldTag(writer, value);
@@ -170,6 +196,8 @@
try
{
+ if (InternalUtils.isBlank(rawValue)) rawValue = _nulls.replaceFromClient();
+
Object translated = _fieldValidationSupport.parseClient(rawValue, _resources, _translate);
_fieldValidationSupport.validate(translated, _resources, _validate);
Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/DefaultNullFieldStrategy.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/DefaultNullFieldStrategy.java?rev=613029&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/DefaultNullFieldStrategy.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/DefaultNullFieldStrategy.java Thu Jan 17 16:52:51 2008
@@ -0,0 +1,39 @@
+// Copyright 2008 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.internal;
+
+import org.apache.tapestry.NullFieldStrategy;
+
+/**
+ * Default strategy, which is to do nothing: null values stay null.
+ */
+public class DefaultNullFieldStrategy implements NullFieldStrategy
+{
+ /**
+ * Returns null.
+ */
+ public Object replaceToClient()
+ {
+ return null;
+ }
+
+ /**
+ * Returns the empty string.
+ */
+ public String replaceFromClient()
+ {
+ return "";
+ }
+}
Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/ZeroNullFieldStrategy.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/ZeroNullFieldStrategy.java?rev=613029&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/ZeroNullFieldStrategy.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/ZeroNullFieldStrategy.java Thu Jan 17 16:52:51 2008
@@ -0,0 +1,39 @@
+// Copyright 2008 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.internal;
+
+import org.apache.tapestry.NullFieldStrategy;
+
+/**
+ * Treats nulls to or from the client as if they were 0's.
+ */
+public class ZeroNullFieldStrategy implements NullFieldStrategy
+{
+ /**
+ * Returns the value 0.
+ */
+ public Object replaceToClient()
+ {
+ return 0l;
+ }
+
+ /**
+ * Returns "0".
+ */
+ public String replaceFromClient()
+ {
+ return "0";
+ }
+}
Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/bindings/NullFieldStrategyBindingFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/bindings/NullFieldStrategyBindingFactory.java?rev=613029&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/bindings/NullFieldStrategyBindingFactory.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/bindings/NullFieldStrategyBindingFactory.java Thu Jan 17 16:52:51 2008
@@ -0,0 +1,44 @@
+// Copyright 2008 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.internal.bindings;
+
+import org.apache.tapestry.Binding;
+import org.apache.tapestry.ComponentResources;
+import org.apache.tapestry.NullFieldStrategy;
+import org.apache.tapestry.ioc.Location;
+import org.apache.tapestry.services.BindingFactory;
+import org.apache.tapestry.services.NullFieldStrategySource;
+
+/**
+ * Treats the expression as the name of a {@link org.apache.tapestry.NullFieldStrategy}, accessed via the {@link
+ * org.apache.tapestry.services.NullFieldStrategySource} service.
+ */
+public class NullFieldStrategyBindingFactory implements BindingFactory
+{
+ private NullFieldStrategySource _strategySource;
+
+ public NullFieldStrategyBindingFactory(NullFieldStrategySource strategySource)
+ {
+ _strategySource = strategySource;
+ }
+
+ public Binding newBinding(String description, ComponentResources container, ComponentResources component,
+ String expression, Location location)
+ {
+ NullFieldStrategy strategy = _strategySource.get(expression);
+
+ return new LiteralBinding(description, strategy, location);
+ }
+}
Modified: 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=613029&r1=613028&r2=613029&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/FieldValidationSupportImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/FieldValidationSupportImpl.java Thu Jan 17 16:52:51 2008
@@ -21,7 +21,6 @@
import org.apache.tapestry.ioc.internal.util.InternalUtils;
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
Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/NullFieldStrategySourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/NullFieldStrategySourceImpl.java?rev=613029&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/NullFieldStrategySourceImpl.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/NullFieldStrategySourceImpl.java Thu Jan 17 16:52:51 2008
@@ -0,0 +1,40 @@
+// Copyright 2008 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.internal.services;
+
+import org.apache.tapestry.NullFieldStrategy;
+import org.apache.tapestry.services.NullFieldStrategySource;
+
+import java.util.Map;
+
+public class NullFieldStrategySourceImpl implements NullFieldStrategySource
+{
+ private final Map<String, NullFieldStrategy> _configuration;
+
+ public NullFieldStrategySourceImpl(Map<String, NullFieldStrategy> configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public NullFieldStrategy get(String name)
+ {
+ NullFieldStrategy result = _configuration.get(name);
+
+ if (result != null) return result;
+
+ throw new IllegalArgumentException(
+ ServicesMessages.unknownNullFieldStrategyName(name, _configuration.keySet()));
+ }
+}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java?rev=613029&r1=613028&r2=613029&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java Thu Jan 17 16:52:51 2008
@@ -395,4 +395,9 @@
{
return MESSAGES.format("page-pool-exausted", pageName, locale.toString(), hardLimit);
}
+
+ static String unknownNullFieldStrategyName(String name, Collection<String> names)
+ {
+ return MESSAGES.format("unknown-null-field-strategy-name", name, InternalUtils.joinSorted(names));
+ }
}
Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/NullFieldStrategySource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/NullFieldStrategySource.java?rev=613029&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/NullFieldStrategySource.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/NullFieldStrategySource.java Thu Jan 17 16:52:51 2008
@@ -0,0 +1,35 @@
+// Copyright 2008 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.services;
+
+import org.apache.tapestry.NullFieldStrategy;
+
+/**
+ * A source for {@link org.apache.tapestry.NullFieldStrategy} instances based on a logical name.
+ *
+ * @see TapestryModule#contributeNullFieldStrategySource(org.apache.tapestry.ioc.MappedConfiguration)
+ */
+public interface NullFieldStrategySource
+{
+ /**
+ * Returns the instance based on the name. Instances are expected to be stateless and therefore, shareable and
+ * thread safe.
+ *
+ * @param name name of the strategy (case is ignored)
+ * @return the strategy
+ * @throws IllegalArgumentException if the name does not match a configured instance
+ */
+ NullFieldStrategy get(String name);
+}
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=613029&r1=613028&r2=613029&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 Thu Jan 17 16:52:51 2008
@@ -19,9 +19,7 @@
import org.apache.tapestry.beaneditor.Validate;
import org.apache.tapestry.corelib.data.GridPagerPosition;
import org.apache.tapestry.grid.GridDataSource;
-import org.apache.tapestry.internal.DefaultValidationDecorator;
-import org.apache.tapestry.internal.InternalConstants;
-import org.apache.tapestry.internal.TapestryInternalUtils;
+import org.apache.tapestry.internal.*;
import org.apache.tapestry.internal.beaneditor.PrimitiveFieldConstraintGenerator;
import org.apache.tapestry.internal.beaneditor.ValidateAnnotationConstraintGenerator;
import org.apache.tapestry.internal.bindings.*;
@@ -112,6 +110,7 @@
binder.bind(PageContentTypeAnalyzer.class, PageContentTypeAnalyzerImpl.class);
binder.bind(ResponseRenderer.class, ResponseRendererImpl.class);
binder.bind(RequestPathOptimizer.class, RequestPathOptimizerImpl.class);
+ binder.bind(NullFieldStrategySource.class, NullFieldStrategySourceImpl.class);
}
public static Alias build(Logger logger,
@@ -139,8 +138,8 @@
}
/**
- * Contributes the factory for serveral built-in binding prefixes ("asset", "literal", prop", "block", "component"
- * "message", "validate", "translate", "var").
+ * Contributes the factory for serveral built-in binding prefixes ("asset", "block", "component", "literal", prop",
+ * "nullfieldstrategy", "message", "validate", "translate", "var").
*/
public static void contributeBindingSource(MappedConfiguration<String, BindingFactory> configuration,
@@ -165,6 +164,7 @@
configuration.add("block", new BlockBindingFactory());
configuration.add("asset", locator.autobuild(AssetBindingFactory.class));
configuration.add("var", new RenderVariableBindingFactory());
+ configuration.add("nullfieldstrategy", locator.autobuild(NullFieldStrategyBindingFactory.class));
}
public static void contributeClasspathAssetAliasManager(MappedConfiguration<String, String> configuration,
@@ -2056,5 +2056,17 @@
if (immediateMode) return locator.autobuild(ImmediateActionRenderResponseGenerator.class);
return locator.autobuild(ActionRenderResponseGeneratorImpl.class);
+ }
+
+ /**
+ * Contributes strategies accessible via the {@link NullFieldStrategySource} service.
+ * <p/>
+ * <dl> <dt>default</dt> <dd>Does nothing, nulls stay null.</dd> <dt>zero</dt> <dd>Null values are converted to
+ * zero.</dd> </dl>
+ */
+ public static void contributeNullFieldStrategySource(MappedConfiguration<String, NullFieldStrategy> configuration)
+ {
+ configuration.add("default", new DefaultNullFieldStrategy());
+ configuration.add("zero", new ZeroNullFieldStrategy());
}
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties?rev=613029&r1=613028&r2=613029&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties Thu Jan 17 16:52:51 2008
@@ -89,4 +89,5 @@
invalid-block-id=Block id '%s' is not valid; block ids must be valid Java identifiers: start with a letter, and consist of letters, numbers and underscores.
page-pool-exausted=The page pool for page '%s' (in locale %s) has been exausted: there are %d instances currently being used and no more can be created. \
Try increasing the hard limit (symbol tapestry.page-pool.hard-limit) to allow additional instances to be created, \
- or increasing the soft wait (symbol tapestry.page-pool.soft-wait) to trade away some throughput for more efficient use of page instances.
\ No newline at end of file
+ or increasing the soft wait (symbol tapestry.page-pool.soft-wait) to trade away some throughput for more efficient use of page instances.
+unknown-null-field-strategy-name=Unrecognized name '%s' locating a null field strategy. Available strategies: %s.
Modified: tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/parameters.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/parameters.apt?rev=613029&r1=613028&r2=613029&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/parameters.apt (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/parameters.apt Thu Jan 17 16:52:51 2008
@@ -123,6 +123,8 @@
*------------+----------------------------------------------------------------------------------+
| literal | A literal string. |
*------------+----------------------------------------------------------------------------------+
+| nullfieldstrategy | Used to locate a pre-defined {{{../../apidocs/org/apache/tapestry/NullFieldStrategy.html}NullFieldStrategy}}|
+*------------+----------------------------------------------------------------------------------+
| message | Retrieves a value from the component's {{{localization.html}message catalog}}. |
*------------+----------------------------------------------------------------------------------+
| prop | The name of a property of the containing component to read or update. |
Added: tapestry/tapestry5/trunk/tapestry-core/src/test/app1/NullStrategyDemo.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/NullStrategyDemo.tml?rev=613029&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app1/NullStrategyDemo.tml (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app1/NullStrategyDemo.tml Thu Jan 17 16:52:51 2008
@@ -0,0 +1,23 @@
+<html t:type="Border" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+
+ <h1>Null Field Strategy Demo</h1>
+
+ <p>
+ Demonstrates the use of the nulls parameter of TextField to change how null values are treated.
+ </p>
+
+
+ <t:form>
+ <t:textfield t:id="number" nulls="zero"/>
+ <br/>
+ <input type="submit" value="Update"/>
+ </t:form>
+
+ <hr/>
+
+ <p>
+ Number property value:
+ <span id="value">${number}</span>
+ </p>
+
+</html>
\ No newline at end of file
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java?rev=613029&r1=613028&r2=613029&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java Thu Jan 17 16:52:51 2008
@@ -1414,4 +1414,25 @@
assertText(locator, "100");
}
+
+ /**
+ * TAPESTRY-2056
+ */
+ @Test
+ public void null_field_strategy()
+ {
+ start("Null Field Strategy Demo");
+
+ String locator = "//span[@id='value']";
+
+ assertText(locator, "");
+
+ assertText("//input[@id='number']/@value", "0");
+
+ type("number", "");
+
+ clickAndWait(SUBMIT);
+
+ assertText(locator, "0");
+ }
}
Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/NullStrategyDemo.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/NullStrategyDemo.java?rev=613029&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/NullStrategyDemo.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/NullStrategyDemo.java Thu Jan 17 16:52:51 2008
@@ -0,0 +1,33 @@
+// Copyright 2008 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.integration.app1.pages;
+
+import org.apache.tapestry.annotations.Persist;
+
+public class NullStrategyDemo
+{
+ @Persist
+ private Long _number;
+
+ public Long getNumber()
+ {
+ return _number;
+ }
+
+ public void setNumber(Long number)
+ {
+ _number = number;
+ }
+}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java?rev=613029&r1=613028&r2=613029&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java Thu Jan 17 16:52:51 2008
@@ -199,7 +199,9 @@
new Item("unlessdemo", "Unless Demo", "use of the Unless component"),
new Item("MagicValueEncoder", "Magic ValueEncoder Demo",
- "Automatic creation of ValueEncoder using the TypeCoercer"));
+ "Automatic creation of ValueEncoder using the TypeCoercer"),
+
+ new Item("NullStrategyDemo", "Null Field Strategy Demo", "use of the nulls parameter of TextField"));
static
{
Modified: 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=613029&r1=613028&r2=613029&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/FieldValidationSupportImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/FieldValidationSupportImplTest.java Thu Jan 17 16:52:51 2008
@@ -18,7 +18,6 @@
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;
Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/NullFieldStrategySourceImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/NullFieldStrategySourceImplTest.java?rev=613029&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/NullFieldStrategySourceImplTest.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/NullFieldStrategySourceImplTest.java Thu Jan 17 16:52:51 2008
@@ -0,0 +1,59 @@
+package org.apache.tapestry.internal.services;
+
+import org.apache.tapestry.NullFieldStrategy;
+import org.apache.tapestry.internal.test.InternalBaseTestCase;
+import org.apache.tapestry.ioc.internal.util.CollectionFactory;
+import org.apache.tapestry.services.NullFieldStrategySource;
+import org.testng.annotations.Test;
+
+import java.util.Collections;
+import java.util.Map;
+
+public class NullFieldStrategySourceImplTest extends InternalBaseTestCase
+{
+ @Test
+ public void success()
+ {
+ NullFieldStrategy strategy = mockNullFieldStrategy();
+
+ replay();
+
+ Map<String, NullFieldStrategy> configuration = Collections.singletonMap("strat", strategy);
+
+ NullFieldStrategySource source = new NullFieldStrategySourceImpl(configuration);
+
+ assertSame(source.get("strat"), strategy);
+
+ verify();
+ }
+
+ @Test
+ public void failure()
+ {
+ Map<String, NullFieldStrategy> configuration = CollectionFactory.newCaseInsensitiveMap();
+
+ configuration.put("fred", mockNullFieldStrategy());
+ configuration.put("barney", mockNullFieldStrategy());
+
+ replay();
+
+ NullFieldStrategySource source = new NullFieldStrategySourceImpl(configuration);
+
+ try
+ {
+ source.get("wilma");
+ unreachable();
+ }
+ catch (IllegalArgumentException ex)
+ {
+ assertEquals(ex.getMessage(),
+ "Unrecognized name 'wilma' locating a null field strategy. Available strategies: barney, fred.");
+ }
+
+ }
+
+ protected final NullFieldStrategy mockNullFieldStrategy()
+ {
+ return newMock(NullFieldStrategy.class);
+ }
+}
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java?rev=613029&r1=613028&r2=613029&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java Thu Jan 17 16:52:51 2008
@@ -56,10 +56,9 @@
}
/**
- * Provides access to additional service lifecycles. One lifecycles is built in ("singleton")
- * but additional ones are accessed via this service (and its mapped configuration). Only
- * proxiable services (those with explicit service interfaces) can be managed in terms of a
- * lifecycle.
+ * Provides access to additional service lifecycles. One lifecycles is built in ("singleton") but additional ones
+ * are accessed via this service (and its mapped configuration). Only proxiable services (those with explicit
+ * service interfaces) can be managed in terms of a lifecycle.
*/
public static ServiceLifecycleSource build(final Map<String, ServiceLifecycle> configuration)
{
@@ -82,11 +81,9 @@
}
/**
- * Contributes "DefaultProvider", ordered last, that delegates to
- * {@link ObjectLocator#getService(Class)}.
+ * Contributes "DefaultProvider", ordered last, that delegates to {@link ObjectLocator#getService(Class)}.
* <p/>
- * Contributes "Value", which injects values (not services) triggered by the {@link Value}
- * annotation.
+ * Contributes "Value", which injects values (not services) triggered by the {@link Value} annotation.
*/
public static void contributeMasterObjectProvider(OrderedConfiguration<ObjectProvider> configuration,
@@ -97,46 +94,22 @@
}
/**
- * Contributes a set of standard type coercions to the {@link TypeCoercer} service:
- * <ul>
- * <li>Object to String</li>
- * <li>String to Double</li>
- * <li>String to BigDecimal</li>
- * <li>BigDecimal to Double</li>
- * <li>Double to BigDecimal</li>
- * <li>String to BigInteger</li>
- * <li>BigInteger to Long</li>
- * <li>String to Long</li>
- * <li>Long to Byte</li>
- * <li>Long to Short</li>
- * <li>Long to Integer</li>
- * <li>Double to Long</li>
- * <li>Double to Float</li>
- * <li>Float to Double</li>
- * <li>Long to Double</li>
- * <li>String to Boolean ("false" is always false, other non-blank strings are true)</li>
- * <li>Long to Boolean (true if long value is non zero)</li>
- * <li>Null to Boolean (always false)</li>
- * <li>Null to String (still null)</li>
- * <li>Collection to Boolean (false if empty)</li>
- * <li>Object[] to List</li>
- * <li>primitive[] to List</li>
- * <li>Object to List (by wrapping as a singleton list)</li>
- * <li>Null to List (still null)</li>
- * <li>Null to Long (zero)</li>
- * <li>Null to BigDecimal (zero)</li>
- * <li>Null to BigInteger (zero)</li>
- * <li>String to File</li>
- * <li>String to {@link org.apache.tapestry.ioc.util.TimeInterval}</li>
- * <li>{@link org.apache.tapestry.ioc.util.TimeInterval} to Long</li>
- * </ul>
+ * Contributes a set of standard type coercions to the {@link TypeCoercer} service: <ul> <li>Object to String</li>
+ * <li>String to Double</li> <li>String to BigDecimal</li> <li>BigDecimal to Double</li> <li>Double to
+ * BigDecimal</li> <li>String to BigInteger</li> <li>BigInteger to Long</li> <li>String to Long</li> <li>Long to
+ * Byte</li> <li>Long to Short</li> <li>Long to Integer</li> <li>Double to Long</li> <li>Double to Float</li>
+ * <li>Float to Double</li> <li>Long to Double</li> <li>String to Boolean ("false" is always false, other non-blank
+ * strings are true)</li> <li>Long to Boolean (true if long value is non zero)</li> <li>Null to Boolean (always
+ * false)</li> <li>Null to String (still null)</li> <li>Collection to Boolean (false if empty)</li> <li>Object[] to
+ * List</li> <li>primitive[] to List</li> <li>Object to List (by wrapping as a singleton list)</li> <li>Null to List
+ * (still null)</li> <li>String to File</li> <li>String to {@link org.apache.tapestry.ioc.util.TimeInterval}</li>
+ * <li>{@link org.apache.tapestry.ioc.util.TimeInterval} to Long</li> </ul>
* <p/>
- * The coercion of String to Long, BigInteger, Double and BigDecimal causes some minor headaches
- * when attempting to add coercions from null to various numeric types: we end up having to have
- * many more coercions for the null case to prevent null --> String --> BigInteger. This may
- * indicate a weakness in the algorithm, in that coercions through String should be considered
- * "weaker" than other coercions. Alternately, coercions from null may need to be handled
- * specially. We'll see if we tweak the algorithm in the future.
+ * The coercion of String to Long, BigInteger, Double and BigDecimal causes some minor headaches when attempting to
+ * add coercions from null to various numeric types: we end up having to have many more coercions for the null case
+ * to prevent null --> String --> BigInteger. This may indicate a weakness in the algorithm, in that coercions
+ * through String should be considered "weaker" than other coercions. Alternately, coercions from null may need to
+ * be handled specially. We'll see if we tweak the algorithm in the future.
*/
@SuppressWarnings("unchecked")
public static void contributeTypeCoercer(Configuration<CoercionTuple> configuration)
@@ -292,38 +265,6 @@
}
});
- add(configuration, void.class, Long.class, new Coercion<Void, Long>()
- {
- public Long coerce(Void input)
- {
- return 0l;
- }
- });
-
- add(configuration, void.class, BigDecimal.class, new Coercion<Void, BigDecimal>()
- {
-
- public BigDecimal coerce(Void input)
- {
- return BigDecimal.ZERO;
- }
- });
-
- add(configuration, void.class, BigInteger.class, new Coercion<Void, BigInteger>()
- {
- public BigInteger coerce(Void input)
- {
- return BigInteger.ZERO;
- }
- });
-
- add(configuration, void.class, Double.class, new Coercion<Void, Double>()
- {
- public Double coerce(Void input)
- {
- return 0d;
- }
- });
add(configuration, Collection.class, Boolean.class, new Coercion<Collection, Boolean>()
{
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/coerce.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/coerce.apt?rev=613029&r1=613028&r2=613029&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/coerce.apt (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/coerce.apt Thu Jan 17 16:52:51 2008
@@ -20,9 +20,7 @@
[images/type-coercer.png] Default Type Coercions
There's a few special coercions related to null there; Object --\> List wraps a lone object as a singleton list, we then need
- null --\> List to ensure that null stays null (rather than a singleton list whose lone element is a null). Likewise, there's
- a number of coercions from null to numeric types (null is coerced to zero). Several more of these are needed than you'd think, because otherwise
- the coercer attempts to coerce through String.
+ null --\> List to ensure that null stays null (rather than a singleton list whose lone element is a null).
Tapestry can <interpolate> necessary coercions. For example, say it is necessary to coerce a StringBuffer to an Integer; the
TypeCoercer will chain together a series of coercions:
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/site/resources/images/type-coercer.png
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/site/resources/images/type-coercer.png?rev=613029&r1=613028&r2=613029&view=diff
==============================================================================
Binary files - no diff available.
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/TypeCoercerImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/TypeCoercerImplTest.java?rev=613029&r1=613028&r2=613029&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/TypeCoercerImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/TypeCoercerImplTest.java Thu Jan 17 16:52:51 2008
@@ -143,43 +143,93 @@
return new Object[][]{
// There's a lot of these!
- {this, String.class, toString()}, {55l, Integer.class, 55}, {"", Boolean.class, false},
- {" ", Boolean.class, false}, {"x", Boolean.class, true}, {" z ", Boolean.class, true},
- {"false", Boolean.class, false}, {" False ", Boolean.class, false}, {null, Boolean.class, false},
- {new Double(256), Integer.class, new Integer(256)}, {new Double(22.7), Integer.class, new Integer(22)},
- {new Integer(0), Boolean.class, false}, {new Long(32838), Boolean.class, true},
- {new Integer(127), Byte.class, new Byte("127")}, {new Double(58), Short.class, new Short("58")},
- {new Integer(33), Long.class, new Long(33)}, {new Integer(22), Float.class, new Float(22)},
+ {this, String.class, toString()},
+
+ {55l, Integer.class, 55},
+
+ {"", Boolean.class, false},
+
+ {" ", Boolean.class, false},
+
+ {"x", Boolean.class, true},
+
+ {" z ", Boolean.class, true},
+
+ {"false", Boolean.class, false},
+
+ {" False ", Boolean.class, false},
+
+ {null, Boolean.class, false},
+
+ {new Double(256), Integer.class, new Integer(256)},
+
+ {new Double(22.7), Integer.class, new Integer(22)},
+
+ {new Integer(0), Boolean.class, false},
+
+ {new Long(32838), Boolean.class, true},
+
+ {new Integer(127), Byte.class, new Byte("127")},
+
+ {new Double(58), Short.class, new Short("58")},
+
+ {new Integer(33), Long.class, new Long(33)},
+
+ {new Integer(22), Float.class, new Float(22)},
+
{new Integer(1234), Double.class, new Double(1234)},
- {floatValue, Double.class, floatValue.doubleValue()}, {Collections.EMPTY_LIST, Boolean.class, false},
+
+ {floatValue, Double.class, floatValue.doubleValue()},
+
+ {Collections.EMPTY_LIST, Boolean.class, false},
+
{Collections.singleton(this), Boolean.class, true},
+
{bigDecimalValue, BigDecimal.class, new BigDecimal(bigDecimalValue)},
+
{new BigDecimal(bigDecimalValue), Double.class, 1.2345656748352436E49},
+
{bigIntegerValue, BigInteger.class, new BigInteger(bigIntegerValue)},
+
{new BigInteger("12345678"), Long.class, 12345678l},
+
{-12345678l, BigInteger.class, new BigInteger("-12345678")},
- {object, List.class, Collections.singletonList(object)}, {null, Iterable.class, null},
- {null, List.class, null}, {null, Collection.class, null}, {null, String.class, null},
+
+ {object, List.class, Collections.singletonList(object)},
+
+ {null, Iterable.class, null},
+
+ {null, List.class, null},
+
+ {null, Collection.class, null},
+
+ {null, String.class, null},
+
{new Object[]{"a", 123}, List.class, Arrays.asList("a", 123)},
+
{new String[]{"a", "b"}, List.class, Arrays.asList("a", "b")},
+
{new byte[]{byte1, byte2}, List.class, Arrays.asList(byte1, byte2)},
+
{new short[]{short1, short2}, List.class, Arrays.asList(short1, short2)},
+
{new int[]{1, 2}, List.class, Arrays.asList(1, 2)},
+
{new long[]{123L, 321L}, List.class, Arrays.asList(123L, 321L)},
+
{new float[]{3.4f, 7.777f}, List.class, Arrays.asList(3.4f, 7.777f)},
+
{new double[]{3.4, 7.777}, List.class, Arrays.asList(3.4, 7.777)},
+
{new char[]{'a', 'b'}, List.class, Arrays.asList('a', 'b')},
+
{new boolean[]{true, false}, List.class, Arrays.asList(true, false)},
{"foo/bar/baz.txt", File.class, new File("foo/bar/baz.txt")},
-
{new TimeInterval("2 h"), Long.class, 2 * 60 * 60 * 1000l},
- {"2 h", TimeInterval.class, new TimeInterval("120 m")},
- {null, Long.class, 0l}, {null, Short.class, (short) 0}, {null, Byte.class, (byte) 0},
- {null, BigDecimal.class, BigDecimal.ZERO}, {null, Float.class, 0f},
- {null, BigInteger.class, BigInteger.ZERO},
+ {"2 h", TimeInterval.class, new TimeInterval("120 m")},
// null to arbitrary object is still null
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=613029&r1=613028&r2=613029&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 Thu Jan 17 16:52:51 2008
@@ -21,7 +21,6 @@
import org.apache.tapestry.corelib.base.AbstractField;
import org.apache.tapestry.corelib.mixins.RenderDisabled;
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;
@@ -37,15 +36,15 @@
public static final String MULTIPART_ENCTYPE = "multipart/form-data";
/**
- * The uploaded file. Note: This is only guaranteed to be valid while processing the form
- * submission. Subsequently the content may have been cleaned up.
+ * The uploaded file. Note: This is only guaranteed to be valid while processing the form submission. Subsequently
+ * the content may have been cleaned up.
*/
@Parameter(required = true, principal = true)
private UploadedFile _value;
/**
- * The object that will perform input validation. The "validate:" binding prefix is generally
- * used to provide this object in a declarative fashion.
+ * The object that will perform input validation. The "validate:" binding prefix is generally used to provide this
+ * object in a declarative fashion.
*/
@Parameter(defaultPrefix = "validate")
@SuppressWarnings("unchecked")
@@ -77,8 +76,7 @@
private RenderDisabled _renderDisabled;
/**
- * Computes a default value for the "validate" parameter using
- * {@link FieldValidatorDefaultSource}.
+ * Computes a default value for the "validate" parameter using {@link FieldValidatorDefaultSource}.
*/
final FieldValidator defaultValidate()
{
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=613029&r1=613028&r2=613029&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 Thu Jan 17 16:52:51 2008
@@ -16,7 +16,6 @@
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;