| // Copyright 2007, 2008, 2010 The Apache Software Foundation |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package org.apache.tapestry5.internal.services; |
| |
| import org.apache.tapestry5.ComponentEventCallback; |
| import org.apache.tapestry5.ComponentResources; |
| import org.apache.tapestry5.EventConstants; |
| import org.apache.tapestry5.FieldTranslator; |
| import org.apache.tapestry5.FieldValidationSupport; |
| import org.apache.tapestry5.FieldValidator; |
| import org.apache.tapestry5.NullFieldStrategy; |
| import org.apache.tapestry5.ValidationException; |
| import org.apache.tapestry5.corelib.internal.InternalMessages; |
| import org.apache.tapestry5.internal.util.Holder; |
| import org.apache.tapestry5.ioc.internal.util.InternalUtils; |
| import org.apache.tapestry5.ioc.services.TypeCoercer; |
| import org.apache.tapestry5.ioc.util.ExceptionUtils; |
| |
| @SuppressWarnings("all") |
| public class FieldValidationSupportImpl implements FieldValidationSupport |
| { |
| private final TypeCoercer typeCoercer; |
| |
| public FieldValidationSupportImpl(TypeCoercer typeCoercer) |
| { |
| this.typeCoercer = typeCoercer; |
| } |
| |
| public String toClient(Object value, ComponentResources componentResources, FieldTranslator<Object> translator, |
| NullFieldStrategy nullFieldStrategy) |
| { |
| assert componentResources != null; |
| assert translator != null; |
| assert nullFieldStrategy != null; |
| final Holder<String> resultHolder = Holder.create(); |
| |
| ComponentEventCallback callback = new ComponentEventCallback() |
| { |
| public boolean handleResult(Object result) |
| { |
| // 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(EventConstants.TO_CLIENT, new Object[] |
| { value }, callback); |
| |
| if (resultHolder.hasValue()) |
| return resultHolder.get(); |
| |
| Object effectiveValue = value; |
| |
| if (effectiveValue == null) |
| { |
| effectiveValue = nullFieldStrategy.replaceToClient(); |
| |
| // Don't try to coerce or translate null. |
| |
| if (effectiveValue == null) |
| return null; |
| } |
| |
| // And now, whether its a value from a bound property, or from the null field strategy, |
| // get it into the right format for the translator and let it translate. |
| |
| Object coerced = typeCoercer.coerce(effectiveValue, translator.getType()); |
| |
| return translator.toClient(coerced); |
| } |
| |
| public Object parseClient(String clientValue, ComponentResources componentResources, |
| FieldTranslator<Object> translator, NullFieldStrategy nullFieldStrategy) throws ValidationException |
| { |
| assert componentResources != null; |
| assert translator != null; |
| assert nullFieldStrategy != null; |
| String effectiveValue = clientValue; |
| |
| if (InternalUtils.isBlank(effectiveValue)) |
| { |
| effectiveValue = nullFieldStrategy.replaceFromClient(); |
| |
| if (effectiveValue == null) |
| return null; |
| } |
| |
| final Holder<Object> resultHolder = Holder.create(); |
| |
| ComponentEventCallback callback = new ComponentEventCallback() |
| { |
| public boolean handleResult(Object result) |
| { |
| resultHolder.put(result); |
| return true; |
| } |
| }; |
| |
| try |
| { |
| componentResources.triggerEvent(EventConstants.PARSE_CLIENT, new Object[] |
| { effectiveValue }, callback); |
| } |
| catch (RuntimeException ex) |
| { |
| rethrowValidationException(ex); |
| } |
| |
| if (resultHolder.hasValue()) |
| return resultHolder.get(); |
| |
| return translator.parse(effectiveValue); |
| } |
| |
| /** |
| * Checks for a {@link org.apache.tapestry5.ValidationException} inside the outer exception and throws that, |
| * otherwise rethrows the runtime exception. |
| * |
| * @param outerException |
| * initially caught exception |
| * @throws ValidationException |
| * if found |
| */ |
| private void rethrowValidationException(RuntimeException outerException) throws ValidationException |
| { |
| ValidationException ve = ExceptionUtils.findCause(outerException, ValidationException.class); |
| |
| if (ve != null) |
| throw ve; |
| |
| throw outerException; |
| } |
| |
| @SuppressWarnings( |
| { "unchecked" }) |
| public void validate(Object value, ComponentResources componentResources, FieldValidator validator) |
| throws ValidationException |
| { |
| assert componentResources != null; |
| assert validator != null; |
| validator.validate(value); |
| |
| try |
| { |
| componentResources.triggerEvent(EventConstants.VALIDATE, new Object[] |
| { value }, null); |
| } |
| catch (RuntimeException ex) |
| { |
| rethrowValidationException(ex); |
| } |
| } |
| } |