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");
}
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;
}
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()));
}
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"));
}
}
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);
}
Aggregations