Skip to content

Commit

Permalink
HV-1055 Avoiding some loops when validating default group
Browse files Browse the repository at this point in the history
  • Loading branch information
gunnarmorling committed Feb 16, 2016
1 parent 98fe04b commit 94f4f56
Showing 1 changed file with 114 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -468,49 +468,33 @@ private <U> void validateConstraintsForDefaultGroup(ValidationContext<?> validat
for ( Class<? super U> clazz : beanMetaData.getClassHierarchy() ) {
BeanMetaData<? super U> hostingBeanMetaData = beanMetaDataManager.getBeanMetaData( clazz );
boolean defaultGroupSequenceIsRedefined = hostingBeanMetaData.defaultGroupSequenceIsRedefined();
Iterator<Sequence> defaultGroupSequence = hostingBeanMetaData.getDefaultValidationSequence( valueContext.getCurrentBean() );

Set<MetaConstraint<?>> metaConstraints = hostingBeanMetaData.getDirectMetaConstraints();

// if the current class redefined the default group sequence, this sequence has to be applied to all the class hierarchy.
if ( defaultGroupSequenceIsRedefined ) {
metaConstraints = hostingBeanMetaData.getMetaConstraints();
}
Iterator<Sequence> defaultGroupSequence = hostingBeanMetaData.getDefaultValidationSequence( valueContext.getCurrentBean() );
Set<MetaConstraint<?>> metaConstraints = hostingBeanMetaData.getMetaConstraints();

PathImpl currentPath = valueContext.getPropertyPath();

while ( defaultGroupSequence.hasNext() ) {
for ( GroupWithInheritance groupOfGroups : defaultGroupSequence.next() ) {
boolean validationSuccessful = true;

for ( Group defaultSequenceMember : groupOfGroups ) {
valueContext.setCurrentGroup( defaultSequenceMember.getDefiningClass() );
for ( MetaConstraint<?> metaConstraint : metaConstraints ) {
// HV-466, an interface implemented more than one time in the hierarchy has to be validated only one
// time. An interface can define more than one constraint, we have to check the class we are validating.
final Class<?> declaringClass = metaConstraint.getLocation().getDeclaringClass();
if ( declaringClass.isInterface() ) {
Class<?> validatedForClass = validatedInterfaces.get( declaringClass );
if ( validatedForClass != null && !validatedForClass.equals( clazz ) ) {
continue;
}
validatedInterfaces.put( declaringClass, clazz );
}

boolean tmp = validateConstraint( validationContext, valueContext, false, metaConstraint );
if ( shouldFailFast( validationContext ) ) {
return;
}
validationSuccessful = validationSuccessful && tmp;
// reset property path
valueContext.setPropertyPath( currentPath );
while ( defaultGroupSequence.hasNext() ) {
for ( GroupWithInheritance groupOfGroups : defaultGroupSequence.next() ) {
boolean validationSuccessful = true;

for ( Group defaultSequenceMember : groupOfGroups ) {
validationSuccessful = validateConstraintsForSingleDefaultGroupElement( validationContext, valueContext, validatedInterfaces, clazz,
metaConstraints, defaultSequenceMember );
}
if ( !validationSuccessful ) {
break;
}
}
if ( !validationSuccessful ) {
break;
}
}
}
// fast path in case the default group sequence hasn't been redefined
else {
Set<MetaConstraint<?>> metaConstraints = hostingBeanMetaData.getDirectMetaConstraints();
validateConstraintsForSingleDefaultGroupElement( validationContext, valueContext, validatedInterfaces, clazz, metaConstraints,
Group.DEFAULT_GROUP );
}

validationContext.markCurrentBeanAsProcessed( valueContext );

// all constraints in the hierarchy has been validated, stop validation.
Expand All @@ -520,6 +504,37 @@ private <U> void validateConstraintsForDefaultGroup(ValidationContext<?> validat
}
}

private <U> boolean validateConstraintsForSingleDefaultGroupElement(ValidationContext<?> validationContext, ValueContext<U, Object> valueContext, final Map<Class<?>, Class<?>> validatedInterfaces,
Class<? super U> clazz, Set<MetaConstraint<?>> metaConstraints, Group defaultSequenceMember) {
boolean validationSuccessful = true;

valueContext.setCurrentGroup( defaultSequenceMember.getDefiningClass() );
PathImpl currentPath = valueContext.getPropertyPath();

for ( MetaConstraint<?> metaConstraint : metaConstraints ) {
// HV-466, an interface implemented more than one time in the hierarchy has to be validated only one
// time. An interface can define more than one constraint, we have to check the class we are validating.
final Class<?> declaringClass = metaConstraint.getLocation().getDeclaringClass();
if ( declaringClass.isInterface() ) {
Class<?> validatedForClass = validatedInterfaces.get( declaringClass );
if ( validatedForClass != null && !validatedForClass.equals( clazz ) ) {
continue;
}
validatedInterfaces.put( declaringClass, clazz );
}

boolean tmp = validateConstraint( validationContext, valueContext, false, metaConstraint );
if ( shouldFailFast( validationContext ) ) {
return false;
}

validationSuccessful = validationSuccessful && tmp;
// reset property path
valueContext.setPropertyPath( currentPath );
}
return validationSuccessful;
}

private void validateConstraintsForNonDefaultGroup(ValidationContext<?> validationContext, ValueContext<?, Object> valueContext) {
BeanMetaData<?> beanMetaData = beanMetaDataManager.getBeanMetaData( valueContext.getCurrentBeanType() );
PathImpl currentPath = valueContext.getPropertyPath();
Expand Down Expand Up @@ -1002,63 +1017,34 @@ private <U> int validatePropertyForDefaultGroup(ValueContext<U, Object> valueCon
for ( Class<? super U> clazz : beanMetaData.getClassHierarchy() ) {
BeanMetaData<? super U> hostingBeanMetaData = beanMetaDataManager.getBeanMetaData( clazz );
boolean defaultGroupSequenceIsRedefined = hostingBeanMetaData.defaultGroupSequenceIsRedefined();
Set<MetaConstraint<?>> metaConstraints = hostingBeanMetaData.getDirectMetaConstraints();
Iterator<Sequence> defaultGroupSequence = hostingBeanMetaData.getDefaultValidationSequence( valueContext.getCurrentBean() );

if ( defaultGroupSequenceIsRedefined ) {
metaConstraints = hostingBeanMetaData.getMetaConstraints();
}
Iterator<Sequence> defaultGroupSequence = hostingBeanMetaData.getDefaultValidationSequence( valueContext.getCurrentBean() );
Set<MetaConstraint<?>> metaConstraints = hostingBeanMetaData.getMetaConstraints();

while ( defaultGroupSequence.hasNext() ) {
for ( GroupWithInheritance groupOfGroups : defaultGroupSequence.next() ) {
boolean validationSuccessful = true;

while ( defaultGroupSequence.hasNext() ) {
for ( GroupWithInheritance groupOfGroups : defaultGroupSequence.next() ) {
boolean validationSuccessful = true;

for ( Group groupClass : groupOfGroups ) {
valueContext.setCurrentGroup( groupClass.getDefiningClass() );
for ( MetaConstraint<?> metaConstraint : metaConstraints ) {
// HV-466, an interface implemented more than one time in the hierarchy has to be validated only one
// time. An interface can define more than one constraint, we have to check the class we are validating.
final Class<?> declaringClass = metaConstraint.getLocation().getDeclaringClass();
if ( declaringClass.isInterface() ) {
Class<?> validatedForClass = validatedInterfaces.get( declaringClass );
if ( validatedForClass != null && !validatedForClass.equals( clazz ) ) {
continue;
}
validatedInterfaces.put( declaringClass, clazz );
}

if ( constraintList.contains( metaConstraint ) ) {
boolean tmp = validateConstraint( validationContext, valueContext, true, metaConstraint );

validationSuccessful = validationSuccessful && tmp;
if ( shouldFailFast( validationContext ) ) {
return validationContext.getFailingConstraints()
.size() - numberOfConstraintViolationsBefore;
}
}

if ( typeUseConstraints.contains( metaConstraint ) ) {
boolean tmp = validatePropertyTypeConstraint(
validationContext,
valueContext,
true,
metaConstraint
);
validationSuccessful = validationSuccessful && tmp;
if ( shouldFailFast( validationContext ) ) {
return validationContext.getFailingConstraints()
.size() - numberOfConstraintViolationsBefore;
}
}
for ( Group groupClass : groupOfGroups ) {
validationSuccessful = validatePropertyForSingleDefaultGroupElement( valueContext, validationContext, constraintList,
typeUseConstraints, validatedInterfaces, clazz, metaConstraints, groupClass );
}
}

if ( !validationSuccessful ) {
break;
if ( !validationSuccessful ) {
break;
}
}
}
}
// fast path in case the default group sequence hasn't been redefined
else {
Set<MetaConstraint<?>> metaConstraints = hostingBeanMetaData.getDirectMetaConstraints();

validatePropertyForSingleDefaultGroupElement( valueContext, validationContext, constraintList,
typeUseConstraints, validatedInterfaces, clazz, metaConstraints, Group.DEFAULT_GROUP );
}

// all the hierarchy has been validated, stop validation.
if ( defaultGroupSequenceIsRedefined ) {
break;
Expand All @@ -1067,6 +1053,51 @@ private <U> int validatePropertyForDefaultGroup(ValueContext<U, Object> valueCon
return validationContext.getFailingConstraints().size() - numberOfConstraintViolationsBefore;
}

private <U> boolean validatePropertyForSingleDefaultGroupElement(ValueContext<U, Object> valueContext, ValidationContext<?> validationContext,
List<MetaConstraint<?>> constraintList, List<MetaConstraint<?>> typeUseConstraints,
final Map<Class<?>, Class<?>> validatedInterfaces, Class<? super U> clazz, Set<MetaConstraint<?>> metaConstraints,
Group groupClass) {
valueContext.setCurrentGroup( groupClass.getDefiningClass() );
boolean validationSuccessful =true;

for ( MetaConstraint<?> metaConstraint : metaConstraints ) {
// HV-466, an interface implemented more than one time in the hierarchy has to be validated only one
// time. An interface can define more than one constraint, we have to check the class we are validating.
final Class<?> declaringClass = metaConstraint.getLocation().getDeclaringClass();
if ( declaringClass.isInterface() ) {
Class<?> validatedForClass = validatedInterfaces.get( declaringClass );
if ( validatedForClass != null && !validatedForClass.equals( clazz ) ) {
continue;
}
validatedInterfaces.put( declaringClass, clazz );
}

if ( constraintList.contains( metaConstraint ) ) {
boolean tmp = validateConstraint( validationContext, valueContext, true, metaConstraint );

validationSuccessful = validationSuccessful && tmp;
if ( shouldFailFast( validationContext ) ) {
return false;
}
}

if ( typeUseConstraints.contains( metaConstraint ) ) {
boolean tmp = validatePropertyTypeConstraint(
validationContext,
valueContext,
true,
metaConstraint
);
validationSuccessful = validationSuccessful && tmp;
if ( shouldFailFast( validationContext ) ) {
return false;
}
}
}

return validationSuccessful;
}

private <T> void validateParametersInContext(ValidationContext<T> validationContext,
Object[] parameterValues,
ValidationOrder validationOrder) {
Expand Down

0 comments on commit 94f4f56

Please sign in to comment.