/** * This validator supports only those classes that are supported by the validation configuration * loader it uses. * * @see org.springmodules.validation.bean.RuleBasedValidator#supports(Class) * @see * org.springmodules.validation.bean.conf.loader.BeanValidationConfigurationLoader#supports(Class) */ public boolean supports(Class clazz) { return configurationLoader.supports(clazz) || super.supports(clazz); }
/** * The heart of this validator. This is a recursive method that validates the given object * (object) under the context of the given object graph root (root). The validation rules to be * applied are loaded using the configured {@link * org.springmodules.validation.bean.conf.loader.BeanValidationConfigurationLoader}. All errors * are registered with the given {@link Errors} object under the context of the object graph root. * * @param root The root of the object graph. * @param obj The object to be validated * @param errors The {@link Errors} instance where the validation errors will be registered. * @param validatedObjects keeps track of all the validated objects (to prevent revalidating the * same objects when a circular relationship exists). */ protected void validateObjectGraphConstraints( Object root, Object obj, Errors errors, Set validatedObjects) { // cannot load any validation rules for null values if (obj == null) { return; } // if this object was already validated, the skipping this valiation. if (validatedObjects.contains(obj)) { if (logger.isDebugEnabled()) { logger.debug( "Skipping validation of object in path '" + errors.getObjectName() + "' for it was already validated"); } return; } if (logger.isDebugEnabled()) { logger.debug("Validating object in path '" + errors.getNestedPath() + "'"); } // loading the bean validation configuration based on the validated object class. Class clazz = obj.getClass(); BeanValidationConfiguration configuration = configurationLoader.loadConfiguration(clazz); if (configuration == null) { return; // no validation configuration for this object, then there's nothing to validate. } // applying all the validation rules for the object and registering the object as "validated" applyBeanValidation(configuration, obj, errors); validatedObjects.add(obj); // after all the validation rules where applied, checking what properties of the object require // their own // validation and recursively calling this method on them. CascadeValidation[] cascadeValidations = configuration.getCascadeValidations(); BeanWrapper wrapper = wrapBean(obj); for (int i = 0; i < cascadeValidations.length; i++) { CascadeValidation cascadeValidation = cascadeValidations[i]; Condition applicabilityCondition = cascadeValidation.getApplicabilityCondition(); if (!applicabilityCondition.check(obj)) { continue; } String propertyName = cascadeValidation.getPropertyName(); Class propertyType = wrapper.getPropertyType(propertyName); Object propertyValue = wrapper.getPropertyValue(propertyName); // if the property value is not there nothing to validate. if (propertyValue == null) { continue; } // if the property is an array of a collection, then iterating on it and validating each // element. Note that // the error codes that are registered for arrays/collection elements follow the pattern // supported by // spring's PropertyAccessor. Also note that just before each recursive call, the context of // the validation // is appropriately adjusted using errors.pushNestedPath(...), and after each call it is being // adjusted back // using errors.popNestedPath(). if (propertyType.isArray()) { validateArrayProperty(root, propertyValue, propertyName, errors, validatedObjects); } else if (List.class.isAssignableFrom(propertyType) || Set.class.isAssignableFrom(propertyType)) { validateListOrSetProperty( root, (Collection) propertyValue, propertyName, errors, validatedObjects); } else if (Map.class.isAssignableFrom(propertyType)) { validateMapProperty(root, ((Map) propertyValue), propertyName, errors, validatedObjects); } else { // if the object is just a normal object (not an array or a collection), then applying its // validation rules. validatedSubBean(root, propertyValue, propertyName, errors, validatedObjects); } } }