Search in sources :

Example 1 with AnyRecord

use of com.linkedin.restli.internal.server.methods.AnyRecord in project rest.li by linkedin.

the class CollectionResponseBuilder method buildRestLiResponseData.

private static RestLiResponseData buildRestLiResponseData(final RestRequest request, final RoutingResult routingResult, final List<? extends RecordTemplate> elements, final PageIncrement pageIncrement, final RecordTemplate customMetadata, final Integer totalResults, final Map<String, String> headers, final List<HttpCookie> cookies) {
    //Extract the resource context that contains projection information for root object entities, metadata and paging.
    final ResourceContext resourceContext = routingResult.getContext();
    //Calculate paging metadata and apply projection
    final CollectionMetadata paging = RestUtils.buildMetadata(request.getURI(), resourceContext, routingResult.getResourceMethod(), elements, pageIncrement, totalResults);
    //PagingMetadata cannot be null at this point so we skip the null check. Notice here that we are using automatic
    //intentionally since resource methods cannot explicitly project paging. However, it should be noted that client
    //resource methods have the option of selectively setting the total to null. This happens if a client decides
    //that they want the total in the paging response, which the resource method will see in their paging path spec,
    //and then specify total when they create CollectionResult. Restli will then also subsequently separately project
    //paging using this same path spec.
    //Note that there is no chance of potential data loss here:
    //If the client decides they don't want total in their paging response, then the resource method will
    //see the lack of total in their paging path spec and then decide to set total to null. We will then also exclude it
    //when we project paging.
    //If the client decides they want total in their paging response, then the resource method will see total in their
    //paging path spec and then decide to set total to a non null value. We will then also include it when we project
    //paging.
    final CollectionMetadata projectedPaging = new CollectionMetadata(RestUtils.projectFields(paging.data(), ProjectionMode.AUTOMATIC, resourceContext.getPagingProjectionMask()));
    //For root object entities
    List<AnyRecord> processedElements = new ArrayList<AnyRecord>(elements.size());
    for (RecordTemplate entry : elements) {
        //We don't permit null elements in our lists. If so, this is a developer error.
        if (entry == null) {
            throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Unexpected null encountered. Null element inside of a List returned by the resource method: " + routingResult.getResourceMethod());
        }
        processedElements.add(new AnyRecord(RestUtils.projectFields(entry.data(), resourceContext.getProjectionMode(), resourceContext.getProjectionMask())));
    }
    //Now for custom metadata
    final AnyRecord projectedCustomMetadata;
    if (customMetadata != null) {
        projectedCustomMetadata = new AnyRecord(RestUtils.projectFields(customMetadata.data(), resourceContext.getMetadataProjectionMode(), resourceContext.getMetadataProjectionMask()));
    } else {
        projectedCustomMetadata = null;
    }
    RestLiResponseDataImpl responseData = new RestLiResponseDataImpl(HttpStatus.S_200_OK, headers, cookies);
    RestLiResponseEnvelope responseEnvelope;
    switch(routingResult.getResourceMethod().getType()) {
        case GET_ALL:
            responseEnvelope = new GetAllResponseEnvelope(processedElements, projectedPaging, projectedCustomMetadata, responseData);
            break;
        case FINDER:
            responseEnvelope = new FinderResponseEnvelope(processedElements, projectedPaging, projectedCustomMetadata, responseData);
            break;
        default:
            throw new IllegalStateException("Resource method is invalid for CollectionResponseBuilder");
    }
    responseData.setResponseEnvelope(responseEnvelope);
    return responseData;
}
Also used : CollectionMetadata(com.linkedin.restli.common.CollectionMetadata) ResourceContext(com.linkedin.restli.server.ResourceContext) AnyRecord(com.linkedin.restli.internal.server.methods.AnyRecord) RestLiServiceException(com.linkedin.restli.server.RestLiServiceException) RecordTemplate(com.linkedin.data.template.RecordTemplate) ArrayList(java.util.ArrayList)

Example 2 with AnyRecord

use of com.linkedin.restli.internal.server.methods.AnyRecord in project rest.li by linkedin.

the class CollectionResponseBuilder method buildResponse.

