Search in sources :

Example 1 with SimpleDataElement

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);
                }
            }
        }
    }
}
Also used : RecordDataSchema(com.linkedin.data.schema.RecordDataSchema) DataSchema(com.linkedin.data.schema.DataSchema) NamedDataSchema(com.linkedin.data.schema.NamedDataSchema) SimpleDataElement(com.linkedin.data.element.SimpleDataElement) DataElement(com.linkedin.data.element.DataElement) Message(com.linkedin.data.message.Message) RecordDataSchema(com.linkedin.data.schema.RecordDataSchema) SimpleDataElement(com.linkedin.data.element.SimpleDataElement) ValidationResult(com.linkedin.data.schema.validation.ValidationResult) DataMap(com.linkedin.data.DataMap)

Example 2 with SimpleDataElement

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;
}
Also used : SimpleDataElement(com.linkedin.data.element.SimpleDataElement) DataElement(com.linkedin.data.element.DataElement) Message(com.linkedin.data.message.Message) SimpleDataElement(com.linkedin.data.element.SimpleDataElement) ValidationOptions(com.linkedin.data.schema.validation.ValidationOptions) ValidationResult(com.linkedin.data.schema.validation.ValidationResult)

Example 3 with SimpleDataElement

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()));
}
Also used : Message(com.linkedin.data.message.Message) PatchRequest(com.linkedin.restli.common.PatchRequest) DataComplexProcessor(com.linkedin.data.transform.DataComplexProcessor) ValidationResult(com.linkedin.data.schema.validation.ValidationResult) ValidationOptions(com.linkedin.data.schema.validation.ValidationOptions) DataProcessingException(com.linkedin.data.transform.DataProcessingException) RecordTemplate(com.linkedin.data.template.RecordTemplate) SimpleDataElement(com.linkedin.data.element.SimpleDataElement) Patch(com.linkedin.data.transform.patch.Patch)

Example 4 with SimpleDataElement

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);
}
Also used : SimpleTestData(com.linkedin.data.it.IteratorTestData.SimpleTestData) SimpleDataElement(com.linkedin.data.element.SimpleDataElement) Test(org.testng.annotations.Test)

Example 5 with SimpleDataElement

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);
}
Also used : SimpleTestData(com.linkedin.data.it.IteratorTestData.SimpleTestData) SimpleDataElement(com.linkedin.data.element.SimpleDataElement) Test(org.testng.annotations.Test)

Aggregations

SimpleDataElement (com.linkedin.data.element.SimpleDataElement)8 DataElement (com.linkedin.data.element.DataElement)4 Test (org.testng.annotations.Test)4 SimpleTestData (com.linkedin.data.it.IteratorTestData.SimpleTestData)3 Message (com.linkedin.data.message.Message)3 ValidationResult (com.linkedin.data.schema.validation.ValidationResult)3 DataMap (com.linkedin.data.DataMap)2 ValidationOptions (com.linkedin.data.schema.validation.ValidationOptions)2 ByteString (com.linkedin.data.ByteString)1 DataSchema (com.linkedin.data.schema.DataSchema)1 NamedDataSchema (com.linkedin.data.schema.NamedDataSchema)1 RecordDataSchema (com.linkedin.data.schema.RecordDataSchema)1 RecordTemplate (com.linkedin.data.template.RecordTemplate)1 DataComplexProcessor (com.linkedin.data.transform.DataComplexProcessor)1 DataProcessingException (com.linkedin.data.transform.DataProcessingException)1 Patch (com.linkedin.data.transform.patch.Patch)1 PatchRequest (com.linkedin.restli.common.PatchRequest)1 HashSet (java.util.HashSet)1