use of com.linkedin.restli.common.PatchRequest in project rest.li by linkedin.
the class BatchPartialUpdateRequestBuilder method buildReadOnlyInput.
private CollectionRequest<KeyValueRecord<K, PatchRequest<V>>> buildReadOnlyInput() {
try {
DataMap map = new DataMap();
@SuppressWarnings({ "unchecked", "rawtypes" }) CollectionRequest<KeyValueRecord<K, PatchRequest<V>>> input = new CollectionRequest(map, KeyValueRecord.class);
for (Map.Entry<K, PatchRequest<V>> inputEntityEntry : _partialUpdateInputMap.entrySet()) {
K key = getReadOnlyOrCopyKey(inputEntityEntry.getKey());
PatchRequest<V> entity = getReadOnlyOrCopyDataTemplate(inputEntityEntry.getValue());
KeyValueRecord<K, PatchRequest<V>> keyValueRecord = _keyValueRecordFactory.create(key, entity);
keyValueRecord.data().setReadOnly();
input.getElements().add(keyValueRecord);
}
map.setReadOnly();
return input;
} catch (CloneNotSupportedException cloneException) {
throw new IllegalArgumentException("Entity cannot be copied.", cloneException);
}
}
use of com.linkedin.restli.common.PatchRequest 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.restli.common.PatchRequest in project rest.li by linkedin.
the class ComplexKeysDataProvider method batchUpdate.
public BatchUpdateResult<ComplexResourceKey<TwoPartKey, TwoPartKey>, Message> batchUpdate(BatchPatchRequest<ComplexResourceKey<TwoPartKey, TwoPartKey>, Message> patches) {
final Map<ComplexResourceKey<TwoPartKey, TwoPartKey>, UpdateResponse> results = new HashMap<>();
for (Map.Entry<ComplexResourceKey<TwoPartKey, TwoPartKey>, PatchRequest<Message>> patch : patches.getData().entrySet()) {
try {
this.partialUpdate(patch.getKey(), patch.getValue());
results.put(patch.getKey(), new UpdateResponse(HttpStatus.S_204_NO_CONTENT));
} catch (DataProcessingException e) {
results.put(patch.getKey(), new UpdateResponse(HttpStatus.S_400_BAD_REQUEST));
}
}
return new BatchUpdateResult<>(results);
}
use of com.linkedin.restli.common.PatchRequest in project rest.li by linkedin.
the class AutomaticValidationDemoResource method batchUpdate.
@RestMethod.BatchPartialUpdate
public BatchUpdateResult<Integer, ValidationDemo> batchUpdate(final BatchPatchRequest<Integer, ValidationDemo> entityUpdates) {
Map<Integer, UpdateResponse> results = new HashMap<>();
Map<Integer, RestLiServiceException> errors = new HashMap<>();
for (Map.Entry<Integer, PatchRequest<ValidationDemo>> entry : entityUpdates.getData().entrySet()) {
Integer key = entry.getKey();
PatchRequest<ValidationDemo> patch = entry.getValue();
results.put(key, new UpdateResponse(HttpStatus.S_204_NO_CONTENT));
}
return new BatchUpdateResult<>(results, errors);
}
use of com.linkedin.restli.common.PatchRequest in project rest.li by linkedin.
the class TestRestLiScatterGather method testSendScatterGatherRequest.
@Test(dataProvider = TestConstants.RESTLI_PROTOCOL_1_2_PREFIX + "scatterGatherDataProvider", // Known to be flaky in CI
retryAnalyzer = SingleRetry.class)
public static void testSendScatterGatherRequest(URIMapper mapper, RootBuilderWrapper<Long, Greeting> builders) throws RemoteInvocationException {
RestLiClientConfig config = new RestLiClientConfig();
config.setScatterGatherStrategy(new DefaultScatterGatherStrategy(mapper));
RestClient restClient = new AlwaysD2RestClient(CLIENT, URI_PREFIX, config);
final int NUM_IDS = 20;
List<Greeting> entities = generateCreate(NUM_IDS);
Long[] requestIds = prepareData(restClient, entities);
// BATCH_GET
testSendSGGetRequests(restClient, requestIds);
testSendSGGetEntityRequests(restClient, requestIds);
testSendSGGetKVRequests(restClient, requestIds);
// BATCH_UPDATE
Map<Long, Greeting> input = generateUpdates(requestIds);
testSendSGUpdateRequests(restClient, input, builders);
// BATCH_PATIAL_UPDATE
Map<Long, PatchRequest<Greeting>> patch = generatePartialUpdates(requestIds);
testSendSGPartialUpdateRequests(restClient, patch, builders);
// BATCH_DELETE
testSendSGDeleteRequests(restClient, requestIds, builders);
}
Aggregations