Kamil Szopa
Kamil Szopa

Reputation: 21

How to implement triple or more segment navigation in OData 4?

I'm working on rest serivce with OData v4 protocol using olingo. I got stack on navigation when I've got let's say:

Company.svc/Departaments(x)/Employees(x)/BusinessTrips

In Olingo's tutorial there is an example where is 2 segments navigation. Where first segment is UriResourceEntitySet and second is UriResourceNavigation.

In the example, these two (especially entitySet) are needed as parameters in method which gets related entity collection from storage.

In my example there is

Company.svc/UriResourceEntitySet/UriResourceNavigation/UriResourceNavigation

what can I say from UriInfo parameter?

I have no clue how to do that. Should I change the method or somehow force the penultimate segment to be EntitySet.

Thanks for your interest, and I'm wait for responses.

@Override
public void readEntityCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType responseFormat)
        throws ODataApplicationException, ODataLibraryException {
    String lastUri = "lastUriResource";
    String sourceNavigationUri = "sourceUriResource";

    EdmEntitySet responseEntitySet = null;
    EntityCollection responseEntityCollection = null;

    List<UriResource> resourcePaths = uriInfo.getUriResourceParts();
    UriResource uriResource = resourcePaths.get(0);
    if (!(uriResource instanceof UriResourceEntitySet)) {
        throw new ODataApplicationException("Only EntitySet is supported", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ENGLISH);
    }

    UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet) uriResource;
    EdmEntitySet startEntitySet = uriResourceEntitySet.getEntitySet();
    if (resourcePaths.size() == 1) {
        responseEntitySet = startEntitySet;
        responseEntityCollection = storage.readEntitySetData(responseEntitySet);
    } else {
        startEntitySet = Util.getNavigationTargetEntitySet(uriInfo);
        HashMap<String, UriResource> uriResourceHashMap = Util.getLastNavigationAndItsSource(uriInfo);
        UriResource lastUriResource = uriResourceHashMap.get(lastUri);
        UriResource sourceUriResource = uriResourceHashMap.get(sourceNavigationUri);
        EdmNavigationProperty edmNavigationProperty = null;
        if (!(lastUriResource instanceof UriResourceNavigation)) {
            throw new ODataApplicationException("Only navigation is supported", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ENGLISH);
        }
        edmNavigationProperty = ((UriResourceNavigation) lastUriResource).getProperty();

        if (!(sourceUriResource instanceof UriResourceEntitySet)) {
            throw new ODataApplicationException("Only Entity Set is supported", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ENGLISH);
        }
        uriResourceEntitySet = (UriResourceEntitySet) sourceUriResource;
        startEntitySet = uriResourceEntitySet.getEntitySet();
        responseEntitySet = Util.getNavigationTargetEntitySet(uriInfo);
        EdmEntityType targetEntityType = edmNavigationProperty.getType();
        List<UriParameter> keyParameters = uriResourceEntitySet.getKeyPredicates();

        Entity sourceEntity = storage.readEntityData(startEntitySet, keyParameters);
        if (sourceEntity == null) {
            throw new ODataApplicationException("Entity not found", HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ROOT);
        }
        responseEntityCollection = storage.getRelatedEntityCollection(sourceEntity, targetEntityType);
    }

    ContextURL contextUrl = ContextURL.with().entitySet(responseEntitySet).build();

    final String id = request.getRawBaseUri() + "/" + responseEntitySet.getName();
    EntityCollectionSerializerOptions options = EntityCollectionSerializerOptions.with().id(id).contextURL(contextUrl).build();
    EdmEntityType edmEntityType = responseEntitySet.getEntityType();

    ODataSerializer serializer = odata.createSerializer(responseFormat);
    SerializerResult serializerResult = serializer.entityCollection(serviceMetaData, edmEntityType, responseEntityCollection, options);
    InputStream inputStream = serializerResult.getContent();

    response.setContent(inputStream);
    response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
    response.setStatusCode(HttpStatusCode.OK.getStatusCode());
}

Upvotes: 2

Views: 349

Answers (1)

mat3e
mat3e

Reputation: 791

Departaments(x) is UriResourceEntitySet. You probably got its EdmEntitySet. Let's say it is stored in prevEdmEntitySet variable.

Employees(x) is UriResourceNavigation. You should take its name and use it with the variable mentioned above:

String propName = uriResourceNavigation.getProperty().getName();
EdmEntitySet currEdmEntitySet = (EdmEntitySet) startEdmEntitySet.getRelatedBindingTarget(propName);

Then you should start the next iteration with prevEdmEntitySet=currEdmEntitySet and repeat for all the UriResourceNavigations (just one more time in your example).

Upvotes: 1

Related Questions