use of com.linkedin.data.schema.DataSchema in project rest.li by linkedin.
the class AnyRecordValidator method validate.
@Override
public void validate(ValidatorContext context) {
DataElement dataElement = context.dataElement();
Object value = dataElement.getValue();
DataSchema schema = dataElement.getSchema();
if (schema.getType() != DataSchema.Type.RECORD || (((RecordDataSchema) schema).getFullName()).equals(SCHEMA_NAME) == false) {
context.addResult(new Message(context.dataElement().path(), "%1$s invoked on schema that is not %2$s", AnyRecordValidator.class.getName(), SCHEMA_NAME));
} else if (value.getClass() != DataMap.class) {
context.addResult(new Message(context.dataElement().path(), "%1$s expects data to be a DataMap, data is %2$s", AnyRecordValidator.class.getName(), value));
} else {
DataMap dataMap = (DataMap) value;
if (dataMap.size() != 1) {
context.addResult(new Message(context.dataElement().path(), "%1$s expects data to be a DataMap with one entry, data is %2$s", AnyRecordValidator.class.getName(), value));
} else {
Map.Entry<String, Object> entry = dataMap.entrySet().iterator().next();
String anySchemaName = entry.getKey();
Object anyValue = entry.getValue();
DataSchema anySchema = schemaFromName(context, anySchemaName);
if (anySchema != null) {
DataElement anyElement = new SimpleDataElement(anyValue, entry.getKey(), anySchema, dataElement);
// do we want to have cache for anySchemaName to validator
// do we care about classMap argument to DataSchemaAnnotationValidator
DataSchemaAnnotationValidator validator = new DataSchemaAnnotationValidator(anySchema);
if (validator.isInitOk() == false) {
boolean errorIfNotValidated = getParameter(context.validationOptions()).isValidSchema();
context.addResult(new Message(context.dataElement().path(), errorIfNotValidated, "%1$s failed to initialize %2$s with %3$s", AnyRecordValidator.class.getName(), DataSchemaAnnotationValidator.class.getSimpleName(), anySchema));
addResult(context, errorIfNotValidated, validator.getInitMessages());
} else {
ValidationResult result = ValidateDataAgainstSchema.validate(anyElement, context.validationOptions(), validator);
addResult(context, result.getMessages());
if (result.hasFix())
context.setHasFix(true);
if (result.hasFixupReadOnlyError())
context.setHasFixupReadOnlyError(true);
}
}
}
}
}
use of com.linkedin.data.schema.DataSchema in project rest.li by linkedin.
the class TestAnyRecordValidator method testValidationResultFlags.
@Test
public void testValidationResultFlags() throws IOException {
Object[][] inputs = { { ANYRECORDCLIENT_SCHEMA, "{" + " \"required\" : {\n" + " \"com.linkedin.data.schema.validator.AnyRecord\" : {\n" + " \"com.linkedin.Cat\" : { \"c\" : 1 }\n" + " }\n" + " }\n" + "}", false, new ValidationOptions(RequiredMode.IGNORE, CoercionMode.NORMAL), ResultFlag.VALID, ResultFlag.HAS_FIX, ResultFlag.NOT_HAS_FIXUP_READONLY_ERROR, new String[] {} }, { ANYRECORDCLIENT_SCHEMA, "{" + " \"required\" : {\n" + " \"com.linkedin.data.schema.validator.AnyRecord\" : {\n" + " \"com.linkedin.Cat\" : { \"c\" : 1 }\n" + " }\n" + " }\n" + "}", true, new ValidationOptions(RequiredMode.IGNORE, CoercionMode.NORMAL), ResultFlag.NOT_VALID, ResultFlag.HAS_FIX, ResultFlag.HAS_FIXUP_READONLY_ERROR, new String[] { "ERROR", "/required/com.linkedin.data.schema.validator.AnyRecord/com.linkedin.Cat/c", "cannot be fixed because DataMap backing com.linkedin.Cat type is read-only" } } };
final boolean debug = false;
final AnyRecordValidator.Parameter anyRecordValidatorParameter = new AnyRecordValidator.Parameter(true, _resolver);
for (Object[] row : inputs) {
int i = 0;
DataSchema schema = (DataSchema) row[i++];
DataMap object = TestUtil.dataMapFromString((String) row[i++]);
boolean makeReadOnly = (Boolean) row[i++];
ValidationOptions options = (ValidationOptions) row[i++];
if (makeReadOnly) {
object.makeReadOnly();
}
AnyRecordValidator.setParameter(options, anyRecordValidatorParameter);
DataSchemaAnnotationValidator validator = new DataSchemaAnnotationValidator(schema);
if (debug)
TestUtil.out.println(validator);
ValidationResult result = ValidateDataAgainstSchema.validate(object, schema, options, validator);
checkValidationResult(result, row, i, debug);
}
}
use of com.linkedin.data.schema.DataSchema in project rest.li by linkedin.
the class TestValidator method testValidatorPriority.
@Test
public void testValidatorPriority() throws IOException {
Map<String, Class<? extends Validator>> validatorClassMap = new HashMap<String, Class<? extends Validator>>();
validatorClassMap.put("v1", OrderValidator.class);
validatorClassMap.put("v2", OrderValidator.class);
validatorClassMap.put("v3", OrderValidator.class);
validatorClassMap.put("v4", OrderValidator.class);
validatorClassMap.put("v5", OrderValidator.class);
validatorClassMap.put("v6", OrderValidator.class);
Object[][] inputs = { { // positive priority values
"{\n" + " \"name\" : \"Foo\",\n" + " \"type\" : \"record\",\n" + " \"fields\" : [], \n" + " \"validate\" : {\n" + " \"v1\" : { \"validatorPriority\" : 1, \"name\" : \"p1\" },\n" + " \"v2\" : { \"validatorPriority\" : 2, \"name\" : \"p2\" },\n" + " \"v3\" : { \"validatorPriority\" : 3, \"name\" : \"p3\" },\n" + " \"v4\" : { \"validatorPriority\" : 4, \"name\" : \"p4\" },\n" + " \"v5\" : { \"validatorPriority\" : 5, \"name\" : \"p5\" },\n" + " \"v6\" : { \"validatorPriority\" : 6, \"name\" : \"p6\" }\n" + " }\n" + "}\n", "{}", new String[] { ":p6", ":p5", ":p5", ":p4", ":p4", ":p3", ":p3", ":p2", ":p2", ":p1" } }, { // negative priority values
"{\n" + " \"name\" : \"Foo\",\n" + " \"type\" : \"record\",\n" + " \"fields\" : [], \n" + " \"validate\" : {\n" + " \"v1\" : { \"validatorPriority\" : -1, \"name\" : \"p-1\" },\n" + " \"v2\" : { \"validatorPriority\" : 0, \"name\" : \"p=0\" },\n" + " \"v3\" : { \"validatorPriority\" : 1, \"name\" : \"p+1\" }\n" + " }\n" + "}\n", "{}", new String[] { ":p+1", ":p=0", ":p=0", ":p-1" } }, { // default priority value
"{\n" + " \"name\" : \"Foo\",\n" + " \"type\" : \"record\",\n" + " \"fields\" : [], \n" + " \"validate\" : {\n" + " \"v1\" : { \"validatorPriority\" : -1, \"name\" : \"p-1\" },\n" + " \"v2\" : { \"name\" : \"pdefault\" },\n" + " \"v3\" : { \"validatorPriority\" : 1, \"name\" : \"p+1\" }\n" + " }\n" + "}\n", "{}", new String[] { ":p+1", ":pdefault", ":pdefault", ":p-1" } }, { // same priority values
"{\n" + " \"name\" : \"Foo\",\n" + " \"type\" : \"record\",\n" + " \"fields\" : [], \n" + " \"validate\" : {\n" + " \"v1\" : { \"validatorPriority\" : -1, \"name\" : \"p-1a\" },\n" + " \"v2\" : { \"validatorPriority\" : -1, \"name\" : \"p-1b\" },\n" + " \"v3\" : { \"validatorPriority\" : 0, \"name\" : \"p0a\" },\n" + " \"v4\" : { \"validatorPriority\" : 0, \"name\" : \"p0b\" },\n" + " \"v5\" : { \"validatorPriority\" : 1, \"name\" : \"p+1a\" },\n" + " \"v6\" : { \"validatorPriority\" : 1, \"name\" : \"p+1b\" }\n" + " }\n" + "}\n", "{}", new String[] { ":p+1a", ":p0a", ":p+1a", ":p0b", ":p+1b", ":p0a", ":p+1b", ":p0b", ":p0a", ":p-1a", ":p0a", ":p-1b", ":p0b", ":p-1a", ":p0b", ":p-1b" } }, { // typeref inner before outer
"{\n" + " \"name\" : \"Foo\",\n" + " \"type\" : \"record\",\n" + " \"fields\" : [\n" + " {\n" + " \"name\" : \"i\",\n" + " \"type\" : {\n" + " \"type\" : \"typeref\",\n" + " \"name\" : \"Ref1\",\n" + " \"ref\" : {\n" + " \"type\" : \"typeref\",\n" + " \"name\" : \"Ref2\",\n" + " \"ref\" : \"int\",\n" + " \"validate\" : {\n" + " \"v1\" : { \"validatorPriority\" : -1, \"name\" : \"r2-1\" },\n" + " \"v2\" : { \"name\" : \"r2=0\" },\n" + " \"v3\" : { \"validatorPriority\" : 1, \"name\" : \"r2+1\" }\n" + " }\n" + " },\n" + " \"validate\" : {\n" + " \"v1\" : { \"validatorPriority\" : -1, \"name\" : \"r1-1\" },\n" + " \"v2\" : { \"name\" : \"r1=0\" },\n" + " \"v3\" : { \"validatorPriority\" : 1, \"name\" : \"r1+1\" }\n" + " }\n" + " }\n" + " }\n" + " ]\n" + "}\n", "{\n" + " \"i\" : 4\n" + "}", new String[] { "/i:r2+1", "/i:r2=0", "/i:r2=0", "/i:r2-1", "/i:r2-1", "/i:r1+1", "/i:r1+1", "/i:r1=0", "/i:r1=0", "/i:r1-1" } }, { // array items before array
"{\n" + " \"name\" : \"Foo\",\n" + " \"type\" : \"record\",\n" + " \"fields\" : [\n" + " {\n" + " \"name\" : \"a\",\n" + " \"type\" : {\n" + " \"type\" : \"array\",\n" + " \"items\" : {\n" + " \"type\" : \"typeref\",\n" + " \"name\" : \"IntRef\",\n" + " \"ref\" : \"int\",\n" + " \"validate\" : {\n" + " \"v1\" : { \"validatorPriority\" : -1, \"name\" : \"i-1\" },\n" + " \"v2\" : { \"name\" : \"i=0\" },\n" + " \"v3\" : { \"validatorPriority\" : 1, \"name\" : \"i+1\" }\n" + " }\n" + " },\n" + " \"validate\" : {\n" + " \"v1\" : { \"validatorPriority\" : -1, \"name\" : \"a-1\" },\n" + " \"v2\" : { \"name\" : \"a=0\" },\n" + " \"v3\" : { \"validatorPriority\" : 1, \"name\" : \"a+1\" }\n" + " }\n" + " }\n" + " }\n" + " ]\n" + "}\n", "{\n" + " \"a\" : [ 1 ]\n" + "}", new String[] { "/a/0:i+1", "/a/0:i=0", "/a/0:i=0", "/a/0:i-1", "/a/0:i-1", "/a:a+1", "/a:a+1", "/a:a=0", "/a:a=0", "/a:a-1" } }, { // map values before map
"{\n" + " \"name\" : \"Foo\",\n" + " \"type\" : \"record\",\n" + " \"fields\" : [\n" + " {\n" + " \"name\" : \"m\",\n" + " \"type\" : {\n" + " \"type\" : \"map\",\n" + " \"values\" : {\n" + " \"type\" : \"typeref\",\n" + " \"name\" : \"IntRef\",\n" + " \"ref\" : \"int\",\n" + " \"validate\" : {\n" + " \"v1\" : { \"validatorPriority\" : -1, \"name\" : \"v-1\" },\n" + " \"v2\" : { \"name\" : \"v=0\" },\n" + " \"v3\" : { \"validatorPriority\" : 1, \"name\" : \"v+1\" }\n" + " }\n" + " },\n" + " \"validate\" : {\n" + " \"v1\" : { \"validatorPriority\" : -1, \"name\" : \"m-1\" },\n" + " \"v2\" : { \"name\" : \"m=0\" },\n" + " \"v3\" : { \"validatorPriority\" : 1, \"name\" : \"m+1\" }\n" + " }\n" + " }\n" + " }\n" + " ]\n" + "}\n", "{\n" + " \"m\" : { \"x\" : 1 } }\n" + "}", new String[] { "/m/x:v+1", "/m/x:v=0", "/m/x:v=0", "/m/x:v-1", "/m/x:v-1", "/m:m+1", "/m:m+1", "/m:m=0", "/m:m=0", "/m:m-1" } }, { // union member before typeref of union
"{\n" + " \"name\" : \"Foo\",\n" + " \"type\" : \"record\",\n" + " \"fields\" : [\n" + " {\n" + " \"name\" : \"u\",\n" + " \"type\" : {\n" + " \"type\" : \"typeref\",\n" + " \"name\" : \"Union\",\n" + " \"ref\" : [\n" + " {\n" + " \"type\" : \"typeref\",\n" + " \"name\" : \"Int\",\n" + " \"ref\" : \"int\",\n" + " \"validate\" : {\n" + " \"v1\" : { \"validatorPriority\" : -1, \"name\" : \"i-1\" },\n" + " \"v2\" : { \"name\" : \"i=0\" },\n" + " \"v3\" : { \"validatorPriority\" : 1, \"name\" : \"i+1\" }\n" + " }\n" + " },\n" + " \"string\"\n" + " ],\n" + " \"validate\" : {\n" + " \"v1\" : { \"validatorPriority\" : -1, \"name\" : \"u-1\" },\n" + " \"v2\" : { \"name\" : \"u=0\" },\n" + " \"v3\" : { \"validatorPriority\" : 1, \"name\" : \"u+1\" }\n" + " }\n" + " }\n" + " }\n" + " ]\n" + "}\n", "{\n" + " \"u\" : { \"int\" : 4 }\n" + "}", new String[] { "/u/int:i+1", "/u/int:i=0", "/u/int:i=0", "/u/int:i-1", "/u/int:i-1", "/u:u+1", "/u:u+1", "/u:u=0", "/u:u=0", "/u:u-1" } } };
boolean debug = false;
for (Object[] row : inputs) {
int i = 0;
String schemaText = (String) row[i++];
String dataMapText = (String) row[i++];
DataSchema schema = dataSchemaFromString(schemaText);
DataMap dataMap = dataMapFromString(dataMapText);
DataSchemaAnnotationValidator dataSchemaAnnotationValidator = new DataSchemaAnnotationValidator();
dataSchemaAnnotationValidator.init(schema, validatorClassMap);
if (debug)
out.println(dataSchemaAnnotationValidator.getInitMessages());
assertTrue(dataSchemaAnnotationValidator.isInitOk());
if (debug)
out.println(dataSchemaAnnotationValidator);
dataSchemaAnnotationValidator.setDebugMode(debug);
OrderValidator._orderList.clear();
ValidationOptions validationOptions = new ValidationOptions();
ValidationResult validationResult = ValidateDataAgainstSchema.validate(dataMap, schema, validationOptions, dataSchemaAnnotationValidator);
assertTrue(validationResult.isValid());
if (debug)
out.println(validationResult.getMessages());
if (debug)
out.println(OrderValidator._orderList);
String[] expectedRelations = (String[]) row[i++];
assertTrue(expectedRelations.length % 2 == 0);
for (int r = 0; r < expectedRelations.length; r += 2) {
OrderRelation orderRelation = new OrderRelation(new OrderEntry(expectedRelations[r]), new OrderEntry(expectedRelations[r + 1]));
assertTrue(orderRelation.isSatisfied(OrderValidator._orderList));
}
}
}
use of com.linkedin.data.schema.DataSchema in project rest.li by linkedin.
the class TestValidator method testBadInitializationOfDataSchemaAnnotationValidator.
@Test
public void testBadInitializationOfDataSchemaAnnotationValidator() throws IOException {
Object[][] input = { { // validate property is not a DataMap
"{\n" + " \"name\" : \"Foo\",\n" + " \"type\" : \"typeref\",\n" + " \"ref\" : \"int\", \n" + " \"validate\" : 32\n" + "}\n", "/Foo", "not a DataMap" }, { // validate property has key that cannot be resolved
"{\n" + " \"name\" : \"Foo\",\n" + " \"type\" : \"typeref\",\n" + " \"ref\" : \"int\", \n" + " \"validate\" : { \"unknown\" : { } }\n" + "}\n", "/Foo", "unable to find Validator for \"unknown\"" }, { // value associated with key is not a DataMap
"{\n" + " \"name\" : \"Foo\",\n" + " \"type\" : \"typeref\",\n" + " \"ref\" : \"int\", \n" + " \"validate\" : { \"bad\" : 10 }\n" + "}\n", "/Foo", "value of \"bad\" is not a DataMap" }, { // constructor throws exception
"{\n" + " \"name\" : \"Foo\",\n" + " \"type\" : \"typeref\",\n" + " \"ref\" : \"int\", \n" + " \"validate\" : { \"bad\" : { } }\n" + "}\n", "/Foo", "BadValidator cannot be instantiated for \"bad\"" }, { // validate in field bad
"{\n" + " \"name\" : \"Foo\",\n" + " \"type\" : \"record\",\n" + " \"fields\" : [\n" + " {\n" + " \"name\" : \"intField\",\n" + " \"type\" : \"int\",\n" + " \"validate\" : { \"bad\" : { } }\n" + " }\n" + " ]\n" + "}\n", "/Foo/intField", "BadValidator cannot be instantiated for \"bad\"" }, { // test path
"{\n" + " \"name\" : \"Foo\",\n" + " \"type\" : \"typeref\",\n" + " \"ref\" : {\n" + " \"name\" : \"Bar\",\n" + " \"type\" : \"record\",\n" + " \"fields\" : [\n" + " {\n" + " \"name\" : \"arrayField\",\n" + " \"type\" : {\n" + " \"type\" : \"array\",\n" + " \"items\" : {\n" + " \"type\" : \"map\",\n" + " \"values\" : \"string\",\n" + " \"validate\" : { \"bad\" : { } }\n" + " }\n" + " }\n" + " }\n" + " ]\n" + " }\n" + "}\n", "/Foo/ref/Bar/arrayField/array/items/map", "BadValidator cannot be instantiated for \"bad\"" }, { // Validator key identifies class that is not a Validator.
"{\n" + " \"name\" : \"Foo\",\n" + " \"type\" : \"typeref\",\n" + " \"ref\" : \"int\", \n" + " \"validate\" : { \"java.util.Map\" : { } }\n" + "}\n", "/Foo", "java.util.Map is not a com.linkedin.data.schema.validator.Validator", "unable to find Validator for \"java.util.Map\"" }, { // Validator key identifies class that is not a Validator.
"{\n" + " \"name\" : \"Foo\",\n" + " \"type\" : \"typeref\",\n" + " \"ref\" : \"int\", \n" + " \"validate\" : { \"notA\" : { } }\n" + "}\n", "/Foo", "com.linkedin.data.schema.validator.NotAValidator is not a com.linkedin.data.schema.validator.Validator", "unable to find Validator for \"notA\"" } };
final boolean debug = false;
Map<String, Class<? extends Validator>> validatorClassMap = new HashMap<String, Class<? extends Validator>>();
validatorClassMap.put("bad", BadValidator.class);
for (Object[] row : input) {
String schemaText = (String) row[0];
if (debug)
TestUtil.out.println(schemaText);
DataSchema schema = dataSchemaFromString(schemaText);
DataSchemaAnnotationValidator annotationValidator = new DataSchemaAnnotationValidator();
annotationValidator.init(schema, validatorClassMap);
if (debug)
TestUtil.out.println(annotationValidator.getInitMessages());
assertFalse(annotationValidator.isInitOk());
assertFalse(annotationValidator.getInitMessages().isEmpty());
for (int i = 1; i < row.length; i++) {
assertTrue(annotationValidator.getInitMessages().toString().contains((String) row[i]));
}
}
}
use of com.linkedin.data.schema.DataSchema in project rest.li by linkedin.
the class TestValidator method testValidator.
public void testValidator(String schemaText, Object[][] input, Map<String, Class<? extends Validator>> validatorClassMap, String[] validatorCheckStrings, int tests) throws IOException, InstantiationException {
DataSchema schema = dataSchemaFromString(schemaText);
DataSchemaAnnotationValidator annotationValidator = new DataSchemaAnnotationValidator();
annotationValidator.init(schema, validatorClassMap);
if (debug)
annotationValidator.setDebugMode(true);
String annotationValidatorString = annotationValidator.toString();
if (debug)
out.println(annotationValidator);
for (String checkString : validatorCheckStrings) {
assertTrue(annotationValidatorString.contains(checkString));
}
for (Object[] row : input) {
DataMap value = (DataMap) row[0];
try {
if ((tests & SCHEMA_VALIDATOR) != 0) {
VisitedTrackingValidator visitedValidator = new VisitedTrackingValidator(annotationValidator);
ValidationOptions validationOptions = new ValidationOptions(RequiredMode.CAN_BE_ABSENT_IF_HAS_DEFAULT, CoercionMode.NORMAL);
ValidationResult result = ValidateDataAgainstSchema.validate(value.copy(), schema, validationOptions, visitedValidator);
checkValidationResult(value, result, row, visitedValidator);
}
if ((tests & OBJECT_VALIDATOR) != 0) {
VisitedTrackingValidator visitedValidator = new VisitedTrackingValidator(annotationValidator);
ValidationOptions validationOptions = new ValidationOptions();
ValidationResult result = ValidateDataAgainstSchema.validate(value.copy(), schema, validationOptions, visitedValidator);
checkValidationResult(value, result, row, visitedValidator);
}
} catch (CloneNotSupportedException e) {
throw new IllegalStateException("unexpected exception", e);
}
}
}
Aggregations