Package com.blazebit.validation.constraint.validator

Source Code of com.blazebit.validation.constraint.validator.CheckEitherValidator

package com.blazebit.validation.constraint.validator;

import com.blazebit.validation.constraint.CheckEither;
import com.blazebit.validation.constraint.PopulationMode;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.ConstraintValidatorContext.ConstraintViolationBuilder;
import javax.validation.ConstraintViolation;
import javax.validation.Path.Node;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

public class CheckEitherValidator implements
    ConstraintValidator<CheckEither, Object> {

  private static final ValidatorFactory factory = Validation
      .buildDefaultValidatorFactory();

  private Class<?>[] value;
  private PopulationMode mode;

  /*
   * Should work with hibernate validator and apache bval, not sure about
   * other implementations
   */
  private boolean supportsConstraintComposition = true;

  @Override
  public void initialize(CheckEither constraintAnnotation) {
    value = constraintAnnotation.value();
    mode = constraintAnnotation.mode();
  }

  @Override
  public boolean isValid(Object object, ConstraintValidatorContext context) {
    if (value.length < 1) {
      return false;
    }

    final Validator validator = factory.getValidator();
    Set<ConstraintViolation<Object>> actualViolations = null;

    for (final Class<?> groupClass : value) {
      final Set<ConstraintViolation<Object>> violations = validator
          .validate(object, groupClass);

      if (violations.isEmpty()) {
        /*
         * We found a validation group that succeeds, so stop with
         * success
         */
        actualViolations = null;
        break;
      } else {
        /* Use population mode rules to preserve the needed violations */
        if (actualViolations == null || mode == PopulationMode.LAST) {
          actualViolations = new HashSet<ConstraintViolation<Object>>();
        }

        if (mode == PopulationMode.ALL
            || (mode == PopulationMode.FIRST && actualViolations
                .isEmpty()) || mode == PopulationMode.LAST) {
          actualViolations = addViolations(violations,
              actualViolations);
        }
      }
    }

    if (actualViolations != null) {
      passViolations(context, actualViolations);
      return false;
    }

    return true;
  }

  /**
   * Add the given source violations to the target set and return the target
   * set. This method will skip violations that have a property path depth
   * greater than 1.
   *
   * @param source
   * @param target
   * @return
   */
  private Set<ConstraintViolation<Object>> addViolations(
      Set<ConstraintViolation<Object>> source,
      Set<ConstraintViolation<Object>> target) {
    if (supportsConstraintComposition) {
      target.addAll(source);
      return target;
    }

    for (final Iterator<ConstraintViolation<Object>> iter = source
        .iterator(); iter.hasNext();) {
      final ConstraintViolation<Object> violation = iter.next();
      final Iterator<Node> nodeIter = violation.getPropertyPath()
          .iterator();

      /*
       * Only include violations that have no property path or just one
       * node
       */
      if (!nodeIter.hasNext()
          || (nodeIter.next() != null && !nodeIter.hasNext())) {
        target.add(violation);
      }
    }

    return target;
  }

  /**
   * Pass the given violations to the given context. This method will skip
   * violations that have a property path depth greater than 1.
   *
   * @param context
   * @param source
   */
  private void passViolations(ConstraintValidatorContext context,
      Set<ConstraintViolation<Object>> source) {
    for (final ConstraintViolation<Object> violation : source) {
      final Iterator<Node> nodeIter = violation.getPropertyPath()
          .iterator();
      final ConstraintViolationBuilder builder = context
          .buildConstraintViolationWithTemplate(violation
              .getMessageTemplate());
            ConstraintValidatorContext nodeContext;

      if (nodeIter.hasNext()) {
        StringBuilder sb = new StringBuilder(nodeIter.next().getName());

        if (supportsConstraintComposition) {
          while (nodeIter.hasNext()) {
            sb.append('.').append(nodeIter.next());
          }
        }

        builder.addNode(sb.toString()).addConstraintViolation();
      } else {
                builder.addConstraintViolation();
            }
    }
  }

}
TOP

Related Classes of com.blazebit.validation.constraint.validator.CheckEitherValidator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.