Skip to content

Commit

Permalink
HV-1763 Switch to a string less approach for signature generation
Browse files Browse the repository at this point in the history
  • Loading branch information
gsmet committed Apr 10, 2020
1 parent 011614e commit 13a1e41
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 54 deletions.
Expand Up @@ -36,6 +36,7 @@
import org.hibernate.validator.internal.metadata.descriptor.ExecutableDescriptorImpl;
import org.hibernate.validator.internal.metadata.facets.Cascadable;
import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind;
import org.hibernate.validator.internal.properties.Signature;
import org.hibernate.validator.internal.util.CollectionHelper;
import org.hibernate.validator.internal.util.ExecutableHelper;
import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper;
Expand Down Expand Up @@ -100,14 +101,14 @@ public final class BeanMetaDataImpl<T> implements BeanMetaData<T> {
* meta-data will be stored).
*/
@Immutable
private final Map<String, ExecutableMetaData> executableMetaDataMap;
private final Map<Signature, ExecutableMetaData> executableMetaDataMap;

/**
* The set of unconstrained executables of the bean. It contains all the relevant signatures, following the same
* rules as {@code executableMetaDataMap}.
*/
@Immutable
private final Set<String> unconstrainedExecutables;
private final Set<Signature> unconstrainedExecutables;

