<commit_before>// Bean Validation
//
// License: Apache License, Version 2.0
// See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.

[[appendix-value-extraction]]

== Value extraction for cascaded validation and type argument constraints (BVAL-508)

This appendix describes the current work-in-progress around the retrieval of values to be validated during cascaded validation and evaluation of type argument constraints.
It is based on the original http://beanvalidation.org/proposals/BVAL-508/[proposals for BVAL-508].

=== Motivation

Value extraction is needed when constraints are applied to the element(s) stored within a container type.
There are two categories:

* Cascaded validation of iterables, maps and arrays as triggered via `@Valid`: `@Valid List<Order> orders`; in this case all the values stored in the list must be extracted so each can be validated
* Validation of type argument constraints as enabled by Java 8: `Optional<@Email String> email` or `Property<@Min(1) Integer> value`;
in this case, e.g. the wrapped `String` and `Integer` values must be extracted so the `@Email` and `@Min` constraints can be applied

Both cases can also overlap: `List<@RetailOrder @Valid Order> retailOrders`.

Type argument constraints and pluggable extractors will also make cascaded validation more flexible.
As of BV 1.1, there was a fixed set of data types supported by cascaded validation mandated by the spec (`Iterable`, arrays, `Map` (only the values would be validated).
This excludes use cases such as custom collection types (e.g. Guava's multi-map),
validation of map keys or collection types of other JVM languages (such as Ceylon's collection framework).

Allowing to put `@Valid` on type parameters allows to express the subject of cascaded validation more specifically:
`Map<@Valid AddressType, @Valid Address> addresses` would describe that both, map keys and values, should be validated.

=== Requirements

1. Constraints can be applied to type arguments (of bean properties, but also executable parameters and method return values): `Property<@Min(1) Integer> value`
1. Individual type parameters can be marked for cascaded validation: `Map<@Valid AddressType, Address> addresses`
1. How values are retrieved must be customizable by means of a pluggable value extractor mechanism, with a set of defined default extractors
1. Sometimes constraints should apply to a value wrapped by a container type, but there is no type parameter to put the constraints to.
JavaFX's `Property` hierarchy is the most prominent example: `@Email StringProperty emailProperty`.
In such case the value should be implicitly extracted from the container if unambiguously doable.
1. Allow to configure type argument constraints and cascades via XML mappings
1. Expose meta-data on type argument constraints and cascades in the constraint metadata API

=== Non-requirements

1. Constraints on type uses in local variables, invocations etc: `@NotNull String name = "Emmanuel";`, `new @NonEmpty @Readonly List<String>(myNonEmptyStringSet)`
1. constraints on type uses in type definitions:

[source,java]
----
class CustList extends List<@NotNull Customer> {
}
----

=== Solution

Value retrieval for cascaded validation and validation of type argument constraints is done via the `ValueExtractor` API:

[source,java]
----
package javax.validation.valueretrieval;

public interface ValueExtractor<T> {

	void extractValues(T originalValue, ValueReceiver receiver);

	interface ValueReceiver {

		void value(Object object, String nodeName);

		void iterableValue(Object object, String nodeName);

		void indexedValue(Object object, String nodeName, int i);

		void keyedValue(Object object, String nodeName, Object key);
	}
}
----

An extractor is tied to one specific type parameter of the type from which it extracts values. The `@ExtractedValue` annotation is used to mark that type parameter. 

As an example, this is how the implementation of the list extractor may look like:

[source,java]
----
class ListValueExtractor implements ValueExtractor<List<@ExtractedValue ?>> {

	@Override
	public void extractValues(List<?> originalValue, ValueReceiver receiver) {
		for ( int i 0 = 0; i < originalValue.length; i++ ) {
			receiver.indexedValue( originalValue.get( i ), "<iterable element>", i );
		}
	}
}
----

The right callback methods (`indexedValue()`, `keyedValue()` etc.) must be called in order to allow for proper construction of the property path as per the rules layed out in the BV 1.1 spec.

If a non-null value is passed for `nodeName`, a path node of type `TYPE_ARGUMENT` will be appended to the property path.
That's desirable for collection types for instance. If null is passed, no node will be appended,
resulting in the same path as if the constraint had been given on the element itself instead of a type parameter.
That's desirable for pure "wrapper types" such as `Optional`.

==== @ExtractedValue

The `@ExtractedValue` annotation is used to denote the element extracted by a given value extractor:

[source,java]
----
package javax.validation.valueextraction;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author <NAME>
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
public @interface ExtractedValue {
}
----

The `@ExtractedValue` annotation must be specified exactly once for a value extractor type.
Thus the following extractor definition is illegal as it specifies `@ExtractedValue` several times:

[source,java]
----
public class DoubleExtractor implements ValueExtractor<Multimap<@ExtractedValue ?, @ExtractedValue ?>> { ... }
----

When defined for a generic type, only wildcard type arguments may be annotated with `@ExtractedValue`.
Thus the following extractor definition is illegal:

[source,java]
----
public class StringListValueExtractor implements ValueExtractor<List<@ExtractedValue String>> { ... }
----

[NOTE]
====
This implies that there may not be more than one extractor for a given generic type.
I.e. there can be an extractor for `List<?>`, but not one for `List<String>` and one for `List<Integer>`.
====

In some cases, an extractor applies to the entire extracted type itself (e.g. for arrays).
In this case the `@ExtractedValue` annotation is to be given on the extracted type itself:

[source,java]
----
class ObjectArrayValueExtractor implements ValueExtractor<@ExtractedValue Object[]> {

	@Override
	public void extractValues(Object[] originalValue, ValueReceiver receiver) {
		for ( int i = 0; i < originalValue.length; i++ ) {
			receiver.indexedValue( originalValue[i], "<iterable element>", i );
		}
	}
}
----

[NOTE]
.Motivation for callback-style API
====
Instead of returning the extracted values from the method call, implementations of `ValueExtractor` pass the extracted values to the given receiver callback.
This helps to avoid object allocations and allows to handle the case of a single extracted value (`Optional<T>`) and multiple extracted values (`List<T>`) in a uniform fashion.
====

==== Default extractors

Compatible implementations provide extractors for the following types out of the box. They must invoke the right callback methods in order to ensure path nodes in the described form are appended:

* Arrays of objects and all primitive data types
** `@Valid` can be given for the array itself or for its component type.
Both will cause the validation of all the array elements
** If a constraint given for an array's component type is validated, a node with the following properties will be added to the path:
*** name: "<iterable element>"
*** kind: `TYPE_ARGUMENT`
*** isInIterable: `false`
*** index: the element's index
*** key: `null`
* `java.util.Iterable`
** When `@Valid` is given on the iterable element itself, the element and all its entries will be validated; this is to grant backwards compatability with BV 1.1
** When `@Valid` is given on the type parameter of an iterable element, all the entries will be validated.
** When validating a type argument constraint for `Iterable`, a node with the following properties will be added to the path:
*** name: "<iterable element>"
*** kind: `TYPE_ARGUMENT`
*** isInIterable: `true`
*** index: the element's index if the iterable is of type `List` or a subtype thereof; `null` otherwise
*** key: `null`
* `java.util.Map`
** When `@Valid` is given on the map element itself, the element and all its values will be validated; this is to grant backwards compatability with BV 1.1
** When `@Valid` is given on the key type parameter, the map keys will be validated
** When `@Valid` is given on the value type parameter, the map values will be validated
** When validating a constraint on the key type argument of `Map`, a node with the following properties will be added to the path:
*** name: "<map key>"
*** kind: `TYPE_ARGUMENT`
*** isInIterable: `true`
*** index: `null`
*** key: "(" + key + ")"; TODO: re-consider
** When validating a constraint on the value type argument of `Map`, a node with the following properties will be added to the path:
*** name: "<map value>"
*** kind: `TYPE_ARGUMENT`
*** isInIterable: `true`
*** index: `null`
*** key: key; TODO: re-consider
* `java.util.Optional`
** No node will be appended to the path when validating type argument constraints on `Optional`
* `javafx.beans.observable.ObservableValue`
** No node will be appended to the path when validating type argument constraints on `ObservableValue`
** Constraints given on an element of type `ObservableValue` apply to the wrapped value by default (see <<appendix-valueextraction-wrappedelements>>).
* `java.lang.Object`
** When `@Valid` is given for an element, the element will be validated

===== Examples

TODO

==== Plugging in custom extractors

Additional value extractors can be registered with the Bean Validation provider in the following ways:

* Invoke the new method `Configuration#addValueExtractor(ValueExtractor<?>)` (to apply it at the validation factory level)
* Invoke the new method `ValidatorContext#addValueExtractor(ValueExtractor<?>)` (to apply it for a single `Validator`)
* Specify the fully qualified class name of one or several extractors in `META-INF/validation.xml`: 

[source,xml]
----
<value-extractors>
    <value-extractor>com.example.MyExtractor</value-extractor>
</value-extractors>
----

[[appendix-valueextraction-wrappedelements]]
==== Applying element-level constraints to wrapped elements

Sometimes there is no type parameter to put a constraint to, but still constraints should be applied to the wrapped value instead of the annotated element
(a field, property getter, method return value or executable parameter).
JavaFX's property hierachy falls into that category, as it defines specific `Property` sub-types which are not generic:

[source,java]
----
@Email StringProperty emailProperty;
----

The `ConstraintAppliesTo` annotation can be used to control the target of validation in such cases:

[source,java]
----
@Target({ METHOD, FIELD, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
public @interface ConstraintsApplyTo {
    ValidationTarget value();
}
----

[source,java]
----
public enum ValidationTarget {
    ANNOTATED_ELEMENT,
    WRAPPED_VALUE;
}
----

Value extractor definitions can be marked with `ConstraintsApplyTo` so that constraints are automatically applied to the wrapped value if a constraint is found for an element handled by that extractor:

[source,java]
----
@ConstraintsApplyTo(WRAPPED_VALUE)
class PropertyExtractor implements ValueExtractor<Property<@ExtractedValue ?>> {

	@Override
	public void extractValues(Property originalValue, ValueReceiver receiver) {
		// ...
	}
}
----

If this extractor was identified as the single most-specific extractor for `StringProperty` (see <<appendix-valueextraction-extractorretrieval>>), the `@Email` constraint above would automatically be applied to the wrapped string value.

In rare cases it may happen that a constraint should be applied to the wrapped value although an extractor exists.
In this case the `ConstraintsApplyTo` annotation can be given on the element itself to prevent the unwrapping:

[source,java]
----
@ConstraintsApplyTo(ANNOTATED_ELEMENT)
@NotNull StringProperty emailProperty;
----

[NOTE]
====
For the sake of readability, when applying constraints to the elements of a generic container type,
it is strongly recommended to put the constraints to the type argument instead of the element itself in conjunction with `@ConstraintsApplyTo`.
I.e. you should prefer

[source,java]
----
List<@Email String> emails;
----

over

[source,java]
----
@Email
@ConstraintsApplyTo(WRAPPED_VALUE)
List<String> emails;
----
====

[[appendix-valueextraction-extractorretrieval]]
==== Retrieval of extractors

When detecting a type argument constraint or cascade, the applicable extractor is determined as follows:

1. Select all those value extractors which handle a type parameter that maps to the type argument annotated with the constraint or `@Valid` annotation;
Example:
** Given `List<@Email String> emails` and considering the default extractors listed above, only the extractors for `List` and `Iterable` are selected.
The former handles the type parameter `T` of type `List`, which directly maps to the type argument annotated with `@Email`.
The latter handles the type parameter `E` of type `Iterable` which (indirectly) maps to the annotated type argument (as `List` extends `Iterable` and binds its type parameter `T` to `E` from `Iterable`).
Other extractors such as the ones for `K` and `V` of `Map` are dismissed, as they handle type parameters not mapping to the annotated type argument
** Given
+
[source,java]
----
interface ConfusingMap<K, V> extends Map<V, K> {}
----
+
[source,java]
----
ConfusingMap<@Email String, String> map;
----
+
And considering the default extractors listed above, only the extractor for the type parameter `V` of `Map` will be selected. This is because the `@Email` constraint is given for the type argument representing type parameter `K` of `ConfusingMap` which maps to type parameter `V` of `Map`.

1. From the remaining candidate value extractors chose the one which is most specific to the container type declaring the annoted type argument.
An extractor A is more specific than another extractor B if A extracts a subtype of the type extracted by B.
Example:
** When obtaining the extractor for type parameter constraint validation, the declared type of the validated element is considered.
This is to be consistent with constraint validator resolution, which is based on the static type of elements, not the runtime type.
** When obtaining the extractor for cascaded validation, the runtime type of the cascasded element is considered.
This is to be consistent with the rules defined for property path construction which are based on the runtime type.
** From the two extractors above, the one for `List` is chosen as `List` is a subtype of `Iterable`.

1. If there are several extractors which are equally specific (e.g. several extractors for `List`), an `UnexpectedTypeException` is raised.
TODO: apply rules similar to "ConstraintValidator resolution algorithm" and further clarify wording

When detecting a regular element-level constraint (i.e. non type argument constraint) the applicable value extractor, if any, is determined as follows:

1. If `@ConstraintsApplyTo(ANNOTATED_ELEMENT)` is given, don't apply any value extractor

1. Determine the set of uniquely mapping type parameters declared by the types in the element type's type hierarchy; Examples:
** element of type `java.lang.String`: () (empty set)
** element of type `java.lang.Iterable`: (T)
** element of type `java.lang.Map`: (K, V)
** element of type `java.util.Collection`: (E) (as the type parameter `E` of `Collection` maps to `T` of `Iterable`, only the type parameter of the subtype is considered)
** `interface A<T> {}`, `interface B<U> {}`, `class C implements A<String>, B<Integer> {}`; element of type `C`: (T, U) (two non mapping type parameters)

1. If `@ConstraintsApplyTo(WRAPPED_VALUE)` is given:
** If no type parameter or more than one type parameter was found in step 2, raise an exception
** Choose the most specific extractor matching the single type parameter found in step 2
** If there are several extractors which are equally specific, an `UnexpectedTypeException` is raised.

1. If `@ConstraintsApplyTo` is not given:
** If no type parameter or more than one type parameter was found in step 2, don't apply any value extractor
** Choose the most specific extractor matching the single type parameter found in step 2 which is marked with `@ConstraintsApplyTo(WRAPPED_VALUE)`
** If there are multiple such extractors, an `UnexpectedTypeException` is raised.

[NOTE]
.Implementation note
====
As extractor retrieval for type parameter constraints is done using the static type of constrained elements,
the retrieval can be done once at initialization time and then be cached.
This is not possible for retrieval of extractors for cascaded validation.
====

==== Examples

* Applying a constraint to the value wrapped by a container type:
+
[source,java]
----
Property<@Min(1) Integer> value;
----
+
Note that `@Valid` is not required; the `@Min` constraint will be validated when the `value` property is subject to validation.

* Applying constraints to each value in a collection type:
+
[source,java]
----
List<@NotNull @Email String> emails;
----

* Cascaded validation of the values in a collection type:
+
[source,java]
----
List<@Valid Order> orders;
----
+
This will validate the constraints on each `Order` element in the list.

* The legacy style for cascaded validation is supported as well:
+
[source,java]
----
@Valid List<Order> orders;
----
+
This would also validate any constraints on a custom list type (e.g. `MyList#getId()`).
TODO: we never clarified that in 1.1. Should it be made explicit?

* Map validation with type argument constraints and cascading:
+
[source,java]
----
@Valid
Map<@RegExp(...) String, @RetailOrder Order> orders;
----
+
This would validate the map's keys against `@RegExp`, the map's values against `@RetailOrder` and apply cascaded validation of the map values (as well as the map object itself).

* When selecting extractors, type parameters must be throroughly traced in the hierarchy.
Consider this case where the order of the type parameters of `Map` is swapped in a sub-type:
+
[source,java]
----
public class CrazyMap<K, V> implements Map<V, K> { ... }
----
+
[source,java]
----
public class Example {
    private CrazyMap<@RegExp(...) String, @Min(0) Long> crazyMap = ...;
}
----
+
Assuming there is no dedicated extractor for `CrazyMap` but only the default ones for `K` and `V` of `Map`,
extraction for `@RegExp` must happen via the default map value extractor and extraction for `@Min` via the default map key extractor.
+
A type parameter in a sub-type may also map to several type parameters in a super-type:
+
[source,java]
----
interface NumericMap<T extends Number> extends Map<T, T> {}
----
+
[source,java]
----
private NumericMap<@Min(1) Integer> integerMap;
----
+
The `@Min` constraint is to be applied to the map's keys and values as the annotated type parameter maps to `K` and `V` of `Map`.

* type argument constraints can be applied to the elements of `Object` arrays and arrays of any primitive type:
+
[source,java]
----
String @Email[] emails;
----
+
[source,java]
----
int @Min(1) [] positiveNumbers;
----

* The extractor for cascaded validation is determined based on an element's runtime type:
+
[source,java]
----
Collection<@Valid Order> orders = new ArrayList<>();
----
+
Here the most-specific extractor for the runtime type `ArrayList` must be applied, causing the property nodes of violations to have an index set (`Node#getIndex()`).

* The container value passed to a value extractor is retrieved from the element that has the type argument carrying the constraint or `@Valid` annotation:
+
[source,java]
----
private Map<String, @Valid @RetailOrder Order> ordersByName;

public Map<@NotNull String, Order> getOrdersByName() {
    return ordersByName;
}
----

When validating the `@NotNull` constraint, the map as returned by the getter will be passed to the map key extractor in order to obtain the map keys.
When validating the `@RetailOrder` constraint and performing cascaded validation,
the map as obtained directly from the field will be passed to the map value extractor in order to obtain the map values.

* Custom extractor for a `Tuple` type:
+
[source,java]
----
public interface Tuple<T1, T2> {
    T1 getFirst();
    T2 getSecond();
}
----
+
[source,java]
----
public class TupleFirstExtractor implements ValueExtractor<Tuple<@ExtractedValue ?, ?>> {

	@Override
	public void extractValues(Tuple<?, ?> originalValue, ValueReceiver receiver) {
		receiver.value( originalValue.getFirst(), "<first>" );
	}
}
----
+
[source,java]
----
public class TupleSecondExtractor implements ValueExtractor<Tuple<?, @ExtractedValue ?>> {

	@Override
	public void extractValues(Tuple<?, ?> originalValue, ValueReceiver receiver) {
		receiver.value( originalValue.getSecond(), "<second>" );
	}
}
----
+
[source,java]
----
private Tuple<@NotNull @Email String, @NotNull @Min(1) Integer> tuple;
----

===== Examples for extractor retrieval

* The most specific extractor matching the constrained type argument is chosen:
+
[source,java]
----
private List<@Email String> emails;
----
+
Based on the algorithm described above and considering the mandated default extractors, only the extractor for `List` and `Iterable` are candidate extractors (all other extractors are defined for a type parameter not mapping to `T` of `List`). The extractor for `List` will be applied as it's more specific than the extractor for `Iterable` (`List` is a subtype of `Iterable`).

* Constraints targeting wrapped values can be given on the wrapping element.
Let there be these definitions:
+
[source,java]
----
class StringWrapper {
    String wrapped;
};
----
+
[source,java]
----
@ConstraintsApplyTo(WRAPPED_VALUE)
class StringWrapperExtractor implements ValueExtractor<@ExtractedValue StringWrapper> { ... }
};
----
+
[source,java]
----
private @Email StringWrapper email;
----
+
The `@Email` constraint will be applied to the wrapped string and can be validated as the extractor defines that element-level constraints should be applied to the wrapped value.
+
If the extractor were not decorated with `@ConstraintsApplyTo` an exception would be raised as there is no validator for `@Email` on `StringWrapper`.
+
Unwrapping could be mandated explicitly in this case:
+
[source,java]
----
@ConstraintsApplyTo(WRAPPED_VALUE)
@Email
private StringWrapper email;
----

===== Invalid examples

* No most specific extractor can be found unambiguously:
+
[source,java]
----
public interface CachedValue<V> {
    V getCachedValue();
}
----
+
[source,java]
----
public interface RealValue<V> {
    V getRealValue();
}
----
+
[source,java]
----
public class CachableValue<V> implements CachedValue<V>, RealValue<V> { ... }
----
+
[source,java]
----
public class CachedValueExtractor implements ValueExtractor<CachedValue<@ExtractedValue ?>> { ... }
----
+
[source,java]
----
public class RealValueExtractor implements ValueExtractor<RealValue<@ExtractedValue ?>> { ... }
----
+
[source,java]
----
private CachableValue<@Min(1) Integer> foo;
----
+
Validation of `foo` will fail, as none of the two matching extractors is more specific than the other one.
An extractor for `CachableValue` must be added, resolving the ambiguity.

* Element-level constraints cannot be applied if there is no type parameter at all or multiple non-mapping type parameters in the annotated element's type hierarchy. Thus an exception will be raised in the following cases:
+
[source,java]
----
// no type parameter
@ConstraintsApplyTo(WRAPPED_VALUE)
@Email
private String email;
----
+
[source,java]
----
// multiple type parameters
@ConstraintsApplyTo(WRAPPED_VALUE)
@Email
private Map<String, String> emails;
----

==== XML based configuration

TODO

==== Metadata retrieval

TODO

==== Misc.

* Regarding group sequences and default group sequences, the same rules apply for type argument constraints as they apply for regular element-level constraints.
* For the conversion of validation groups the same rules apply no matter whether `@Valid` is given for a regular element or for a type argument.
I.e. the following group conversion declaration is valid:

[source,java]
----
private List<@Valid @ConvertGroup(from=Default.class, to=Other.class) Order> orders;
----

=== Open questions

1. Should nested containers be supported: `List<Map<String, @NotNull String>> addressesByType`?
Or `Optional<List<@Email>> optionalEmails`;
The latter seems very reasonable.

1. `ConstraintsApplyTo` only allows one behavior per annotated element. Should it be per constraint?
E.g. for `@NotNull @Email StringProperty email` it may be desirable to apply `@NotNull` to the wrapper but `@Email` to the wrapped value. That's not possible currently.

1. Should `ConstraintsApplyTo` also be used for tagging extractors triggering "auto-extraction". Maybe a separate annotation would be less confusing, e.g. `@AutoExtract` or so?

1. Should a path node be added for type argument constraints of `Optional` and similar types?
+
__This proposal suggests to not do it, but Emmanuel is not convinced of this__.

1. Should value extractors be discoverable via the service loader mechanism (i.e. by means of `META-INF/services/javax.validation.valueextraction.ValueExtractor` files)
+
__Pro: It'd allow 3rd party libs such as Google Guava to provide custom extractors for their container types and have them automatically be applied without any effort for the user__.
+
__Cons: Need a way to disable or override some extractors with others. Which might make it a nogo__.

1. What to return from `PropertyDescriptor#getElementClass()` if there is a field of type `Foo` but a getter of type `Optional<Foo>`.
So far, BV assumed the types of field and getter to be the same and exposed a single property descriptor
(which btw. also may fall apart as of BV 1.1 when the field is of a sub-type of the getter's type).
What to return here?

1. Should the presence of type argument constraints alone trigger cascaded validation?
+
E.g. consider the case of `Tuple` above:
+
[source,java]
----
Tuple<@Min(1) Integer, @Email String> tuple;
----
+
__Here it may be nice to validate e.g. `@NotNull` constraints given within the `Tuple` class itself when validating the type argument constraints. With the current proposal their validation requires a separate `@Valid` on the element. Personally I think that's better (more consistent)__. 

1. For an element with a type argument, should it be allowed to specify constraints on the element (and use `@ConstraintsApplyTo(WRAPPED_ELEMENT)`) or should it be disallowed?
+
[source,java]
----
@Email @ConstraintsApplyTo(WRAPPED_ELEMENT) Optional<String> email;
----

1. Should we allow extractors to be defined for specific parameterized types, e.g.:
+
[source,java]
----
public class ListOfIntegerExtractor implements ValueExtractor<List<@ExtractedValue Integer>> { ... }

public class ListOfStringExtractor implements ValueExtractor<List<@ExtractedValue String>> { ... }
----
+
Currently, only one extractor (for type `List<?>` is allowed).
+
__I can't see a compelling use case for this (when would extractor behavior differ between different parameterizations of the same generic type) and am leaning towards only supporting the wildcard parameterization (`implements ValueExtractor<List<@ExtractedValue ?>>`)__.
+
1. Can we find another name than "type argument constraints"? While that suits for the most cases, it doesn't when applying constraints to the component type of an array: `String @NotBlank [] names`.
+
__I think "type use" is the correct one in Java terminology. But would anyone get what a "type use constraint" is?__.
1. Vet the API by exploring advanced use cases, e.g. Guava's https://github.com/google/guava/wiki/NewCollectionTypesExplained#table[Table], http://google.github.io/guava/releases/snapshot/api/docs/com/google/common/graph/Graph.html[Graph], http://google.github.io/guava/releases/snapshot/api/docs/com/google/common/graph/ValueGraph.html[ValueGraph] and http://google.github.io/guava/releases/snapshot/api/docs/com/google/common/graph/Network.html[Network] types
1. In the original proposal it was foreseen that `@ExtractedValue` could refer to type-parameters from super-types. Is that still needed?<commit_msg>BVAL-508 Adding example for extractor for Guava's Table type<commit_after>// Bean Validation
//
// License: Apache License, Version 2.0
// See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.

[[appendix-value-extraction]]

== Value extraction for cascaded validation and type argument constraints (BVAL-508)

This appendix describes the current work-in-progress around the retrieval of values to be validated during cascaded validation and evaluation of type argument constraints.
It is based on the original http://beanvalidation.org/proposals/BVAL-508/[proposals for BVAL-508].

=== Motivation

Value extraction is needed when constraints are applied to the element(s) stored within a container type.
There are two categories:

* Cascaded validation of iterables, maps and arrays as triggered via `@Valid`: `@Valid List<Order> orders`; in this case all the values stored in the list must be extracted so each can be validated
* Validation of type argument constraints as enabled by Java 8: `Optional<@Email String> email` or `Property<@Min(1) Integer> value`;
in this case, e.g. the wrapped `String` and `Integer` values must be extracted so the `@Email` and `@Min` constraints can be applied

Both cases can also overlap: `List<@RetailOrder @Valid Order> retailOrders`.

Type argument constraints and pluggable extractors will also make cascaded validation more flexible.
As of BV 1.1, there was a fixed set of data types supported by cascaded validation mandated by the spec (`Iterable`, arrays, `Map` (only the values would be validated).
This excludes use cases such as custom collection types (e.g. Guava's multi-map),
validation of map keys or collection types of other JVM languages (such as Ceylon's collection framework).

Allowing to put `@Valid` on type parameters allows to express the subject of cascaded validation more specifically:
`Map<@Valid AddressType, @Valid Address> addresses` would describe that both, map keys and values, should be validated.

=== Requirements

1. Constraints can be applied to type arguments (of bean properties, but also executable parameters and method return values): `Property<@Min(1) Integer> value`
1. Individual type parameters can be marked for cascaded validation: `Map<@Valid AddressType, Address> addresses`
1. How values are retrieved must be customizable by means of a pluggable value extractor mechanism, with a set of defined default extractors
1. Sometimes constraints should apply to a value wrapped by a container type, but there is no type parameter to put the constraints to.
JavaFX's `Property` hierarchy is the most prominent example: `@Email StringProperty emailProperty`.
In such case the value should be implicitly extracted from the container if unambiguously doable.
1. Allow to configure type argument constraints and cascades via XML mappings
1. Expose meta-data on type argument constraints and cascades in the constraint metadata API

=== Non-requirements

1. Constraints on type uses in local variables, invocations etc: `@NotNull String name = "Emmanuel";`, `new @NonEmpty @Readonly List<String>(myNonEmptyStringSet)`
1. constraints on type uses in type definitions:

[source,java]
----
class CustList extends List<@NotNull Customer> {
}
----

=== Solution

Value retrieval for cascaded validation and validation of type argument constraints is done via the `ValueExtractor` API:

[source,java]
----
package javax.validation.valueretrieval;

public interface ValueExtractor<T> {

	void extractValues(T originalValue, ValueReceiver receiver);

	interface ValueReceiver {

		void value(Object object, String nodeName);

		void iterableValue(Object object, String nodeName);

		void indexedValue(Object object, String nodeName, int i);

		void keyedValue(Object object, String nodeName, Object key);
	}
}
----

An extractor is tied to one specific type parameter of the type from which it extracts values. The `@ExtractedValue` annotation is used to mark that type parameter. 

As an example, this is how the implementation of the list extractor may look like:

[source,java]
----
class ListValueExtractor implements ValueExtractor<List<@ExtractedValue ?>> {

	@Override
	public void extractValues(List<?> originalValue, ValueReceiver receiver) {
		for ( int i 0 = 0; i < originalValue.length; i++ ) {
			receiver.indexedValue( originalValue.get( i ), "<iterable element>", i );
		}
	}
}
----

The right callback methods (`indexedValue()`, `keyedValue()` etc.) must be called in order to allow for proper construction of the property path as per the rules layed out in the BV 1.1 spec.

If a non-null value is passed for `nodeName`, a path node of type `TYPE_ARGUMENT` will be appended to the property path.
That's desirable for collection types for instance. If null is passed, no node will be appended,
resulting in the same path as if the constraint had been given on the element itself instead of a type parameter.
That's desirable for pure "wrapper types" such as `Optional`.

==== @ExtractedValue

The `@ExtractedValue` annotation is used to denote the element extracted by a given value extractor:

[source,java]
----
package javax.validation.valueextraction;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author <NAME>
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
public @interface ExtractedValue {
}
----

The `@ExtractedValue` annotation must be specified exactly once for a value extractor type.
Thus the following extractor definition is illegal as it specifies `@ExtractedValue` several times:

[source,java]
----
public class DoubleExtractor implements ValueExtractor<Multimap<@ExtractedValue ?, @ExtractedValue ?>> { ... }
----

When defined for a generic type, only wildcard type arguments may be annotated with `@ExtractedValue`.
Thus the following extractor definition is illegal:

[source,java]
----
public class StringListValueExtractor implements ValueExtractor<List<@ExtractedValue String>> { ... }
----

[NOTE]
====
This implies that there may not be more than one extractor for a given generic type.
I.e. there can be an extractor for `List<?>`, but not one for `List<String>` and one for `List<Integer>`.
====

In some cases, an extractor applies to the entire extracted type itself (e.g. for arrays).
In this case the `@ExtractedValue` annotation is to be given on the extracted type itself:

[source,java]
----
class ObjectArrayValueExtractor implements ValueExtractor<@ExtractedValue Object[]> {

	@Override
	public void extractValues(Object[] originalValue, ValueReceiver receiver) {
		for ( int i = 0; i < originalValue.length; i++ ) {
			receiver.indexedValue( originalValue[i], "<iterable element>", i );
		}
	}
}
----

[NOTE]
.Motivation for callback-style API
====
Instead of returning the extracted values from the method call, implementations of `ValueExtractor` pass the extracted values to the given receiver callback.
This helps to avoid object allocations and allows to handle the case of a single extracted value (`Optional<T>`) and multiple extracted values (`List<T>`) in a uniform fashion.
====

==== Default extractors

Compatible implementations provide extractors for the following types out of the box. They must invoke the right callback methods in order to ensure path nodes in the described form are appended:

* Arrays of objects and all primitive data types
** `@Valid` can be given for the array itself or for its component type.
Both will cause the validation of all the array elements
** If a constraint given for an array's component type is validated, a node with the following properties will be added to the path:
*** name: "<iterable element>"
*** kind: `TYPE_ARGUMENT`
*** isInIterable: `false`
*** index: the element's index
*** key: `null`
* `java.util.Iterable`
** When `@Valid` is given on the iterable element itself, the element and all its entries will be validated; this is to grant backwards compatability with BV 1.1
** When `@Valid` is given on the type parameter of an iterable element, all the entries will be validated.
** When validating a type argument constraint for `Iterable`, a node with the following properties will be added to the path:
*** name: "<iterable element>"
*** kind: `TYPE_ARGUMENT`
*** isInIterable: `true`
*** index: the element's index if the iterable is of type `List` or a subtype thereof; `null` otherwise
*** key: `null`
* `java.util.Map`
** When `@Valid` is given on the map element itself, the element and all its values will be validated; this is to grant backwards compatability with BV 1.1
** When `@Valid` is given on the key type parameter, the map keys will be validated
** When `@Valid` is given on the value type parameter, the map values will be validated
** When validating a constraint on the key type argument of `Map`, a node with the following properties will be added to the path:
*** name: "<map key>"
*** kind: `TYPE_ARGUMENT`
*** isInIterable: `true`
*** index: `null`
*** key: "(" + key + ")"; TODO: re-consider
** When validating a constraint on the value type argument of `Map`, a node with the following properties will be added to the path:
*** name: "<map value>"
*** kind: `TYPE_ARGUMENT`
*** isInIterable: `true`
*** index: `null`
*** key: key; TODO: re-consider
* `java.util.Optional`
** No node will be appended to the path when validating type argument constraints on `Optional`
* `javafx.beans.observable.ObservableValue`
** No node will be appended to the path when validating type argument constraints on `ObservableValue`
** Constraints given on an element of type `ObservableValue` apply to the wrapped value by default (see <<appendix-valueextraction-wrappedelements>>).
* `java.lang.Object`
** When `@Valid` is given for an element, the element will be validated

===== Examples

TODO

==== Plugging in custom extractors

Additional value extractors can be registered with the Bean Validation provider in the following ways:

* Invoke the new method `Configuration#addValueExtractor(ValueExtractor<?>)` (to apply it at the validation factory level)
* Invoke the new method `ValidatorContext#addValueExtractor(ValueExtractor<?>)` (to apply it for a single `Validator`)
* Specify the fully qualified class name of one or several extractors in `META-INF/validation.xml`: 

[source,xml]
----
<value-extractors>
    <value-extractor>com.example.MyExtractor</value-extractor>
</value-extractors>
----

[[appendix-valueextraction-wrappedelements]]
==== Applying element-level constraints to wrapped elements

Sometimes there is no type parameter to put a constraint to, but still constraints should be applied to the wrapped value instead of the annotated element
(a field, property getter, method return value or executable parameter).
JavaFX's property hierachy falls into that category, as it defines specific `Property` sub-types which are not generic:

[source,java]
----
@Email StringProperty emailProperty;
----

The `ConstraintAppliesTo` annotation can be used to control the target of validation in such cases:

[source,java]
----
@Target({ METHOD, FIELD, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
public @interface ConstraintsApplyTo {
    ValidationTarget value();
}
----

[source,java]
----
public enum ValidationTarget {
    ANNOTATED_ELEMENT,
    WRAPPED_VALUE;
}
----

Value extractor definitions can be marked with `ConstraintsApplyTo` so that constraints are automatically applied to the wrapped value if a constraint is found for an element handled by that extractor:

[source,java]
----
@ConstraintsApplyTo(WRAPPED_VALUE)
class PropertyExtractor implements ValueExtractor<Property<@ExtractedValue ?>> {

	@Override
	public void extractValues(Property originalValue, ValueReceiver receiver) {
		// ...
	}
}
----

If this extractor was identified as the single most-specific extractor for `StringProperty` (see <<appendix-valueextraction-extractorretrieval>>), the `@Email` constraint above would automatically be applied to the wrapped string value.

In rare cases it may happen that a constraint should be applied to the wrapped value although an extractor exists.
In this case the `ConstraintsApplyTo` annotation can be given on the element itself to prevent the unwrapping:

[source,java]
----
@ConstraintsApplyTo(ANNOTATED_ELEMENT)
@NotNull StringProperty emailProperty;
----

[NOTE]
====
For the sake of readability, when applying constraints to the elements of a generic container type,
it is strongly recommended to put the constraints to the type argument instead of the element itself in conjunction with `@ConstraintsApplyTo`.
I.e. you should prefer

[source,java]
----
List<@Email String> emails;
----

over

[source,java]
----
@Email
@ConstraintsApplyTo(WRAPPED_VALUE)
List<String> emails;
----
====

[[appendix-valueextraction-extractorretrieval]]
==== Retrieval of extractors

When detecting a type argument constraint or cascade, the applicable extractor is determined as follows:

1. Select all those value extractors which handle a type parameter that maps to the type argument annotated with the constraint or `@Valid` annotation;
Example:
** Given `List<@Email String> emails` and considering the default extractors listed above, only the extractors for `List` and `Iterable` are selected.
The former handles the type parameter `T` of type `List`, which directly maps to the type argument annotated with `@Email`.
The latter handles the type parameter `E` of type `Iterable` which (indirectly) maps to the annotated type argument (as `List` extends `Iterable` and binds its type parameter `T` to `E` from `Iterable`).
Other extractors such as the ones for `K` and `V` of `Map` are dismissed, as they handle type parameters not mapping to the annotated type argument
** Given
+
[source,java]
----
interface ConfusingMap<K, V> extends Map<V, K> {}
----
+
[source,java]
----
ConfusingMap<@Email String, String> map;
----
+
And considering the default extractors listed above, only the extractor for the type parameter `V` of `Map` will be selected. This is because the `@Email` constraint is given for the type argument representing type parameter `K` of `ConfusingMap` which maps to type parameter `V` of `Map`.

1. From the remaining candidate value extractors chose the one which is most specific to the container type declaring the annoted type argument.
An extractor A is more specific than another extractor B if A extracts a subtype of the type extracted by B.
Example:
** When obtaining the extractor for type parameter constraint validation, the declared type of the validated element is considered.
This is to be consistent with constraint validator resolution, which is based on the static type of elements, not the runtime type.
** When obtaining the extractor for cascaded validation, the runtime type of the cascasded element is considered.
This is to be consistent with the rules defined for property path construction which are based on the runtime type.
** From the two extractors above, the one for `List` is chosen as `List` is a subtype of `Iterable`.

1. If there are several extractors which are equally specific (e.g. several extractors for `List`), an `UnexpectedTypeException` is raised.
TODO: apply rules similar to "ConstraintValidator resolution algorithm" and further clarify wording

When detecting a regular element-level constraint (i.e. non type argument constraint) the applicable value extractor, if any, is determined as follows:

1. If `@ConstraintsApplyTo(ANNOTATED_ELEMENT)` is given, don't apply any value extractor

1. Determine the set of uniquely mapping type parameters declared by the types in the element type's type hierarchy; Examples:
** element of type `java.lang.String`: () (empty set)
** element of type `java.lang.Iterable`: (T)
** element of type `java.lang.Map`: (K, V)
** element of type `java.util.Collection`: (E) (as the type parameter `E` of `Collection` maps to `T` of `Iterable`, only the type parameter of the subtype is considered)
** `interface A<T> {}`, `interface B<U> {}`, `class C implements A<String>, B<Integer> {}`; element of type `C`: (T, U) (two non mapping type parameters)

1. If `@ConstraintsApplyTo(WRAPPED_VALUE)` is given:
** If no type parameter or more than one type parameter was found in step 2, raise an exception
** Choose the most specific extractor matching the single type parameter found in step 2
** If there are several extractors which are equally specific, an `UnexpectedTypeException` is raised.

1. If `@ConstraintsApplyTo` is not given:
** If no type parameter or more than one type parameter was found in step 2, don't apply any value extractor
** Choose the most specific extractor matching the single type parameter found in step 2 which is marked with `@ConstraintsApplyTo(WRAPPED_VALUE)`
** If there are multiple such extractors, an `UnexpectedTypeException` is raised.

[NOTE]
.Implementation note
====
As extractor retrieval for type parameter constraints is done using the static type of constrained elements,
the retrieval can be done once at initialization time and then be cached.
This is not possible for retrieval of extractors for cascaded validation.
====

==== Examples

* Applying a constraint to the value wrapped by a container type:
+
[source,java]
----
Property<@Min(1) Integer> value;
----
+
Note that `@Valid` is not required; the `@Min` constraint will be validated when the `value` property is subject to validation.

* Applying constraints to each value in a collection type:
+
[source,java]
----
List<@NotNull @Email String> emails;
----

* Cascaded validation of the values in a collection type:
+
[source,java]
----
List<@Valid Order> orders;
----
+
This will validate the constraints on each `Order` element in the list.

* The legacy style for cascaded validation is supported as well:
+
[source,java]
----
@Valid List<Order> orders;
----
+
This would also validate any constraints on a custom list type (e.g. `MyList#getId()`).
TODO: we never clarified that in 1.1. Should it be made explicit?

* Map validation with type argument constraints and cascading:
+
[source,java]
----
@Valid
Map<@RegExp(...) String, @RetailOrder Order> orders;
----
+
This would validate the map's keys against `@RegExp`, the map's values against `@RetailOrder` and apply cascaded validation of the map values (as well as the map object itself).

* When selecting extractors, type parameters must be throroughly traced in the hierarchy.
Consider this case where the order of the type parameters of `Map` is swapped in a sub-type:
+
[source,java]
----
public class CrazyMap<K, V> implements Map<V, K> { ... }
----
+
[source,java]
----
public class Example {
    private CrazyMap<@RegExp(...) String, @Min(0) Long> crazyMap = ...;
}
----
+
Assuming there is no dedicated extractor for `CrazyMap` but only the default ones for `K` and `V` of `Map`,
extraction for `@RegExp` must happen via the default map value extractor and extraction for `@Min` via the default map key extractor.
+
A type parameter in a sub-type may also map to several type parameters in a super-type:
+
[source,java]
----
interface NumericMap<T extends Number> extends Map<T, T> {}
----
+
[source,java]
----
private NumericMap<@Min(1) Integer> integerMap;
----
+
The `@Min` constraint is to be applied to the map's keys and values as the annotated type parameter maps to `K` and `V` of `Map`.

* type argument constraints can be applied to the elements of `Object` arrays and arrays of any primitive type:
+
[source,java]
----
String @Email[] emails;
----
+
[source,java]
----
int @Min(1) [] positiveNumbers;
----

* The extractor for cascaded validation is determined based on an element's runtime type:
+
[source,java]
----
Collection<@Valid Order> orders = new ArrayList<>();
----
+
Here the most-specific extractor for the runtime type `ArrayList` must be applied, causing the property nodes of violations to have an index set (`Node#getIndex()`).

* The container value passed to a value extractor is retrieved from the element that has the type argument carrying the constraint or `@Valid` annotation:
+
[source,java]
----
private Map<String, @Valid @RetailOrder Order> ordersByName;

public Map<@NotNull String, Order> getOrdersByName() {
    return ordersByName;
}
----

When validating the `@NotNull` constraint, the map as returned by the getter will be passed to the map key extractor in order to obtain the map keys.
When validating the `@RetailOrder` constraint and performing cascaded validation,
the map as obtained directly from the field will be passed to the map value extractor in order to obtain the map values.

* Custom extractor for a `Tuple` type:
+
[source,java]
----
public interface Tuple<T1, T2> {
    T1 getFirst();
    T2 getSecond();
}
----
+
[source,java]
----
public class TupleFirstExtractor implements ValueExtractor<Tuple<@ExtractedValue ?, ?>> {

	@Override
	public void extractValues(Tuple<?, ?> originalValue, ValueReceiver receiver) {
		receiver.value( originalValue.getFirst(), "<first>" );
	}
}
----
+
[source,java]
----
public class TupleSecondExtractor implements ValueExtractor<Tuple<?, @ExtractedValue ?>> {

	@Override
	public void extractValues(Tuple<?, ?> originalValue, ValueReceiver receiver) {
		receiver.value( originalValue.getSecond(), "<second>" );
	}
}
----
+
[source,java]
----
private Tuple<@NotNull @Email String, @NotNull @Min(1) Integer> tuple;
----

===== Examples for extractor retrieval

* The most specific extractor matching the constrained type argument is chosen:
+
[source,java]
----
private List<@Email String> emails;
----
+
Based on the algorithm described above and considering the mandated default extractors, only the extractor for `List` and `Iterable` are candidate extractors (all other extractors are defined for a type parameter not mapping to `T` of `List`). The extractor for `List` will be applied as it's more specific than the extractor for `Iterable` (`List` is a subtype of `Iterable`).

* Constraints targeting wrapped values can be given on the wrapping element.
Let there be these definitions:
+
[source,java]
----
class StringWrapper {
    String wrapped;
};
----
+
[source,java]
----
@ConstraintsApplyTo(WRAPPED_VALUE)
class StringWrapperExtractor implements ValueExtractor<@ExtractedValue StringWrapper> { ... }
};
----
+
[source,java]
----
private @Email StringWrapper email;
----
+
The `@Email` constraint will be applied to the wrapped string and can be validated as the extractor defines that element-level constraints should be applied to the wrapped value.
+
If the extractor were not decorated with `@ConstraintsApplyTo` an exception would be raised as there is no validator for `@Email` on `StringWrapper`.
+
Unwrapping could be mandated explicitly in this case:
+
[source,java]
----
@ConstraintsApplyTo(WRAPPED_VALUE)
@Email
private StringWrapper email;
----

===== Invalid examples

* No most specific extractor can be found unambiguously:
+
[source,java]
----
public interface CachedValue<V> {
    V getCachedValue();
}
----
+
[source,java]
----
public interface RealValue<V> {
    V getRealValue();
}
----
+
[source,java]
----
public class CachableValue<V> implements CachedValue<V>, RealValue<V> { ... }
----
+
[source,java]
----
public class CachedValueExtractor implements ValueExtractor<CachedValue<@ExtractedValue ?>> { ... }
----
+
[source,java]
----
public class RealValueExtractor implements ValueExtractor<RealValue<@ExtractedValue ?>> { ... }
----
+
[source,java]
----
private CachableValue<@Min(1) Integer> foo;
----
+
Validation of `foo` will fail, as none of the two matching extractors is more specific than the other one.
An extractor for `CachableValue` must be added, resolving the ambiguity.

* Element-level constraints cannot be applied if there is no type parameter at all or multiple non-mapping type parameters in the annotated element's type hierarchy. Thus an exception will be raised in the following cases:
+
[source,java]
----
// no type parameter
@ConstraintsApplyTo(WRAPPED_VALUE)
@Email
private String email;
----
+
[source,java]
----
// multiple type parameters
@ConstraintsApplyTo(WRAPPED_VALUE)
@Email
private Map<String, String> emails;
----

==== XML based configuration

TODO

==== Metadata retrieval

TODO

==== Misc.

* Regarding group sequences and default group sequences, the same rules apply for type argument constraints as they apply for regular element-level constraints.
* For the conversion of validation groups the same rules apply no matter whether `@Valid` is given for a regular element or for a type argument.
I.e. the following group conversion declaration is valid:

[source,java]
----
private List<@Valid @ConvertGroup(from=Default.class, to=Other.class) Order> orders;
----

=== Open questions

1. Should nested containers be supported: `List<Map<String, @NotNull String>> addressesByType`?
Or `Optional<List<@Email>> optionalEmails`;
The latter seems very reasonable.

1. `ConstraintsApplyTo` only allows one behavior per annotated element. Should it be per constraint?
E.g. for `@NotNull @Email StringProperty email` it may be desirable to apply `@NotNull` to the wrapper but `@Email` to the wrapped value. That's not possible currently.

1. Should `ConstraintsApplyTo` also be used for tagging extractors triggering "auto-extraction". Maybe a separate annotation would be less confusing, e.g. `@AutoExtract` or so?

1. Should a path node be added for type argument constraints of `Optional` and similar types?
+
__This proposal suggests to not do it, but Emmanuel is not convinced of this__.

1. Should value extractors be discoverable via the service loader mechanism (i.e. by means of `META-INF/services/javax.validation.valueextraction.ValueExtractor` files)
+
__Pro: It'd allow 3rd party libs such as Google Guava to provide custom extractors for their container types and have them automatically be applied without any effort for the user__.
+
__Cons: Need a way to disable or override some extractors with others. Which might make it a nogo__.

1. What to return from `PropertyDescriptor#getElementClass()` if there is a field of type `Foo` but a getter of type `Optional<Foo>`.
So far, BV assumed the types of field and getter to be the same and exposed a single property descriptor
(which btw. also may fall apart as of BV 1.1 when the field is of a sub-type of the getter's type).
What to return here?

1. Should the presence of type argument constraints alone trigger cascaded validation?
+
E.g. consider the case of `Tuple` above:
+
[source,java]
----
Tuple<@Min(1) Integer, @Email String> tuple;
----
+
__Here it may be nice to validate e.g. `@NotNull` constraints given within the `Tuple` class itself when validating the type argument constraints. With the current proposal their validation requires a separate `@Valid` on the element. Personally I think that's better (more consistent)__. 

1. For an element with a type argument, should it be allowed to specify constraints on the element (and use `@ConstraintsApplyTo(WRAPPED_ELEMENT)`) or should it be disallowed?
+
[source,java]
----
@Email @ConstraintsApplyTo(WRAPPED_ELEMENT) Optional<String> email;
----

1. Should we allow extractors to be defined for specific parameterized types, e.g.:
+
[source,java]
----
public class ListOfIntegerExtractor implements ValueExtractor<List<@ExtractedValue Integer>> { ... }

public class ListOfStringExtractor implements ValueExtractor<List<@ExtractedValue String>> { ... }
----
+
Currently, only one extractor (for type `List<?>` is allowed).
+
__I can't see a compelling use case for this (when would extractor behavior differ between different parameterizations of the same generic type) and am leaning towards only supporting the wildcard parameterization (`implements ValueExtractor<List<@ExtractedValue ?>>`)__.
+
1. Can we find another name than "type argument constraints"? While that suits for the most cases, it doesn't when applying constraints to the component type of an array: `String @NotBlank [] names`.
+
__I think "type use" is the correct one in Java terminology. But would anyone get what a "type use constraint" is?__.
1. Vet the API by exploring advanced use cases, e.g. Guava's https://github.com/google/guava/wiki/NewCollectionTypesExplained#table[Table], http://google.github.io/guava/releases/snapshot/api/docs/com/google/common/graph/Graph.html[Graph], http://google.github.io/guava/releases/snapshot/api/docs/com/google/common/graph/ValueGraph.html[ValueGraph] and http://google.github.io/guava/releases/snapshot/api/docs/com/google/common/graph/Network.html[Network] types.
+
Example for `Table`:
+
[source,java]
----
class TableValueExtractor implements ValueExtractor<Table<?, ?, @ExtractedValue ?>> {

	@Override
	public void extractValues(Table<?, ?, ?> originalValue, ValueExtractor.ValueReceiver receiver) {

		for ( Cell<?, ?, ?> cell : originalValue.cellSet() ) {
			receiver.keyedValue(
					cell.getValue(),
					"<table cell>",
					new CellKey( cell.getRowKey(), cell.getColumnKey() )
			);
		}
	}
}
----
+
[source,java]
----
public static class CellKey {

	private final Object rowKey;
	private final Object columnKey;

	public CellKey(Object rowKey, Object columnKey) {
		this.rowKey = rowKey;
		this.columnKey = columnKey;
	}

	@Override
	public String toString() {
		return "(" + rowKey + "," + columnKey + ")";
	}

	// equals(), hashCode() ...
}
----
+
When having an invalid table cell in the following and validating it:
+
[source,java]
----
public class Customer {

    Table<Year, String, @Min(1) Integer> revenuePerYearAndCategory = HashBasedTable.create();
}
----
+
Then this will be the result:
+
[source,java]
----
ConstraintViolation<Customer> violation = ...;

assertThat( violation.getPropertyPath.toString() ).isEqualTo( "revenuePerYearAndCategory[(2015,cds)].<table cell>" );

Iterator<Node> path = violation.getPropertyPath().iterator();

Node node = path.next();
assertThat( node.getName() ).isEqualTo( "revenuePerYearAndCategory" );
assertThat( node.getKind() ).isEqualTo( ElementKind.PROPERTY );
assertThat( node.getKey() ).isNull();
assertThat( node.getIndex() ).isNull();

node = path.next();
assertThat( node.getName() ).isEqualTo( "<table cell>" );
assertThat( node.getKind() ).isEqualTo( ElementKind.TYPE_ARGUMENT );
assertThat( node.getKey() ).isEqualTo( new CellKey(Year.of( 2015 ), "cds") );
assertThat( node.getIndex() ).isNull();

assertThat( path.hasNext() ).isFalse();
----

1. In the original proposal it was foreseen that `@ExtractedValue` could refer to type-parameters from super-types. Is that still needed?
{'fraction_non_alphanumeric': 0.0972210505002784, 'fraction_numerical': 0.0026996473585637875, 'mean_word_length': 4.692824896743828, 'pattern_counts': {'":': 0, '<': 229, '<?xml version=': 0, '>': 225, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4429652', 'n_tokens_mistral': 16234, 'n_tokens_neox': 15635, 'n_words': 7408}