@Override
public PartialRestResponse buildResponse(RoutingResult routingResult, RestLiResponseData responseData) {
    CollectionResponseEnvelope response = responseData.getCollectionResponseEnvelope();
    PartialRestResponse.Builder builder = new PartialRestResponse.Builder();
    CollectionResponse<AnyRecord> collectionResponse = new CollectionResponse<AnyRecord>(AnyRecord.class);
    collectionResponse.setPaging(response.getCollectionResponsePaging());
    DataList elementsMap = (DataList) collectionResponse.data().get(CollectionResponse.ELEMENTS);
    for (RecordTemplate entry : response.getCollectionResponse()) {
        CheckedUtil.addWithoutChecking(elementsMap, entry.data());
    }
    if (response.getCollectionResponseCustomMetadata() != null) {
        collectionResponse.setMetadataRaw(response.getCollectionResponseCustomMetadata().data());
    }
    builder.entity(collectionResponse);
    return builder.headers(responseData.getHeaders()).cookies(responseData.getCookies()).build();
}
Also used : DataList(com.linkedin.data.DataList) AnyRecord(com.linkedin.restli.internal.server.methods.AnyRecord) CollectionResponse(com.linkedin.restli.common.CollectionResponse) RecordTemplate(com.linkedin.data.template.RecordTemplate)

Example 3 with AnyRecord

use of com.linkedin.restli.internal.server.methods.AnyRecord in project rest.li by linkedin.

the class BatchCreateResponseBuilder method buildRestLiResponseData.

@Override
public RestLiResponseData buildRestLiResponseData(RestRequest request, RoutingResult routingResult, Object result, Map<String, String> headers, List<HttpCookie> cookies) {
    if (result instanceof BatchCreateKVResult) {
        BatchCreateKVResult<?, ?> list = (BatchCreateKVResult<?, ?>) result;
        if (list.getResults() == null) {
            throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Unexpected null encountered. Null List inside of a BatchCreateKVResult returned by the resource method: " + routingResult.getResourceMethod());
        }
        List<BatchCreateResponseEnvelope.CollectionCreateResponseItem> collectionCreateList = new ArrayList<BatchCreateResponseEnvelope.CollectionCreateResponseItem>(list.getResults().size());
        for (CreateKVResponse e : list.getResults()) {
            if (e == null) {
                throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Unexpected null encountered. Null element inside of List inside of a BatchCreateResult returned by the resource method: " + routingResult.getResourceMethod());
            } else {
                Object id = ResponseUtils.translateCanonicalKeyToAlternativeKeyIfNeeded(e.getId(), routingResult);
                if (e.getError() == null) {
                    final ResourceContext resourceContext = routingResult.getContext();
                    DataMap entityData = e.getEntity() != null ? e.getEntity().data() : null;
                    final DataMap data = RestUtils.projectFields(entityData, resourceContext.getProjectionMode(), resourceContext.getProjectionMask());
                    CreateIdEntityStatus<Object, RecordTemplate> entry = new CreateIdEntityStatus<Object, RecordTemplate>(e.getStatus().getCode(), id, new AnyRecord(data), null, ProtocolVersionUtil.extractProtocolVersion(headers));
                    collectionCreateList.add(new BatchCreateResponseEnvelope.CollectionCreateResponseItem(entry));
                } else {
                    collectionCreateList.add(new BatchCreateResponseEnvelope.CollectionCreateResponseItem(e.getError(), id));
                }
            }
        }
        RestLiResponseDataImpl responseData = new RestLiResponseDataImpl(HttpStatus.S_200_OK, headers, cookies);
        responseData.setResponseEnvelope(new BatchCreateResponseEnvelope(collectionCreateList, true, responseData));
        return responseData;
    } else {
        BatchCreateResult<?, ?> list = (BatchCreateResult<?, ?>) result;
        //Verify that a null list was not passed into the BatchCreateResult. If so, this is a developer error.
        if (list.getResults() == null) {
            throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Unexpected null encountered. Null List inside of a BatchCreateResult returned by the resource method: " + routingResult.getResourceMethod());
        }
        List<BatchCreateResponseEnvelope.CollectionCreateResponseItem> collectionCreateList = new ArrayList<BatchCreateResponseEnvelope.CollectionCreateResponseItem>(list.getResults().size());
        for (CreateResponse e : list.getResults()) {
            //Verify that a null element was not passed into the BatchCreateResult list. If so, this is a developer error.
            if (e == null) {
                throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Unexpected null encountered. Null element inside of List inside of a BatchCreateResult returned by the resource method: " + routingResult.getResourceMethod());
            } else {
                Object id = ResponseUtils.translateCanonicalKeyToAlternativeKeyIfNeeded(e.getId(), routingResult);
                if (e.getError() == null) {
                    CreateIdStatus<Object> entry = new CreateIdStatus<Object>(e.getStatus().getCode(), id, null, ProtocolVersionUtil.extractProtocolVersion(headers));
                    collectionCreateList.add(new BatchCreateResponseEnvelope.CollectionCreateResponseItem(entry));
                } else {
                    collectionCreateList.add(new BatchCreateResponseEnvelope.CollectionCreateResponseItem(e.getError(), id));
                }
            }
        }
        RestLiResponseDataImpl responseData = new RestLiResponseDataImpl(HttpStatus.S_200_OK, headers, cookies);
        responseData.setResponseEnvelope(new BatchCreateResponseEnvelope(collectionCreateList, responseData));
        return responseData;
    }
}
Also used : ResourceContext(com.linkedin.restli.server.ResourceContext) AnyRecord(com.linkedin.restli.internal.server.methods.AnyRecord) CreateIdEntityStatus(com.linkedin.restli.common.CreateIdEntityStatus) CreateResponse(com.linkedin.restli.server.CreateResponse) ArrayList(java.util.ArrayList) CreateIdStatus(com.linkedin.restli.common.CreateIdStatus) DataMap(com.linkedin.data.DataMap) RestLiServiceException(com.linkedin.restli.server.RestLiServiceException) RecordTemplate(com.linkedin.data.template.RecordTemplate) BatchCreateResult(com.linkedin.restli.server.BatchCreateResult) BatchCreateKVResult(com.linkedin.restli.server.BatchCreateKVResult) CreateKVResponse(com.linkedin.restli.server.CreateKVResponse)

