-
Notifications
You must be signed in to change notification settings - Fork 578
HV-1623 Build an abstraction over reflection in engine code #963
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
NOTE to myself: address this - #949 (comment) |
914ae77
to
f7d2382
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @marko-bekhta ,
I pushed a few cleanup commits and changes. It would be nice if you could review them.
I also added a few comments, the biggest issue being the property / field / getter thing. It's the last big area that needs improving in this patch IMHO. AFAICS, Gunnar had the same doubts as me so let's tackle this.
Apart from that, and my other more minor comments, I think we are very near being in a commitable state.
@@ -17,15 +16,15 @@ | |||
*/ | |||
class ConstructorConstraintMappingContextImpl extends ExecutableConstraintMappingContextImpl implements ConstructorConstraintMappingContext { | |||
|
|||
<T> ConstructorConstraintMappingContextImpl(TypeConstraintMappingContextImpl<T> typeContext, Constructor<T> constructor) { | |||
<T> ConstructorConstraintMappingContextImpl(TypeConstraintMappingContextImpl<T> typeContext, Callable constructor) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still have my reservations about not making Constructor
a thing. Typically, I did it in the java bean part in one of my commit. I think it wouldn't be bad to have this distinction.
@@ -17,15 +16,15 @@ | |||
*/ | |||
class MethodConstraintMappingContextImpl extends ExecutableConstraintMappingContextImpl implements MethodConstraintMappingContext { | |||
|
|||
MethodConstraintMappingContextImpl(TypeConstraintMappingContextImpl<?> typeContext, Method method) { | |||
super( typeContext, method ); | |||
MethodConstraintMappingContextImpl(TypeConstraintMappingContextImpl<?> typeContext, Callable callable) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And I would also make Method
a thing.
@@ -64,17 +57,17 @@ protected PropertyConstraintMappingContextImpl getThis() { | |||
|
|||
@Override | |||
public PropertyConstraintMappingContext constraint(ConstraintDef<?, ?> definition) { | |||
if ( member instanceof Field ) { | |||
if ( property instanceof JavaBeanField ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our abstraction doesn't work very well here.
That's why I'm not a big fan of merging field and getters so early and not being able to have a distinction between them at the base layer (by base, I mean Property
, Callable
and so on).
TBH, considering the behavior is entirely different, I'm not a big fan of this class. Note that the issue was preexisting, it's not something you introduced.
this.cascadingMetaData = cascadingMetaData; | ||
this.constraintLocationKind = property instanceof JavaBeanField ? ConstraintLocationKind.PROPERTY : ConstraintLocationKind.METHOD; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't have to rely on JavaBeanField
here.
That will probably change if we reintroduce the difference between getters and properties. Frankly, I would really like to be able to follow the path of a getter and understand how it's specific.
If we end up still having to do that, I think we should have a ConstrainedElementKind getConstrainedElementKind()
in Constrainable
(instead of Callable
). That might help for other spots too.
CONSTRUCTOR( ElementType.CONSTRUCTOR ), | ||
METHOD( ElementType.METHOD ), | ||
PARAMETER( ElementType.PARAMETER ), | ||
PROPERTY( ElementType.FIELD ), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So it's used for getters + fields?
*/ | ||
ConstraintLocationKind getKind(); | ||
|
||
enum ConstraintLocationKind { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wondering if we should move this one into a separate file as it's now a first class citizen.
@@ -47,7 +47,7 @@ | |||
* @author Gunnar Morling | |||
*/ | |||
enum ConstrainedElementKind { | |||
TYPE, FIELD, CONSTRUCTOR, METHOD, PARAMETER | |||
TYPE, CONSTRUCTOR, METHOD, PARAMETER, PROPERTY |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So that means PROPERTY
is used for getters and fields, I suppose?
We would have to check this wrt the other changes regarding getter + field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey, this ties in a bit with my recent comment: the "raw" model was not meant to do abstractions from actual elements (fields, getters etc.). Adding PROPERTY
to ConstraintElementKind
blurries that line. I didn't look into the entire PR, so perhaps it makes sense, but I wanted to bring up that it appears as quite some deviation from the existing abstractions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 that's the same problem. Will work on it :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gunnarmorling yup, we are well aware of the issue. That's the big thing that still needs fixing in this PR.
@@ -136,7 +149,7 @@ private static Field getAccessible(Field original) { | |||
|
|||
/** | |||
* Runs the given privileged action, using a privileged block if required. | |||
* <p> | |||
* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should remove this.
@@ -146,7 +127,7 @@ private static Method getAccessible(Method original) { | |||
|
|||
/** | |||
* Runs the given privileged action, using a privileged block if required. | |||
* <p> | |||
* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here. IMHO a quick check of the diff is in order :).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gsmet you beat me to it with all new changes :) I've just looked through and added a couple questions/comments. Thanks!
@@ -39,7 +39,6 @@ | |||
private final Map<String, Object> messageParameters; | |||
private final Map<String, Object> expressionVariables; | |||
private final Class<T> rootBeanClass; | |||
private final ElementType elementType; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've remembered what I wanted to ask about this commit :) I was just curious why we had ElementType
in here in the first place ? Everything else in here looks fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No idea tbh. Probably a leftover of some sort.
|
||
TypeVariable<?>[] getTypeParameters(); | ||
|
||
<A extends Annotation> A getAnnotation(Class<A> annotationClass); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how about using Optional here? or would it be inconsistent with the rest of the code in, I suspect, AnnotationMetaDataProvider
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made it consistent with the reflection API. I think it's good enough as it is.
@@ -88,6 +76,11 @@ public String getParameterName(ExecutableParameterNameProvider parameterNameProv | |||
return declaringClass; | |||
} | |||
|
|||
@Override | |||
public ConstrainedElementKind getConstrainedElementKind() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that JavaBeanMethod
already returns the same element kind. Do we need to override it here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
@@ -83,60 +107,67 @@ public Type getType() { | |||
} | |||
|
|||
@Override | |||
public Class<?>[] getParameterTypes() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one was hard to read 😄
@@ -63,6 +66,31 @@ public String getPropertyName() { | |||
return getName(); | |||
} | |||
|
|||
@Override | |||
public AnnotatedType getAnnotatedType() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like these changes. We don't expose the reflection Member
from these classes and annotation provider got cleaner. Only question left - should we iterate once more and hide the annotations as well ? I had such idea at first but discarded it till later times. I was thinking about moving all this logic of finding constraints into these org.hibernate.validator.internal.properties.javabean.*
classes that would make the AnnotationMetaDataProvider
much smaller. And also "hide" the reflection even more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now, I don't think we should hide the reflection from AnnotationMetaDataProvider
: it's tied to Java beans anyway. Maybe we will need to do it later but I think it can be kept for another day.
} | ||
|
||
@Override | ||
public Class<?> getDeclaringClass() { | ||
return executable.getDeclaringClass(); | ||
return callable.getDeclaringClass(); | ||
} | ||
|
||
@Override | ||
public Constrainable getMember() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe let's rename the method as well? getConstrainable()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
As for this part:
I agree. That's why I also left that ^ note to myself to fix things. It might be that we'd need to find a better name instead of a property. Right now we represent getters as methods all the way till the aggregation of the metadata. Hence using 'field' would be a better approach, but I'm not sure if these classes/enum values with property in the name are not also needed for non java bean types. I'll try to check that later today and will get back to you. |
f7d2382
to
9d4d486
Compare
Just force-pushed an update to fix the unused import issue. |
9d4d486
to
6b119f8
Compare
@marko-bekhta fixed the issues you raised. I'm done with my changes now. As for the naming, I think I would go with property = field + getter. And be consistent with it all the way. I would also try to make the getter case clearer than before. It's full of special cases everywhere about it being a method or a property, it's kinda confusing IMHO. |
Ok, thanks! Maybe let me know once it's sorted out and I could take another
look.
|
@gunnarmorling I'll ping you before we merge this one so that you can take a look if you want. |
Excellent, thanks!
|
6b119f8
to
4c8d377
Compare
0902c7e
to
730323b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@marko-bekhta nice progress, I added a couple of comments (one is hidden but it's still something to take into account).
Thanks!
* @author Guillaume Smet | ||
* @author Marko Bekhta | ||
*/ | ||
public class ClassLevelMetaData extends AbstractConstraintMetaData { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for this change.
I would call it ClassMetaData
though, considering we don't have the Level
part for the others.
* | ||
* @author Marko Bekhta | ||
*/ | ||
public class ClassLevelDescriptorImpl extends ElementDescriptorImpl implements ElementDescriptor { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here about removing the Level
part.
@Override | ||
public String toString() { | ||
final StringBuilder sb = new StringBuilder(); | ||
sb.append( "ClassLevelDescriptorImpl" ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use getClass().getSimpleName()
here to avoid future inconsistencies.
import org.hibernate.validator.internal.util.TypeResolutionHelper; | ||
|
||
/** | ||
* Constraint mapping creational context implementation {@link PropertyConstraintMappingContextImpl} for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a word missing or a typo here.
import org.hibernate.validator.internal.util.TypeResolutionHelper; | ||
|
||
/** | ||
* Constraint mapping creational context implementation {@link PropertyConstraintMappingContextImpl} for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
else { | ||
throw LOG.getUnexpectedElementType( elementType, ElementType.FIELD, ElementType.METHOD ); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we should deprecate property(String property, ElementType type)
and introduce field()
and getter()
. That would be more in line with what we do in the XML.
Then I would instantiate directly FieldPropertyConstraintMappingContextImpl
and GetterPropertyConstraintMappingContextImpl
in those methods and disambiguate the types and throw the exception in the deprecated property()
.
That if we take the road of having a specific DSL for JSON. My opinion is that it will be better. WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Applied the change in the last commit. As for the JSON and all that "free-form validation" I'd say that as a lot of stuff there would be different and probably tagged as @Incubating
we'd better separate these things. We already know that cascading would be different and for properties we need to pass a property type.
@@ -149,7 +150,7 @@ public MethodConstraintMappingContext method(String name, Class<?>... parameterT | |||
throw LOG.getBeanDoesNotContainMethodException( beanClass, name, parameterTypes ); | |||
} | |||
|
|||
JavaBeanExecutable<?> javaBeanExecutable = JavaBeanExecutable.of( method ); | |||
JavaBeanMethod javaBeanExecutable = (JavaBeanMethod) JavaBeanExecutable.of( method ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mmmh, let's instantiate a JavaBeanMethod
directly with the constructor instead of casting then :)
And let's call the variable javaBeanMethod
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as method here can be either method or getter we couldn't just use a constructor hence I've added an overloaded version of JavaBeanExecutable#of()
one takes Method
and returns JavaBeanMethod
which might also be a getter, and the other one is the one that we already have that can also handle constructors.
730323b
to
b6f913d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@marko-bekhta great work. Added a couple of comments on your last commit.
* <p> | ||
* Until this method is called constraints apply on class level. After calling this method constraints | ||
* apply on the specified field property. | ||
* </p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't ask me why but in the javadoc, we don't close the <p>
, we only open a new one when needed.
* A given field may only be configured once. | ||
* </p> | ||
* | ||
* @param property The field name, that represents a property on which to apply the following constraints. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor nitpicking: no comma here, that
directly qualifies the field name
.
|
||
@Override | ||
public PropertyConstraintMappingContext field(String property) { | ||
Contracts.assertNotNull( property, "The property name must not be null." ); | ||
Contracts.assertNotEmpty( property, MESSAGES.propertyNameMustNotBeEmpty() ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I would instead change Contracts.assertNotEmpty()
to use StringHelper.isNullOrEmptyString()
.
* @param property The field name, that represents a property on which to apply the following constraints. | ||
* | ||
* @return A creational context representing the selected field property. | ||
* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's remove this line.
* to apply the following constraints. | ||
* | ||
* @return A creational context representing the selected getter property. | ||
* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's remove this line.
* </p> | ||
* | ||
* @param property The getter property name (Java Bean notation), that represents a property on which | ||
* to apply the following constraints. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a4e97df
to
74c7d49
Compare
@@ -133,8 +133,7 @@ public PropertyConstraintMappingContext property(String property, ElementType el | |||
|
|||
@Override | |||
public PropertyConstraintMappingContext field(String property) { | |||
Contracts.assertNotNull( property, "The property name must not be null." ); | |||
Contracts.assertNotEmpty( property, MESSAGES.propertyNameMustNotBeEmpty() ); | |||
Contracts.assertNeitherNullNorEmpty( property, MESSAGES.propertyNameMustBeNeitherNullNorEmpty() ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hum, sorry if I wasn't clear but I did expect you to only change the method content, not the method name or the message.
Being not empty implies being not null. See NotEmptyValidatorForCharSequence
for instance :).
52471dd
to
0b0438e
Compare
@gsmet that's good. I've added one more commit for naming consistency - it should probably be squashed either into your naming commit or maybe into the first one? As for the |
- based on the usage of the method we cannot receive methods into it, hence the check can be removed. And also the method can be named more specific to represent what it is really should be doing.
- changed Constrainable to Property to better represent the intended objects to be processed by the builder - removed unused parameters, fields and methods
… field - create different implementations of PropertyConstraintMappingContextImpl for getter and field to separate the logic.
…) and getter() instead - add two new methods field() and getter() to replace deprecated property() - update property constraint mapping implementations to use generics and get rid of casting objects
… the same time - based on our usage of not empty check passed parameters should not be null as well hence the implementation of the check can use StringHelper.isNullOrEmptyString utility method.
We don't need the elements to be typed so let's be looser to open the gate for JSON properties (which will probably simply be treated as fields).
…s in property metadata - need to throw an exception rather than just create it - removed the usage of Optional as it isn't needed anymore
8f68c33
to
0332e6c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That looks pretty cool! A few comments inline! Apart from the comment API change I don't see anything critical, we'll see how the abstraction works once adding another (non-JavaBeans) implementation.
*/ | ||
@Deprecated |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gsmet While I agree that the two new methods are nicer, I'm unsure whether it's worth the API change (hazzle with WildFly etc.).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Btw. one advantage of the original form was that it'll also better work with models that don't distinguish between fields/getters (HV-1000). In that case we could think of either accepting null for type
(or simply ignoring whatever is passed) or add an overload property(String name)
. So it feels we're limiting ourselves with this change a little bit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I agree that the two new methods are nicer, I'm unsure whether it's worth the API change (hazzle with WildFly etc.).
The old method is still there, it's marked as deprecated.
Btw. one advantage of the original form was that it'll also better work with models that don't distinguish between fields/getters (HV-1000).
The original form was misleading because there is indeed a difference in treatment between fields and getters and they are totally different beasts.
As for HV-1000 (which is one of the ultimate goals of this PR), there's a good chance the programmatic API entry points will be different (mostly because we will have to define the type for cascaded validation) so we will be able to have a property()
.
If we end up reusing the same API classes, then we will unmark property()
as deprecated but I still think keeping getter()
and field()
makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gunnarmorling from what we have right now for json and maps, PropertyTarget
for new programmatic mapping has just this method:
public interface PropertyTarget {
PropertyConstraintMappingContext property(String property, Class<?> propertyType);
}
as we need to pass the type of the property. Otherwise we would have all the info to create Property
. Passing this type also serves as a type validation which I think is a nice bonus :).
So most likely we will end up adding another method anyway.
Having those two shortcuts for field and getter is consistent with what we have for XML configuration (that's what we talked with @gsmet about). Hence if there might be issues with deprecation of property()
maybe we should leave it as is also but keep the two shortcuts ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The old method is still there, it's marked as deprecated.
Understood, but the goal of deprecation is removal, no? Feel free do it if you think it's worth it, to me it doesn't necessarily appear that way (given all the discussions we had in the past...).
As for HV-1000 [...] entry points will be different
Mh, I see. I was hoping that wouldn't be the case.
so we will be able to have a property().
I see.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Understood, but the goal of deprecation is removal, no?
Maybe at some point. But I agree we might just keep the method here forever.
To be honest, it's more to be clear than getters and fields should be different from the get to and to offer similar APIs for programmatic API and XML definition.
Object value, | ||
Path propertyPath, | ||
ConstraintDescriptor<?> constraintDescriptor, | ||
Object dynamicPayload) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks :)
|
||
@Override | ||
public String toString() { | ||
return "ClassLevelMetaData [type=" + getType() + "]]"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/ClassLevelMetaData/ClassMetaData/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@marko-bekhta see, that's why I want us to use getClass().getSimpleName()
:)
Fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And I trusted IDEA to be good with such kind of refactorings!!! 😄 Thanks!
return annotationIgnoredForMembers.get( member ); | ||
public boolean areMemberConstraintsIgnoredFor(Constrainable constrainable) { | ||
Class<?> clazz = constrainable.getDeclaringClass(); | ||
if ( annotationIgnoredForMembers.containsKey( constrainable ) ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer to get()
once and then check on null, so to avoid one lookup.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, this is a bit outside the scope of this PR as it's preexisting.
I opened https://hibernate.atlassian.net/browse/HV-1631. Will push an additional commit with this change.
if ( annotationIgnoresForReturnValues.containsKey( member ) ) { | ||
return annotationIgnoresForReturnValues.get( member ); | ||
public boolean areReturnValueConstraintsIgnoredFor(Constrainable constrainable) { | ||
if ( annotationIgnoresForReturnValues.containsKey( constrainable ) ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
|
||
boolean isPrivate(); | ||
|
||
String getSignature(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose that's for logging only?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not only. The signature is used a mean to identify the executable in various parts of the code.
/** | ||
* @author Marko Bekhta | ||
*/ | ||
public interface Constrainable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A class-level comment would be nice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
String getName(); | ||
|
||
Class<?> getDeclaringClass(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't this break the "abstraction"? I.e. what to return for a JSON type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mmmh, yes it does. I think @marko-bekhta had in mind to provide a PropertyHolder
class here or something similar.
The class is used in some portions of the code where it's not really easy to abstract from it.
Let's see how it goes with the JSON PR and act accordingly.
I created https://hibernate.atlassian.net/browse/HV-1632 where I describe the challenges. It's really not a simple matter.
/** | ||
* @author Marko Bekhta | ||
*/ | ||
public interface ConstrainableType { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this doing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now, nothing. I think Marko wanted a common interface for the JavaBean
and the upcoming PropertyHolder
.
Let's add a comment.
And it's merged! @marko-bekhta thanks for the hard work on this one. @gunnarmorling thanks for the review. |
this is an "abstraction" part of this PR #938
there are a few more clean up commits added on top of the existing changes in the mentioned PR.
As for the last commit that wraps
ElementType
- I am not very happy about it and I'll be looking into changing it. Initially I wanted to useConstraintLocation
to determineElementType
needed for calls like this - https://github.com/hibernate/hibernate-validator/blob/master/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java#L1282-L1287 but then there's this usage https://github.com/hibernate/hibernate-validator/blob/master/engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ElementDescriptorImpl.java#L145 ofElementType
from constraint descriptors which I didn't know about and it broke the initial approach on this :) But I plan to revisit this idea once more and try to clean things up in this area ofElementType
usage.