<div dir="auto"><div><br><div class="gmail_extra"><br><div class="gmail_quote">On Jun 21, 2017 2:58 AM, &quot;Gunnar Morling&quot; &lt;<a href="mailto:gunnar@hibernate.org">gunnar@hibernate.org</a>&gt; wrote:<br type="attribution"><blockquote class="quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="quoted-text">&gt; My thinking was to make it possible for a user to configure container<br>
&gt; element constraints for various levels of the inheritance hierarchy<br>
&gt; for a given e.g. method return type. So continuing the lookup example,<br>
&gt; perhaps we want to constrain the key of a LookupTable only for<br>
&gt; LookupImpl and not for every implementation of ILookup.<br>
<br>
</div>Ah, got you.<br>
<br>
I don&#39;t think it&#39;s something we should support really, as it&#39;d abandon<br>
the symmetry of capabilities of annotations and XML. For such use<br>
case, LookupImpl#getLookup() should declare a return type of Map&lt;...,<br>
...&gt; itself, so container element constraints can be applied via<br>
&lt;beanClass class=&quot;LookupImpl&quot;&gt;...&lt;/<wbr>beanClass&gt;.<br>
<div class="elided-text"></div></blockquote></div></div></div><div dir="auto"><br></div><div dir="auto">I suppose allowing a particular XML class configuration to target a superclass method in the suggested manner would confer an advantage not available to the annotation based config. Let&#39;s finish it up then. :-)</div><div dir="auto"><br></div><div dir="auto">Matt</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="elided-text"><br>
2017-06-20 22:36 GMT+02:00 Matt Benson &lt;<a href="mailto:mbenson@apache.org">mbenson@apache.org</a>&gt;:<br>
&gt; On Tue, Jun 20, 2017 at 8:04 AM, Gunnar Morling &lt;<a href="mailto:gunnar@hibernate.org">gunnar@hibernate.org</a>&gt; wrote:<br>
&gt;&gt; 2017-06-19 17:50 GMT+02:00 Matt Benson &lt;<a href="mailto:mbenson@apache.org">mbenson@apache.org</a>&gt;:<br>
&gt;&gt;&gt; On Mon, Jun 19, 2017 at 8:04 AM, Gunnar Morling &lt;<a href="mailto:gunnar@hibernate.org">gunnar@hibernate.org</a>&gt; wrote:<br>
&gt;&gt;&gt;&gt; Hi,<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; Putting constraints to type parameters of generic types or methods as<br>
&gt;&gt;&gt;&gt; well as putting constraints to type arguments in extends/implements<br>
&gt;&gt;&gt;&gt; clauses isn&#39;t supported as of BV 2.0. I thought that&#39;s mentioned<br>
&gt;&gt;&gt;&gt; somewhere in the spec, but couldn&#39;t find it during a quick check. If<br>
&gt;&gt;&gt;&gt; it&#39;s indeed missing, I&#39;ll add it. We can look into this for 2.1 of<br>
&gt;&gt;&gt;&gt; course.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; I&#39;m pretty sure wildcards are explicitly mentioned as not being<br>
&gt;&gt;&gt; supported, and bounds are mentioned there. I don&#39;t remember type vars<br>
&gt;&gt;&gt; being included in that. You say &quot;as of BV 2.0.&quot; Can I take that to<br>
&gt;&gt;&gt; mean that you think it&#39;s at least possible that this might be<br>
&gt;&gt;&gt; something the spec should support in the future? Is this basically a<br>
&gt;&gt;&gt; case of limiting feature creep so that we can finish this iteration<br>
&gt;&gt;&gt; ASAP?<br>
&gt;&gt;<br>
&gt;&gt; Yes, it&#39;s definitely something we can consider to support in a future<br>
&gt;&gt; revision. But for BV 2.0 it&#39;s too late to add it, as I&#39;ll have to<br>
&gt;&gt; submit the Proposed Final Draft tomorrow or say latest Thursday. While<br>
&gt;&gt; we can do some more adjustments until Final Approval Ballot, this may<br>
&gt;&gt; only be corrections and clarifications of already added stuff at this<br>
&gt;&gt; point unfortunately.<br>
&gt;&gt;<br>
&gt;&gt; For sure we should explore this on the implementation level, so we<br>
&gt;&gt; have some experiences already when starting to work on the next spec<br>
&gt;&gt; revision.<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; I also suspect that it will make sense to introduce a &lt;container&gt;<br>
&gt;&gt;&gt;&gt;&gt; element to the XML mapping schema with an optional type, to<br>
&gt;&gt;&gt;&gt;&gt; (optionally?) house the &lt;container-element-type&gt; elements.<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; If we&#39;ve established that the ContainerElementType needs the container<br>
&gt;&gt;&gt; type to be certain of providing enough information to locate the<br>
&gt;&gt;&gt; relevant value extractor, then consider the XML mapping. Say we have:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; interface ILookup {<br>
&gt;&gt;&gt;   Map&lt;String, String&gt; getLookup();<br>
&gt;&gt;&gt; }<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; class LookupTable extends Hashtable&lt;String, String&gt; {<br>
&gt;&gt;&gt; }<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; class LookupImpl implements ILookup {<br>
&gt;&gt;&gt;   private LookupTable lookupTable;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;   LookupTable getLookup() {<br>
&gt;&gt;&gt;     return lookupTable;<br>
&gt;&gt;&gt;   }<br>
&gt;&gt;&gt; }<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; And we want to constrain the type parameters of the Map in XML:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; &lt;bean class=&quot;ILookup&quot;&gt;<br>
&gt;&gt;&gt;   &lt;getter name=&quot;getLookup&quot;&gt;<br>
&gt;&gt;&gt;     &lt;!-- TBD --&gt;<br>
&gt;&gt;&gt;   &lt;/getter&gt;<br>
&gt;&gt;&gt; &lt;/bean&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; We could do:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; &lt;container-element-type container-type=&quot;java.util.Map&quot; type-argument-index=&quot;0&quot;&gt;<br>
&gt;&gt;&gt;   &lt;constraint annotation=&quot;NotNull&quot; /&gt;<br>
&gt;&gt;&gt;   &lt;constraint annotation=&quot;NotBlank&quot; /&gt;<br>
&gt;&gt;&gt; &lt;/container-element-type&gt;<br>
&gt;&gt;&gt; &lt;container-element-type container-type=&quot;java.util.Map&quot; type-argument-index=&quot;1&quot;&gt;<br>
&gt;&gt;&gt;   &lt;constraint annotation=&quot;NotBlank&quot; /&gt;<br>
&gt;&gt;&gt; &lt;/container-element-type&gt;<br>
&gt;&gt;<br>
&gt;&gt; I don&#39;t think there&#39;s a need to specify the container type in this<br>
&gt;&gt; case, as this can be obtained from the configured field, method etc.<br>
&gt;&gt; So for configuring ILookup#getLookup(), it&#39;d look like this with the<br>
&gt;&gt; currently proposed schema:<br>
&gt;&gt;<br>
&gt;&gt;     &lt;bean class=&quot;ILookup&quot;&gt;<br>
&gt;&gt;         &lt;getter name=&quot;lookup&quot;&gt;<br>
&gt;&gt;             &lt;container-element-type type-argument-index=&quot;0&quot;&gt;<br>
&gt;&gt;                 &lt;constraint annotation=&quot;NotNull&quot; /&gt;<br>
&gt;&gt;                 &lt;constraint annotation=&quot;NotBlank&quot; /&gt;<br>
&gt;&gt;             &lt;/container-element-type&gt;<br>
&gt;&gt;             &lt;container-element-type type-argument-index=&quot;1&quot;&gt;<br>
&gt;&gt;                 &lt;constraint annotation=&quot;NotBlank&quot; /&gt;<br>
&gt;&gt;             &lt;/container-element-type&gt;<br>
&gt;&gt;         &lt;/getter&gt;<br>
&gt;&gt;     &lt;/bean&gt;<br>
&gt;&gt;<br>
&gt;&gt; I.e. this is about Map&lt;String, String&gt; as that&#39;s the type of<br>
&gt;&gt; ILookup#getLookup().<br>
&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; ... and for simplicity&#39;s sake, since the typical container likely has<br>
&gt;&gt;&gt; a single element type, we probably should continue to support this.<br>
&gt;&gt;&gt; But should we also allow, e.g.:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; &lt;container type=&quot;java.util.Map&quot;&gt;<br>
&gt;&gt;&gt;   &lt;container-element-type type-argument-index=&quot;0&quot;&gt;<br>
&gt;&gt;&gt;     &lt;constraint annotation=&quot;NotNull&quot; /&gt;<br>
&gt;&gt;&gt;     &lt;constraint annotation=&quot;NotBlank&quot; /&gt;<br>
&gt;&gt;&gt;   &lt;/container-element-type&gt;<br>
&gt;&gt;&gt;   &lt;container-element-type type-argument-index=&quot;1&quot;&gt;<br>
&gt;&gt;&gt;     &lt;constraint annotation=&quot;NotBlank&quot; /&gt;<br>
&gt;&gt;&gt;   &lt;/container-element-type&gt;<br>
&gt;&gt;&gt; &lt;/container-type&gt;<br>
&gt;&gt;<br>
&gt;&gt; I think it&#39;s answered by my previous comment?<br>
&gt;&gt;<br>
&gt;<br>
&gt; My thinking was to make it possible for a user to configure container<br>
&gt; element constraints for various levels of the inheritance hierarchy<br>
&gt; for a given e.g. method return type. So continuing the lookup example,<br>
&gt; perhaps we want to constrain the key of a LookupTable only for<br>
&gt; LookupImpl and not for every implementation of ILookup. Given the time<br>
&gt; issue though we can leave this alone for now.<br>
&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; WRT the optionality of the type argument index, it&#39;s clear that for<br>
&gt;&gt;&gt; containers with a single element type, that could be omitted. Is it<br>
&gt;&gt;&gt; further intended that where the list of container-element-type<br>
&gt;&gt;&gt; elements has a length matching the number of type variables declared<br>
&gt;&gt;&gt; on the container type, these should be understood to specify a 1:1<br>
&gt;&gt;&gt; ordered correspondence? If so, is there a place (and hopefully a more<br>
&gt;&gt;&gt; intelligible way ;) ) to clarify that in the spec?<br>
&gt;&gt;<br>
&gt;&gt; That behaviour is not intended. I don&#39;t like the idea of relying on<br>
&gt;&gt; ordering, as it&#39;d require you to specify (empty) container element<br>
&gt;&gt; type nodes for all type arguments, also if only one is to be<br>
&gt;&gt; constrained.<br>
&gt;&gt;<br>
&gt;&gt; That&#39;s what we currently say in the spec:<br>
&gt;&gt;<br>
&gt;&gt;     &quot;The type-argument-index is used to specify the index of the<br>
&gt;&gt; configured type argument. The type-argument-index can be omitted, if<br>
&gt;&gt; the container element type has exactly one type argument. [...] If an<br>
&gt;&gt; invalid container type element configuration is detected, a<br>
&gt;&gt; ValidationException is raised. This includes the following<br>
&gt;&gt; configuration errors:<br>
&gt;&gt;<br>
&gt;&gt;     * The type of the surrounding element (field, getter etc.) has no<br>
&gt;&gt; type arguments.<br>
&gt;&gt;     * The type of the surrounding element has no type argument with<br>
&gt;&gt; the index given via type-argument-index.<br>
&gt;&gt;     * The type of the surrounding element has multiple type arguments<br>
&gt;&gt; and no index is given via type-argument-index.<br>
&gt;&gt;     * The same type argument of the surrounding element is configured<br>
&gt;&gt; multiple times.&quot;<br>
&gt;&gt;<br>
&gt;&gt; Do you think this is clear enough or should we change the wording in some way?<br>
&gt;&gt;<br>
&gt;<br>
&gt; Seems okay to me.<br>
&gt;<br>
&gt; Matt<br>
&gt;<br>
&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Matt<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; Could you elaborate on that point a bit? What exactly is the use case for this?<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; --Gunnar<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; 2017-06-18 17:34 GMT+02:00 Matt Benson &lt;<a href="mailto:mbenson@apache.org">mbenson@apache.org</a>&gt;:<br>
&gt;&gt;&gt;&gt;&gt; More thoughts in this vein:<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; At first I thought that method overrides were the only place you might<br>
&gt;&gt;&gt;&gt;&gt; have &gt; 1 container class represented, but why wouldn&#39;t we support<br>
&gt;&gt;&gt;&gt;&gt; e.g.:<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; class Roles implements Set&lt;@NotEmpty String&gt; {<br>
&gt;&gt;&gt;&gt;&gt; ...<br>
&gt;&gt;&gt;&gt;&gt; }<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; ? Then it&#39;d be possible to extract container elements even at the bean level.<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; Next, consider parameters. the spec currently says that wildcards<br>
&gt;&gt;&gt;&gt;&gt; aren&#39;t supported, but what about:<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; &lt;X extends Set&lt;@NotEmpty String&gt; &amp; Iterable&lt;@NotNull String&gt;&gt; void foo(X);<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; In this way a parameter could expose multiple container types (pretend<br>
&gt;&gt;&gt;&gt;&gt; I used unrelated interfaces if that helps). We could save generic<br>
&gt;&gt;&gt;&gt;&gt; extends support for a future iteration of the spec, but semantically<br>
&gt;&gt;&gt;&gt;&gt; it makes sense to me so I&#39;d expect we&#39;ll eventually have to do it in<br>
&gt;&gt;&gt;&gt;&gt; any case. I suppose you could even do fields if you annotated some<br>
&gt;&gt;&gt;&gt;&gt; type parameter of the bean.<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; I also suspect that it will make sense to introduce a &lt;container&gt;<br>
&gt;&gt;&gt;&gt;&gt; element to the XML mapping schema with an optional type, to<br>
&gt;&gt;&gt;&gt;&gt; (optionally?) house the &lt;container-element-type&gt; elements.<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; Matt<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; On Fri, Jun 16, 2017 at 1:38 PM, Gunnar Morling &lt;<a href="mailto:gunnar@hibernate.org">gunnar@hibernate.org</a>&gt; wrote:<br>
&gt;&gt;&gt;&gt;&gt;&gt; 2017-06-16 14:06 GMT+02:00 Matt Benson &lt;<a href="mailto:mbenson@apache.org">mbenson@apache.org</a>&gt;:<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt; On Fri, Jun 16, 2017 at 2:43 AM, Gunnar Morling &lt;<a href="mailto:gunnar@hibernate.org">gunnar@hibernate.org</a>&gt; wrote:<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; Hi Matt,<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; Thanks for bringing this up!<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; I think adding ContainerElementTypeDescriptor<wbr>#getContainerClass() is<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; one thing needed, but it&#39;s not enough. Currently we have<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; List&lt;<wbr>ContainerElementTypeDescriptor<wbr>&gt; getContainerElementTypes() on<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; PropertyDescriptor etc. which returns the container element<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; descriptors in the order of type arguments. This also doesn&#39;t really<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; fit for User#getRoles().<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; So we could make this a Set&lt;<wbr>ContainerElementTypeDescriptor<wbr>&gt; instead,<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; and then each element from that set exposes containerClass and<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; typeArgumentIndex as you suggest.<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; It&#39;s getting a bit tricky though to get the effective set of all<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; container element constraints. Eg. say we have:<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;     public interface IUserBase {<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;         Set&lt;@NotBlank String&gt; getRoles();<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;     }<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;     public interface IUser extends IUserBase {<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;         Set&lt;@NotEmpty String&gt; getRoles();<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;     }<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;     public class UserImpl implements IUser {<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;         Roles getRoles();<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;     }<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; Then when querying<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;     validator.<wbr>getConstraintsForClass( IUser.class )<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;         .getConstraintsForProperty( &quot;roles&quot; )<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;         .getContainerElementTypes();<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; We&#39;d get a set with these elements:<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;     - ContainerElementDescriptor(<wbr>containerClass=IUser.class,<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; typeArgumentIndex=0, constraints={(type=NotEmpty,<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; defined=DEFINED_LOCALLY), (type=NotBlank,<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; defined=DEFINED_IN_HIERARCHY)}<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;     - ContainerElementDescriptor(<wbr>containerClass=User.class,<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; typeArgumentIndex=0, constraints={(type=NotBlank, defined=<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; DEFINED_LOCALLY)}<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt; I was thinking that the containerClass would be Set.class.<br>
&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt; Yes, you are right of course.<br>
&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; The descriptor for IUser would have to return the inherited @NotBlank<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; as per the defined semantics of getConstraintDescriptors(). So one<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; would have to examine all ContainerElementDescriptors and just collect<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; the ones that are DEFINED_LOCALLY to have the effective set without<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; duplicates.<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt; I agree that the set of ContainerElementTypeDescriptor<wbr>s needs to be<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt; reduced to unique type parameters, but I&#39;m not sure I&#39;m following your<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt; argument above. My suggestion above (containerClass=Set.class) would<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt; give an easy way to identify what needs to be collapsed where: onto<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt; Set&lt;[0]&gt;. Consider this:<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt; public class Roles&lt;S extends System&gt; implements Set&lt;String&gt; {<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;   public S getSystem() {<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;     ...<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;   }<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;   ...<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt; }<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt; public class UserImpl implements IUser {<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;   public Roles&lt;@ValidSystem UserSystem&gt; getRoles() {<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;     ...<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;   }<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt; }<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt; Here Roles would implement a custom container type on top of Iterable<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt; via Set, so the method would return separate ContainerTypeElements for<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt; Roles&lt;[0]&gt; and Set&lt;[0]&gt;. Does that make sense?<br>
&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt; Yes, it does.<br>
&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt; And in my previous example we&#39;d have getContainerElementTypes() return<br>
&gt;&gt;&gt;&gt;&gt;&gt; a set with one descriptor:<br>
&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt; ContainerElementDescriptor(<wbr>containerClass=Set.class,<br>
&gt;&gt;&gt;&gt;&gt;&gt; typeArgumentIndex=0, constraints={(type=NotEmpty, defined=<br>
&gt;&gt;&gt;&gt;&gt;&gt; DEFINED_IN_HIERARCHY), (type=NotBlank, defined=DEFINED_IN_HIERARCHY)}<br>
&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt; (both constraints are defined in the hierarchy from the perspective of UserImpl)<br>
&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt; Matt<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; The alternative would be to explicitly redeclare<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; getConstraintDescriptors() for ContainerElementDescriptor and say that<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; it doesn&#39;t expose constraints from the hierarchy. But this would make<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; it very difficult for the user to find all those constraints applying<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; to a given container element type (esp. as type arguments could switch<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; their order in the hierarchy). So that&#39;d not be my preferred route.<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; WDYT?<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; I&#39;ve filed <a href="https://hibernate.atlassian.net/browse/BVAL-655" rel="noreferrer" target="_blank">https://hibernate.atlassian.<wbr>net/browse/BVAL-655</a> for this issue.<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; --Gunnar<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; 2017-06-15 17:38 GMT+02:00 Matt Benson &lt;<a href="mailto:mbenson@apache.org">mbenson@apache.org</a>&gt;:<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; The various descriptor types return constraint information from the<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; entire hierarchy by default. However, in thinking about this I quickly<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; encountered a puzzle which I cannot solve using the current version of<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; the specification. Consider:<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; public interface User {<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;   Set&lt;@NotEmpty String&gt; getRoles();<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; }<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; public class Roles implements Set&lt;String&gt; {<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;  ...<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; }<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; public class UserImpl implements User {<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;   @Override<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;   public Roles getRoles();<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; }<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; What should the metadata of UserImpl provide? The Iterable value<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; extractor is applicable to Roles, but because the return value of the<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; getter has been narrowed, there is no type parameter at this point in<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; the hierarchy. It seems strange for a PropertyDescriptor of type Roles<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; to return a ContainerElementTypeDescriptor with index 0. This example<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; would AFAICT apply to e.g. javafx StringProperty as well, so it&#39;s<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; probably a question we need to resolve, unless I have missed something<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; that should be obvious. I think this could be solved if the CETD were<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; to explicitly specify the type with which its argument index is<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; associated. The alternative would be to require a custom<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; ValueExtractor? This seems cumbersome and unnecessary.<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; Thanks,<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; Matt<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; ______________________________<wbr>_________________<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; beanvalidation-dev mailing list<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; <a href="mailto:beanvalidation-dev@lists.jboss.org">beanvalidation-dev@lists.<wbr>jboss.org</a><br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; <a href="https://lists.jboss.org/mailman/listinfo/beanvalidation-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/<wbr>mailman/listinfo/<wbr>beanvalidation-dev</a><br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; ______________________________<wbr>_________________<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; beanvalidation-dev mailing list<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; <a href="mailto:beanvalidation-dev@lists.jboss.org">beanvalidation-dev@lists.<wbr>jboss.org</a><br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; <a href="https://lists.jboss.org/mailman/listinfo/beanvalidation-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/<wbr>mailman/listinfo/<wbr>beanvalidation-dev</a><br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt; ______________________________<wbr>_________________<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt; beanvalidation-dev mailing list<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt; <a href="mailto:beanvalidation-dev@lists.jboss.org">beanvalidation-dev@lists.<wbr>jboss.org</a><br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt; <a href="https://lists.jboss.org/mailman/listinfo/beanvalidation-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/<wbr>mailman/listinfo/<wbr>beanvalidation-dev</a><br>
&gt;&gt;&gt;&gt;&gt;&gt; ______________________________<wbr>_________________<br>
&gt;&gt;&gt;&gt;&gt;&gt; beanvalidation-dev mailing list<br>
&gt;&gt;&gt;&gt;&gt;&gt; <a href="mailto:beanvalidation-dev@lists.jboss.org">beanvalidation-dev@lists.<wbr>jboss.org</a><br>
&gt;&gt;&gt;&gt;&gt;&gt; <a href="https://lists.jboss.org/mailman/listinfo/beanvalidation-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/<wbr>mailman/listinfo/<wbr>beanvalidation-dev</a><br>
&gt;&gt;&gt;&gt;&gt; ______________________________<wbr>_________________<br>
&gt;&gt;&gt;&gt;&gt; beanvalidation-dev mailing list<br>
&gt;&gt;&gt;&gt;&gt; <a href="mailto:beanvalidation-dev@lists.jboss.org">beanvalidation-dev@lists.<wbr>jboss.org</a><br>
&gt;&gt;&gt;&gt;&gt; <a href="https://lists.jboss.org/mailman/listinfo/beanvalidation-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/<wbr>mailman/listinfo/<wbr>beanvalidation-dev</a><br>
&gt;&gt;&gt;&gt; ______________________________<wbr>_________________<br>
&gt;&gt;&gt;&gt; beanvalidation-dev mailing list<br>
&gt;&gt;&gt;&gt; <a href="mailto:beanvalidation-dev@lists.jboss.org">beanvalidation-dev@lists.<wbr>jboss.org</a><br>
&gt;&gt;&gt;&gt; <a href="https://lists.jboss.org/mailman/listinfo/beanvalidation-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/<wbr>mailman/listinfo/<wbr>beanvalidation-dev</a><br>
&gt;&gt;&gt; ______________________________<wbr>_________________<br>
&gt;&gt;&gt; beanvalidation-dev mailing list<br>
&gt;&gt;&gt; <a href="mailto:beanvalidation-dev@lists.jboss.org">beanvalidation-dev@lists.<wbr>jboss.org</a><br>
&gt;&gt;&gt; <a href="https://lists.jboss.org/mailman/listinfo/beanvalidation-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/<wbr>mailman/listinfo/<wbr>beanvalidation-dev</a><br>
&gt;&gt; ______________________________<wbr>_________________<br>
&gt;&gt; beanvalidation-dev mailing list<br>
&gt;&gt; <a href="mailto:beanvalidation-dev@lists.jboss.org">beanvalidation-dev@lists.<wbr>jboss.org</a><br>
&gt;&gt; <a href="https://lists.jboss.org/mailman/listinfo/beanvalidation-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/<wbr>mailman/listinfo/<wbr>beanvalidation-dev</a><br>
&gt; ______________________________<wbr>_________________<br>
&gt; beanvalidation-dev mailing list<br>
&gt; <a href="mailto:beanvalidation-dev@lists.jboss.org">beanvalidation-dev@lists.<wbr>jboss.org</a><br>
&gt; <a href="https://lists.jboss.org/mailman/listinfo/beanvalidation-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/<wbr>mailman/listinfo/<wbr>beanvalidation-dev</a><br>
______________________________<wbr>_________________<br>
beanvalidation-dev mailing list<br>
<a href="mailto:beanvalidation-dev@lists.jboss.org">beanvalidation-dev@lists.<wbr>jboss.org</a><br>
<a href="https://lists.jboss.org/mailman/listinfo/beanvalidation-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/<wbr>mailman/listinfo/<wbr>beanvalidation-dev</a><br>
</div></blockquote></div><br></div></div></div>