Example 4 with AnyRecord

use of com.linkedin.restli.internal.server.methods.AnyRecord in project rest.li by linkedin.

the class BatchGetResponseBuilder method buildRestLiResponseData.

@Override
public RestLiResponseData buildRestLiResponseData(RestRequest request, RoutingResult routingResult, Object result, Map<String, String> headers, List<HttpCookie> cookies) {
    @SuppressWarnings({ "unchecked" }) final Map<Object, RecordTemplate> /** constrained by signature of {@link com.linkedin.restli.server.resources.CollectionResource#batchGet(java.util.Set)} */
    entities = (Map<Object, RecordTemplate>) result;
    Map<Object, HttpStatus> statuses = Collections.emptyMap();
    Map<Object, RestLiServiceException> serviceErrors = Collections.emptyMap();
    if (result instanceof BatchResult) {
        @SuppressWarnings({ "unchecked" }) final BatchResult<Object, RecordTemplate> /** constrained by signature of {@link com.linkedin.restli.server.resources.CollectionResource#batchGet(java.util.Set)} */
        batchResult = (BatchResult<Object, RecordTemplate>) result;
        statuses = batchResult.getStatuses();
        serviceErrors = batchResult.getErrors();
    }
    try {
        if (statuses.containsKey(null)) {
            throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Unexpected null encountered. Null key inside of a Map returned by the resource method: " + routingResult.getResourceMethod());
        }
    } catch (NullPointerException e) {
    // Some map implementations will throw an NPE if they do not support null keys.
    // In this case it is OK to swallow this exception and proceed.
    }
    Map<Object, BatchResponseEntry> batchResult = new HashMap<Object, BatchResponseEntry>(entities.size() + serviceErrors.size());
    for (Map.Entry<Object, RecordTemplate> entity : entities.entrySet()) {
        if (entity.getKey() == null) {
            throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Unexpected null encountered. Null key inside of a Map returned by the resource method: " + routingResult.getResourceMethod());
        }
        Object finalKey = ResponseUtils.translateCanonicalKeyToAlternativeKeyIfNeeded(entity.getKey(), routingResult);
        final DataMap projectedData = RestUtils.projectFields(entity.getValue().data(), routingResult.getContext().getProjectionMode(), routingResult.getContext().getProjectionMask());
        AnyRecord anyRecord = new AnyRecord(projectedData);
        batchResult.put(finalKey, new BatchResponseEntry(statuses.get(entity.getKey()), anyRecord));
    }
    for (Map.Entry<Object, RestLiServiceException> entity : serviceErrors.entrySet()) {
        if (entity.getKey() == null || entity.getValue() == null) {
            throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Unexpected null encountered. Null key inside of a Map returned by the resource method: " + routingResult.getResourceMethod());
        }
        Object finalKey = ResponseUtils.translateCanonicalKeyToAlternativeKeyIfNeeded(entity.getKey(), routingResult);
        batchResult.put(finalKey, new BatchResponseEntry(statuses.get(entity.getKey()), entity.getValue()));
    }
    final Map<Object, RestLiServiceException> contextErrors = ((ServerResourceContext) routingResult.getContext()).getBatchKeyErrors();
    for (Map.Entry<Object, RestLiServiceException> entry : contextErrors.entrySet()) {
        Object finalKey = ResponseUtils.translateCanonicalKeyToAlternativeKeyIfNeeded(entry.getKey(), routingResult);
        batchResult.put(finalKey, new BatchResponseEntry(statuses.get(entry.getKey()), entry.getValue()));
    }
    RestLiResponseDataImpl responseData = new RestLiResponseDataImpl(HttpStatus.S_200_OK, headers, cookies);
    responseData.setResponseEnvelope(new BatchGetResponseEnvelope(batchResult, responseData));
    return responseData;
}
Also used : AnyRecord(com.linkedin.restli.internal.server.methods.AnyRecord) HttpStatus(com.linkedin.restli.common.HttpStatus) HashMap(java.util.HashMap) BatchResult(com.linkedin.restli.server.BatchResult) DataMap(com.linkedin.data.DataMap) BatchResponseEntry(com.linkedin.restli.internal.server.response.BatchResponseEnvelope.BatchResponseEntry) RestLiServiceException(com.linkedin.restli.server.RestLiServiceException) ServerResourceContext(com.linkedin.restli.internal.server.ServerResourceContext) RecordTemplate(com.linkedin.data.template.RecordTemplate) HashMap(java.util.HashMap) DataMap(com.linkedin.data.DataMap) Map(java.util.Map)

