/**
   * Validates the given nested property bean (sub-bean).
   *
   * @param root The root of the object graph that is being validated.
   * @param subBean The given nested property value (the sub-bean).
   * @param propertyName The name of the array property.
   * @param errors The {@link Errors} instance where all validation errors will be registered.
   * @param validatedObjects A registry of all objects that were already validated.
   */
  protected void validatedSubBean(
      Object root, Object subBean, String propertyName, Errors errors, Set validatedObjects) {

    errors.pushNestedPath(propertyName);
    validateObjectGraphConstraints(root, subBean, errors, validatedObjects);
    errors.popNestedPath();
  }
  /**
   * Applies all validation rules as defined in the {@link
   * org.springmodules.validation.bean.conf.BeanValidationConfiguration} retrieved for the given
   * bean from the configured {@link
   * org.springmodules.validation.bean.conf.loader.BeanValidationConfigurationLoader}.
   *
   * @see Validator#validate(Object, org.springframework.validation.Errors)
   */
  public void validate(Object obj, Errors errors) {

    // validation the object graph using the class validation manager.
    validateObjectGraphConstraints(obj, obj, errors, new HashSet());

    // applying the registered validation rules.
    super.validate(obj, errors);
  }
  /**
   * Validates the elements of the given array property.
   *
   * @param root The root of the object graph that is being validated.
   * @param array The given array.
   * @param propertyName The name of the array property.
   * @param errors The {@link Errors} instance where all validation errors will be registered.
   * @param validatedObjects A registry of all objects that were already validated.
   */
  protected void validateArrayProperty(
      Object root, Object array, String propertyName, Errors errors, Set validatedObjects) {

    for (int i = 0; i < Array.getLength(array); i++) {
      String nestedPath = propertyName + PROPERTY_KEY_PREFIX + i + PROPERTY_KEY_SUFFIX;
      errors.pushNestedPath(nestedPath);
      validateObjectGraphConstraints(root, Array.get(array, i), errors, validatedObjects);
      errors.popNestedPath();
    }
  }
  /**
   * Validates the elements of the given list or set property.
   *
   * @param root The root of the object graph that is being validated.
   * @param collection The given list or set.
   * @param propertyName The name of the array property.
   * @param errors The {@link Errors} instance where all validation errors will be registered.
   * @param validatedObjects A registry of all objects that were already validated.
   */
  protected void validateListOrSetProperty(
      Object root,
      Collection collection,
      String propertyName,
      Errors errors,
      Set validatedObjects) {

    int i = 0;
    for (Iterator iter = collection.iterator(); iter.hasNext(); ) {
      Object element = iter.next();
      String nestedPath = propertyName + PROPERTY_KEY_PREFIX + i + PROPERTY_KEY_SUFFIX;
      errors.pushNestedPath(nestedPath);
      validateObjectGraphConstraints(root, element, errors, validatedObjects);
      errors.popNestedPath();
      i++;
    }
  }
 /**
  * Validates the elements within the given map property.
  *
  * @param root The root of the object graph that is being validated.
  * @param map The given map or set.
  * @param propertyName The name of the array property.
  * @param errors The {@link Errors} instance where all validation errors will be registered.
  * @param validatedObjects A registry of all objects that were already validated.
  */
 protected void validateMapProperty(
     Object root, Map map, String propertyName, Errors errors, Set validatedObjects) {
   for (Iterator entries = map.entrySet().iterator(); entries.hasNext(); ) {
     Entry entry = (Entry) entries.next();
     Object key = entry.getKey();
     if (!(key instanceof String)) {
       // skipping validation of elements that are mapped to non-string keys for there is no proper
       // representation of such elements as property path.
       continue;
     }
     Object value = entry.getValue();
     String nestedPath =
         propertyName + PROPERTY_KEY_PREFIX + String.valueOf(key) + PROPERTY_KEY_SUFFIX;
     errors.pushNestedPath(nestedPath);
     validateObjectGraphConstraints(root, value, errors, validatedObjects);
     errors.popNestedPath();
   }
 }