For example, the following is schema that declares a "validate" property.
{ "type" : "typeref", "name" : "Digits", "ref" : "string", "validate" : { "regex" : { "regex" : "[0-9]*" } } }
The value of this property must be a {@link DataMap}. Each entry in this {@link DataMap}declares a {@link Validator} that has to be created. The key of the entry determines{@link Validator} subclass to instantiate.
The key to {@link Validator} class lookup algorithm first looks up the key-to-classmap provided to the constructor to obtain the {@link Validator} subclass. If the keydoes not exist in the map, then look for a class whose name is equal to the provided key and is a subclass of {@link Validator}. If there is no match, then look for a class whose fully qualified name is derived from the provided by key by using {@code com.linkedin.data.schema.validator} as the Java package name and capitalizingthe first character of the key and appending "Validator" to the key as the name of the class, and the class is a subclass of {@link Validator}.
Once the {@link Validator} subclass is found, its one-argument constructor thattakes a single {@link DataMap} parameter is invoked with value of the entry.
In the above example, this class will lookup "regex" in the key-to-class map, find {@link RegexValidator} class, and invoke the {@link RegexValidator#RegexValidator(com.linkedin.data.DataMap)}constructor with the following {@link DataMap}.
{ "regex" : "[0-9]*" }
This will construct a {@link RegexValidator} that will validate that values ofthis type will contain only numeric digits.
A {@link Validator} instantiated by this class is likely to be called concurrently frommultiple threads. The same instance will be called to validate different values. For deterministic behavior an instance should not maintain state across multiple invocations.
Once initialized, a {@link DataSchemaAnnotationValidator} does not maintain stateacross calls to its {@link #validate(ValidatorContext)} method. Hence, a singleinstance may be called concurrently by multiple threads. Hence, the more expensive tasks of iterating through a {@link DataSchema} andconstructing {@link Validator} instance only needs to occur once.
Initialization is successful if all keys of "validate" properties can be successfully resolved to a {@link Validator} class and an instance of the class can be successfullyconstructed using the value associated with the key. The {@link #getInitMessages()}method can be used to obtain a more detailed message on the "validate" properties and associated keys that could not be initialized successfully.
A partially successful initialized {@link DataSchemaAnnotationValidator} may stillbe useful. It is possible that new keys added to the "validate" property may not be known to other clients of schema.
Validator Execution Order
Execution ordering of multiple validators specified within the same "validate" property is determined by the "validatorPriority" property of each validator. "validate" : { "higherPriorityValidator" : { "validatorPriority" : 1 }, "defaultPriorityValidator" : { }, "lowerPriorityValidator" : { "validatorPriority" : -1 } }
The higher the priority value, the higher the priority of the validator, i.e. a validator with higher prority value will be executed before the validators with lower priority values. The default priority value for a validator that does not specify a priority value is 0. Execution order of validators with the same priority value is not defined or specified.
Validators may be attached to a field as well as the type of the field. This class will always execute the validators associated to the type of the field before it will execute the validators associated with the field.
If schema of a data element is a typeref, then the validator associated with the typeref is executed after the validator of the referenced type.
Beyond the above execution ordering guarantees provided by this class, the execution order of validators among different data elements is determined by the traversal order of the caller (i.e. how data elements passed to the {@link #validate(ValidatorContext)} method of this class. Typically, the caller will be{@link com.linkedin.data.schema.validation.ValidateDataAgainstSchema}and this caller performs a post-order traversal of data elements.
|
|
|
|