Example 5 with AnyRecord

use of com.linkedin.restli.internal.server.methods.AnyRecord in project rest.li by linkedin.

the class TestRestLiValidationFromClient method testInvalidInputEntityValidation.

@Test
public void testInvalidInputEntityValidation() {
    try {
        ValidationDemosCreateRequestBuilder.validateInput(null);
        Assert.fail("Expected IllegalArgumentException.");
    } catch (IllegalArgumentException e) {
        Assert.assertEquals(e.getMessage(), "Record template is null.");
    }
    try {
        ValidationDemosCreateRequestBuilder.validateInput(new ValidationDemo(null));
        Assert.fail("Expected IllegalArgumentException.");
    } catch (IllegalArgumentException e) {
        Assert.assertEquals(e.getMessage(), "Record template does not have data.");
    }
    try {
        RestLiDataValidator anyRecordValidator = new RestLiDataValidator(Collections.<String, List<String>>emptyMap(), AnyRecord.class, ResourceMethod.CREATE);
        anyRecordValidator.validateInput(new AnyRecord(new DataMap()));
        Assert.fail("Expected IllegalArgumentException.");
    } catch (IllegalArgumentException e) {
        Assert.assertEquals(e.getMessage(), "Record template does not have a schema.");
    }
}
Also used : AnyRecord(com.linkedin.restli.internal.server.methods.AnyRecord) RestLiDataValidator(com.linkedin.restli.common.validation.RestLiDataValidator) ValidationDemo(com.linkedin.restli.examples.greetings.api.ValidationDemo) DataMap(com.linkedin.data.DataMap) Test(org.testng.annotations.Test)

Aggregations

AnyRecord (com.linkedin.restli.internal.server.methods.AnyRecord)25 DataMap (com.linkedin.data.DataMap)18 RecordTemplate (com.linkedin.data.template.RecordTemplate)17 RestLiServiceException (com.linkedin.restli.server.RestLiServiceException)10 ResourceContext (com.linkedin.restli.server.ResourceContext)8 HashMap (java.util.HashMap)8 ProtocolVersion (com.linkedin.restli.common.ProtocolVersion)7 ArrayList (java.util.ArrayList)7 ServerResourceContext (com.linkedin.restli.internal.server.ServerResourceContext)6 BatchResponseEntry (com.linkedin.restli.internal.server.response.BatchResponseEnvelope.BatchResponseEntry)6 Map (java.util.Map)6 DataList (com.linkedin.data.DataList)5 CollectionMetadata (com.linkedin.restli.common.CollectionMetadata)4 HttpStatus (com.linkedin.restli.common.HttpStatus)4 CreateResponse (com.linkedin.restli.server.CreateResponse)4 RecordDataSchema (com.linkedin.data.schema.RecordDataSchema)3 RequestContext (com.linkedin.r2.message.RequestContext)3 CreateIdStatus (com.linkedin.restli.common.CreateIdStatus)3 UpdateStatus (com.linkedin.restli.common.UpdateStatus)3 ResourceContextImpl (com.linkedin.restli.internal.server.ResourceContextImpl)3