use of com.linkedin.data.element.SimpleDataElement 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.element.SimpleDataElement in project rest.li by linkedin.
the class RestLiDataValidator method checkNewRecordsAreNotMissingFields.
/**
* Validates that new whole records created as part of of a patch set operation aren't missing required fields,
* with ReadOnly fields being treated as optional.
*/
private ValidationResult checkNewRecordsAreNotMissingFields(RecordTemplate entity, MessageList<Message> messages) {
for (Message message : messages) {
Object[] path = message.getPath();
if (path[path.length - 1].toString().equals(PatchConstants.SET_COMMAND)) {
// Replace $set with the field name to get the full path
path[path.length - 1] = message.getFormat();
DataElement element = DataElementUtil.element(new SimpleDataElement(entity.data(), entity.schema()), path);
ValidationOptions validationOptions = new ValidationOptions();
validationOptions.setTreatOptional(_readOnlyOptionalPredicate);
ValidationResult result = ValidateDataAgainstSchema.validate(element, validationOptions);
if (!result.isValid()) {
return result;
}
}
}
return null;
}
use of com.linkedin.data.element.SimpleDataElement in project rest.li by linkedin.
the class RestLiDataValidator method validatePatch.
/**
* Checks that if the patch is applied to a valid entity, the modified entity will also be valid.
* This method...
* (1) Checks that required/ReadOnly/CreateOnly fields are not deleted.
* (2) Checks that new values for record templates contain all required fields (treating ReadOnly fields as optional).
* (3) Applies the patch to an empty entity and validates the entity for custom validation rules
* and Rest.li annotations, allowing the following exceptions:
* - Allows required fields to be absent by using {@link RequiredMode#IGNORE},
* because a patch does not necessarily contain all fields.
* - Allows array-descendant ReadOnly/CreateOnly fields to be set, since there's currently no way to "patch" arrays.
*
* @param patchRequest the patch
* @return the final validation result
*/
private ValidationResult validatePatch(PatchRequest<?> patchRequest) {
// Instantiate an empty entity.
RecordTemplate entity;
try {
entity = _valueClass.newInstance();
} catch (InstantiationException e) {
return validationResultWithErrorMessage(INSTANTIATION_ERROR);
} catch (IllegalAccessException e) {
return validationResultWithErrorMessage(ILLEGAL_ACCESS_ERROR);
}
// Apply the patch to the entity and get paths that $set and $delete operations were performed on.
@SuppressWarnings("unchecked") PatchRequest<RecordTemplate> patch = (PatchRequest<RecordTemplate>) patchRequest;
DataComplexProcessor processor = new DataComplexProcessor(new Patch(true), patch.getPatchDocument(), entity.data());
MessageList<Message> messages;
try {
messages = processor.runDataProcessing(false);
} catch (DataProcessingException e) {
return validationResultWithErrorMessage("Error while applying patch: " + e.getMessage());
}
// Check that required/ReadOnly/CreateOnly fields are not deleted
ValidationErrorResult checkDeleteResult = new ValidationErrorResult();
checkDeletesAreValid(entity.schema(), messages, checkDeleteResult);
if (!checkDeleteResult.isValid()) {
return checkDeleteResult;
}
// Check that new values for record templates contain all required fields
ValidationResult checkSetResult = checkNewRecordsAreNotMissingFields(entity, messages);
if (checkSetResult != null) {
return checkSetResult;
}
// It's okay if required fields are absent in a partial update request, so use ignore mode.
return ValidateDataAgainstSchema.validate(new SimpleDataElement(entity.data(), entity.schema()), new ValidationOptions(RequiredMode.IGNORE), getValidatorForInputEntityValidation(entity.schema()));
}
use of com.linkedin.data.element.SimpleDataElement in project rest.li by linkedin.
the class TestRemover method testRemoveByPredicate.
@Test
public void testRemoveByPredicate() throws Exception {
SimpleTestData data = IteratorTestData.createSimpleTestData();
SimpleDataElement el = data.getDataElement();
Builder.create(el.getValue(), el.getSchema(), IterationOrder.PRE_ORDER).filterBy(Predicates.pathMatchesPathSpec(IteratorTestData.PATH_TO_ID)).remove();
assertTrue(data.getValue().getDataList("foo").getDataMap(0).getInteger("id") == null);
assertTrue(data.getValue().getDataList("foo").getDataMap(1).getInteger("id") == null);
assertTrue(data.getValue().getDataList("foo").getDataMap(2).getInteger("id") == null);
}
use of com.linkedin.data.element.SimpleDataElement in project rest.li by linkedin.
the class TestRemover method testRemoveByPredicateWithPostOrder.
@Test
public void testRemoveByPredicateWithPostOrder() throws Exception {
SimpleTestData data = IteratorTestData.createSimpleTestData();
SimpleDataElement el = data.getDataElement();
Builder.create(el.getValue(), el.getSchema(), IterationOrder.POST_ORDER).filterBy(Predicates.pathMatchesPathSpec(IteratorTestData.PATH_TO_ID)).remove();
assertTrue(data.getValue().getDataList("foo").getDataMap(0).getInteger("id") == null);
assertTrue(data.getValue().getDataList("foo").getDataMap(1).getInteger("id") == null);
assertTrue(data.getValue().getDataList("foo").getDataMap(2).getInteger("id") == null);
}
Aggregations