Search in sources :

Example 6 with Message

use of com.linkedin.data.message.Message in project rest.li by linkedin.

the class TestValidator method checkValidationResult.

public void checkValidationResult(Object value, ValidationResult result, Object[] row, VisitedTrackingValidator visitedValidator) throws IOException {
    Collection<Message> messages = result.getMessages();
    StringBuilder resultStringBuilder = new StringBuilder(dataMapToString((DataMap) result.getFixed()));
    if (messages.size() > 0) {
        resultStringBuilder.append("\n").append(messages.toString());
    }
    String resultString = resultStringBuilder.toString();
    if (debug)
        out.println("value: " + value.toString() + "\nresult:\n" + resultString);
    for (int col = 1; col < row.length; col++) {
        String checkString = (String) row[col];
        boolean ok = resultString.contains(checkString);
        assertTrue(ok, resultString + " does not contain " + checkString);
    }
    Set<String> visitedMoreThanOnce = visitedValidator.getVisitedMoreThanOnce();
    assertTrue(visitedMoreThanOnce.isEmpty(), visitedMoreThanOnce + " is visited more than once");
}
Also used : Message(com.linkedin.data.message.Message) TestUtil.dataSchemaFromPdlString(com.linkedin.data.TestUtil.dataSchemaFromPdlString) TestUtil.dataMapFromString(com.linkedin.data.TestUtil.dataMapFromString) TestUtil.dataSchemaFromString(com.linkedin.data.TestUtil.dataSchemaFromString) DataMap(com.linkedin.data.DataMap)

Example 7 with Message

use of com.linkedin.data.message.Message 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 8 with Message

use of com.linkedin.data.message.Message 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 9 with Message

use of com.linkedin.data.message.Message in project rest.li by linkedin.

the class TestRestLiValidation method testCustomValidatorMap.

@Test
public void testCustomValidatorMap() {
    // Provide Rest.li annotations manually since the validator is not called from the server or through generated request builders.
    Map<String, List<String>> annotations = new HashMap<>();
    annotations.put("createOnly", Arrays.asList("stringB", "intB", "UnionFieldWithInlineRecord/com.linkedin.restli.examples.greetings.api.myRecord/foo2", "MapWithTyperefs/*/id"));
    annotations.put("readOnly", Arrays.asList("stringA", "intA", "UnionFieldWithInlineRecord/com.linkedin.restli.examples.greetings.api.myRecord/foo1", "ArrayWithInlineRecord/*/bar1", "validationDemoNext/stringB", "validationDemoNext/UnionFieldWithInlineRecord"));
    // Invalid entity, because intB is not a multiple of seven.
    ValidationDemo.UnionFieldWithInlineRecord unionField1 = new ValidationDemo.UnionFieldWithInlineRecord();
    unionField1.setMyEnum(myEnum.FOOFOO);
    ValidationDemo entity = new ValidationDemo().setIntB(24).setStringB("some string").setUnionFieldWithInlineRecord(unionField1);
    // Validate without the class map
    RestLiDataValidator validator = new RestLiDataValidator(annotations, ValidationDemo.class, ResourceMethod.CREATE);
    ValidationResult result = validator.validateInput(entity);
    Assert.assertTrue(result.isValid());
    // Validate with the class map
    Map<String, Class<? extends Validator>> validatorClassMap = new HashMap<>();
    validatorClassMap.put("seven", SevenValidator.class);
    validator = new RestLiDataValidator(annotations, ValidationDemo.class, ResourceMethod.CREATE, validatorClassMap);
    result = validator.validateInput(entity);
    Assert.assertFalse(result.isValid());
    Assert.assertEquals(result.getMessages().size(), 1);
    for (Message message : result.getMessages()) {
        Assert.assertTrue(message.toString().contains("24 is not a multiple of seven"));
    }
}
Also used : Message(com.linkedin.data.message.Message) HashMap(java.util.HashMap) ValidationResult(com.linkedin.data.schema.validation.ValidationResult) ValidationDemo(com.linkedin.restli.examples.greetings.api.ValidationDemo) RestLiDataValidator(com.linkedin.restli.common.validation.RestLiDataValidator) List(java.util.List) ArrayList(java.util.ArrayList) BeforeClass(org.testng.annotations.BeforeClass) AfterClass(org.testng.annotations.AfterClass) Validator(com.linkedin.data.schema.validator.Validator) AbstractValidator(com.linkedin.data.schema.validator.AbstractValidator) RestLiDataValidator(com.linkedin.restli.common.validation.RestLiDataValidator) Test(org.testng.annotations.Test)

Example 10 with Message

use of com.linkedin.data.message.Message in project rest.li by linkedin.

the class MockValidationErrorHandler method updateErrorDetails.

@Override
public void updateErrorDetails(RestLiServiceException exception, Collection<Message> messages) {
    MockBadRequest badRequest = new MockBadRequest();
    MockInputErrorArray inputErrors = new MockInputErrorArray();
    for (Message message : messages) {
        if (message.isError() && message.getErrorDetails() instanceof MockInputError) {
            inputErrors.add((MockInputError) message.getErrorDetails());
        }
    }
    badRequest.setInputErrors(inputErrors);
    exception.setErrorDetails(badRequest);
    exception.setCode(ERROR_CODE);
}
Also used : MockInputError(com.linkedin.restli.server.errors.MockInputError) Message(com.linkedin.data.message.Message) MockInputErrorArray(com.linkedin.restli.server.errors.MockInputErrorArray) MockBadRequest(com.linkedin.restli.server.errors.MockBadRequest)

Aggregations

Message (com.linkedin.data.message.Message)20 DataElement (com.linkedin.data.element.DataElement)7 ValidationResult (com.linkedin.data.schema.validation.ValidationResult)5 DataMap (com.linkedin.data.DataMap)4 SimpleDataElement (com.linkedin.data.element.SimpleDataElement)4 RecordDataSchema (com.linkedin.data.schema.RecordDataSchema)3 TestUtil.dataMapFromString (com.linkedin.data.TestUtil.dataMapFromString)2 TestUtil.dataSchemaFromString (com.linkedin.data.TestUtil.dataSchemaFromString)2 DataSchema (com.linkedin.data.schema.DataSchema)2 NamedDataSchema (com.linkedin.data.schema.NamedDataSchema)2 ValidationOptions (com.linkedin.data.schema.validation.ValidationOptions)2 DataComplexProcessor (com.linkedin.data.transform.DataComplexProcessor)2 DataProcessingException (com.linkedin.data.transform.DataProcessingException)2 MockBadRequest (com.linkedin.restli.server.errors.MockBadRequest)2 MockInputError (com.linkedin.restli.server.errors.MockInputError)2 MockInputErrorArray (com.linkedin.restli.server.errors.MockInputErrorArray)2 HashMap (java.util.HashMap)2 Map (java.util.Map)2 Test (org.testng.annotations.Test)2 ByteString (com.linkedin.data.ByteString)1