001: /*
002: * Copyright 2005-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005: * in compliance with the License. You may obtain a copy of the License at
006: *
007: * http://www.apache.org/licenses/LICENSE-2.0
008: *
009: * Unless required by applicable law or agreed to in writing, software distributed under the License
010: * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011: * or implied. See the License for the specific language governing permissions and limitations under
012: * the License.
013: */
014:
015: package org.strecks.validator.strategy;
016:
017: import java.lang.reflect.Method;
018: import java.lang.reflect.Type;
019: import java.util.List;
020: import java.util.Map;
021: import java.util.Set;
022:
023: import javax.servlet.http.HttpServletRequest;
024:
025: import org.apache.commons.logging.Log;
026: import org.apache.commons.logging.LogFactory;
027: import org.apache.struts.action.ActionErrors;
028: import org.apache.struts.action.ActionForm;
029: import org.apache.struts.action.ActionMapping;
030: import org.apache.struts.action.ActionMessage;
031: import org.strecks.converter.ConversionState;
032: import org.strecks.exceptions.ApplicationRuntimeException;
033: import org.strecks.util.ReflectHelper;
034: import org.strecks.validator.Validator;
035: import org.strecks.validator.internal.MethodValidators;
036: import org.strecks.validator.internal.OrderedProperty;
037: import org.strecks.validator.internal.ValidationInfo;
038: import org.strecks.validator.internal.ValidatorWrapper;
039:
040: /**
041: * Default implementation of <code>ValidationHandler</code>. Validates annotations first, then
042: * calls wrapped form's <code>validate()</code> method, merging the results in a returned
043: * <code>ActionErrors</code> object.
044: * @author Phil Zoio
045: */
046: public class DefaultValidationStrategy implements ValidationHandler {
047:
048: private static Log log = LogFactory
049: .getLog(DefaultValidationStrategy.class);
050:
051: public ActionErrors validate(ValidationInfo validationInfo,
052: ActionForm form, ActionMapping mapping,
053: HttpServletRequest request,
054: Map<String, Object> convertedValues) {
055:
056: Map<OrderedProperty, MethodValidators> validators = validationInfo
057: .getValidators();
058:
059: ActionErrors actionErrors = null;
060: Set<OrderedProperty> keySet = validators.keySet();
061:
062: for (OrderedProperty orderedProperty : keySet) {
063:
064: String propertyName = orderedProperty.getPropertyName();
065:
066: MethodValidators methodValidators = validators
067: .get(orderedProperty);
068:
069: Object convertedValue = null;
070: if (methodValidators.getRequiresConversion()) {
071: if (convertedValues != null) {
072: convertedValue = convertedValues.get(propertyName);
073: }
074: }
075:
076: List<ValidatorWrapper> list = methodValidators
077: .getValidators();
078:
079: boolean gotRawValue = false;
080:
081: Object rawValue = null;
082:
083: for (ValidatorWrapper wrapper : list) {
084: if (!gotRawValue) {
085: Method getter = wrapper.getGetterMethod();
086: rawValue = ReflectHelper.invokeMethod(form, getter);
087: gotRawValue = true;
088: }
089:
090: boolean validate = true;
091:
092: Validator validator = wrapper.getValidator();
093:
094: if (wrapper.getUsesConvertedValue()) {
095: if (convertedValue != null) {
096: if (convertedValue == ConversionState.FAILURE) {
097: validate = false;
098: } else if (convertedValue == ConversionState.NULL) {
099: validate = true;
100: } else {
101: validate = validate(wrapper
102: .getGetterMethod()
103: .getDeclaringClass(), propertyName,
104: convertedValue, validator);
105: }
106: }
107: } else {
108: validate = validate(wrapper.getGetterMethod()
109: .getDeclaringClass(), propertyName,
110: rawValue, validator);
111: }
112:
113: if (!validate) {
114: actionErrors = appendError(actionErrors, rawValue,
115: propertyName, wrapper);
116: break;
117: }
118: }
119: }
120:
121: ActionErrors formErrors = form.validate(mapping, request);
122:
123: if (formErrors != null) {
124: //thanks to Robin Young for this fix
125: if (actionErrors == null) {
126: actionErrors = new ActionErrors();
127: }
128: actionErrors.add(formErrors);
129: }
130:
131: return actionErrors;
132:
133: }
134:
135: private ActionErrors appendError(ActionErrors actionErrors,
136: Object rawValue, String propertyName,
137: ValidatorWrapper wrapper) {
138: List<Object> params = wrapper.getParams();
139:
140: Object[] parameters = wrapper.getParameterProvider()
141: .getParameters(rawValue, params);
142:
143: ActionMessage actionMessage = new ActionMessage(wrapper
144: .getKey(), parameters);
145: if (actionErrors == null)
146: actionErrors = new ActionErrors();
147:
148: actionErrors.add(propertyName, actionMessage);
149:
150: if (log.isDebugEnabled()) {
151: log.debug("Validation failed for property " + propertyName);
152: }
153: return actionErrors;
154: }
155:
156: @SuppressWarnings("unchecked")
157: boolean validate(Class containingClass, String propertyName,
158: Object value, Validator validator) {
159: try {
160: boolean validate = validator.validate(value);
161: return validate;
162: } catch (ClassCastException e) {
163: Class<?> sourceType = value.getClass();
164:
165: Class<? extends Validator> validatorClass = validator
166: .getClass();
167: Type[] genericTypes = ReflectHelper.getGenericTypes(
168: validatorClass, Validator.class);
169: String description = ReflectHelper
170: .getTypeArrayDescription(genericTypes);
171:
172: throw new ApplicationRuntimeException(
173: "Mismatch between parameterization type of validator: "
174: + validatorClass.getName()
175: + description
176: + ", and type of property being validated: property "
177: + propertyName + " in class "
178: + containingClass.getName() + "("
179: + sourceType + ")");
180: }
181: }
182:
183: }
|