Repository: olingo-odata4 Updated Branches: refs/heads/master 0be567b9c -> 7f86b264f
[OLINGO-422] FIT test - recognition of inlined entities/entitysets in EDM-enabled client Change-Id: If2dae9882209616963b4a1459c8b8a1b923a8dc4 Signed-off-by: Michael Bolz <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/7f86b264 Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/7f86b264 Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/7f86b264 Branch: refs/heads/master Commit: 7f86b264f0b17cedb3140af97e99722bd0d4e4f1 Parents: 0be567b Author: Klaus Straubinger <[email protected]> Authored: Tue Oct 14 16:39:07 2014 +0200 Committer: Michael Bolz <[email protected]> Committed: Tue Oct 14 19:21:46 2014 +0200 ---------------------------------------------------------------------- .../fit/tecsvc/client/ExpandSelectITCase.java | 156 +++++++++++++++++++ .../core/serialization/AbstractODataBinder.java | 86 ++++++---- 2 files changed, 216 insertions(+), 26 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7f86b264/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ExpandSelectITCase.java ---------------------------------------------------------------------- diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ExpandSelectITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ExpandSelectITCase.java new file mode 100644 index 0000000..0183215 --- /dev/null +++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ExpandSelectITCase.java @@ -0,0 +1,156 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.olingo.fit.tecsvc.client; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.util.List; +import org.apache.olingo.client.api.CommonODataClient; +import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest; +import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse; +import org.apache.olingo.client.core.ODataClientFactory; +import org.apache.olingo.commons.api.domain.CommonODataEntity; +import org.apache.olingo.commons.api.domain.ODataInlineEntity; +import org.apache.olingo.commons.api.domain.ODataInlineEntitySet; +import org.apache.olingo.commons.api.domain.ODataLink; +import org.apache.olingo.commons.api.domain.ODataLinkType; +import org.apache.olingo.commons.api.domain.v4.ODataEntity; +import org.apache.olingo.commons.api.domain.v4.ODataProperty; +import org.apache.olingo.commons.api.http.HttpStatusCode; +import org.apache.olingo.fit.AbstractBaseTestITCase; +import org.apache.olingo.fit.tecsvc.TecSvcConst; +import org.junit.Test; + +public final class ExpandSelectITCase extends AbstractBaseTestITCase { + + @Test + public void readSelect() { + final CommonODataClient<?> client = getClient(); + final ODataEntityRequest<ODataEntity> request = client.getRetrieveRequestFactory() + .getEntityRequest(client.newURIBuilder(TecSvcConst.BASE_URI) + .appendEntitySetSegment("ESAllPrim").appendKeySegment(Short.MAX_VALUE) + .select("PropertyInt32,PropertyInt16") + .build()); + assertNotNull(request); + + final ODataRetrieveResponse<ODataEntity> response = request.execute(); + assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode()); + + final ODataEntity entity = response.getBody(); + assertNotNull(entity); + + assertNotNull(entity.getProperties()); + assertEquals(2, entity.getProperties().size()); + assertNull(entity.getProperty("PropertyString")); + + ODataProperty property = entity.getProperty("PropertyInt16"); + assertNotNull(property); + assertNotNull(property.getPrimitiveValue()); + assertEquals(Integer.valueOf(Short.MAX_VALUE), property.getPrimitiveValue().toValue()); + + property = entity.getProperty("PropertyInt32"); + assertNotNull(property); + assertNotNull(property.getPrimitiveValue()); + assertEquals(Integer.MAX_VALUE, property.getPrimitiveValue().toValue()); + } + + @Test + public void readExpandSelect() { + final CommonODataClient<?> client = getClient(); + final ODataEntityRequest<ODataEntity> request = client.getRetrieveRequestFactory() + .getEntityRequest(client.newURIBuilder(TecSvcConst.BASE_URI) + .appendEntitySetSegment("ESTwoPrim").appendKeySegment(-365) + .expand("NavPropertyETAllPrimMany($select=PropertyTimeOfDay,PropertySByte)") + .select("PropertyString") + .build()); + assertNotNull(request); + + final ODataRetrieveResponse<ODataEntity> response = request.execute(); + assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode()); + + final ODataEntity entity = response.getBody(); + assertNotNull(entity); + + assertNull(entity.getProperty("PropertyInt16")); + + final ODataProperty property = entity.getProperty("PropertyString"); + assertNotNull(property); + assertNotNull(property.getPrimitiveValue()); + assertEquals("Test String2", property.getPrimitiveValue().toValue()); + + assertNull(entity.getNavigationLink("NavPropertyETAllPrimOne")); + + final ODataLink link = entity.getNavigationLink("NavPropertyETAllPrimMany"); + assertNotNull(link); + assertEquals(ODataLinkType.ENTITY_SET_NAVIGATION, link.getType()); + final ODataInlineEntitySet inlineEntitySet = link.asInlineEntitySet(); + assertNotNull(inlineEntitySet); + final List<? extends CommonODataEntity> entities = inlineEntitySet.getEntitySet().getEntities(); + assertNotNull(entities); + assertEquals(2, entities.size()); + final CommonODataEntity inlineEntity = entities.get(0); + assertEquals(2, inlineEntity.getProperties().size()); + assertEquals(-128, inlineEntity.getProperty("PropertySByte").getPrimitiveValue().toValue()); + assertEquals(new java.sql.Timestamp(85754000), + inlineEntity.getProperty("PropertyTimeOfDay").getPrimitiveValue().toValue()); + } + + @Test + public void readExpandTwoLevels() { + final CommonODataClient<?> client = getClient(); + final ODataEntityRequest<ODataEntity> request = client.getRetrieveRequestFactory() + .getEntityRequest(client.newURIBuilder(TecSvcConst.BASE_URI) + .appendEntitySetSegment("ESTwoPrim").appendKeySegment(32767) + .expand("NavPropertyETAllPrimOne($expand=NavPropertyETTwoPrimOne)") + .build()); + assertNotNull(request); + + final ODataRetrieveResponse<ODataEntity> response = request.execute(); + assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode()); + + final ODataEntity entity = response.getBody(); + assertNotNull(entity); + assertEquals(2, entity.getProperties().size()); + + assertNull(entity.getNavigationLink("NavPropertyETAllPrimMany")); + + final ODataLink link = entity.getNavigationLink("NavPropertyETAllPrimOne"); + assertNotNull(link); + assertEquals(ODataLinkType.ENTITY_NAVIGATION, link.getType()); + final ODataInlineEntity inlineEntity = link.asInlineEntity(); + assertNotNull(inlineEntity); + assertEquals(16, inlineEntity.getEntity().getProperties().size()); + + final ODataLink innerLink = inlineEntity.getEntity().getNavigationLink("NavPropertyETTwoPrimOne"); + assertNotNull(innerLink); + assertEquals(ODataLinkType.ENTITY_NAVIGATION, innerLink.getType()); + final CommonODataEntity innerEntity = innerLink.asInlineEntity().getEntity(); + assertNotNull(innerEntity); + assertEquals(2, innerEntity.getProperties().size()); + assertEquals(32767, innerEntity.getProperty("PropertyInt16").getPrimitiveValue().toValue()); + assertEquals("Test String4", innerEntity.getProperty("PropertyString").getPrimitiveValue().toValue()); + } + + @Override + protected CommonODataClient<?> getClient() { + return ODataClientFactory.getEdmEnabledV4(TecSvcConst.BASE_URI); + } +} http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7f86b264/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/AbstractODataBinder.java ---------------------------------------------------------------------- diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/AbstractODataBinder.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/AbstractODataBinder.java index dcaa03b..23587af 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/AbstractODataBinder.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/AbstractODataBinder.java @@ -38,6 +38,7 @@ import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.data.EntitySet; import org.apache.olingo.commons.api.data.Link; import org.apache.olingo.commons.api.data.Linked; +import org.apache.olingo.commons.api.data.LinkedComplexValue; import org.apache.olingo.commons.api.data.Property; import org.apache.olingo.commons.api.data.ResWrap; import org.apache.olingo.commons.api.data.Valuable; @@ -288,48 +289,55 @@ public abstract class AbstractODataBinder implements CommonODataBinder { final Linked linked, final ODataLinked odataLinked, final String metadataETag, final URI base) { for (Link link : linked.getNavigationLinks()) { + final String href = link.getHref(); + final String title = link.getTitle(); final Entity inlineEntity = link.getInlineEntity(); final EntitySet inlineEntitySet = link.getInlineEntitySet(); - if (inlineEntity == null && inlineEntitySet == null) { ODataLinkType linkType = null; if (edmType instanceof EdmStructuredType) { - final EdmNavigationProperty navProp = ((EdmStructuredType) edmType).getNavigationProperty(link.getTitle()); + final EdmNavigationProperty navProp = ((EdmStructuredType) edmType).getNavigationProperty(title); if (navProp != null) { - linkType = navProp.isCollection() - ? ODataLinkType.ENTITY_SET_NAVIGATION - : ODataLinkType.ENTITY_NAVIGATION; + linkType = navProp.isCollection() ? + ODataLinkType.ENTITY_SET_NAVIGATION : + ODataLinkType.ENTITY_NAVIGATION; } } if (linkType == null) { - linkType = link.getType() == null - ? ODataLinkType.ENTITY_NAVIGATION - : ODataLinkType.fromString(client.getServiceVersion(), link.getRel(), link.getType()); + linkType = link.getType() == null ? + ODataLinkType.ENTITY_NAVIGATION : + ODataLinkType.fromString(client.getServiceVersion(), link.getRel(), link.getType()); } - odataLinked.addLink(linkType == ODataLinkType.ENTITY_NAVIGATION - ? client.getObjectFactory(). - newEntityNavigationLink(link.getTitle(), URIUtils.getURI(base, link.getHref())) - : client.getObjectFactory(). - newEntitySetNavigationLink(link.getTitle(), URIUtils.getURI(base, link.getHref()))); + odataLinked.addLink(linkType == ODataLinkType.ENTITY_NAVIGATION ? + client.getObjectFactory().newEntityNavigationLink(title, URIUtils.getURI(base, href)) : + client.getObjectFactory().newEntitySetNavigationLink(title, URIUtils.getURI(base, href))); } else if (inlineEntity != null) { - odataLinked.addLink(new ODataInlineEntity(client.getServiceVersion(), - URIUtils.getURI(base, link.getHref()), ODataLinkType.ENTITY_NAVIGATION, link.getTitle(), - getODataEntity(new ResWrap<Entity>( - inlineEntity.getBaseURI() == null ? null : inlineEntity.getBaseURI(), - metadataETag, - inlineEntity)))); + odataLinked.addLink(createODataInlineEntity(inlineEntity, + URIUtils.getURI(base, href), title, metadataETag)); } else { - odataLinked.addLink(new ODataInlineEntitySet(client.getServiceVersion(), - URIUtils.getURI(base, link.getHref()), ODataLinkType.ENTITY_SET_NAVIGATION, link.getTitle(), - getODataEntitySet(new ResWrap<EntitySet>( - inlineEntitySet.getBaseURI() == null ? null : inlineEntitySet.getBaseURI(), - metadataETag, - inlineEntitySet)))); + odataLinked.addLink(createODataInlineEntitySet(inlineEntitySet, + URIUtils.getURI(base, href), title, metadataETag)); } } } + private ODataInlineEntity createODataInlineEntity(final Entity inlineEntity, + final URI uri, final String title, final String metadataETag) { + return new ODataInlineEntity(client.getServiceVersion(), uri, ODataLinkType.ENTITY_NAVIGATION, title, + getODataEntity(new ResWrap<Entity>( + inlineEntity.getBaseURI() == null ? null : inlineEntity.getBaseURI(), metadataETag, + inlineEntity))); + } + + private ODataInlineEntitySet createODataInlineEntitySet(final EntitySet inlineEntitySet, + final URI uri, final String title, final String metadataETag) { + return new ODataInlineEntitySet(client.getServiceVersion(), uri, ODataLinkType.ENTITY_SET_NAVIGATION, title, + getODataEntitySet(new ResWrap<EntitySet>( + inlineEntitySet.getBaseURI() == null ? null : inlineEntitySet.getBaseURI(), metadataETag, + inlineEntitySet))); + } + private EdmEntityType findEntityType( final String entitySetOrSingletonOrType, final EdmEntityContainer container) { @@ -474,12 +482,17 @@ public abstract class AbstractODataBinder implements CommonODataBinder { entity.setMediaETag(resource.getPayload().getMediaETag()); } - for (Property property : resource.getPayload().getProperties()) { + for (final Property property : resource.getPayload().getProperties()) { EdmType propertyType = null; if (edmType instanceof EdmEntityType) { final EdmElement edmProperty = ((EdmEntityType) edmType).getProperty(property.getName()); if (edmProperty != null) { propertyType = edmProperty.getType(); + if (edmProperty instanceof EdmNavigationProperty) { + final String propertyTypeName = propertyType.getFullQualifiedName().getFullQualifiedNameAsString(); + entity.addLink(createLinkFromNavigationProperty(property, propertyTypeName)); + break; + } } } add(entity, getODataProperty(propertyType, property)); @@ -488,6 +501,27 @@ public abstract class AbstractODataBinder implements CommonODataBinder { return entity; } + private ODataLink createLinkFromNavigationProperty(final Property property, final String propertyTypeName) { + if (property.isCollection()) { + EntitySet inlineEntitySet = new EntitySetImpl(); + for (final Object inlined : property.asCollection()) { + Entity inlineEntity = new EntityImpl(); + inlineEntity.setType(propertyTypeName); + inlineEntity.getProperties().addAll( + inlined instanceof LinkedComplexValue ? ((LinkedComplexValue) inlined).getValue() : + inlined instanceof Property ? ((Property) inlined).asComplex() : null); + inlineEntitySet.getEntities().add(inlineEntity); + } + return createODataInlineEntitySet(inlineEntitySet, null, property.getName(), null); + } else { + Entity inlineEntity = new EntityImpl(); + inlineEntity.setType(propertyTypeName); + inlineEntity.getProperties().addAll( + property.isLinkedComplex() ? property.asLinkedComplex().getValue() : property.asComplex()); + return createODataInlineEntity(inlineEntity, null, property.getName(), null); + } + } + protected EdmTypeInfo buildTypeInfo(final ContextURL contextURL, final String metadataETag, final String propertyName, final String propertyType) {
