From 7a4b562724d928e6eedde9817625a8eb19cf8517 Mon Sep 17 00:00:00 2001 From: Christian Holzer Date: Tue, 24 Feb 2015 09:54:03 +0100 Subject: [PATCH] [OLINGO-545] Deep Insert and Navigation Property Binding while creating and updating entities added Signed-off-by: Michael Bolz --- .../fit/tecsvc/client/BindingITCase.java | 224 +++++++++++ .../fit/tecsvc/client/DeepInsertITCase.java | 360 ++++++++++++++++++ .../client/OrderBySystemQueryITCase.java | 9 +- .../client/SystemQueryOptionITCase.java | 40 +- .../server/tecsvc/data/DataProvider.java | 281 ++++++++++++-- .../processor/TechnicalEntityProcessor.java | 40 +- .../tecsvc/processor/TechnicalProcessor.java | 4 + .../queryoptions/SystemQueryOptions.java | 41 -- .../queryoptions/options/CountHandler.java | 1 - .../queryoptions/options/OrderByHandler.java | 7 +- .../options/ServerSidePagingHandler.java | 24 +- .../SystemQueryOptionsRuntimeException.java} | 14 +- 12 files changed, 906 insertions(+), 139 deletions(-) create mode 100644 fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BindingITCase.java create mode 100644 fit/src/test/java/org/apache/olingo/fit/tecsvc/client/DeepInsertITCase.java delete mode 100644 lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/SystemQueryOptions.java rename lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/{expression/FilterRuntimeException.java => options/SystemQueryOptionsRuntimeException.java} (72%) diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BindingITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BindingITCase.java new file mode 100644 index 000000000..b76c17c2b --- /dev/null +++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BindingITCase.java @@ -0,0 +1,224 @@ +/* + * 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 java.net.URI; +import java.util.HashMap; +import java.util.Iterator; + +import org.apache.olingo.client.api.ODataClient; +import org.apache.olingo.client.api.communication.request.cud.UpdateType; +import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest; +import org.apache.olingo.client.api.communication.response.ODataEntityCreateResponse; +import org.apache.olingo.client.api.communication.response.ODataEntityUpdateResponse; +import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse; +import org.apache.olingo.client.core.ODataClientFactory; +import org.apache.olingo.commons.api.domain.ODataEntity; +import org.apache.olingo.commons.api.domain.ODataLink; +import org.apache.olingo.commons.api.domain.ODataObjectFactory; +import org.apache.olingo.commons.api.domain.ODataValue; +import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException; +import org.apache.olingo.commons.api.edm.FullQualifiedName; +import org.apache.olingo.commons.api.format.ODataFormat; +import org.apache.olingo.commons.api.http.HttpHeader; +import org.apache.olingo.fit.AbstractBaseTestITCase; +import org.apache.olingo.fit.tecsvc.TecSvcConst; +import org.junit.Test; + +public class BindingITCase extends AbstractBaseTestITCase { + private static final String SERVICE_URI = TecSvcConst.BASE_URI; + + private static final String SERVICE_NAMESPACE = "olingo.odata.test1"; + private static final String ES_KEY_NAV = "ESKeyNav"; + private static final String ES_TWO_KEY_NAV = "ESTwoKeyNav"; + private static final String ET_KEY_NAV_NAME = "ETKeyNav"; + private static final FullQualifiedName ET_KEY_NAV = new FullQualifiedName(SERVICE_NAMESPACE, ET_KEY_NAV_NAME); + private static final String CT_PRIM_COMP = "CTPrimComp"; + private static final String CT_TWO_PRIM = "CTTwoPrim"; + private static final String CT_ALL_PRIM = "CTAllPrim"; + private static final String CT_NAV_FIVE_PROP = "CTNavFiveProp"; + private static final String PROPERTY_INT16 = "PropertyInt16"; + private static final String PROPERTY_STRING = "PropertyString"; + private static final String PROPERTY_COMP = "PropertyComp"; + private static final String PROPERTY_COMP_COMP = "PropertyCompComp"; + private static final String PROPERTY_COMP_TWO_PRIM = "PropertyCompTwoPrim"; + private static final String PROPERTY_COMP_ALL_PRIM = "PropertyCompAllPrim"; + private static final String NAV_PROPERTY_ET_KEY_NAV_ONE = "NavPropertyETKeyNavOne"; + private static final String NAV_PROPERTY_ET_KEY_NAV_MANY = "NavPropertyETKeyNavMany"; + private static final String NAV_PROPERTY_ET_TWO_KEY_NAV_MANY = "NavPropertyETTwoKeyNavMany"; + + @Test + public void testCreateBindingSimple() throws EdmPrimitiveTypeException { + final ODataClient client = getClient(); + final URI createURI = client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_KEY_NAV).build(); + final ODataObjectFactory of = client.getObjectFactory(); + + // Create entity (EntitySet: ESKeyNav, Type: ETKeyNav) + final ODataEntity entity = of.newEntity(ET_KEY_NAV); + entity.getProperties() + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder().buildInt16((short) 42))); + entity.getProperties() + .add(of.newPrimitiveProperty(PROPERTY_STRING, of.newPrimitiveValueBuilder().buildString("42"))); + entity.getProperties() + .add(of.newComplexProperty(PROPERTY_COMP, of.newComplexValue(CT_NAV_FIVE_PROP) + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder().buildInt16((short) 42))))); + entity.getProperties() + .add(of.newComplexProperty(PROPERTY_COMP_ALL_PRIM, of.newComplexValue(CT_ALL_PRIM) + .add(of.newPrimitiveProperty(PROPERTY_STRING, of.newPrimitiveValueBuilder().buildString("42"))))); + entity.getProperties() + .add(of.newComplexProperty(PROPERTY_COMP_TWO_PRIM, of.newComplexValue(CT_TWO_PRIM) + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder().buildInt16((short) 42))) + .add(of.newPrimitiveProperty(PROPERTY_STRING, of.newPrimitiveValueBuilder().buildString("42"))))); + entity.getProperties() + .add(of.newComplexProperty(PROPERTY_COMP_COMP, of.newComplexValue(CT_PRIM_COMP) + .add(of.newPrimitiveProperty(PROPERTY_STRING, of.newPrimitiveValueBuilder().buildString("42"))) + .add(of.newComplexProperty(PROPERTY_COMP, of.newComplexValue(CT_NAV_FIVE_PROP) + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder().buildInt16((short) 42))))))); + + // Bind existing entities via binding synatx + final ODataLink navLinkOne = + of.newEntityNavigationLink(NAV_PROPERTY_ET_KEY_NAV_ONE, client.newURIBuilder(SERVICE_URI) + .appendEntitySetSegment( + ES_KEY_NAV).appendKeySegment(1).build()); + final ODataLink navLinkMany1 = + of.newEntitySetNavigationLink(NAV_PROPERTY_ET_KEY_NAV_MANY, client.newURIBuilder(SERVICE_URI) + .appendEntitySetSegment( + ES_KEY_NAV).appendKeySegment(2).build()); + final ODataLink navLinkMany2 = + of.newEntitySetNavigationLink(NAV_PROPERTY_ET_KEY_NAV_MANY, client.newURIBuilder(SERVICE_URI) + .appendEntitySetSegment( + ES_KEY_NAV).appendKeySegment(3).build()); + + final HashMap combinedKey = new HashMap(); + combinedKey.put(PROPERTY_INT16, 1); + combinedKey.put(PROPERTY_STRING, "1"); + final ODataLink navLink2Many = + of.newEntitySetNavigationLink(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY, client.newURIBuilder(SERVICE_URI) + .appendEntitySetSegment(ES_TWO_KEY_NAV).appendKeySegment(combinedKey).build()); + + entity.addLink(navLinkOne); + entity.addLink(navLinkMany1); + entity.addLink(navLinkMany2); + entity.addLink(navLink2Many); + + final ODataEntityCreateResponse createResponse = + client.getCUDRequestFactory().getEntityCreateRequest(createURI, entity).execute(); + final String cookie = createResponse.getHeader(HttpHeader.SET_COOKIE).iterator().next(); + final Short entityInt16Key = + createResponse.getBody().getProperty(PROPERTY_INT16).getPrimitiveValue().toCastValue(Short.class); + + // Check the just created entity + final URI entityGetURI = + client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_KEY_NAV).appendKeySegment(entityInt16Key).expand( + NAV_PROPERTY_ET_KEY_NAV_ONE, NAV_PROPERTY_ET_KEY_NAV_MANY, NAV_PROPERTY_ET_TWO_KEY_NAV_MANY).build(); + + final ODataEntityRequest entityGetRequest = + client.getRetrieveRequestFactory().getEntityRequest(entityGetURI); + entityGetRequest.addCustomHeader(HttpHeader.COOKIE, cookie); + final ODataRetrieveResponse entityGetResponse = entityGetRequest.execute(); + + // NAV_PROPERTY_ET_KEY_NAV_ONE + assertEquals(1, entityGetResponse.getBody().getProperty(NAV_PROPERTY_ET_KEY_NAV_ONE).getComplexValue().get( + PROPERTY_INT16).getPrimitiveValue().toValue()); + + // NAV_PROPERTY_ET_KEY_NAV_MANY(0) + Iterator iterator = + entityGetResponse.getBody().getProperty(NAV_PROPERTY_ET_KEY_NAV_MANY).getCollectionValue().iterator(); + assertEquals(2, iterator.next().asComplex().get(PROPERTY_INT16).getPrimitiveValue().toValue()); + + // NAV_PROPERTY_ET_KEY_NAV_MANY(1) + assertEquals(3, iterator.next().asComplex().get(PROPERTY_INT16).getPrimitiveValue().toValue()); + + // NAV_PROPERTY_ET_TWO_KEY_NAV_MANY(0) + assertEquals(1, entityGetResponse.getBody().getProperty(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY).getCollectionValue() + .iterator().next().asComplex().get(PROPERTY_INT16).getPrimitiveValue().toValue()); + assertEquals("1", entityGetResponse.getBody().getProperty(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY).getCollectionValue() + .iterator().next().asComplex().get(PROPERTY_STRING).getPrimitiveValue().toValue()); + + // Check if partner navigation link has been set up + final URI etTwoKeyNavEntityURI = + client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_TWO_KEY_NAV).appendKeySegment(combinedKey).expand( + NAV_PROPERTY_ET_KEY_NAV_ONE).build(); + final ODataEntityRequest etTwoKeyNavEntityRequest = + client.getRetrieveRequestFactory().getEntityRequest(etTwoKeyNavEntityURI); + etTwoKeyNavEntityRequest.addCustomHeader(HttpHeader.COOKIE, cookie); + final ODataRetrieveResponse etTwoKeyNavEntityResponse = etTwoKeyNavEntityRequest.execute(); + + assertEquals(entityInt16Key, etTwoKeyNavEntityResponse.getBody().getProperty(NAV_PROPERTY_ET_KEY_NAV_ONE) + .getComplexValue().get(PROPERTY_INT16).getPrimitiveValue().toCastValue(Short.class)); + } + + @Test + public void testUpdateBinding() { + // The entity MUST NOT contain related entities as inline content. It MAY contain binding information + // for navigation properties. For single-valued navigation properties this replaces the relationship. + // For collection-valued navigation properties this adds to the relationship. + + final ODataClient client = getClient(); + final URI entityURI = + client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_KEY_NAV).appendKeySegment(1).build(); + final ODataObjectFactory of = client.getObjectFactory(); + + // ESKeyNav(1).NavPropertyETKeyNavOne = ESKeyNav(2) + // ESKeyNav(1).NavPropertyETKeyNavMany = { ESKeyNav(1), ESKeyNav(2) } + // => Replace NavPropertyETKeyNavOne with ESKeyNav(3) + // => Add to NavPropertyETKeyNavOne ESKeyNav(3) + final ODataEntity entity = of.newEntity(ET_KEY_NAV); + final ODataLink navLinkOne = + of.newEntityNavigationLink(NAV_PROPERTY_ET_KEY_NAV_ONE, client.newURIBuilder(SERVICE_URI) + .appendEntitySetSegment(ES_KEY_NAV).appendKeySegment(3).build()); + final ODataLink navLinkMany = + of.newEntitySetNavigationLink(NAV_PROPERTY_ET_KEY_NAV_MANY, client.newURIBuilder(SERVICE_URI) + .appendEntitySetSegment(ES_KEY_NAV).appendKeySegment(3).build()); + entity.addLink(navLinkOne); + entity.addLink(navLinkMany); + + final ODataEntityUpdateResponse updateResponse = + client.getCUDRequestFactory().getEntityUpdateRequest(entityURI, UpdateType.PATCH, entity).execute(); + final String cookie = updateResponse.getHeader(HttpHeader.SET_COOKIE).iterator().next(); + + // Check if update was successful + final URI entityGetURI = + client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_KEY_NAV).appendKeySegment(1).expand( + NAV_PROPERTY_ET_KEY_NAV_ONE, NAV_PROPERTY_ET_KEY_NAV_MANY).build(); + final ODataEntityRequest entityRequest = + client.getRetrieveRequestFactory().getEntityRequest(entityGetURI); + entityRequest.addCustomHeader(HttpHeader.COOKIE, cookie); + final ODataRetrieveResponse entityResponse = entityRequest.execute(); + + assertEquals(3, entityResponse.getBody().getProperty(NAV_PROPERTY_ET_KEY_NAV_ONE).getComplexValue().get( + PROPERTY_INT16).getPrimitiveValue().toValue()); + assertEquals(3, entityResponse.getBody().getProperty(NAV_PROPERTY_ET_KEY_NAV_MANY).getCollectionValue().size()); + + Iterator iterator = + entityResponse.getBody().getProperty(NAV_PROPERTY_ET_KEY_NAV_MANY).getCollectionValue().iterator(); + assertEquals(1, iterator.next().asComplex().get(PROPERTY_INT16).getPrimitiveValue().toValue()); + assertEquals(2, iterator.next().asComplex().get(PROPERTY_INT16).getPrimitiveValue().toValue()); + assertEquals(3, iterator.next().asComplex().get(PROPERTY_INT16).getPrimitiveValue().toValue()); + } + + @Override + protected ODataClient getClient() { + ODataClient odata = ODataClientFactory.getV4(); + odata.getConfiguration().setDefaultPubFormat(ODataFormat.JSON); + return odata; + } +} diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/DeepInsertITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/DeepInsertITCase.java new file mode 100644 index 000000000..3dfcbd373 --- /dev/null +++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/DeepInsertITCase.java @@ -0,0 +1,360 @@ +/* + * 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 java.net.URI; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.apache.olingo.client.api.ODataClient; +import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest; +import org.apache.olingo.client.api.communication.response.ODataEntityCreateResponse; +import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse; +import org.apache.olingo.client.core.ODataClientFactory; +import org.apache.olingo.commons.api.domain.ODataEntity; +import org.apache.olingo.commons.api.domain.ODataEntitySet; +import org.apache.olingo.commons.api.domain.ODataInlineEntity; +import org.apache.olingo.commons.api.domain.ODataInlineEntitySet; +import org.apache.olingo.commons.api.domain.ODataObjectFactory; +import org.apache.olingo.commons.api.domain.ODataProperty; +import org.apache.olingo.commons.api.domain.ODataValue; +import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException; +import org.apache.olingo.commons.api.edm.FullQualifiedName; +import org.apache.olingo.commons.api.format.ODataFormat; +import org.apache.olingo.commons.api.http.HttpHeader; +import org.apache.olingo.commons.api.http.HttpStatusCode; +import org.apache.olingo.fit.AbstractBaseTestITCase; +import org.apache.olingo.fit.tecsvc.TecSvcConst; +import org.junit.AfterClass; +import org.junit.Test; + +public class DeepInsertITCase extends AbstractBaseTestITCase { + + private static final String SERVICE_URI = TecSvcConst.BASE_URI; + private static final String SERVICE_NAMESPACE = "olingo.odata.test1"; + private static final String ES_KEY_NAV = "ESKeyNav"; + private static final String ES_TWO_KEY_NAV = "ESTwoKeyNav"; + private static final String ET_KEY_NAV_NAME = "ETKeyNav"; + private static final String ET_TWO_KEY_NAV_NAME = "ETTwoKeyNav"; + private static final FullQualifiedName ET_KEY_NAV = new FullQualifiedName(SERVICE_NAMESPACE, ET_KEY_NAV_NAME); + private static final FullQualifiedName ET_TWO_KEY_NAV = new FullQualifiedName(SERVICE_NAMESPACE, ET_TWO_KEY_NAV_NAME); + private static final String CT_PRIM_COMP = "CTPrimComp"; + private static final String CT_TWO_PRIM = "CTTwoPrim"; + private static final String CT_ALL_PRIM = "CTAllPrim"; + private static final String CT_NAV_FIVE_PROP = "CTNavFiveProp"; + private static final String PROPERTY_INT16 = "PropertyInt16"; + private static final String PROPERTY_STRING = "PropertyString"; + private static final String PROPERTY_COMP = "PropertyComp"; + private static final String PROPERTY_COMP_COMP = "PropertyCompComp"; + private static final String PROPERTY_COMP_TWO_PRIM = "PropertyCompTwoPrim"; + private static final String PROPERTY_COMP_ALL_PRIM = "PropertyCompAllPrim"; + private static final String NAV_PROPERTY_ET_KEY_NAV_ONE = "NavPropertyETKeyNavOne"; + private static final String NAV_PROPERTY_ET_TWO_KEY_NAV_ONE = "NavPropertyETTwoKeyNavOne"; + private static final String NAV_PROPERTY_ET_TWO_KEY_NAV_MANY = "NavPropertyETTwoKeyNavMany"; + + @AfterClass + public static void tearDownAfterClass() throws Exception {} + + @Test + public void testSimpleDeepInsert() throws EdmPrimitiveTypeException { + final ODataClient client = getClient(); + final URI createURI = client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_KEY_NAV).build(); + final ODataObjectFactory of = client.getObjectFactory(); + final ODataEntity entity = client.getObjectFactory().newEntity(ET_KEY_NAV); + + // Prepare entity(EntitySet: ESKeyNav, Type: ETKeyNav) + entity.getProperties() + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder().buildInt16((short) 42))); + entity.getProperties() + .add(of.newPrimitiveProperty(PROPERTY_STRING, of.newPrimitiveValueBuilder().buildString("42"))); + entity.getProperties() + .add(of.newComplexProperty(PROPERTY_COMP, of.newComplexValue(CT_NAV_FIVE_PROP) + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder().buildInt16((short) 42))))); + entity.getProperties() + .add(of.newComplexProperty(PROPERTY_COMP_ALL_PRIM, of.newComplexValue(CT_ALL_PRIM) + .add(of.newPrimitiveProperty(PROPERTY_STRING, of.newPrimitiveValueBuilder().buildString("42"))))); + entity.getProperties() + .add(of.newComplexProperty(PROPERTY_COMP_TWO_PRIM, of.newComplexValue(CT_TWO_PRIM) + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder().buildInt16((short) 42))) + .add(of.newPrimitiveProperty(PROPERTY_STRING, of.newPrimitiveValueBuilder().buildString("42"))))); + entity.getProperties() + .add(of.newComplexProperty(PROPERTY_COMP_COMP, of.newComplexValue(CT_PRIM_COMP) + .add(of.newPrimitiveProperty(PROPERTY_STRING, of.newPrimitiveValueBuilder().buildString("42"))) + .add(of.newComplexProperty(PROPERTY_COMP, of.newComplexValue(CT_NAV_FIVE_PROP) + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder().buildInt16((short) 42))))))); + + // Non collection navigation property + // Create related entity(EntitySet: ESTwoKeyNav, Type: ETTwoKeyNav, Nav. Property: NavPropertyETTwoKeyNavOne) + final ODataEntity inlineEntitySingle = client.getObjectFactory().newEntity(ET_TWO_KEY_NAV); + inlineEntitySingle.getProperties() + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder().buildInt16((short) 43))); + inlineEntitySingle.getProperties() + .add(of.newPrimitiveProperty(PROPERTY_STRING, of.newPrimitiveValueBuilder().buildString("43"))); + inlineEntitySingle.getProperties() + .add(of.newComplexProperty(PROPERTY_COMP, of.newComplexValue(CT_PRIM_COMP) + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder().buildInt16((short) 431))))); + inlineEntitySingle.getProperties() + .add(of.newComplexProperty(PROPERTY_COMP_TWO_PRIM, of.newComplexValue(CT_TWO_PRIM) + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder().buildInt16((short) 432))) + .add(of.newPrimitiveProperty(PROPERTY_STRING, of.newPrimitiveValueBuilder().buildString("432"))))); + + // Collection navigation property + // The navigation property has a partner navigation property named "NavPropertyETKeyNavOne" + // Create related entity(EntitySet: ESTwoKeyNav, Type: NavPropertyETTwoKeyNavMany + final ODataEntity inlineEntityCol1 = client.getObjectFactory().newEntity(ET_TWO_KEY_NAV); + inlineEntityCol1.getProperties() + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder().buildInt16((short) 44))); + inlineEntityCol1.getProperties() + .add(of.newPrimitiveProperty(PROPERTY_STRING, of.newPrimitiveValueBuilder().buildString("44"))); + inlineEntityCol1.getProperties() + .add(of.newComplexProperty(PROPERTY_COMP, of.newComplexValue(CT_PRIM_COMP) + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder().buildInt16((short) 441))))); + inlineEntityCol1.getProperties() + .add(of.newComplexProperty(PROPERTY_COMP_TWO_PRIM, of.newComplexValue(CT_TWO_PRIM) + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder().buildInt16((short) 442))) + .add(of.newPrimitiveProperty(PROPERTY_STRING, of.newPrimitiveValueBuilder().buildString("442"))))); + + final ODataEntity inlineEntityCol2 = client.getObjectFactory().newEntity(ET_TWO_KEY_NAV); + inlineEntityCol2.getProperties() + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder().buildInt16((short) 45))); + inlineEntityCol2.getProperties() + .add(of.newPrimitiveProperty(PROPERTY_STRING, of.newPrimitiveValueBuilder().buildString("45"))); + inlineEntityCol2.getProperties() + .add(of.newComplexProperty(PROPERTY_COMP, of.newComplexValue(CT_PRIM_COMP) + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder().buildInt16((short) 451))))); + inlineEntityCol2.getProperties() + .add(of.newComplexProperty(PROPERTY_COMP_TWO_PRIM, of.newComplexValue(CT_TWO_PRIM) + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder().buildInt16((short) 452))) + .add(of.newPrimitiveProperty(PROPERTY_STRING, of.newPrimitiveValueBuilder().buildString("452"))))); + + final ODataInlineEntity newDeepInsertEntityLink = + of.newDeepInsertEntity(NAV_PROPERTY_ET_TWO_KEY_NAV_ONE, inlineEntitySingle); + final ODataEntitySet newDeepInsertEntitySet = of.newEntitySet(); + newDeepInsertEntitySet.getEntities().add(inlineEntityCol1); + newDeepInsertEntitySet.getEntities().add(inlineEntityCol2); + final ODataInlineEntitySet newDeepInsertEntitySetLink = + of.newDeepInsertEntitySet(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY, newDeepInsertEntitySet); + + entity.addLink(newDeepInsertEntityLink); + entity.addLink(newDeepInsertEntitySetLink); + + // Perform create request + final ODataEntityCreateResponse responseCreate = client.getCUDRequestFactory() + .getEntityCreateRequest(createURI, entity) + .execute(); + assertEquals(HttpStatusCode.CREATED.getStatusCode(), responseCreate.getStatusCode()); + + final String cookie = responseCreate.getHeader(HttpHeader.SET_COOKIE).toString(); + + // Fetch ESKeyNav entity with expand of NavPropertyETTwoKeyNavOne nav. property + ODataProperty propertyInt16 = responseCreate.getBody().getProperty(PROPERTY_INT16); + final URI esKeyNavURI = + client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_KEY_NAV).appendKeySegment( + propertyInt16.getPrimitiveValue().toValue()).expand(NAV_PROPERTY_ET_TWO_KEY_NAV_ONE, + NAV_PROPERTY_ET_TWO_KEY_NAV_MANY).build(); + + final ODataEntityRequest esKeyNavRequest = client.getRetrieveRequestFactory() + .getEntityRequest(esKeyNavURI); + esKeyNavRequest.addCustomHeader(HttpHeader.COOKIE, cookie); + final ODataRetrieveResponse esKeyNavResponse = esKeyNavRequest.execute(); + + // Check nav. property NavPropertyETTwoKeyNavOne + assertNotNull(esKeyNavResponse.getBody().getProperty(NAV_PROPERTY_ET_TWO_KEY_NAV_ONE)); + assertEquals(431, esKeyNavResponse.getBody().getProperty(NAV_PROPERTY_ET_TWO_KEY_NAV_ONE).getComplexValue().get( + PROPERTY_COMP).getComplexValue().get(PROPERTY_INT16).getPrimitiveValue().toValue()); + + // Check nav. property NavPropertyETTwoKeyNavMany + assertNotNull(esKeyNavResponse.getBody().getProperty(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY)); + assertEquals(2, esKeyNavResponse.getBody().getProperty(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY).getCollectionValue() + .size()); + Iterator twoKeyNavManyIterator = + esKeyNavResponse.getBody().getProperty(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY).getCollectionValue().iterator(); + final ODataValue firstTwoKeyNavEnity = twoKeyNavManyIterator.next(); // First entity + assertEquals(441, firstTwoKeyNavEnity.asComplex().get(PROPERTY_COMP).getValue().asComplex().get( + PROPERTY_INT16).getPrimitiveValue().toValue()); + final ODataValue secondTwoKeyNavEnity = twoKeyNavManyIterator.next(); // Second entity + assertEquals(451, secondTwoKeyNavEnity.asComplex().get(PROPERTY_COMP).getValue().asComplex().get( + PROPERTY_INT16).getPrimitiveValue().toValue()); + + // Fetch ESTwoKeyNav entities and check if available and the partner relation have been set up + // Check ESTwoKeyNav(Created via NavPropertyETTwoKeyNavOne) + Map composedKey = new HashMap(); + composedKey.put(PROPERTY_INT16, esKeyNavResponse.getBody().getProperty(NAV_PROPERTY_ET_TWO_KEY_NAV_ONE) + .getComplexValue().get(PROPERTY_INT16) + .getPrimitiveValue().toValue()); + composedKey.put(PROPERTY_STRING, esKeyNavResponse.getBody().getProperty(NAV_PROPERTY_ET_TWO_KEY_NAV_ONE) + .getComplexValue().get(PROPERTY_STRING) + .getPrimitiveValue().toValue()); + + final URI esTwoKeyNavEntitySingleURI = client.newURIBuilder(SERVICE_URI) + .appendEntitySetSegment(ES_TWO_KEY_NAV) + .appendKeySegment(composedKey) + .build(); + + final ODataEntityRequest esTwoKeyNavSingleRequest = client.getRetrieveRequestFactory() + .getEntityRequest(esTwoKeyNavEntitySingleURI); + esTwoKeyNavSingleRequest.addCustomHeader(HttpHeader.COOKIE, cookie); + final ODataRetrieveResponse esTwoKeyNavSingleResponse = esTwoKeyNavSingleRequest.execute(); + assertEquals(431, esTwoKeyNavSingleResponse.getBody().getProperty(PROPERTY_COMP).getComplexValue().get( + PROPERTY_INT16).getPrimitiveValue().toValue()); + + // Check ESTwoKeyNav(Created via NavPropertyETTwoKeyNavMany(0)) + composedKey.clear(); + composedKey.put(PROPERTY_INT16, firstTwoKeyNavEnity.asComplex().get(PROPERTY_INT16).getPrimitiveValue().toValue()); + composedKey.put(PROPERTY_STRING, firstTwoKeyNavEnity.asComplex().get(PROPERTY_STRING).getPrimitiveValue() + .toValue()); + + URI esTwoKeyNavEntityManyOneURI = + client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_TWO_KEY_NAV).appendKeySegment(composedKey) + .expand(NAV_PROPERTY_ET_KEY_NAV_ONE).build(); + + final ODataEntityRequest esTwoKeyNavManyOneRequest = + client.getRetrieveRequestFactory().getEntityRequest(esTwoKeyNavEntityManyOneURI); + esTwoKeyNavManyOneRequest.addCustomHeader(HttpHeader.COOKIE, cookie); + final ODataRetrieveResponse esTwoKeyNavManyOneResponse = esTwoKeyNavManyOneRequest.execute(); + + assertEquals(441, esTwoKeyNavManyOneResponse.getBody().getProperty(PROPERTY_COMP).getComplexValue().get( + PROPERTY_INT16).getPrimitiveValue().toValue()); + assertNotNull(esTwoKeyNavManyOneResponse.getBody().getProperty(NAV_PROPERTY_ET_KEY_NAV_ONE).getComplexValue()); + assertEquals(propertyInt16.getPrimitiveValue().toValue(), esTwoKeyNavManyOneResponse.getBody().getProperty( + NAV_PROPERTY_ET_KEY_NAV_ONE).getComplexValue().get(PROPERTY_INT16).getPrimitiveValue().toValue()); + + // Check ESTwoKeyNav(Created via NavPropertyETTwoKeyNavMany(1)) + composedKey.clear(); + composedKey.put(PROPERTY_INT16, secondTwoKeyNavEnity.asComplex().get(PROPERTY_INT16).getPrimitiveValue().toValue()); + composedKey.put(PROPERTY_STRING, secondTwoKeyNavEnity.asComplex().get(PROPERTY_STRING).getPrimitiveValue() + .toValue()); + + URI esTwoKeyNavEntityManyTwoURI = + client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_TWO_KEY_NAV).appendKeySegment(composedKey) + .expand(NAV_PROPERTY_ET_KEY_NAV_ONE).build(); + + final ODataEntityRequest esTwoKeyNavManyTwoRequest = + client.getRetrieveRequestFactory().getEntityRequest(esTwoKeyNavEntityManyTwoURI); + esTwoKeyNavManyTwoRequest.addCustomHeader(HttpHeader.COOKIE, cookie); + final ODataRetrieveResponse esTwoKeyNavManyTwoResponse = esTwoKeyNavManyTwoRequest.execute(); + + assertEquals(451, esTwoKeyNavManyTwoResponse.getBody().getProperty(PROPERTY_COMP).getComplexValue().get( + PROPERTY_INT16).getPrimitiveValue().toValue()); + assertNotNull(esTwoKeyNavManyTwoResponse.getBody().getProperty(NAV_PROPERTY_ET_KEY_NAV_ONE).getComplexValue()); + assertEquals(propertyInt16.getPrimitiveValue().toValue(), esTwoKeyNavManyTwoResponse.getBody().getProperty( + NAV_PROPERTY_ET_KEY_NAV_ONE).getComplexValue().get(PROPERTY_INT16).getPrimitiveValue().toValue()); + } + + @Test + public void testDeepInsertSameEntitySet() throws EdmPrimitiveTypeException { + final ODataClient client = getClient(); + final URI createURI = client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_KEY_NAV).build(); + final ODataObjectFactory of = client.getObjectFactory(); + final ODataEntity entity = client.getObjectFactory().newEntity(ET_KEY_NAV); + + // Prepare entity(EntitySet: ESKeyNav, Type: ETKeyNav) + entity.getProperties() + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder().buildInt16((short) 42))); + entity.getProperties() + .add(of.newPrimitiveProperty(PROPERTY_STRING, of.newPrimitiveValueBuilder().buildString("42"))); + entity.getProperties() + .add(of.newComplexProperty(PROPERTY_COMP, of.newComplexValue(CT_NAV_FIVE_PROP) + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder().buildInt16((short) 42))))); + entity.getProperties() + .add(of.newComplexProperty(PROPERTY_COMP_ALL_PRIM, of.newComplexValue(CT_ALL_PRIM) + .add(of.newPrimitiveProperty(PROPERTY_STRING, of.newPrimitiveValueBuilder().buildString("42"))))); + entity.getProperties() + .add(of.newComplexProperty(PROPERTY_COMP_TWO_PRIM, of.newComplexValue(CT_TWO_PRIM) + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder().buildInt16((short) 42))) + .add(of.newPrimitiveProperty(PROPERTY_STRING, of.newPrimitiveValueBuilder().buildString("42"))))); + entity.getProperties() + .add(of.newComplexProperty(PROPERTY_COMP_COMP, of.newComplexValue(CT_PRIM_COMP) + .add(of.newPrimitiveProperty(PROPERTY_STRING, of.newPrimitiveValueBuilder().buildString("42"))) + .add(of.newComplexProperty(PROPERTY_COMP, of.newComplexValue(CT_NAV_FIVE_PROP) + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder().buildInt16((short) 42))))))); + + // Prepare inline entity(EntitySet: ESKeyNav, Type: ETKeyNav) + final ODataEntity innerEntity = of.newEntity(ET_KEY_NAV); + innerEntity.getProperties() + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder().buildInt16((short) 43))); + innerEntity.getProperties() + .add(of.newPrimitiveProperty(PROPERTY_STRING, of.newPrimitiveValueBuilder().buildString("43"))); + innerEntity.getProperties() + .add(of.newComplexProperty(PROPERTY_COMP, of.newComplexValue(CT_NAV_FIVE_PROP) + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder().buildInt16((short) 431))))); + innerEntity.getProperties() + .add(of.newComplexProperty(PROPERTY_COMP_ALL_PRIM, of.newComplexValue(CT_ALL_PRIM) + .add(of.newPrimitiveProperty(PROPERTY_STRING, of.newPrimitiveValueBuilder().buildString("431"))))); + innerEntity.getProperties() + .add(of.newComplexProperty(PROPERTY_COMP_TWO_PRIM, of.newComplexValue(CT_TWO_PRIM) + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder().buildInt16((short) 431))) + .add(of.newPrimitiveProperty(PROPERTY_STRING, of.newPrimitiveValueBuilder().buildString("431"))))); + innerEntity + .getProperties() + .add(of.newComplexProperty(PROPERTY_COMP_COMP, of.newComplexValue(CT_PRIM_COMP) + .add(of.newPrimitiveProperty(PROPERTY_STRING, of.newPrimitiveValueBuilder().buildString("431"))) + .add(of.newComplexProperty(PROPERTY_COMP, of.newComplexValue(CT_NAV_FIVE_PROP) + .add(of.newPrimitiveProperty(PROPERTY_INT16, of.newPrimitiveValueBuilder() + .buildInt16((short) 431))))))); + + ODataInlineEntity inlineEntity = of.newDeepInsertEntity(NAV_PROPERTY_ET_KEY_NAV_ONE, innerEntity); + entity.addLink(inlineEntity); + + final ODataEntityCreateResponse responseCreate = + client.getCUDRequestFactory().getEntityCreateRequest(createURI, entity).execute(); + final String cookie = responseCreate.getHeader(HttpHeader.SET_COOKIE).iterator().next(); + final Short esKeyNavEntityKey = + responseCreate.getBody().getProperty(PROPERTY_INT16).getPrimitiveValue().toCastValue(Short.class); + + // Fetch Entity + URI fetchEntityURI = + client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_KEY_NAV).appendKeySegment(esKeyNavEntityKey) + .expand(NAV_PROPERTY_ET_KEY_NAV_ONE).build(); + + ODataEntityRequest entityRequest = client.getRetrieveRequestFactory().getEntityRequest(fetchEntityURI); + entityRequest.addCustomHeader(HttpHeader.COOKIE, cookie); + final ODataRetrieveResponse entityResponse = entityRequest.execute(); + + // Check values + assertEquals(431, entityResponse.getBody().getProperty(NAV_PROPERTY_ET_KEY_NAV_ONE).getComplexValue().get( + PROPERTY_COMP).getComplexValue().get(PROPERTY_INT16).getPrimitiveValue().toValue()); + + Short innerEntityInt16Key = + entityResponse.getBody().getProperty(NAV_PROPERTY_ET_KEY_NAV_ONE).getComplexValue().get(PROPERTY_INT16) + .getPrimitiveValue().toCastValue(Short.class); + + final URI innerEntityURI = + client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_KEY_NAV).appendKeySegment(innerEntityInt16Key) + .build(); + final ODataEntityRequest innerRequest = + client.getRetrieveRequestFactory().getEntityRequest(innerEntityURI); + innerRequest.addCustomHeader(HttpHeader.COOKIE, cookie); + ODataRetrieveResponse innerResponse = innerRequest.execute(); + + assertEquals(431, innerResponse.getBody().getProperty(PROPERTY_COMP).getComplexValue().get(PROPERTY_INT16) + .getPrimitiveValue().toValue()); + } + + @Override + protected ODataClient getClient() { + ODataClient odata = ODataClientFactory.getV4(); + odata.getConfiguration().setDefaultPubFormat(ODataFormat.JSON); + return odata; + } +} diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/OrderBySystemQueryITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/OrderBySystemQueryITCase.java index 21d248c89..15990072e 100644 --- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/OrderBySystemQueryITCase.java +++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/OrderBySystemQueryITCase.java @@ -137,12 +137,11 @@ public class OrderBySystemQueryITCase extends AbstractBaseTestITCase { private ODataRetrieveResponse sendRequest(String entitySet, String orderByString) { final ODataClient client = getClient(); - String escapedFilterString = escapeFilterString(orderByString); final URI uri = client.newURIBuilder(SERVICE_URI) .appendEntitySetSegment(entitySet) - .orderBy(escapedFilterString) + .orderBy(orderByString) .build(); ODataEntitySetRequest request = client.getRetrieveRequestFactory().getEntitySetRequest(uri); @@ -158,11 +157,7 @@ public class OrderBySystemQueryITCase extends AbstractBaseTestITCase { assertEquals(errorCode.getStatusCode(), e.getStatusLine().getStatusCode()); } } - - private String escapeFilterString(String filterString) { - return filterString.replace(" ", "%20"); - } - + @Override protected ODataClient getClient() { ODataClient odata = ODataClientFactory.getV4(); diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/SystemQueryOptionITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/SystemQueryOptionITCase.java index 193800db2..a49562ee8 100644 --- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/SystemQueryOptionITCase.java +++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/SystemQueryOptionITCase.java @@ -29,15 +29,15 @@ import org.apache.olingo.client.api.communication.ODataClientErrorException; import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse; import org.apache.olingo.client.api.uri.QueryOption; import org.apache.olingo.client.core.ODataClientFactory; -import org.apache.olingo.commons.api.domain.CommonODataEntity; -import org.apache.olingo.commons.api.domain.CommonODataEntitySet; +import org.apache.olingo.commons.api.domain.ODataEntity; +import org.apache.olingo.commons.api.domain.ODataEntitySet; import org.apache.olingo.commons.api.format.ODataFormat; 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 class SystemQueryOptionITCas extends AbstractBaseTestITCase { +public class SystemQueryOptionITCase extends AbstractBaseTestITCase { private static final String PROPERTY_INT16 = "PropertyInt16"; private static final String ES_SERVER_SIDE_PAGING = "ESServerSidePaging"; private static final String ES_ALL_PRIM = "ESAllPrim"; @@ -51,7 +51,7 @@ public class SystemQueryOptionITCas extends AbstractBaseTestITCase { .addQueryOption(QueryOption.COUNT, "true") .build(); - ODataRetrieveResponse response = client.getRetrieveRequestFactory() + ODataRetrieveResponse response = client.getRetrieveRequestFactory() .getEntitySetRequest(uri) .execute(); @@ -67,7 +67,7 @@ public class SystemQueryOptionITCas extends AbstractBaseTestITCase { .addQueryOption(QueryOption.COUNT, "true") .build(); - ODataRetrieveResponse response = client.getRetrieveRequestFactory() + ODataRetrieveResponse response = client.getRetrieveRequestFactory() .getEntitySetRequest(uri) .execute(); @@ -83,14 +83,14 @@ public class SystemQueryOptionITCas extends AbstractBaseTestITCase { .addQueryOption(QueryOption.TOP, new Integer(5).toString()) .build(); - ODataRetrieveResponse response = client.getRetrieveRequestFactory() + ODataRetrieveResponse response = client.getRetrieveRequestFactory() .getEntitySetRequest(uri) .execute(); assertEquals(5, response.getBody().getEntities().size()); for (int i = 0; i < 5; i++) { - CommonODataEntity entity = response.getBody().getEntities().get(i); + ODataEntity entity = response.getBody().getEntities().get(i); assertEquals(new Integer(i + 1).toString(), entity.getProperty(PROPERTY_INT16).getValue().toString()); } } @@ -103,14 +103,14 @@ public class SystemQueryOptionITCas extends AbstractBaseTestITCase { .addQueryOption(QueryOption.SKIP, new Integer(5).toString()) .build(); - ODataRetrieveResponse response = client.getRetrieveRequestFactory() + ODataRetrieveResponse response = client.getRetrieveRequestFactory() .getEntitySetRequest(uri) .execute(); assertEquals(10, response.getBody().getEntities().size()); for (int i = 0; i < 10; i++) { - CommonODataEntity entity = response.getBody().getEntities().get(i); + ODataEntity entity = response.getBody().getEntities().get(i); assertEquals(new Integer(i + 6).toString(), entity.getProperty(PROPERTY_INT16).getValue().toString()); } } @@ -124,7 +124,7 @@ public class SystemQueryOptionITCas extends AbstractBaseTestITCase { .addQueryOption(QueryOption.SKIP, new Integer(503).toString()) .build(); - ODataRetrieveResponse response = client.getRetrieveRequestFactory() + ODataRetrieveResponse response = client.getRetrieveRequestFactory() .getEntitySetRequest(uri) .execute(); @@ -139,7 +139,7 @@ public class SystemQueryOptionITCas extends AbstractBaseTestITCase { .addQueryOption(QueryOption.SKIP, new Integer(10000).toString()) .build(); - ODataRetrieveResponse response = client.getRetrieveRequestFactory() + ODataRetrieveResponse response = client.getRetrieveRequestFactory() .getEntitySetRequest(uri) .execute(); @@ -158,7 +158,7 @@ public class SystemQueryOptionITCas extends AbstractBaseTestITCase { .addQueryOption(QueryOption.TOP, new Integer(43).toString()) // 102, 101, ...., 59 .build(); - ODataRetrieveResponse response = client.getRetrieveRequestFactory() + ODataRetrieveResponse response = client.getRetrieveRequestFactory() .getEntitySetRequest(uri) .execute(); @@ -169,7 +169,7 @@ public class SystemQueryOptionITCas extends AbstractBaseTestITCase { // Check first 10 entities for (int i = 0; i < 10; i++) { - CommonODataEntity entity = response.getBody().getEntities().get(i); + ODataEntity entity = response.getBody().getEntities().get(i); assertEquals(new Integer(id).toString(), entity.getProperty(PROPERTY_INT16).getValue().toString()); id--; } @@ -180,7 +180,7 @@ public class SystemQueryOptionITCas extends AbstractBaseTestITCase { assertEquals(Integer.valueOf(105), response.getBody().getCount()); assertEquals(10, response.getBody().getEntities().size()); for (int i = 0; i < 10; i++) { - CommonODataEntity entity = response.getBody().getEntities().get(i); + ODataEntity entity = response.getBody().getEntities().get(i); assertEquals(new Integer(id).toString(), entity.getProperty(PROPERTY_INT16).getValue().toString()); id--; } @@ -191,7 +191,7 @@ public class SystemQueryOptionITCas extends AbstractBaseTestITCase { assertEquals(Integer.valueOf(105), response.getBody().getCount()); assertEquals(3, response.getBody().getEntities().size()); for (int i = 0; i < 3; i++) { - CommonODataEntity entity = response.getBody().getEntities().get(i); + ODataEntity entity = response.getBody().getEntities().get(i); assertEquals(new Integer(id).toString(), entity.getProperty(PROPERTY_INT16).getValue().toString()); id--; } @@ -207,7 +207,7 @@ public class SystemQueryOptionITCas extends AbstractBaseTestITCase { .appendEntitySetSegment(ES_SERVER_SIDE_PAGING) .build(); - ODataRetrieveResponse response = client.getRetrieveRequestFactory() + ODataRetrieveResponse response = client.getRetrieveRequestFactory() .getEntitySetRequest(uri) .execute(); @@ -234,7 +234,7 @@ public class SystemQueryOptionITCas extends AbstractBaseTestITCase { .addQueryOption(QueryOption.COUNT, Boolean.TRUE.toString()) .build(); - ODataRetrieveResponse response = client.getRetrieveRequestFactory() + ODataRetrieveResponse response = client.getRetrieveRequestFactory() .getEntitySetRequest(uri) .execute(); @@ -273,7 +273,7 @@ public class SystemQueryOptionITCas extends AbstractBaseTestITCase { .build(); try { - ODataRetrieveResponse response = client.getRetrieveRequestFactory() + ODataRetrieveResponse response = client.getRetrieveRequestFactory() .getEntitySetRequest(uri) .execute(); fail(); @@ -291,7 +291,7 @@ public class SystemQueryOptionITCas extends AbstractBaseTestITCase { .addQueryOption(QueryOption.TOP, new Integer(-5).toString()) .build(); try { - ODataRetrieveResponse response = client.getRetrieveRequestFactory() + ODataRetrieveResponse response = client.getRetrieveRequestFactory() .getEntitySetRequest(uri) .execute(); fail(); @@ -301,7 +301,7 @@ public class SystemQueryOptionITCas extends AbstractBaseTestITCase { } @Override - protected CommonODataClient getClient() { + protected ODataClient getClient() { ODataClient odata = ODataClientFactory.getV4(); odata.getConfiguration().setDefaultPubFormat(ODataFormat.JSON); return odata; diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java index cb944677d..472b53084 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java @@ -6,9 +6,9 @@ * 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 @@ -18,8 +18,10 @@ */ package org.apache.olingo.server.tecsvc.data; +import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; +import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Locale; @@ -29,24 +31,39 @@ 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.Property; +import org.apache.olingo.commons.api.domain.ODataLinkType; +import org.apache.olingo.commons.api.edm.Edm; +import org.apache.olingo.commons.api.edm.EdmBindingTarget; import org.apache.olingo.commons.api.edm.EdmComplexType; import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmEntityType; +import org.apache.olingo.commons.api.edm.EdmNavigationProperty; import org.apache.olingo.commons.api.edm.EdmPrimitiveType; import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException; import org.apache.olingo.commons.api.edm.EdmProperty; import org.apache.olingo.commons.api.edm.EdmStructuredType; +import org.apache.olingo.commons.api.edm.EdmType; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.commons.core.data.EntityImpl; +import org.apache.olingo.commons.core.data.EntitySetImpl; +import org.apache.olingo.commons.core.data.LinkImpl; +import org.apache.olingo.commons.core.edm.primitivetype.EdmInt16; +import org.apache.olingo.commons.core.edm.primitivetype.EdmInt32; +import org.apache.olingo.commons.core.edm.primitivetype.EdmInt64; +import org.apache.olingo.commons.core.edm.primitivetype.EdmString; +import org.apache.olingo.server.api.OData; import org.apache.olingo.server.api.ODataApplicationException; +import org.apache.olingo.server.api.deserializer.DeserializerException; import org.apache.olingo.server.api.uri.UriParameter; public class DataProvider { protected static final String MEDIA_PROPERTY_NAME = "$value"; - private static final String KEY_NAME = "PropertyInt16"; +// private static final String KEY_NAME = "PropertyInt16"; - private Map data; + final private Map data; + private Edm edm; + private OData odata; public DataProvider() { data = new DataCreator().getData(); @@ -116,35 +133,97 @@ public class DataProvider { } } +// public Entity create(final EdmEntitySet edmEntitySet) throws DataProviderException { +// final EdmEntityType edmEntityType = edmEntitySet.getEntityType(); +// List entities = readAll(edmEntitySet).getEntities(); +// Entity entity = new EntityImpl(); +// final List keyNames = edmEntityType.getKeyPredicateNames(); +// if (keyNames.size() == 1 && keyNames.get(0).equals(KEY_NAME)) { +// entity.addProperty(DataCreator.createPrimitive(KEY_NAME, findFreeKeyValue(entities))); +// } else { +// throw new DataProviderException("Key construction not supported!"); +// } +// createProperties(edmEntityType, entity.getProperties()); +// entities.add(entity); +// return entity; +// } +// +// private Integer findFreeKeyValue(final List entities) { +// Integer result = 0; +// boolean free; +// do { +// ++result; +// free = true; +// for (final Entity entity : entities) { +// if (result.equals(entity.getProperty(KEY_NAME).getValue())) { +// free = false; +// break; +// } +// } +// } while (!free); +// return result; +// } + public Entity create(final EdmEntitySet edmEntitySet) throws DataProviderException { final EdmEntityType edmEntityType = edmEntitySet.getEntityType(); - List entities = readAll(edmEntitySet).getEntities(); - Entity entity = new EntityImpl(); - final List keyNames = edmEntityType.getKeyPredicateNames(); - if (keyNames.size() == 1 && keyNames.get(0).equals(KEY_NAME)) { - entity.addProperty(DataCreator.createPrimitive(KEY_NAME, findFreeKeyValue(entities))); - } else { - throw new DataProviderException("Key construction not supported!"); + final EntitySet entitySet = readAll(edmEntitySet); + final List entities = entitySet.getEntities(); + final Map newKey = findFreeComposedKey(entities, edmEntitySet.getEntityType()); + final Entity newEntity = new EntityImpl(); + + for (final String keyName : edmEntityType.getKeyPredicateNames()) { + newEntity.addProperty(DataCreator.createPrimitive(keyName, newKey.get(keyName))); } - createProperties(edmEntityType, entity.getProperties()); - entities.add(entity); - return entity; + + createProperties(edmEntityType, newEntity.getProperties()); + entities.add(newEntity); + + return newEntity; } - private Integer findFreeKeyValue(final List entities) { - Integer result = 0; - boolean free; - do { - ++result; - free = true; - for (final Entity entity : entities) { - if (result.equals(entity.getProperty(KEY_NAME).getValue())) { - free = false; - break; + private Map findFreeComposedKey(final List entities, final EdmEntityType entityType) + throws DataProviderException { + // Weak key construction + // 3e € entity: (V k € keys: k !€ e.ki) => e.(k1, k2, k3) !€ entitySet + final HashMap keys = new HashMap(); + for (final String keyName : entityType.getKeyPredicateNames()) { + final EdmType type = entityType.getProperty(keyName).getType(); + Object newValue = null; + + if (type instanceof EdmInt16 || type instanceof EdmInt32 || type instanceof EdmInt64) { + // Integer keys + newValue = Integer.valueOf(1); + + while (!isFree(newValue, keyName, entities)) { + newValue = ((Integer) newValue) + 1; } + } else if (type instanceof EdmString) { + // String keys + newValue = String.valueOf(1); + int i = 0; + + while (!isFree(newValue, keyName, entities)) { + newValue = String.valueOf(i); + i++; + } + } else { + throw new DataProviderException("Key type not supported"); } - } while (!free); - return result; + + keys.put(keyName, newValue); + } + + return keys; + } + + private boolean isFree(final Object value, final String keyPropertyName, final List entities) { + for (final Entity entity : entities) { + if (value != null && value.equals(entity.getProperty(keyPropertyName).getValue())) { + return false; + } + } + + return true; } private void createProperties(final EdmStructuredType type, List properties) throws DataProviderException { @@ -173,10 +252,14 @@ public class DataProvider { } } - public void update(final EdmEntitySet edmEntitySet, Entity entity, final Entity changedEntity, final boolean patch) - throws DataProviderException { + public void update(final String rawBaseUri, final EdmEntitySet edmEntitySet, Entity entity, + final Entity changedEntity, final boolean patch, + final boolean isInsert) throws DataProviderException { + final EdmEntityType entityType = edmEntitySet.getEntityType(); final List keyNames = entityType.getKeyPredicateNames(); + + // Update Properties for (final String propertyName : entityType.getPropertyNames()) { if (!keyNames.contains(propertyName)) { updateProperty(entityType.getStructuralProperty(propertyName), @@ -185,8 +268,140 @@ public class DataProvider { patch); } } + + // Deep insert (only if not an update) + if (isInsert) { + handleDeepInsert(rawBaseUri, edmEntitySet, entity, changedEntity); + } else if (isInsert && changedEntity.getNavigationLinks().size() != 0) { + throw new DataProviderException("Deep inserts are not allowed in update operations using PUT or PATCH requests."); + } + if (!changedEntity.getNavigationBindings().isEmpty()) { - throw new DataProviderException("Binding operations are not yet supported."); + applyNavigationBinding(rawBaseUri, edmEntitySet, entity, changedEntity.getNavigationBindings()); + } + } + + private void applyNavigationBinding(final String rawBaseUri, final EdmEntitySet edmEntitySet, + final Entity entity, final List navigationBindings) throws DataProviderException { + + for (final Link link : navigationBindings) { + final EdmNavigationProperty edmNavProperty = edmEntitySet.getEntityType().getNavigationProperty(link.getTitle()); + final EdmEntitySet edmTargetEntitySet = + (EdmEntitySet) edmEntitySet.getRelatedBindingTarget(edmNavProperty.getName()); + + if (edmNavProperty.isCollection()) { + for (final String bindingLink : link.getBindingLinks()) { + final Entity destEntity = getEntityByURI(rawBaseUri, edmTargetEntitySet, bindingLink); + createLink(edmNavProperty, entity, destEntity); + } + } else { + final String bindingLink = link.getBindingLink(); + final Entity destEntity = getEntityByURI(rawBaseUri, edmTargetEntitySet, bindingLink); + createLink(edmNavProperty, entity, destEntity); + } + } + } + + private Entity getEntityByURI(final String rawBaseUri, final EdmEntitySet edmEntitySetTarget, + final String bindingLink) throws DataProviderException { + + try { + final List keys = odata.createUriHelper() + .getKeyPredicatesFromEntityLink(edm, bindingLink, rawBaseUri); + final Entity entity = read(edmEntitySetTarget, keys); + + if(entity == null) { + throw new DataProviderException("Entity " + bindingLink + " not found"); + } + + return entity; + } catch (DeserializerException e) { + throw new DataProviderException("Invalid entity binding link", e); + } + } + + private void handleDeepInsert(final String rawBaseUri, final EdmEntitySet edmEntitySet, Entity entity, + final Entity changedEntity) + throws DataProviderException { + final EdmEntityType entityType = edmEntitySet.getEntityType(); + + for (final String navPropertyName : entityType.getNavigationPropertyNames()) { + final Link navigationLink = changedEntity.getNavigationLink(navPropertyName); + + if (navigationLink != null) { + // Deep inserts are not allowed in update operations, so we can be sure, that we do not override + // a navigation link! + final EdmNavigationProperty navigationProperty = entityType.getNavigationProperty(navPropertyName); + final EdmBindingTarget target = edmEntitySet.getRelatedBindingTarget(navPropertyName); + final EdmEntityType inlineEntityType = navigationProperty.getType(); + + if (navigationProperty.isCollection()) { + final List entities = + createInlineEntities(rawBaseUri, target, inlineEntityType, navigationLink.getInlineEntitySet()); + + for (final Entity inlineEntity : entities) { + createLink(navigationProperty, entity, inlineEntity); + } + } else { + final Entity inlineEntity = + createInlineEntity(rawBaseUri, target, inlineEntityType, navigationLink.getInlineEntity()); + createLink(navigationProperty, entity, inlineEntity); + } + } + } + } + + private List createInlineEntities(final String rawBaseUri, final EdmBindingTarget target, + final EdmEntityType type, final EntitySet changedEntitsSet) throws DataProviderException { + List entities = new ArrayList(); + + for (final Entity newEntity : changedEntitsSet.getEntities()) { + entities.add(createInlineEntity(rawBaseUri, target, type, newEntity)); + } + + return entities; + } + + private Entity createInlineEntity(final String rawBaseUri, final EdmBindingTarget target, + final EdmEntityType type, final Entity changedEntity) throws DataProviderException { + + final Entity inlineEntity = create((EdmEntitySet) target); + update(rawBaseUri, (EdmEntitySet) target, inlineEntity, changedEntity, false, true); + + return inlineEntity; + } + + private void createLink(final EdmNavigationProperty navigationProperty, final Entity srcEntity, + final Entity destEntity) { + setLink(navigationProperty, srcEntity, destEntity); + + final EdmNavigationProperty partnerNavigationProperty = navigationProperty.getPartner(); + if (partnerNavigationProperty != null) { + setLink(partnerNavigationProperty, destEntity, srcEntity); + } + } + + // TODO Duplicated code in DataCreator + private void setLink(final EdmNavigationProperty navigationProperty, final Entity srcEntity, + final Entity destEntity) { + + Link link = srcEntity.getNavigationLink(navigationProperty.getName()); + if (link == null) { + link = new LinkImpl(); + link.setTitle(navigationProperty.getName()); + srcEntity.getNavigationLinks().add(link); + } + + if (navigationProperty.isCollection()) { + if (link.getInlineEntitySet() == null) { + link.setType(ODataLinkType.ENTITY_SET_NAVIGATION.toString()); + link.setInlineEntitySet(new EntitySetImpl()); + } + + link.getInlineEntitySet().getEntities().add(destEntity); + } else { + link.setType(ODataLinkType.ENTITY_NAVIGATION.toString()); + link.setInlineEntity(destEntity); } } @@ -238,6 +453,14 @@ public class DataProvider { entity.setMediaContentType(type); } + public void setEdm(final Edm edm) { + this.edm = edm; + } + + public void setOData(final OData odata) { + this.odata = odata; + } + public static class DataProviderException extends ODataApplicationException { private static final long serialVersionUID = 5098059649321796156L; diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java index 8fe587964..8414a21d5 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java @@ -53,8 +53,12 @@ import org.apache.olingo.server.api.uri.UriResourceEntitySet; import org.apache.olingo.server.api.uri.queryoption.ExpandOption; import org.apache.olingo.server.api.uri.queryoption.SelectOption; import org.apache.olingo.server.tecsvc.data.DataProvider; -import org.apache.olingo.server.tecsvc.processor.queryoptions.SystemQueryOptions; +import org.apache.olingo.server.tecsvc.processor.queryoptions.options.CountHandler; +import org.apache.olingo.server.tecsvc.processor.queryoptions.options.FilterHandler; +import org.apache.olingo.server.tecsvc.processor.queryoptions.options.OrderByHandler; import org.apache.olingo.server.tecsvc.processor.queryoptions.options.ServerSidePagingHandler; +import org.apache.olingo.server.tecsvc.processor.queryoptions.options.SkipHandler; +import org.apache.olingo.server.tecsvc.processor.queryoptions.options.TopHandler; /** * Technical Processor for entity-related functionality. @@ -83,9 +87,17 @@ public class TechnicalEntityProcessor extends TechnicalProcessor entitySet.getEntities().addAll(entitySetInitial.getEntities()); // Apply system query options - SystemQueryOptions.applySystemQueryOptions(entitySet, edmEntitySet, uriInfo); - ServerSidePagingHandler.applyServerSidePaging(entitySet, request.getRawRequestUri(), uriInfo); - + FilterHandler.applyFilterSystemQuery(uriInfo.getFilterOption(), entitySet, edmEntitySet); + CountHandler.applyCountSystemQueryOption(uriInfo.getCountOption(), entitySet); + OrderByHandler.applyOrderByOption(uriInfo.getOrderByOption(), entitySet, edmEntitySet); + SkipHandler.applySkipSystemQueryHandler(uriInfo.getSkipOption(), entitySet); + TopHandler.applyTopSystemQueryOption(uriInfo.getTopOption(), entitySet); + + ServerSidePagingHandler.applyServerSidePaging(uriInfo.getSkipTokenOption(), + entitySet, + edmEntitySet, + request.getRawRequestUri()); + final ODataFormat format = ODataFormat.fromContentType(requestedContentType); ODataSerializer serializer = odata.createSerializer(format); final ExpandOption expand = uriInfo.getExpandOption(); @@ -114,7 +126,7 @@ public class TechnicalEntityProcessor extends TechnicalProcessor public void countEntityCollection(final ODataRequest request, ODataResponse response, final UriInfo uriInfo) throws ODataApplicationException, SerializerException { validateOptions(uriInfo.asUriInfoResource()); - getEdmEntitySet(uriInfo); // including checks + getEdmEntitySet(uriInfo); // including checks EntitySet entitySet = readEntityCollection(uriInfo); if (entitySet == null) { throw new ODataApplicationException("Nothing found.", HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ROOT); @@ -150,7 +162,7 @@ public class TechnicalEntityProcessor extends TechnicalProcessor @Override public void readMediaEntity(final ODataRequest request, ODataResponse response, final UriInfo uriInfo, final ContentType responseFormat) throws ODataApplicationException, SerializerException { - getEdmEntitySet(uriInfo); // including checks + getEdmEntitySet(uriInfo); // including checks final Entity entity = readEntity(uriInfo); response.setContent(odata.createFixedFormatSerializer().binary(dataProvider.readMedia(entity))); response.setStatusCode(HttpStatusCode.OK.getStatusCode()); @@ -167,7 +179,7 @@ public class TechnicalEntityProcessor extends TechnicalProcessor @Override public void createEntity(final ODataRequest request, ODataResponse response, final UriInfo uriInfo, final ContentType requestFormat, final ContentType responseFormat) - throws ODataApplicationException, DeserializerException, SerializerException { + throws ODataApplicationException, DeserializerException, SerializerException { if (uriInfo.asUriInfoResource().getUriResourceParts().size() > 1) { throw new ODataApplicationException("Invalid resource type.", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); @@ -182,10 +194,10 @@ public class TechnicalEntityProcessor extends TechnicalProcessor dataProvider.setMedia(entity, odata.createFixedFormatDeserializer().binary(request.getBody()), requestFormat.toContentTypeString()); } else { - dataProvider.update(edmEntitySet, entity, + dataProvider.update(request.getRawBaseUri(), edmEntitySet, entity, odata.createDeserializer(ODataFormat.fromContentType(requestFormat)) .entity(request.getBody(), edmEntityType), - false); + false, true); } final ODataFormat format = ODataFormat.fromContentType(responseFormat); @@ -204,21 +216,22 @@ public class TechnicalEntityProcessor extends TechnicalProcessor @Override public void updateEntity(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo, final ContentType requestFormat, final ContentType responseFormat) - throws ODataApplicationException, DeserializerException, SerializerException { + throws ODataApplicationException, DeserializerException, SerializerException { final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo); Entity entity = readEntity(uriInfo); checkRequestFormat(requestFormat); ODataDeserializer deserializer = odata.createDeserializer(ODataFormat.fromContentType(requestFormat)); final Entity changedEntity = deserializer.entity(request.getBody(), edmEntitySet.getEntityType()); - dataProvider.update(edmEntitySet, entity, changedEntity, request.getMethod() == HttpMethod.PATCH); + dataProvider.update(request.getRawBaseUri(), edmEntitySet, entity, changedEntity, + request.getMethod() == HttpMethod.PATCH, false); response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode()); } @Override public void updateMediaEntity(final ODataRequest request, ODataResponse response, final UriInfo uriInfo, final ContentType requestFormat, final ContentType responseFormat) - throws ODataApplicationException, DeserializerException, SerializerException { - getEdmEntitySet(uriInfo); // including checks + throws ODataApplicationException, DeserializerException, SerializerException { + getEdmEntitySet(uriInfo); // including checks Entity entity = readEntity(uriInfo); checkRequestFormat(requestFormat); dataProvider.setMedia(entity, odata.createFixedFormatDeserializer().binary(request.getBody()), @@ -244,7 +257,6 @@ public class TechnicalEntityProcessor extends TechnicalProcessor } private void setCount(EntitySet entitySet) { - // TODO: set count (correctly) and next link if (entitySet.getCount() == null) { entitySet.setCount(entitySet.getEntities().size()); } diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java index c5853b112..36d02b8c8 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java @@ -46,6 +46,7 @@ public abstract class TechnicalProcessor implements Processor { protected OData odata; protected DataProvider dataProvider; + protected ServiceMetadata serviceMetadata; protected TechnicalProcessor(final DataProvider dataProvider) { this.dataProvider = dataProvider; @@ -54,6 +55,9 @@ public abstract class TechnicalProcessor implements Processor { @Override public void init(final OData odata, final ServiceMetadata serviceMetadata) { this.odata = odata; + this.serviceMetadata = serviceMetadata; + this.dataProvider.setOData(odata); + this.dataProvider.setEdm(serviceMetadata.getEdm()); } protected EdmEntitySet getEdmEntitySet(final UriInfoResource uriInfo) throws ODataApplicationException { diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/SystemQueryOptions.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/SystemQueryOptions.java deleted file mode 100644 index e1c49df87..000000000 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/SystemQueryOptions.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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.server.tecsvc.processor.queryoptions; - -import org.apache.olingo.commons.api.data.EntitySet; -import org.apache.olingo.commons.api.edm.EdmEntitySet; -import org.apache.olingo.server.api.ODataApplicationException; -import org.apache.olingo.server.api.uri.UriInfo; -import org.apache.olingo.server.tecsvc.processor.queryoptions.options.CountHandler; -import org.apache.olingo.server.tecsvc.processor.queryoptions.options.FilterHandler; -import org.apache.olingo.server.tecsvc.processor.queryoptions.options.OrderByHandler; -import org.apache.olingo.server.tecsvc.processor.queryoptions.options.SkipHandler; -import org.apache.olingo.server.tecsvc.processor.queryoptions.options.TopHandler; - -public class SystemQueryOptions { - public static void applySystemQueryOptions(final EntitySet entitySet, final EdmEntitySet edmEntitySet, - final UriInfo uriInfo) throws ODataApplicationException { - - FilterHandler.applyFilterSystemQuery(uriInfo.getFilterOption(), entitySet, edmEntitySet); - CountHandler.applyCountSystemQueryOption(uriInfo.getCountOption(), entitySet); - OrderByHandler.applyOrderByOption(uriInfo.getOrderByOption(), entitySet, edmEntitySet); - SkipHandler.applySkipSystemQueryHandler(uriInfo.getSkipOption(), entitySet); - TopHandler.applyTopSystemQueryOption(uriInfo.getTopOption(), entitySet); - } -} diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/CountHandler.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/CountHandler.java index f5b15e765..59f6a4e34 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/CountHandler.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/CountHandler.java @@ -27,5 +27,4 @@ public class CountHandler { entitySet.setCount(entitySet.getEntities().size()); } } - } diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/OrderByHandler.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/OrderByHandler.java index 976efb5bd..71b9a81a0 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/OrderByHandler.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/OrderByHandler.java @@ -31,7 +31,6 @@ import org.apache.olingo.server.api.uri.queryoption.OrderByItem; import org.apache.olingo.server.api.uri.queryoption.OrderByOption; import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitException; import org.apache.olingo.server.tecsvc.processor.queryoptions.expression.ExpressionVisitorImpl; -import org.apache.olingo.server.tecsvc.processor.queryoptions.expression.FilterRuntimeException; import org.apache.olingo.server.tecsvc.processor.queryoptions.expression.operand.TypedOperand; public class OrderByHandler { @@ -44,7 +43,7 @@ public class OrderByHandler { try { applyOrderByOptionInternal(orderByOption, entitySet, edmEntitySet); - } catch (FilterRuntimeException e) { + } catch (SystemQueryOptionsRuntimeException e) { if (e.getCause() instanceof ODataApplicationException) { // Throw the nested exception, to send the correct HTTP status code in the HTTP response throw (ODataApplicationException) e.getCause(); @@ -93,9 +92,9 @@ public class OrderByHandler { result = item.isDescending() ? result * -1 : result; } catch (ODataApplicationException e) { - throw new FilterRuntimeException(e); + throw new SystemQueryOptionsRuntimeException(e); } catch (ExpressionVisitException e) { - throw new FilterRuntimeException(e); + throw new SystemQueryOptionsRuntimeException(e); } } return result; diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/ServerSidePagingHandler.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/ServerSidePagingHandler.java index db8b6fbf3..98ff0d954 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/ServerSidePagingHandler.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/ServerSidePagingHandler.java @@ -23,22 +23,23 @@ import java.net.URISyntaxException; import java.util.Locale; import org.apache.olingo.commons.api.data.EntitySet; +import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.commons.core.Encoder; import org.apache.olingo.server.api.ODataApplicationException; -import org.apache.olingo.server.api.uri.UriInfo; import org.apache.olingo.server.api.uri.queryoption.SkipTokenOption; import org.apache.olingo.server.api.uri.queryoption.SystemQueryOptionKind; public class ServerSidePagingHandler { private static final int MAX_PAGE_SIZE = 10; + private static final String ES_SERVER_SIDE_PAGING = "ESServerSidePaging"; - public static void - applyServerSidePaging(final EntitySet entitySet, final String rawRequestUri, final UriInfo uriInfo) - throws ODataApplicationException { - if (shouldApplyServerSidePaging(entitySet)) { + public static void applyServerSidePaging(final SkipTokenOption skipTokenOption, final EntitySet entitySet, + final EdmEntitySet edmEntitySet, final String rawRequestUri) throws ODataApplicationException { + + if (shouldApplyServerSidePaging(edmEntitySet)) { final int maxPageSize = getMaxPageSize(); - final int page = getPage(uriInfo.getSkipTokenOption()); + final int page = getPage(skipTokenOption); final int itemsToSkip = maxPageSize * page; if (itemsToSkip <= entitySet.getEntities().size()) { @@ -48,16 +49,15 @@ public class ServerSidePagingHandler { // Determine if a new next Link has to be provided if (remainingItems > maxPageSize) { - entitySet.setNext(createNextLink(uriInfo, rawRequestUri, page + 1)); + entitySet.setNext(createNextLink(rawRequestUri, page + 1)); } } else { - throw new ODataApplicationException("Invalid skiptoken", HttpStatusCode.BAD_REQUEST.getStatusCode(), - Locale.ROOT); + throw new ODataApplicationException("Nothing found.", HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ROOT); } } } - private static URI createNextLink(final UriInfo uriInfo, final String rawRequestUri, final Integer page) + private static URI createNextLink(final String rawRequestUri, final Integer page) throws ODataApplicationException { try { @@ -99,8 +99,8 @@ public class ServerSidePagingHandler { } } - private static boolean shouldApplyServerSidePaging(final EntitySet entitySet) { - return true; + private static boolean shouldApplyServerSidePaging(final EdmEntitySet edmEntitySet) { + return ES_SERVER_SIDE_PAGING.equals(edmEntitySet.getName()); } private static int getMaxPageSize() { diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/expression/FilterRuntimeException.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/SystemQueryOptionsRuntimeException.java similarity index 72% rename from lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/expression/FilterRuntimeException.java rename to lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/SystemQueryOptionsRuntimeException.java index 64865641e..c682795db 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/expression/FilterRuntimeException.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/SystemQueryOptionsRuntimeException.java @@ -16,23 +16,15 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.olingo.server.tecsvc.processor.queryoptions.expression; +package org.apache.olingo.server.tecsvc.processor.queryoptions.options; import org.apache.olingo.commons.api.ODataRuntimeException; -public class FilterRuntimeException extends ODataRuntimeException { +public class SystemQueryOptionsRuntimeException extends ODataRuntimeException { private static final long serialVersionUID = 1L; - public FilterRuntimeException(Exception cause) { + public SystemQueryOptionsRuntimeException(Exception cause) { super(cause); } - - public FilterRuntimeException(String msg, Exception cause) { - super(msg, cause); - } - - public FilterRuntimeException(String msg) { - super(msg); - } }