/**
* Property meta data keyed against the property name
Expand Down Expand Up @@ -181,7 +182,7 @@ public BeanMetaDataImpl(Class<T> beanClass,
Set<PropertyMetaData> propertyMetaDataSet = newHashSet();

Set<ExecutableMetaData> executableMetaDataSet = newHashSet();
Set<String> tmpUnconstrainedExecutables = newHashSet();
Set<Signature> tmpUnconstrainedExecutables = newHashSet();

boolean hasConstraints = false;
Set<MetaConstraint<?>> allMetaConstraints = newHashSet();
Expand Down Expand Up @@ -302,7 +303,7 @@ public Set<MetaConstraint<?>> getDirectMetaConstraints() {

@Override
public Optional<ExecutableMetaData> getMetaDataFor(Executable executable) {
String signature = ExecutableHelper.getSignature( executable );
Signature signature = ExecutableHelper.getSignature( executable );

if ( unconstrainedExecutables.contains( signature ) ) {
return Optional.empty();
Expand Down Expand Up @@ -357,21 +358,22 @@ public List<Class<? super T>> getClassHierarchy() {
}

private static BeanDescriptor createBeanDescriptor(Class<?> beanClass, Set<MetaConstraint<?>> allMetaConstraints,
Map<String, PropertyMetaData> propertyMetaDataMap, Map<String, ExecutableMetaData> executableMetaDataMap, boolean defaultGroupSequenceRedefined,
Map<String, PropertyMetaData> propertyMetaDataMap, Map<Signature, ExecutableMetaData> executableMetaDataMap,
boolean defaultGroupSequenceRedefined,
List<Class<?>> resolvedDefaultGroupSequence) {
Map<String, PropertyDescriptor> propertyDescriptors = getConstrainedPropertiesAsDescriptors(
propertyMetaDataMap,
defaultGroupSequenceRedefined,
resolvedDefaultGroupSequence
);

Map<String, ExecutableDescriptorImpl> methodsDescriptors = getConstrainedMethodsAsDescriptors(
Map<Signature, ExecutableDescriptorImpl> methodsDescriptors = getConstrainedMethodsAsDescriptors(
executableMetaDataMap,
defaultGroupSequenceRedefined,
resolvedDefaultGroupSequence
);

Map<String, ConstructorDescriptor> constructorsDescriptors = getConstrainedConstructorsAsDescriptors(
Map<Signature, ConstructorDescriptor> constructorsDescriptors = getConstrainedConstructorsAsDescriptors(
executableMetaDataMap,
defaultGroupSequenceRedefined,
resolvedDefaultGroupSequence
Expand Down Expand Up @@ -414,9 +416,10 @@ private static Map<String, PropertyDescriptor> getConstrainedPropertiesAsDescrip
return theValue;
}

private static Map<String, ExecutableDescriptorImpl> getConstrainedMethodsAsDescriptors(Map<String, ExecutableMetaData> executableMetaDataMap,
private static Map<Signature, ExecutableDescriptorImpl> getConstrainedMethodsAsDescriptors(
Map<Signature, ExecutableMetaData> executableMetaDataMap,
boolean defaultGroupSequenceIsRedefined, List<Class<?>> resolvedDefaultGroupSequence) {
Map<String, ExecutableDescriptorImpl> constrainedMethodDescriptors = newHashMap();
Map<Signature, ExecutableDescriptorImpl> constrainedMethodDescriptors = newHashMap();

for ( ExecutableMetaData executableMetaData : executableMetaDataMap.values() ) {
if ( executableMetaData.getKind() == ElementKind.METHOD
Expand All @@ -426,7 +429,7 @@ private static Map<String, ExecutableDescriptorImpl> getConstrainedMethodsAsDesc
resolvedDefaultGroupSequence
);

for ( String signature : executableMetaData.getSignatures() ) {
for ( Signature signature : executableMetaData.getSignatures() ) {
constrainedMethodDescriptors.put( signature, descriptor );
}
}
Expand All @@ -435,9 +438,9 @@ private static Map<String, ExecutableDescriptorImpl> getConstrainedMethodsAsDesc
return constrainedMethodDescriptors;
}

private static Map<String, ConstructorDescriptor> getConstrainedConstructorsAsDescriptors(Map<String, ExecutableMetaData> executableMetaDataMap,
private static Map<Signature, ConstructorDescriptor> getConstrainedConstructorsAsDescriptors(Map<Signature, ExecutableMetaData> executableMetaDataMap,
boolean defaultGroupSequenceIsRedefined, List<Class<?>> resolvedDefaultGroupSequence) {
Map<String, ConstructorDescriptor> constrainedMethodDescriptors = newHashMap();
Map<Signature, ConstructorDescriptor> constrainedMethodDescriptors = newHashMap();

for ( ExecutableMetaData executableMetaData : executableMetaDataMap.values() ) {
if ( executableMetaData.getKind() == ElementKind.CONSTRUCTOR && executableMetaData.isConstrained() ) {
Expand Down Expand Up @@ -501,11 +504,11 @@ private Set<MetaConstraint<?>> getDirectConstraints() {
* Builds up the method meta data for this type; each meta-data entry will be stored under the signature of the
* represented method and all the methods it overrides.
*/
private Map<String, ExecutableMetaData> bySignature(Set<ExecutableMetaData> executables) {
Map<String, ExecutableMetaData> theValue = newHashMap();
private Map<Signature, ExecutableMetaData> bySignature(Set<ExecutableMetaData> executables) {
Map<Signature, ExecutableMetaData> theValue = newHashMap();

for ( ExecutableMetaData executableMetaData : executables ) {
for ( String signature : executableMetaData.getSignatures() ) {
for ( Signature signature : executableMetaData.getSignatures() ) {
theValue.put( signature, executableMetaData );
}
}
Expand Down
Expand Up @@ -31,6 +31,7 @@
import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable;
import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter;
import org.hibernate.validator.internal.properties.Callable;
import org.hibernate.validator.internal.properties.Signature;
import org.hibernate.validator.internal.util.CollectionHelper;
import org.hibernate.validator.internal.util.ExecutableHelper;
import org.hibernate.validator.internal.util.ExecutableParameterNameProvider;
Expand Down Expand Up @@ -72,7 +73,7 @@ public class ExecutableMetaData extends AbstractConstraintMetaData {
* overrides a super type method with generic parameters, in which case the signature of the super-type and the
* sub-type method will differ.
*/
private final Set<String> signatures;
private final Set<Signature> signatures;

private final ReturnValueMetaData returnValueMetaData;
private final ElementKind kind;
Expand All @@ -82,7 +83,7 @@ private ExecutableMetaData(
Type returnType,
Class<?>[] parameterTypes,
ElementKind kind,
Set<String> signatures,
Set<Signature> signatures,
Set<MetaConstraint<?>> returnValueConstraints,
Set<MetaConstraint<?>> returnValueContainerElementConstraints,
List<ParameterMetaData> parameterMetaDataList,
Expand Down Expand Up @@ -137,7 +138,7 @@ public Class<?>[] getParameterTypes() {
* method represents a sub-type method overriding a super-type method using a generic type parameter in its
* parameters.
*/
public Set<String> getSignatures() {
public Set<Signature> getSignatures() {
return signatures;
}

Expand Down Expand Up @@ -249,7 +250,7 @@ public boolean equals(Object obj) {
* @author Kevin Pollet &lt;kevin.pollet@serli.com&gt; (C) 2011 SERLI
*/
public static class Builder extends MetaDataBuilder {
private final Set<String> signatures = newHashSet();
private final Set<Signature> signatures = newHashSet();

/**
* Either CONSTRUCTOR, METHOD or GETTER.
Expand Down
Expand Up @@ -21,6 +21,7 @@
import jakarta.validation.metadata.MethodType;
import jakarta.validation.metadata.PropertyDescriptor;

import org.hibernate.validator.internal.properties.Signature;
import org.hibernate.validator.internal.util.CollectionHelper;
import org.hibernate.validator.internal.util.Contracts;
import org.hibernate.validator.internal.util.ExecutableHelper;
Expand All @@ -37,15 +38,15 @@ public class BeanDescriptorImpl extends ElementDescriptorImpl implements BeanDes
@Immutable
private final Map<String, PropertyDescriptor> constrainedProperties;
@Immutable
private final Map<String, ExecutableDescriptorImpl> constrainedMethods;
private final Map<Signature, ExecutableDescriptorImpl> constrainedMethods;
@Immutable
private final Map<String, ConstructorDescriptor> constrainedConstructors;
private final Map<Signature, ConstructorDescriptor> constrainedConstructors;

public BeanDescriptorImpl(Type beanClass,
Set<ConstraintDescriptorImpl<?>> classLevelConstraints,
Map<String, PropertyDescriptor> constrainedProperties,
Map<String, ExecutableDescriptorImpl> constrainedMethods,
Map<String, ConstructorDescriptor> constrainedConstructors,
Map<Signature, ExecutableDescriptorImpl> constrainedMethods,
Map<Signature, ConstructorDescriptor> constrainedConstructors,
boolean defaultGroupSequenceRedefined,
List<Class<?>> defaultGroupSequence) {
super( beanClass, classLevelConstraints, defaultGroupSequenceRedefined, defaultGroupSequence );
Expand Down
Expand Up @@ -31,7 +31,7 @@ public interface Callable extends Constrainable {

boolean isPrivate();

String getSignature();
Signature getSignature();

boolean overrides(ExecutableHelper executableHelper, Callable superTypeMethod);

Expand Down
@@ -0,0 +1,44 @@
/*
* Hibernate Validator, declare and validate application constraints
*
* License: Apache License, Version 2.0
* See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
*/
package org.hibernate.validator.internal.properties;

import java.util.Arrays;

public final class Signature {

private final String name;

private final Class<?>[] parameterTypes;

public Signature(String name, Class<?>... parameterTypes) {
this.name = name;
this.parameterTypes = parameterTypes;
}

@Override
public boolean equals(Object obj) {
if ( obj == null ) {
return false;
}

// we can safely assume the type will always be the right one
Signature other = (Signature) obj;

if ( !this.name.equals( other.name ) ) {
return false;
}

return Arrays.equals( this.parameterTypes, other.parameterTypes );
}

@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + Arrays.hashCode( parameterTypes );
return result;
}
}
Expand Up @@ -20,6 +20,7 @@
import java.util.List;

import org.hibernate.validator.internal.properties.Callable;
import org.hibernate.validator.internal.properties.Signature;
import org.hibernate.validator.internal.util.CollectionHelper;
import org.hibernate.validator.internal.util.ExecutableHelper;
import org.hibernate.validator.internal.util.ExecutableParameterNameProvider;
Expand Down Expand Up @@ -91,7 +92,7 @@ public boolean isPrivate() {
}

@Override
public String getSignature() {
public Signature getSignature() {
return ExecutableHelper.getSignature( executable );
}

Expand Down
Expand Up @@ -16,6 +16,7 @@
import java.security.PrivilegedAction;

import org.hibernate.validator.internal.properties.Callable;
import org.hibernate.validator.internal.properties.Signature;
import org.hibernate.validator.internal.util.classhierarchy.Filters;
import org.hibernate.validator.internal.util.logging.Log;
import org.hibernate.validator.internal.util.logging.LoggerFactory;
Expand Down Expand Up @@ -175,30 +176,12 @@ public static String getSimpleName(Executable executable) {
return executable instanceof Constructor ? executable.getDeclaringClass().getSimpleName() : executable.getName();
}

public static String getSignature(Executable executable) {
public static Signature getSignature(Executable executable) {
return getSignature( getSimpleName( executable ), executable.getParameterTypes() );
}

/**
* This method needs to be fast.
* <p>
* The purpose of it is to get uniqueness, we don't really care about prettiness.
*/
public static String getSignature(String name, Class<?>[] parameterTypes) {
StringBuilder signature = new StringBuilder( name.length() + 2 + parameterTypes.length * 25 );
signature.append( name ).append( '(' );
boolean separator = false;
for ( Class<?> parameterType : parameterTypes ) {
if ( separator ) {
signature.append( ',' );
}
else {
separator = true;
}
signature.append( parameterType.getName() );
}
signature.append( ')' );
return signature.toString();
public static Signature getSignature(String name, Class<?>[] parameterTypes) {
return new Signature( name, parameterTypes );
}

/**
Expand Down
Expand Up @@ -35,6 +35,7 @@
import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl;
import org.hibernate.validator.internal.metadata.provider.MetaDataProvider;
import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy;
import org.hibernate.validator.internal.properties.Signature;
import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper;
import org.hibernate.validator.internal.util.ExecutableHelper;
import org.hibernate.validator.internal.util.ExecutableParameterNameProvider;
Expand Down Expand Up @@ -152,7 +153,7 @@ public void getIdentifierForMethod() throws Exception {
ExecutableMetaData methodMetaData = beanMetaData.getMetaDataFor( method ).get();

assertThat( methodMetaData.getSignatures() ).containsOnly(
"createCustomer(java.lang.CharSequence,java.lang.String)"
new Signature( "createCustomer", CharSequence.class, String.class )
);
}

Expand All @@ -161,15 +162,15 @@ public void getIdentifierForParameterlessMethod() throws Exception {
Method method = CustomerRepositoryExt.class.getMethod( "foo" );
ExecutableMetaData methodMetaData = beanMetaData.getMetaDataFor( method ).get();

assertThat( methodMetaData.getSignatures() ).containsOnly( "foo()" );
assertThat( methodMetaData.getSignatures() ).containsOnly( new Signature( "foo" ) );
}

@Test
public void getIdentifierForConstructor() throws Exception {
Constructor<CustomerRepositoryExt> constructor = CustomerRepositoryExt.class.getConstructor( String.class );
ExecutableMetaData constructorMetaData = beanMetaData.getMetaDataFor( constructor ).get();

assertThat( constructorMetaData.getSignatures() ).containsOnly( "CustomerRepositoryExt(java.lang.String)" );
assertThat( constructorMetaData.getSignatures() ).containsOnly( new Signature( "CustomerRepositoryExt", String.class ) );
}

@Test
Expand All @@ -180,24 +181,24 @@ public void getIdentifierForOverridingGenericMethod() throws Exception {
ExecutableMetaData methodMetaData = beanMetaData.getMetaDataFor( method ).get();

assertThat( methodMetaData.getSignatures() )
.describedAs( "Expecting super-type and sub-type method signatures" )
.containsOnly( "createJob(java.lang.Object)", "createJob(java.util.UUID)" );
.describedAs( "Expecting super-type and sub-type method signatures" )
.containsOnly( new Signature( "createJob", Object.class ), new Signature( "createJob", UUID.class ) );

method = JobRepository.class.getMethod( "createJob", Object.class );
beanMetaData = beanMetaDataManager.getBeanMetaData( JobRepository.class );
methodMetaData = beanMetaData.getMetaDataFor( method ).get();

assertThat( methodMetaData.getSignatures() )
.describedAs( "Expecting only super-type method signature" )
.containsOnly( "createJob(java.lang.Object)" );
.containsOnly( new Signature( "createJob", Object.class ) );

method = SpecialJobRepositoryImpl.class.getMethod( "createJob", Object.class );
beanMetaData = beanMetaDataManager.getBeanMetaData( SpecialJobRepositoryImpl.class );
methodMetaData = beanMetaData.getMetaDataFor( method ).get();

assertThat( methodMetaData.getSignatures() )
.describedAs( "Expecting method signatures from super-types" )
.containsOnly( "createJob(java.lang.Object)", "createJob(java.util.UUID)" );
.containsOnly( new Signature( "createJob", Object.class ), new Signature( "createJob", UUID.class ) );
}

@Test
Expand All @@ -209,7 +210,7 @@ public void getIdentifierForOverloadedMethod() throws Exception {

assertThat( methodMetaData.getSignatures() )
.describedAs( "Expecting sub-type method signature which overloads but not overrides super-type methods" )
.containsOnly( "createJob(java.lang.String)" );
.containsOnly( new Signature( "createJob", String.class ) );
}

@Test
Expand Down

0 comments on commit 13a1e41

Please sign in to comment.