try {
final MetaBean initialMetaBean = new DynamicMetaBean(metaBeanFinder);
initialMetaBean.setBeanClass(beanType);
GroupValidationContext<T> context = createContext(initialMetaBean, object, beanType, groups);
ValidationContextTraversal contextTraversal = createValidationContextTraversal(context);
PathNavigation.navigate(propertyName, contextTraversal);
MetaProperty prop = context.getMetaProperty();
boolean fixed = false;
if (value != VALIDATE_PROPERTY) {
assert !context.getPropertyPath().isRootPath();
if (prop == null && value != null) {
context.setMetaBean(metaBeanFinder.findForClass(value.getClass()));
}
if (!cascade) {
//TCK doesn't care what type a property is if there are no constraints to validate:
FeaturesCapable meta = prop == null ? context.getMetaBean() : prop;
if (ArrayUtils.isEmpty(meta.getValidations())) {
return Collections.<ConstraintViolation<T>> emptySet();
}
}
if (!TypeUtils.isAssignable(value == null ? null : value.getClass(), contextTraversal.getType())) {
throw new IncompatiblePropertyValueException(String.format(
"%3$s is not a valid value for property %2$s of type %1$s", beanType, propertyName, value));
}
if (prop == null) {
context.setBean(value);
} else {
context.setFixedValue(value);
fixed = true;
}
}
boolean doCascade = cascade && (prop == null || prop.getMetaBean() != null);
Object bean = context.getBean();
ConstraintValidationListener<T> result = context.getListener();
Groups sequence = context.getGroups();
// 1. process groups
for (Group current : sequence.getGroups()) {
context.setCurrentGroup(current);
if (!doCascade || prop != null) {
validatePropertyInGroup(context);
}
if (doCascade) {
contextTraversal.moveDownIfNecessary();
if (context.getMetaBean() instanceof DynamicMetaBean) {
context.setMetaBean(context.getMetaBean().resolveMetaBean(
ObjectUtils.defaultIfNull(context.getBean(), contextTraversal.getRawType())));
}
validateBeanNet(context);
if (prop != null) {
context.moveUp(bean, prop.getParentMetaBean());
context.setMetaProperty(prop);
if (fixed) {
context.setFixedValue(value);
}
}
}
}
// 2. process sequences
int groupViolations = result.getConstraintViolations().size();
outer: for (List<Group> eachSeq : sequence.getSequences()) {
for (Group current : eachSeq) {
context.setCurrentGroup(current);
if (!doCascade || prop != null) {
validatePropertyInGroup(context);
}
if (doCascade) {
contextTraversal.moveDownIfNecessary();
if (context.getMetaBean() instanceof DynamicMetaBean) {
context.setMetaBean(context.getMetaBean().resolveMetaBean(
ObjectUtils.defaultIfNull(context.getBean(), contextTraversal.getRawType())));
}
validateBeanNet(context);
if (prop != null) {
context.moveUp(bean, prop.getParentMetaBean());
context.setMetaProperty(prop);