/**
   * Validates the Bean Validation constraints specified at the parameters and/or return value of
   * the intercepted constructor.
   *
   * @param ctx The context of the intercepted constructor invocation.
   * @throws Exception Any exception caused by the intercepted constructor invocation. A {@link
   *     ConstraintViolationException} in case at least one constraint violation occurred either
   *     during parameter or return value validation.
   */
  @AroundConstruct
  public void validateConstructorInvocation(InvocationContext ctx) throws Exception {
    ExecutableValidator executableValidator = validator.forExecutables();
    Set<? extends ConstraintViolation<?>> violations =
        executableValidator.validateConstructorParameters(
            ctx.getConstructor(), ctx.getParameters());

    if (!violations.isEmpty()) {
      throw new ConstraintViolationException(
          getMessage(ctx.getConstructor(), ctx.getParameters(), violations), violations);
    }

    ctx.proceed();
    Object createdObject = ctx.getTarget();

    violations =
        validator
            .forExecutables()
            .validateConstructorReturnValue(ctx.getConstructor(), createdObject);

    if (!violations.isEmpty()) {
      throw new ConstraintViolationException(
          getMessage(ctx.getConstructor(), ctx.getParameters(), violations), violations);
    }
  }
  @Test
  public void shouldUnwrapParameterValueBasedOnProgrammaticConfiguration() throws Exception {
    HibernateValidatorConfiguration configuration = ValidatorUtil.getConfiguration();
    ConstraintMapping mapping = configuration.createConstraintMapping();
    mapping
        .type(OrderLine.class)
        .method("setId", Property.class)
        .parameter(0)
        .unwrapValidatedValue(true);

    Validator validator =
        configuration
            .addMapping(mapping)
            .addValidatedValueHandler(new PropertyValueUnwrapper())
            .buildValidatorFactory()
            .getValidator();

    OrderLine orderLine = new OrderLine();
    Method method = OrderLine.class.getMethod("setId", Property.class);
    Object[] parameterValues = new Object[] {new Property<Long>(0L)};

    Set<ConstraintViolation<OrderLine>> violations =
        validator.forExecutables().validateParameters(orderLine, method, parameterValues);

    assertEquals(violations.size(), 1);
  }
  @Test
  public void shouldUnwrapPropertyValuesDuringReturnValueValidation() throws Exception {
    Customer customer = new Customer();
    Method method = Customer.class.getMethod("retrieveName");
    Property<String> returnValue = new Property<String>("Bob");

    Set<ConstraintViolation<Customer>> violations =
        validator.forExecutables().validateReturnValue(customer, method, returnValue);

    assertEquals(violations.size(), 1);
  }
  @Test
  public void shouldUnwrapPropertyValuesDuringParameterValidation() throws Exception {
    Customer customer = new Customer();
    Method method = Customer.class.getMethod("setName", Property.class);
    Object[] parameterValues = new Object[] {new Property<String>("Bob")};

    Set<ConstraintViolation<Customer>> violations =
        validator.forExecutables().validateParameters(customer, method, parameterValues);

    assertEquals(violations.size(), 1);
  }
  @Test
  public void shouldRaiseConstraintsViolationCauseTitleAndPriceNull() throws NoSuchMethodException {

    ExecutableValidator methodValidator = validator.forExecutables();
    Constructor<Book03> constructor =
        Book03.class.getConstructor(
            String.class, Float.class, String.class, String.class, Integer.class, Boolean.class);
    Set<ConstraintViolation<Book03>> violations =
        methodValidator.validateConstructorParameters(
            constructor, new Object[] {null, null, null, null, null, null});
    displayContraintViolations(violations);
    assertEquals(2, violations.size());
  }
  @Test
  public void shouldRaiseNoConstraintViolation() throws NoSuchMethodException {

    ExecutableValidator methodValidator = validator.forExecutables();
    Constructor<Book03> constructor =
        Book03.class.getConstructor(
            String.class, Float.class, String.class, String.class, Integer.class, Boolean.class);
    Set<ConstraintViolation<Book03>> violations =
        methodValidator.validateConstructorParameters(
            constructor,
            new Object[] {"H2G2", 12.5f, "Best IT Scifi Book", "1234-4566-9876", 247, false});
    assertEquals(0, violations.size());
  }
  /**
   * Validates the Bean Validation constraints specified at the parameters and/or return value of
   * the intercepted method.
   *
   * @param ctx The context of the intercepted method invocation.
   * @return The result of the method invocation.
   * @throws Exception Any exception caused by the intercepted method invocation. A {@link
   *     ConstraintViolationException} in case at least one constraint violation occurred either
   *     during parameter or return value validation.
   */
  @AroundInvoke
  public Object validateMethodInvocation(InvocationContext ctx) throws Exception {
    ExecutableValidator executableValidator = validator.forExecutables();
    Set<ConstraintViolation<Object>> violations =
        executableValidator.validateParameters(
            ctx.getTarget(), ctx.getMethod(), ctx.getParameters());

    if (!violations.isEmpty()) {
      throw new ConstraintViolationException(
          getMessage(ctx.getMethod(), ctx.getParameters(), violations), violations);
    }

    Object result = ctx.proceed();

    violations = executableValidator.validateReturnValue(ctx.getTarget(), ctx.getMethod(), result);

    if (!violations.isEmpty()) {
      throw new ConstraintViolationException(
          getMessage(ctx.getMethod(), ctx.getParameters(), violations), violations);
    }

    return result;
  }
 @Override
 public ExecutableValidator forExecutables() {
   return delegate.forExecutables();
 }