Repository: olingo-odata4 Updated Branches: refs/heads/master 3ba5cb36d -> 7902e7232
[OLINGO-286] fixed: provided intengration test for '13.2 Interoperable OData Clients' Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/259eb078 Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/259eb078 Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/259eb078 Branch: refs/heads/master Commit: 259eb07851593ba863ac820c2fa2e40d5e792b56 Parents: a57926b Author: fmartelli <[email protected]> Authored: Thu May 22 17:04:04 2014 +0200 Committer: fmartelli <[email protected]> Committed: Thu May 22 17:04:04 2014 +0200 ---------------------------------------------------------------------- .../java/org/apache/olingo/fit/V4Services.java | 32 +- .../olingo/fit/utils/AbstractUtilities.java | 5 +- fit/src/main/resources/esigate.properties | 2 +- .../olingo/fit/proxy/v4/AbstractTestITCase.java | 2 +- .../olingo/fit/v3/AbstractTestITCase.java | 2 +- .../olingo/fit/v4/AbstractTestITCase.java | 2 +- .../olingo/fit/v4/ConformanceTestITCase.java | 420 +++++++++++++++++++ 7 files changed, 448 insertions(+), 17 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/259eb078/fit/src/main/java/org/apache/olingo/fit/V4Services.java ---------------------------------------------------------------------- diff --git a/fit/src/main/java/org/apache/olingo/fit/V4Services.java b/fit/src/main/java/org/apache/olingo/fit/V4Services.java index db88da0..e4a2c73 100644 --- a/fit/src/main/java/org/apache/olingo/fit/V4Services.java +++ b/fit/src/main/java/org/apache/olingo/fit/V4Services.java @@ -114,6 +114,16 @@ public class V4Services extends AbstractServices { } @GET + @Path("/redirect/{name}({id})") + public Response conformanceRedirect( + @Context UriInfo uriInfo, + @PathParam("name") String name, + @PathParam("id") String id) { + return Response.temporaryRedirect( + URI.create(uriInfo.getRequestUri().toASCIIString().replace("/redirect", ""))).build(); + } + + @GET @Path("/$crossjoin({elements:.*})") public Response crossjoin( @PathParam("elements") String elements, @@ -364,7 +374,7 @@ public class V4Services extends AbstractServices { return StringUtils.isBlank(filter) && StringUtils.isBlank(search) ? NumberUtils.isNumber(type) ? super.getEntityInternal( - uriInfo.getRequestUri().toASCIIString(), accept, "People", type, format, null, null, true) + uriInfo.getRequestUri().toASCIIString(), accept, "People", type, format, null, null, true) : super.getEntitySet(accept, "People", type) : super.getEntitySet(uriInfo, accept, "People", top, skip, format, count, filter, orderby, skiptoken); } @@ -668,7 +678,7 @@ public class V4Services extends AbstractServices { @PathParam("entityId") String entityId, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) String format) { - return getContainedEntity(accept, entityId, "MyPaymentInstruments", entityId+ "901", format); + return getContainedEntity(accept, entityId, "MyPaymentInstruments", entityId + "901", format); } @GET @@ -738,7 +748,7 @@ public class V4Services extends AbstractServices { return utils.getValue().createResponse( FSManager.instance(version).readFile(Constants.get(version, ConstantKey.REF) - + File.separatorChar + filename, utils.getKey()), + + File.separatorChar + filename, utils.getKey()), null, utils.getKey()); } catch (Exception e) { @@ -760,7 +770,7 @@ public class V4Services extends AbstractServices { final Response response = getEntityInternal(uriInfo.getRequestUri().toASCIIString(), - accept, entitySetName, entityId, accept, StringUtils.EMPTY, StringUtils.EMPTY, false); + accept, entitySetName, entityId, accept, StringUtils.EMPTY, StringUtils.EMPTY, false); return response.getStatus() >= 400 ? postNewEntity(uriInfo, accept, contentType, prefer, entitySetName, changes) : super.patchEntity(uriInfo, accept, contentType, prefer, ifMatch, entitySetName, entityId, changes); @@ -858,8 +868,8 @@ public class V4Services extends AbstractServices { } else { final ResWrap<JSONEntityImpl> jcontainer = mapper.readValue(IOUtils.toInputStream(entity, Constants.ENCODING), - new TypeReference<JSONEntityImpl>() { - }); + new TypeReference<JSONEntityImpl>() { + }); entry = dataBinder.toAtomEntity(jcontainer.getPayload()); @@ -957,7 +967,7 @@ public class V4Services extends AbstractServices { final ResWrap<JSONEntityImpl> jsonContainer = mapper.readValue( IOUtils.toInputStream(changes, Constants.ENCODING), new TypeReference<JSONEntityImpl>() { - }); + }); jsonContainer.getPayload().setType(typeInfo.getFullQualifiedName().toString()); entryChanges = dataBinder.toAtomEntity(jsonContainer.getPayload()); } @@ -991,7 +1001,7 @@ public class V4Services extends AbstractServices { // 1. Fetch the contained entity to be removed final InputStream entry = FSManager.instance(version). readFile(containedPath(entityId, containedEntitySetName). - append('(').append(containedEntityId).append(')').toString(), Accept.ATOM); + append('(').append(containedEntityId).append(')').toString(), Accept.ATOM); final ResWrap<AtomEntityImpl> container = atomDeserializer.read(entry, AtomEntityImpl.class); // 2. Remove the contained entity @@ -1237,8 +1247,8 @@ public class V4Services extends AbstractServices { } else { final ResWrap<JSONPropertyImpl> paramContainer = mapper.readValue(IOUtils.toInputStream(param, Constants.ENCODING), - new TypeReference<JSONPropertyImpl>() { - }); + new TypeReference<JSONPropertyImpl>() { + }); property = paramContainer.getPayload(); } @@ -1278,7 +1288,7 @@ public class V4Services extends AbstractServices { final ResWrap<AtomPropertyImpl> result = new ResWrap<AtomPropertyImpl>( URI.create(Constants.get(version, ConstantKey.ODATA_METADATA_PREFIX) - + "Microsoft.Test.OData.Services.ODataWCFService.Address"), + + "Microsoft.Test.OData.Services.ODataWCFService.Address"), null, (AtomPropertyImpl) entity.getProperty("address")); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/259eb078/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java ---------------------------------------------------------------------- diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java b/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java index 00259321..0c60609 100644 --- a/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java +++ b/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java @@ -367,7 +367,8 @@ public abstract class AbstractUtilities { final Map<String, NavigationProperty> navigationProperties = metadata.getNavigationProperties(entitySetName); - if (navigationProperties.get(linkName).isEntitySet()) { + // check for nullability in order to support navigation property on open types + if (navigationProperties.get(linkName) != null && navigationProperties.get(linkName).isEntitySet()) { try { final Map.Entry<String, List<String>> currents = extractLinkURIs(entitySetName, entityKey, linkName); uris.addAll(currents.getValue()); @@ -701,7 +702,7 @@ public abstract class AbstractUtilities { + ",ProductID=" + entity.getProperty("ProductID").getValue().asPrimitive().get(); } Commons.SEQUENCE.put(entitySetName, productID); - }else if ("Message".equals(entitySetName)) { + } else if ("Message".equals(entitySetName)) { int messageId; if (entity.getProperty("MessageId") == null || entity.getProperty("FromUsername") == null) { if (Commons.SEQUENCE.containsKey(entitySetName)) { http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/259eb078/fit/src/main/resources/esigate.properties ---------------------------------------------------------------------- diff --git a/fit/src/main/resources/esigate.properties b/fit/src/main/resources/esigate.properties index 38c4450..0db861a 100644 --- a/fit/src/main/resources/esigate.properties +++ b/fit/src/main/resources/esigate.properties @@ -17,7 +17,7 @@ # under the License. # -webapp.remoteUrlBase=http://localhost:${cargo.servlet.port}/stub/StaticService/V30/Static.svc/ +webapp.remoteUrlBase=http://localhost:${cargo.servlet.port}/stub/StaticService/ visibleUrlBase=http://localhost:${cargo.servlet.port}/stub/DefaultService.svc/ useCache=true extensions=org.apache.olingo.fit.rproxy.LinkRewrite http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/259eb078/fit/src/test/java/org/apache/olingo/fit/proxy/v4/AbstractTestITCase.java ---------------------------------------------------------------------- diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/AbstractTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/AbstractTestITCase.java index 4efc7d0..d3301e8 100644 --- a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/AbstractTestITCase.java +++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/AbstractTestITCase.java @@ -75,7 +75,7 @@ public abstract class AbstractTestITCase { testActionOverloadingServiceRootURL = "http://localhost:9080/stub/StaticService/V40/ActionOverloading.svc"; testOpenTypeServiceRootURL = "http://localhost:9080/stub/StaticService/V40/OpenType.svc"; testLargeModelServiceRootURL = "http://localhost:9080/stub/StaticService/V40/Static.svc/large"; - testAuthServiceRootURL = "http://localhost:9080/stub/DefaultService.svc"; + testAuthServiceRootURL = "http://localhost:9080/stub/DefaultService.svc/V40/Static.svc"; containerFactory = EntityContainerFactory.getV4(testStaticServiceRootURL); containerFactory.getClient().getConfiguration().setDefaultBatchAcceptFormat(ContentType.APPLICATION_OCTET_STREAM); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/259eb078/fit/src/test/java/org/apache/olingo/fit/v3/AbstractTestITCase.java ---------------------------------------------------------------------- diff --git a/fit/src/test/java/org/apache/olingo/fit/v3/AbstractTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/v3/AbstractTestITCase.java index d9bf300..aacecdc 100644 --- a/fit/src/test/java/org/apache/olingo/fit/v3/AbstractTestITCase.java +++ b/fit/src/test/java/org/apache/olingo/fit/v3/AbstractTestITCase.java @@ -93,7 +93,7 @@ public abstract class AbstractTestITCase extends AbstractBaseTestITCase { testActionOverloadingServiceRootURL = "http://localhost:9080/stub/StaticService/V30/ActionOverloading.svc"; testOpenTypeServiceRootURL = "http://localhost:9080/stub/StaticService/V30/OpenType.svc"; testLargeModelServiceRootURL = "http://localhost:9080/stub/StaticService/V30/Static.svc/large"; - testAuthServiceRootURL = "http://localhost:9080/stub/DefaultService.svc"; + testAuthServiceRootURL = "http://localhost:9080/stub/DefaultService.svc/V30/Static.svc"; client.getConfiguration().setDefaultBatchAcceptFormat(ContentType.APPLICATION_OCTET_STREAM); } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/259eb078/fit/src/test/java/org/apache/olingo/fit/v4/AbstractTestITCase.java ---------------------------------------------------------------------- diff --git a/fit/src/test/java/org/apache/olingo/fit/v4/AbstractTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/v4/AbstractTestITCase.java index 32a6e19..31619e3 100644 --- a/fit/src/test/java/org/apache/olingo/fit/v4/AbstractTestITCase.java +++ b/fit/src/test/java/org/apache/olingo/fit/v4/AbstractTestITCase.java @@ -73,7 +73,7 @@ public abstract class AbstractTestITCase extends AbstractBaseTestITCase { testKeyAsSegmentServiceRootURL = "http://localhost:9080/stub/StaticService/V40/KeyAsSegment.svc"; testOpenTypeServiceRootURL = "http://localhost:9080/stub/StaticService/V40/OpenType.svc"; testLargeModelServiceRootURL = "http://localhost:9080/stub/StaticService/V40/Static.svc/large"; - testAuthServiceRootURL = "http://localhost:9080/stub/DefaultService.svc"; + testAuthServiceRootURL = "http://localhost:9080/stub/DefaultService.svc/V40/Static.svc"; edmClient = ODataClientFactory.getEdmEnabledV4(testStaticServiceRootURL); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/259eb078/fit/src/test/java/org/apache/olingo/fit/v4/ConformanceTestITCase.java ---------------------------------------------------------------------- diff --git a/fit/src/test/java/org/apache/olingo/fit/v4/ConformanceTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/v4/ConformanceTestITCase.java new file mode 100644 index 0000000..7e95014 --- /dev/null +++ b/fit/src/test/java/org/apache/olingo/fit/v4/ConformanceTestITCase.java @@ -0,0 +1,420 @@ +/* + * 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.v4; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; + +import org.junit.Test; +import java.net.URI; + +import org.apache.olingo.client.api.communication.header.HeaderName; +import org.apache.olingo.client.api.communication.request.cud.ODataDeleteRequest; +import org.apache.olingo.client.api.communication.request.cud.ODataEntityCreateRequest; +import org.apache.olingo.client.api.communication.request.cud.ODataEntityUpdateRequest; +import org.apache.olingo.client.api.communication.request.cud.v4.UpdateType; +import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest; +import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest; +import org.apache.olingo.client.api.communication.request.retrieve.v4.ODataDeltaRequest; +import org.apache.olingo.client.api.communication.request.v4.AsyncRequestWrapper; +import org.apache.olingo.client.api.communication.response.ODataDeleteResponse; +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.api.communication.response.v4.AsyncResponseWrapper; +import org.apache.olingo.client.api.uri.CommonURIBuilder; +import org.apache.olingo.client.api.uri.v4.URIBuilder; +import org.apache.olingo.client.core.http.BasicAuthHttpClientFactory; +import org.apache.olingo.client.core.http.DefaultHttpClientFactory; +import org.apache.olingo.client.core.uri.URIUtils; +import org.apache.olingo.commons.api.domain.ODataCollectionValue; +import org.apache.olingo.commons.api.domain.v4.ODataDelta; +import org.apache.olingo.commons.api.domain.v4.ODataEntity; +import org.apache.olingo.commons.api.domain.v4.ODataEntitySet; +import org.apache.olingo.commons.api.domain.v4.ODataProperty; +import org.apache.olingo.commons.api.domain.v4.ODataValue; +import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind; +import org.apache.olingo.commons.api.edm.FullQualifiedName; +import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion; +import org.apache.olingo.commons.api.format.ODataPubFormat; +import org.apache.olingo.commons.core.domain.v4.ODataEntityImpl; + +/** + * 13.2 Interoperable OData Clients + * <br /> + * http://docs.oasis-open.org/odata/odata/v4.0/os/part1-protocol/odata-v4.0-os-part1-protocol.html#_Toc372793762 + */ +public class ConformanceTestITCase extends AbstractTestITCase { + + /** + * 1. MUST specify the OData-MaxVersion header in requests (section 8.2.6). + */ + @Test + public void item1() { + final URIBuilder uriBuilder = client.newURIBuilder(testStaticServiceRootURL). + appendEntitySetSegment("Customers").appendKeySegment(1).expand("Company"); + + final ODataEntityRequest<ODataEntity> req = + client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build()); + + assertEquals("4.0", req.getHeader("OData-MaxVersion")); + assertEquals("4.0", req.getHeader(HeaderName.odataMaxVersion.toString())); + + assertNotNull(req.execute().getBody()); + } + + /** + * 2. MUST specify OData-Version (section 8.1.5) and Content-Type (section 8.1.1) in any request with a payload. + */ + @Test + public void item2() { + final ODataEntity order = + new ODataEntityImpl(new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.Order")); + + final ODataProperty orderId = getClient().getObjectFactory().newPrimitiveProperty("OrderID", + getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt32(2000)); + order.getProperties().add(orderId); + + final ODataProperty orderDate = getClient().getObjectFactory().newPrimitiveProperty("OrderDate", + getClient().getObjectFactory().newPrimitiveValueBuilder(). + setType(EdmPrimitiveTypeKind.DateTimeOffset).setText("2011-03-04T16:03:57Z").build()); + order.getProperties().add(orderDate); + + final ODataProperty shelfLife = getClient().getObjectFactory().newPrimitiveProperty("ShelfLife", + getClient().getObjectFactory().newPrimitiveValueBuilder(). + setType(EdmPrimitiveTypeKind.Duration).setText("PT0.0000001S").build()); + order.getProperties().add(shelfLife); + + final ODataCollectionValue<ODataValue> orderShelfLifesValue = getClient().getObjectFactory(). + newCollectionValue("Collection(Duration)"); + orderShelfLifesValue.add(getClient().getObjectFactory().newPrimitiveValueBuilder(). + setType(EdmPrimitiveTypeKind.Duration).setText("PT0.0000001S").build()); + orderShelfLifesValue.add(getClient().getObjectFactory().newPrimitiveValueBuilder(). + setType(EdmPrimitiveTypeKind.Duration).setText("PT0.0000002S").build()); + final ODataProperty orderShelfLifes = getClient().getObjectFactory(). + newCollectionProperty("OrderShelfLifes", orderShelfLifesValue); + order.getProperties().add(orderShelfLifes); + + final ODataEntityCreateRequest<ODataEntity> req = getClient().getCUDRequestFactory().getEntityCreateRequest( + getClient().newURIBuilder(testStaticServiceRootURL). + appendEntitySetSegment("Orders").build(), order); + req.setFormat(ODataPubFormat.JSON_FULL_METADATA); + + // check for OData-Version + assertEquals("4.0", req.getHeader("OData-Version")); + assertEquals("4.0", req.getHeader(HeaderName.odataVersion.toString())); + + // check for Content-Type + assertEquals( + ODataPubFormat.JSON_FULL_METADATA.toString(ODataServiceVersion.V40), + req.getHeader("Content-Type")); + assertEquals( + ODataPubFormat.JSON_FULL_METADATA.toString(ODataServiceVersion.V40), + req.getHeader(HeaderName.contentType.toString())); + assertEquals( + ODataPubFormat.JSON_FULL_METADATA.toString(ODataServiceVersion.V40), + req.getContentType()); + + final ODataEntity created = req.execute().getBody(); + assertNotNull(created); + + final URI deleteURI = created.getEditLink() == null + ? getClient().newURIBuilder(testStaticServiceRootURL). + appendEntitySetSegment("Orders").appendKeySegment(2000).build() + : created.getEditLink(); + final ODataDeleteRequest deleteReq = getClient().getCUDRequestFactory().getDeleteRequest(deleteURI); + final ODataDeleteResponse deleteRes = deleteReq.execute(); + assertEquals(204, deleteRes.getStatusCode()); + } + + /** + * 4. MUST follow redirects (section 9.1.5). + */ + @Test + public void item4() { + final URIBuilder uriBuilder = client.newURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("redirect"). + appendEntitySetSegment("Customers").appendKeySegment(1).expand("Company"); + + final ODataEntityRequest<ODataEntity> req = + client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build()); + + assertEquals("4.0", req.getHeader("OData-MaxVersion")); + assertEquals("4.0", req.getHeader(HeaderName.odataMaxVersion.toString())); + + final ODataRetrieveResponse<ODataEntity> res = req.execute(); + final ODataEntity entity = res.getBody(); + + assertNotNull(entity); + assertEquals("Microsoft.Test.OData.Services.ODataWCFService.Customer", entity.getTypeName().toString()); + assertTrue(entity.getProperty("Home").hasPrimitiveValue()); + assertEquals("Edm.GeographyPoint", entity.getProperty("Home").getPrimitiveValue().getTypeName()); + } + + /** + * 5. MUST correctly handle next links (section 11.2.5.7). + */ + @Test + public void item5() { + final URIBuilder uriBuilder = client.newURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("People"); + + ODataEntitySetRequest<ODataEntitySet> req = client.getRetrieveRequestFactory(). + getEntitySetRequest(uriBuilder.build()); + req.setFormat(ODataPubFormat.JSON_FULL_METADATA); + req.setPrefer(client.newPreferences().maxPageSize(5)); + + ODataRetrieveResponse<ODataEntitySet> res = req.execute(); + ODataEntitySet feed = res.getBody(); + + assertNotNull(feed); + + assertEquals(5, feed.getEntities().size()); + assertNotNull(feed.getNext()); + + final URI expected = URI.create(testStaticServiceRootURL + "/People?$skiptoken=5"); + final URI found = URIUtils.getURI(testStaticServiceRootURL, feed.getNext().toASCIIString()); + + assertEquals(expected, found); + + req = client.getRetrieveRequestFactory().getEntitySetRequest(found); + req.setFormat(ODataPubFormat.JSON_FULL_METADATA); + + res = req.execute(); + feed = res.getBody(); + + assertNotNull(feed); + } + + /** + * 6. MUST support instances returning properties and navigation properties not specified in metadata (section 11.2). + */ + @Test + public void item6() { + final Integer id = 2000; + + ODataEntity rowIndex = getClient().getObjectFactory().newEntity( + new FullQualifiedName("Microsoft.Test.OData.Services.OpenTypesServiceV4.RowIndex")); + getClient().getBinder().add(rowIndex, + getClient().getObjectFactory().newPrimitiveProperty("Id", + getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt32(id))); + + // add property not in metadata + getClient().getBinder().add(rowIndex, + getClient().getObjectFactory().newPrimitiveProperty("aString", + getClient().getObjectFactory().newPrimitiveValueBuilder().buildString("string"))); + + // add navigation property not in metadata + rowIndex.addLink(client.getObjectFactory().newEntityNavigationLink( + "Row", URI.create(testOpenTypeServiceRootURL + "/Row(71f7d0dc-ede4-45eb-b421-555a2aa1e58f)"))); + + final ODataEntityCreateRequest<ODataEntity> createReq = getClient().getCUDRequestFactory(). + getEntityCreateRequest(getClient().newURIBuilder(testOpenTypeServiceRootURL). + appendEntitySetSegment("RowIndex").build(), rowIndex); + + final ODataEntityCreateResponse<ODataEntity> createRes = createReq.execute(); + assertEquals(201, createRes.getStatusCode()); + + final URIBuilder builder = getClient().newURIBuilder(testOpenTypeServiceRootURL). + appendEntitySetSegment("RowIndex").appendKeySegment(id); + + + rowIndex = read(ODataPubFormat.JSON_FULL_METADATA, builder.build()); + assertNotNull(rowIndex); + assertEquals(EdmPrimitiveTypeKind.Int32, rowIndex.getProperty("Id").getPrimitiveValue().getTypeKind()); + assertEquals(EdmPrimitiveTypeKind.String, rowIndex.getProperty("aString").getPrimitiveValue().getTypeKind()); + assertNotNull(rowIndex.getNavigationLink("Row")); + + final ODataDeleteResponse deleteRes = getClient().getCUDRequestFactory(). + getDeleteRequest(rowIndex.getEditLink()).execute(); + assertEquals(204, deleteRes.getStatusCode()); + } + + /** + * 7. MUST generate PATCH requests for updates, if the client supports updates (section 11.4.3). + */ + @Test + public void item7() { + final URI uri = client.newURIBuilder(testStaticServiceRootURL). + appendEntitySetSegment("Customers").appendKeySegment(1).build(); + + final ODataEntity patch = client.getObjectFactory().newEntity( + new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.Customer")); + patch.setEditLink(uri); + + final String newname = "New Name (" + System.currentTimeMillis() + ")"; + patch.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty("FirstName", + getClient().getObjectFactory().newPrimitiveValueBuilder().buildString(newname))); + + final ODataEntityUpdateRequest<ODataEntity> req = + getClient().getCUDRequestFactory().getEntityUpdateRequest(UpdateType.PATCH, patch); + + final ODataEntityUpdateResponse<ODataEntity> res = req.execute(); + assertEquals(204, res.getStatusCode()); + + final ODataEntity actual = read(ODataPubFormat.JSON, uri); + + assertEquals(newname, actual.getProperty("FirstName").getValue().toString()); + } + + /** + * 8. SHOULD support basic authentication as specified in [RFC2617] over HTTPS. + * <br /> + * Unfortunately no service over HTTPs is available yet. + */ + @Test + public void item8() { + client.getConfiguration().setHttpClientFactory(new BasicAuthHttpClientFactory("odatajclient", "odatajclient")); + + final CommonURIBuilder<?> uriBuilder = client.newURIBuilder(testAuthServiceRootURL). + appendEntitySetSegment("Customers").appendKeySegment(1).expand("Company"); + + final ODataEntityRequest<ODataEntity> req = client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build()); + req.setFormat(ODataPubFormat.JSON_FULL_METADATA); + + assertNotNull(req.execute().getBody()); + + client.getConfiguration().setHttpClientFactory(new DefaultHttpClientFactory()); + } + + /** + * 9. MAY request entity references in place of entities previously returned in the response (section 11.2.7). + */ + @Test + public void item9() { + final URIBuilder uriBuilder = client.newURIBuilder(testStaticServiceRootURL). + appendEntitySetSegment("Orders").appendKeySegment(8).appendNavigationSegment("CustomerForOrder"). + appendRefSegment(); + + ODataEntityRequest<ODataEntity> req = client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build()); + req.setFormat(ODataPubFormat.JSON_FULL_METADATA); + + ODataRetrieveResponse<ODataEntity> res = req.execute(); + assertNotNull(res); + + final ODataEntity entity = res.getBody(); + assertNotNull(entity); + assertTrue(entity.getReference().endsWith("/StaticService/V40/Static.svc/Customers(PersonID=1)")); + + final URI referenceURI = + client.newURIBuilder(testStaticServiceRootURL).appendEntityIdSegment(entity.getReference()).build(); + + req = client.getRetrieveRequestFactory().getEntityRequest(referenceURI); + req.setFormat(ODataPubFormat.JSON_FULL_METADATA); + + res = req.execute(); + assertNotNull(res); + assertNotNull(res.getBody()); + } + + /** + * 10. MAY support deleted entities, link entities, deleted link entities in a delta response (section 11.3). + */ + @Test + public void item10() { + final ODataEntitySetRequest<ODataEntitySet> req = client.getRetrieveRequestFactory().getEntitySetRequest( + client.newURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Customers").build()); + req.setPrefer(client.newPreferences().trackChanges()); + + final ODataEntitySet customers = req.execute().getBody(); + assertNotNull(customers); + assertNotNull(customers.getDeltaLink()); + + final ODataDeltaRequest deltaReq = client.getRetrieveRequestFactory().getDeltaRequest(customers.getDeltaLink()); + deltaReq.setFormat(ODataPubFormat.JSON_FULL_METADATA); + + final ODataDelta delta = deltaReq.execute().getBody(); + assertNotNull(delta); + + assertNotNull(delta.getDeltaLink()); + assertTrue(delta.getDeltaLink().isAbsolute()); + assertEquals(5, delta.getCount(), 0); + + assertEquals(1, delta.getDeletedEntities().size()); + assertTrue(delta.getDeletedEntities().get(0).getId().isAbsolute()); + assertTrue(delta.getDeletedEntities().get(0).getId().toASCIIString().endsWith("Customers('ANTON')")); + + assertEquals(1, delta.getAddedLinks().size()); + assertTrue(delta.getAddedLinks().get(0).getSource().isAbsolute()); + assertTrue(delta.getAddedLinks().get(0).getSource().toASCIIString().endsWith("Customers('BOTTM')")); + assertEquals("Orders", delta.getAddedLinks().get(0).getRelationship()); + + assertEquals(1, delta.getDeletedLinks().size()); + assertTrue(delta.getDeletedLinks().get(0).getSource().isAbsolute()); + assertTrue(delta.getDeletedLinks().get(0).getSource().toASCIIString().endsWith("Customers('ALFKI')")); + assertEquals("Orders", delta.getDeletedLinks().get(0).getRelationship()); + + assertEquals(2, delta.getEntities().size()); + ODataProperty property = delta.getEntities().get(0).getProperty("ContactName"); + assertNotNull(property); + assertTrue(property.hasPrimitiveValue()); + property = delta.getEntities().get(1).getProperty("ShippingAddress"); + assertNotNull(property); + assertTrue(property.hasComplexValue()); + } + + /** + * 11. MAY support asynchronous responses (section 9.1.3). + */ + @Test + public void item11() { + final URIBuilder uriBuilder = client.newURIBuilder(testStaticServiceRootURL). + appendEntitySetSegment("async").appendEntitySetSegment("Orders"); + + final ODataEntitySetRequest<ODataEntitySet> req = + client.getRetrieveRequestFactory().getEntitySetRequest(uriBuilder.build()); + req.setFormat(ODataPubFormat.JSON_FULL_METADATA); + + final AsyncRequestWrapper<ODataRetrieveResponse<ODataEntitySet>> async = + client.getAsyncRequestFactory().<ODataRetrieveResponse<ODataEntitySet>>getAsyncRequestWrapper(req); + async.callback(URI.create("http://client.service.it/callback/endpoint")); + + final AsyncResponseWrapper<ODataRetrieveResponse<ODataEntitySet>> responseWrapper = async.execute(); + + assertTrue(responseWrapper.isPreferenceApplied()); + assertTrue(responseWrapper.isDone()); + + final ODataRetrieveResponse<ODataEntitySet> res = responseWrapper.getODataResponse(); + final ODataEntitySet entitySet = res.getBody(); + + assertFalse(entitySet.getEntities().isEmpty()); + } + + /** + * 12. MAY support odata.metadata=minimal in a JSON response (see [OData-JSON]). + */ + @Test + public void item12() { + final URIBuilder uriBuilder = client.newURIBuilder(testStaticServiceRootURL). + appendEntitySetSegment("Customers").appendKeySegment(1).expand("Company"); + + final ODataEntityRequest<ODataEntity> req = + client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build()); + req.setFormat(ODataPubFormat.JSON); + + assertEquals("application/json;odata.metadata=minimal", req.getHeader("Accept")); + assertEquals("application/json;odata.metadata=minimal", req.getHeader(HeaderName.accept.toString())); + assertEquals("application/json;odata.metadata=minimal", req.getAccept()); + + final ODataRetrieveResponse<ODataEntity> res = req.execute(); + assertTrue(res.getContentType().startsWith("application/json; odata.metadata=minimal")); + + assertNotNull(res.getBody()); + } +}
