You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ed...@apache.org on 2014/02/14 23:22:05 UTC

[29/51] [partial] [OLINGO-146] Java Client Lib contributed under SGA from Microsoft Open Technologies, Inc. The majority of this was written by Francesco Chicchiriccò

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/7baecb90/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/GeoSpatialTestITCase.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/GeoSpatialTestITCase.java b/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/GeoSpatialTestITCase.java
new file mode 100644
index 0000000..ce73c49
--- /dev/null
+++ b/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/GeoSpatialTestITCase.java
@@ -0,0 +1,369 @@
+/**
+ * Copyright © Microsoft Open Technologies, Inc.
+ *
+ * All Rights Reserved
+ *
+ * Licensed 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
+ *
+ * THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ * ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A
+ * PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT.
+ *
+ * See the Apache License, Version 2.0 for the specific language
+ * governing permissions and limitations under the License.
+ */
+package com.msopentech.odatajclient.engine.it;
+
+import static org.junit.Assert.*;
+
+import com.msopentech.odatajclient.engine.client.http.HttpMethod;
+import com.msopentech.odatajclient.engine.communication.request.UpdateType;
+import com.msopentech.odatajclient.engine.communication.request.cud.ODataDeleteRequest;
+import com.msopentech.odatajclient.engine.communication.request.cud.ODataEntityCreateRequest;
+import com.msopentech.odatajclient.engine.communication.request.cud.ODataEntityUpdateRequest;
+import com.msopentech.odatajclient.engine.communication.response.ODataEntityCreateResponse;
+import com.msopentech.odatajclient.engine.communication.response.ODataEntityUpdateResponse;
+import com.msopentech.odatajclient.engine.metadata.edm.geospatial.Geospatial;
+import com.msopentech.odatajclient.engine.metadata.edm.geospatial.GeospatialCollection;
+import com.msopentech.odatajclient.engine.metadata.edm.geospatial.LineString;
+import com.msopentech.odatajclient.engine.metadata.edm.geospatial.MultiLineString;
+import com.msopentech.odatajclient.engine.metadata.edm.geospatial.MultiPoint;
+import com.msopentech.odatajclient.engine.metadata.edm.geospatial.MultiPolygon;
+import com.msopentech.odatajclient.engine.metadata.edm.geospatial.Polygon;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Test;
+import com.msopentech.odatajclient.engine.data.ODataEntity;
+import com.msopentech.odatajclient.engine.data.ODataProperty;
+import com.msopentech.odatajclient.engine.metadata.edm.EdmSimpleType;
+import com.msopentech.odatajclient.engine.metadata.edm.geospatial.Point;
+import com.msopentech.odatajclient.engine.format.ODataPubFormat;
+import com.msopentech.odatajclient.engine.uri.URIBuilder;
+
+public class GeoSpatialTestITCase extends AbstractTestITCase {
+    // test with json full metadata
+
+    @Test
+    public void withJSON() {
+        ODataPubFormat format = ODataPubFormat.JSON_FULL_METADATA;
+        String contentType = "application/json;odata=fullmetadata";
+        String prefer = "return-content";
+        int id = 11155;
+        geoSpacialTest(format, contentType, prefer, id);
+    }
+    // test with atom
+
+    @Test
+    public void withATOM() {
+        ODataPubFormat format = ODataPubFormat.ATOM;
+        String contentType = "application/atom+xml";
+        String prefer = "return-content";
+        int id = 12091;
+        geoSpacialTest(format, contentType, prefer, id);
+    }
+    // test with no metadata
+
+    @Test
+    public void withJSONMinimalMetadata() {
+        ODataPubFormat format = ODataPubFormat.JSON;
+        String contentType = "application/json";
+        String prefer = "return-content";
+        int id = 111166;
+        geoSpacialTest(format, contentType, prefer, id);
+    }
+    // test with json and atom as accept and content-type header respectively
+
+    @Test
+    public void withJSONAndATOMReturn() {
+        ODataPubFormat format = ODataPubFormat.ATOM;
+        String contentType = "application/json;odata=fullmetadata";
+        String prefer = "return-content";
+        int id = 124;
+        geoSpacialTest(format, contentType, prefer, id);
+    }
+    // test with atom and json as content Type and accept header respectively
+
+    @Test
+    public void withATOMAndJSONReturn() {
+        ODataPubFormat format = ODataPubFormat.JSON_FULL_METADATA;
+        String contentType = "application/atom+xml";
+        String prefer = "return-content";
+        int id = 11135;
+        geoSpacialTest(format, contentType, prefer, id);
+    }
+    // geo spacial entity create test
+
+    public void geoSpacialTest(final ODataPubFormat format, final String contentType, final String prefer, final int id) {
+        try {
+            final ODataEntity entity =
+                    client.getObjectFactory().newEntity(
+                            "Microsoft.Test.OData.Services.AstoriaDefaultService.AllSpatialTypes");
+            entity.addProperty(client.getObjectFactory().newPrimitiveProperty("Id",
+                    client.getPrimitiveValueBuilder().setText(String.valueOf(id)).setType(EdmSimpleType.Int32).
+                    build()));
+
+            final Point point1 = new Point(Geospatial.Dimension.GEOGRAPHY);
+            point1.setX(6.2);
+            point1.setY(1.1);
+            final Point point2 = new Point(Geospatial.Dimension.GEOGRAPHY);
+            point2.setX(33.33);
+            point2.setY(-2.5);
+
+            // create a point
+            entity.addProperty(client.getObjectFactory().newPrimitiveProperty("GeogPoint",
+                    client.getGeospatialValueBuilder().setType(EdmSimpleType.GeographyPoint).
+                    setValue(point1).build()));
+
+            // create  multiple point
+            final List<Point> points = new ArrayList<Point>();
+            points.add(point1);
+            points.add(point2);
+            final MultiPoint multipoint = new MultiPoint(Geospatial.Dimension.GEOGRAPHY, points);
+            entity.addProperty(client.getObjectFactory().newPrimitiveProperty("GeogMultiPoint",
+                    client.getGeospatialValueBuilder().setType(EdmSimpleType.GeographyMultiPoint).
+                    setValue(multipoint).build()));
+
+            // create a line
+            final List<Point> linePoints = new ArrayList<Point>();
+            linePoints.add(point1);
+            linePoints.add(point2);
+            final LineString lineString = new LineString(Geospatial.Dimension.GEOGRAPHY, linePoints);
+
+            entity.addProperty(client.getObjectFactory().newPrimitiveProperty("GeogLine",
+                    client.getGeospatialValueBuilder().setType(EdmSimpleType.GeographyLineString).
+                    setValue(lineString).build()));
+
+            // create a polygon
+            linePoints.set(1, point2);
+            linePoints.add(point2);
+            linePoints.add(point1);
+            final Polygon polygon = new Polygon(Geospatial.Dimension.GEOGRAPHY, linePoints, linePoints);
+            entity.addProperty(client.getObjectFactory().newPrimitiveProperty("GeogPolygon",
+                    client.getGeospatialValueBuilder().setType(EdmSimpleType.GeographyPolygon).
+                    setValue(polygon).build()));
+
+            // create a multi line string
+            final List<LineString> multipleLines = new ArrayList<LineString>();
+            multipleLines.add(lineString);
+            multipleLines.add(lineString);
+            final MultiLineString multiLine = new MultiLineString(Geospatial.Dimension.GEOGRAPHY, multipleLines);
+            entity.addProperty(client.getObjectFactory().newPrimitiveProperty("GeogMultiLine",
+                    client.getGeospatialValueBuilder().setType(EdmSimpleType.GeographyMultiLineString).
+                    setValue(multiLine).build()));
+
+            // create a multi polygon        
+            final List<Polygon> polygons = new ArrayList<Polygon>();
+            polygons.add(polygon);
+            polygons.add(polygon);
+            final MultiPolygon multiPolygon = new MultiPolygon(Geospatial.Dimension.GEOGRAPHY, polygons);
+            entity.addProperty(client.getObjectFactory().newPrimitiveProperty("GeogMultiPolygon",
+                    client.getGeospatialValueBuilder().setType(EdmSimpleType.GeographyMultiPolygon).
+                    setValue(multiPolygon).build()));
+
+            // create  acolletion of various shapes
+            final List<Geospatial> geospatialCollection = new ArrayList<Geospatial>();
+            geospatialCollection.add(point1);
+            geospatialCollection.add(lineString);
+            geospatialCollection.add(polygon);
+            final GeospatialCollection collection = new GeospatialCollection(Geospatial.Dimension.GEOGRAPHY,
+                    geospatialCollection);
+            entity.addProperty(client.getObjectFactory().newPrimitiveProperty("GeogCollection",
+                    client.getGeospatialValueBuilder().setType(EdmSimpleType.GeographyCollection).
+                    setValue(collection).build()));
+
+            // with geometry test
+            final Point goemPoint1 = new Point(Geospatial.Dimension.GEOMETRY);
+            goemPoint1.setX(6.2);
+            goemPoint1.setY(1.1);
+            final Point goemPoint2 = new Point(Geospatial.Dimension.GEOMETRY);
+            goemPoint2.setX(33.33);
+            goemPoint2.setY(-2.5);
+
+            // create a point
+            entity.addProperty(client.getObjectFactory().newPrimitiveProperty("GeomPoint",
+                    client.getGeospatialValueBuilder().setType(EdmSimpleType.GeometryPoint).
+                    setValue(goemPoint2).build()));
+
+            // create  multiple point
+            final List<Point> geomPoints = new ArrayList<Point>();
+            geomPoints.add(point1);
+            geomPoints.add(point2);
+            final MultiPoint geomMultipoint = new MultiPoint(Geospatial.Dimension.GEOMETRY, geomPoints);
+            entity.addProperty(client.getObjectFactory().newPrimitiveProperty("GeomMultiPoint",
+                    client.getGeospatialValueBuilder().setType(EdmSimpleType.GeometryMultiPoint).
+                    setValue(geomMultipoint).build()));
+
+            // create a line
+            final List<Point> geomLinePoints = new ArrayList<Point>();
+            geomLinePoints.add(goemPoint1);
+            geomLinePoints.add(goemPoint2);
+            final LineString geomLineString = new LineString(Geospatial.Dimension.GEOMETRY, geomLinePoints);
+
+            entity.addProperty(client.getObjectFactory().newPrimitiveProperty("GeomLine",
+                    client.getGeospatialValueBuilder().setType(EdmSimpleType.GeometryLineString).
+                    setValue(geomLineString).build()));
+
+            // create a polygon
+            geomLinePoints.set(1, goemPoint2);
+            geomLinePoints.add(goemPoint2);
+            geomLinePoints.add(goemPoint1);
+            final Polygon geomPolygon = new Polygon(Geospatial.Dimension.GEOMETRY, geomLinePoints, geomLinePoints);
+            entity.addProperty(client.getObjectFactory().newPrimitiveProperty("GeomPolygon",
+                    client.getGeospatialValueBuilder().setType(EdmSimpleType.GeometryPolygon).
+                    setValue(geomPolygon).build()));
+
+            // create a multi line string
+            final List<LineString> geomMultipleLines = new ArrayList<LineString>();
+            geomMultipleLines.add(geomLineString);
+            geomMultipleLines.add(geomLineString);
+            final MultiLineString geomMultiLine = new MultiLineString(Geospatial.Dimension.GEOMETRY, geomMultipleLines);
+            entity.addProperty(client.getObjectFactory().newPrimitiveProperty("GeomMultiLine",
+                    client.getGeospatialValueBuilder().setType(EdmSimpleType.GeometryMultiLineString).
+                    setValue(geomMultiLine).build()));
+
+            // create a multi polygon        
+            final List<Polygon> geomPolygons = new ArrayList<Polygon>();
+            geomPolygons.add(geomPolygon);
+            geomPolygons.add(geomPolygon);
+            final MultiPolygon geomMultiPolygon = new MultiPolygon(Geospatial.Dimension.GEOMETRY, geomPolygons);
+            entity.addProperty(client.getObjectFactory().newPrimitiveProperty("GeomMultiPolygon",
+                    client.getGeospatialValueBuilder().setType(EdmSimpleType.GeographyMultiPolygon).
+                    setValue(geomMultiPolygon).build()));
+
+            // create  a collection of various shapes
+            final List<Geospatial> geomspatialCollection = new ArrayList<Geospatial>();
+            geomspatialCollection.add(goemPoint1);
+            geomspatialCollection.add(geomLineString);
+            final GeospatialCollection geomCollection = new GeospatialCollection(Geospatial.Dimension.GEOMETRY,
+                    geomspatialCollection);
+            entity.addProperty(client.getObjectFactory().newPrimitiveProperty("GeomCollection",
+                    client.getGeospatialValueBuilder().setType(EdmSimpleType.GeometryCollection).
+                    setValue(geomCollection).build()));
+
+            // create request
+            final ODataEntityCreateRequest createReq = client.getCUDRequestFactory().
+                    getEntityCreateRequest(client.getURIBuilder(testDefaultServiceRootURL).
+                            appendEntityTypeSegment("AllGeoTypesSet").build(), entity);
+            createReq.setFormat(format);
+            createReq.setContentType(contentType);
+            createReq.setPrefer(prefer);
+            final ODataEntityCreateResponse createRes = createReq.execute();
+            final ODataEntity entityAfterCreate = createRes.getBody();
+            final ODataProperty geogCollection = entityAfterCreate.getProperty("GeogCollection");
+            if (format.equals(ODataPubFormat.JSON) || format.equals(ODataPubFormat.JSON_NO_METADATA)) {
+                assertTrue(geogCollection.hasComplexValue());
+            } else {
+                assertEquals(EdmSimpleType.GeographyCollection.toString(), geogCollection.getPrimitiveValue().
+                        getTypeName());
+
+                final ODataProperty geometryCollection = entityAfterCreate.getProperty("GeomCollection");
+                assertEquals(EdmSimpleType.GeographyCollection.toString(),
+                        geogCollection.getPrimitiveValue().getTypeName());
+
+                int count = 0;
+                for (Geospatial g : geogCollection.getPrimitiveValue().<GeospatialCollection>toCastValue()) {
+                    assertNotNull(g);
+                    count++;
+                }
+                assertEquals(3, count);
+                count = 0;
+                for (Geospatial g : geometryCollection.getPrimitiveValue().<GeospatialCollection>toCastValue()) {
+                    assertNotNull(g);
+                    count++;
+                }
+                assertEquals(2, count);
+            }
+            // update geog points 
+            final Point updatePoint1 = new Point(Geospatial.Dimension.GEOGRAPHY);
+            updatePoint1.setX(21.2);
+            updatePoint1.setY(31.1);
+            final Point updatePoint2 = new Point(Geospatial.Dimension.GEOGRAPHY);
+            updatePoint2.setX(99.99);
+            updatePoint2.setY(-3.24);
+            ODataProperty property = entityAfterCreate.getProperty("GeogPoint");
+            entityAfterCreate.removeProperty(property);
+            entityAfterCreate.addProperty(client.getObjectFactory().newPrimitiveProperty("GeogPoint",
+                    client.getGeospatialValueBuilder().setType(EdmSimpleType.GeographyPoint).
+                    setValue(updatePoint1).build()));
+            updateGeog(format, contentType, prefer, entityAfterCreate, UpdateType.REPLACE, entityAfterCreate.getETag());
+
+            // update geography line  
+            final List<Point> updateLinePoints = new ArrayList<Point>();
+            updateLinePoints.add(updatePoint1);
+            updateLinePoints.add(updatePoint2);
+            final LineString updateLineString = new LineString(Geospatial.Dimension.GEOGRAPHY, updateLinePoints);
+            ODataProperty lineProperty = entityAfterCreate.getProperty("GeogLine");
+            entityAfterCreate.removeProperty(lineProperty);
+            entityAfterCreate.addProperty(client.getObjectFactory().newPrimitiveProperty("GeogLine",
+                    client.getGeospatialValueBuilder().setType(EdmSimpleType.GeographyLineString).
+                    setValue(updateLineString).build()));
+            //updateGeog(format,contentType, prefer, entityAfterCreate, UpdateType.REPLACE,entityAfterCreate.getETag());
+
+            // update a geography polygon
+            updateLinePoints.set(1, updatePoint2);
+            updateLinePoints.add(updatePoint2);
+            updateLinePoints.add(updatePoint1);
+            final Polygon updatePolygon =
+                    new Polygon(Geospatial.Dimension.GEOGRAPHY, updateLinePoints, updateLinePoints);
+            ODataProperty polygonProperty = entityAfterCreate.getProperty("GeogPolygon");
+            entityAfterCreate.removeProperty(polygonProperty);
+            entityAfterCreate.addProperty(client.getObjectFactory().newPrimitiveProperty("GeogPolygon",
+                    client.getGeospatialValueBuilder().setType(EdmSimpleType.GeographyPolygon).
+                    setValue(updatePolygon).build()));
+            //updateGeog(format,contentType, prefer, entityAfterCreate, UpdateType.REPLACE,entityAfterCreate.getETag());
+
+            // delete the entity
+            URIBuilder deleteUriBuilder = client.getURIBuilder(testDefaultServiceRootURL).
+                    appendEntityTypeSegment("AllGeoTypesSet(" + id + ")");
+            ODataDeleteRequest deleteReq = client.getCUDRequestFactory().getDeleteRequest(deleteUriBuilder.build());
+            deleteReq.setFormat(format);
+            deleteReq.setContentType(contentType);
+            assertEquals(204, deleteReq.execute().getStatusCode());
+        } catch (Exception e) {
+            LOG.error("", e);
+            if (format.equals(ODataPubFormat.JSON) || format.equals(ODataPubFormat.JSON_NO_METADATA)) {
+                assertTrue(true);
+            } else {
+                fail(e.getMessage());
+            }
+        } catch (AssertionError e) {
+            LOG.error("", e);
+            fail(e.getMessage());
+        }
+    }
+    // update operation of geo spacial properties
+
+    private void updateGeog(final ODataPubFormat format, final String contentType,
+            final String prefer, final ODataEntity entityAfterCreate, final UpdateType type,
+            final String tag) {
+        final ODataEntityUpdateRequest req = client.getCUDRequestFactory().getEntityUpdateRequest(type,
+                entityAfterCreate);
+        if (client.getConfiguration().isUseXHTTPMethod()) {
+            assertEquals(HttpMethod.POST, req.getMethod());
+        } else {
+            assertEquals(type.getMethod(), req.getMethod());
+        }
+        req.setFormat(format);
+        req.setContentType(contentType);
+        req.setPrefer(prefer);
+        if (StringUtils.isNotEmpty(tag)) {
+            req.setIfMatch(tag);
+        }
+        final ODataEntityUpdateResponse res = req.execute();
+
+        if (prefer.equals("return-content")) {
+            assertEquals(200, res.getStatusCode());
+            ODataEntity entityAfterUpdate = res.getBody();
+            assertNotNull(entityAfterUpdate);
+        } else {
+            assertEquals(204, res.getStatusCode());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/7baecb90/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/InvokeOperationTestITCase.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/InvokeOperationTestITCase.java b/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/InvokeOperationTestITCase.java
new file mode 100644
index 0000000..55601e0
--- /dev/null
+++ b/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/InvokeOperationTestITCase.java
@@ -0,0 +1,661 @@
+/**
+ * Copyright © Microsoft Open Technologies, Inc.
+ *
+ * All Rights Reserved
+ *
+ * Licensed 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
+ *
+ * THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ * ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A
+ * PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT.
+ *
+ * See the Apache License, Version 2.0 for the specific language
+ * governing permissions and limitations under the License.
+ */
+package com.msopentech.odatajclient.engine.it;
+
+import static org.junit.Assert.*;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Test;
+
+import com.msopentech.odatajclient.engine.communication.request.cud.ODataDeleteRequest;
+import com.msopentech.odatajclient.engine.communication.request.cud.ODataEntityCreateRequest;
+import com.msopentech.odatajclient.engine.communication.request.invoke.ODataInvokeRequest;
+import com.msopentech.odatajclient.engine.communication.request.retrieve.ODataEntityRequest;
+import com.msopentech.odatajclient.engine.communication.response.ODataDeleteResponse;
+import com.msopentech.odatajclient.engine.communication.response.ODataEntityCreateResponse;
+import com.msopentech.odatajclient.engine.communication.response.ODataInvokeResponse;
+import com.msopentech.odatajclient.engine.data.ODataCollectionValue;
+import com.msopentech.odatajclient.engine.data.ODataComplexValue;
+import com.msopentech.odatajclient.engine.data.ODataEntity;
+import com.msopentech.odatajclient.engine.data.ODataEntitySet;
+import com.msopentech.odatajclient.engine.data.ODataNoContent;
+import com.msopentech.odatajclient.engine.data.ODataOperation;
+import com.msopentech.odatajclient.engine.data.ODataPrimitiveValue;
+import com.msopentech.odatajclient.engine.data.ODataProperty;
+import com.msopentech.odatajclient.engine.data.ODataValue;
+import com.msopentech.odatajclient.engine.metadata.EdmType;
+import com.msopentech.odatajclient.engine.metadata.EdmV3Metadata;
+import com.msopentech.odatajclient.engine.metadata.EdmV3Type;
+import com.msopentech.odatajclient.engine.metadata.edm.EdmSimpleType;
+import com.msopentech.odatajclient.engine.metadata.edm.v3.EntityContainer;
+import com.msopentech.odatajclient.engine.metadata.edm.v3.FunctionImport;
+import com.msopentech.odatajclient.engine.format.ODataPubFormat;
+import com.msopentech.odatajclient.engine.uri.URIBuilder;
+import com.msopentech.odatajclient.engine.utils.URIUtils;
+
+public class InvokeOperationTestITCase extends AbstractTestITCase {
+    // get operation with no parameters
+
+    private void invokeOperationWithNoParameters(final ODataPubFormat format,
+            final String contentType,
+            final String prefer) {
+
+        ODataProperty property;
+        final EdmV3Metadata metadata =
+                client.getRetrieveRequestFactory().getMetadataRequest(testDefaultServiceRootURL).execute().getBody();
+        assertNotNull(metadata);
+
+        final EntityContainer container = metadata.getSchema(0).getEntityContainers().get(0);
+        //get primitive value property
+        FunctionImport funcImp = container.getFunctionImport("GetPrimitiveString");
+
+        URIBuilder builder = client.getURIBuilder(testDefaultServiceRootURL).
+                appendFunctionImportSegment(URIUtils.rootFunctionImportURISegment(container, funcImp));
+
+        ODataInvokeRequest<ODataProperty> req =
+                client.getInvokeRequestFactory().getInvokeRequest(builder.build(), metadata, funcImp);
+        req.setFormat(format);
+        req.setContentType(contentType);
+        req.setPrefer(prefer);
+        ODataInvokeResponse<ODataProperty> res = req.execute();
+        if (prefer.equals("return-content")) {
+            assertNotNull(res);
+            property = res.getBody();
+            assertNotNull(property);
+            assertEquals("Foo", property.getPrimitiveValue().<String>toCastValue());
+        } else {
+            assertEquals(204, res.getStatusCode());
+        }
+
+        //get collection of complex type property
+        funcImp = container.getFunctionImport("EntityProjectionReturnsCollectionOfComplexTypes");
+
+        builder = client.getURIBuilder(testDefaultServiceRootURL).
+                appendFunctionImportSegment(URIUtils.rootFunctionImportURISegment(container, funcImp));
+
+        req = client.getInvokeRequestFactory().getInvokeRequest(builder.build(), metadata, funcImp);
+        req.setFormat(format);
+        req.setContentType(contentType);
+        req.setPrefer(prefer);
+        res = req.execute();
+        if (prefer.equals("return-content")) {
+            assertNotNull(res);
+            property = res.getBody();
+            assertNotNull(property);
+            assertTrue(property.hasCollectionValue());
+        } else {
+            assertEquals(204, res.getStatusCode());
+        }
+    }
+
+    // get operation with no parameters and format as JSON full metadata
+    @Test
+    public void invokeNoParamWithJSON() {
+        ODataPubFormat format = ODataPubFormat.JSON_FULL_METADATA;
+        String contentType = "application/json;odata=fullmetadata";
+        String prefer = "return-content";
+        try {
+            invokeOperationWithNoParameters(format, contentType, prefer);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        } catch (AssertionError e) {
+            fail(e.getMessage());
+        }
+    }
+    // get operation with no parameters and format as ATOM
+
+    @Test
+    public void invokeNoParamWithATOM() {
+        ODataPubFormat format = ODataPubFormat.ATOM;
+        String contentType = "application/atom+xml";
+        String prefer = "return-content";
+        try {
+            invokeOperationWithNoParameters(format, contentType, prefer);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        } catch (AssertionError e) {
+            fail(e.getMessage());
+        }
+    }
+    // get operation with no parameters and format as JSON minimal metadata
+
+    @Test
+    public void invokeNoParamWithJSONMinimal() {
+        ODataPubFormat format = ODataPubFormat.JSON;
+        String contentType = "application/json";
+        String prefer = "return-content";
+        try {
+            invokeOperationWithNoParameters(format, contentType, prefer);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        } catch (AssertionError e) {
+            fail(e.getMessage());
+        }
+    }
+    // get operation with no parameters and format as JSON no metadata
+
+    @Test
+    public void invokeNoParamWithJSONNoMetadata() {
+        ODataPubFormat format = ODataPubFormat.JSON_NO_METADATA;
+        String contentType = "application/json;odata=nometadata";
+        String prefer = "return-content";
+        try {
+            invokeOperationWithNoParameters(format, contentType, prefer);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        } catch (AssertionError e) {
+            fail(e.getMessage());
+        }
+    }
+    // get operation with no parameters, format as JSON and content type header as ATOM
+
+    @Test
+    public void invokeNoParamWithJSONAndATOM() {
+        ODataPubFormat format = ODataPubFormat.JSON_FULL_METADATA;
+        String contentType = "application/atom+xml";
+        String prefer = "return-content";
+        try {
+            invokeOperationWithNoParameters(format, contentType, prefer);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        } catch (AssertionError e) {
+            fail(e.getMessage());
+        }
+    }
+    // get operation with no parameters, format as ATOM and content type header as JSON
+
+    @Test
+    public void invokeNoParamWithATOMAndJSON() {
+        ODataPubFormat format = ODataPubFormat.ATOM;
+        String contentType = "application/json;odata=fullmetadata";
+        String prefer = "return-content";
+        try {
+            invokeOperationWithNoParameters(format, contentType, prefer);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        } catch (AssertionError e) {
+            fail(e.getMessage());
+        }
+    }
+    // get operation with no parameters
+
+    private void invokeOperationWithParameters(
+            final ODataPubFormat format,
+            final String contentType,
+            final String prefer) {
+        // primitive result
+        EdmV3Metadata metadata =
+                client.getRetrieveRequestFactory().getMetadataRequest(testDefaultServiceRootURL).execute().getBody();
+        assertNotNull(metadata);
+
+        EntityContainer container = metadata.getSchema(0).getEntityContainers().get(0);
+        FunctionImport imp = container.getFunctionImport("GetArgumentPlusOne");
+
+        URIBuilder builder = client.getURIBuilder(testDefaultServiceRootURL).
+                appendFunctionImportSegment(URIUtils.rootFunctionImportURISegment(container, imp));
+
+        EdmType type = new EdmV3Type(imp.getParameters().get(0).getType());
+        ODataPrimitiveValue argument = client.getPrimitiveValueBuilder().
+                setType(type.getSimpleType()).
+                setValue(33).
+                build();
+        Map<String, ODataValue> parameters = new HashMap<String, ODataValue>();
+        parameters.put(imp.getParameters().get(0).getName(), argument);
+
+        final ODataInvokeRequest<ODataProperty> primitiveReq =
+                client.getInvokeRequestFactory().getInvokeRequest(builder.build(), metadata, imp,
+                        parameters);
+        primitiveReq.setFormat(format);
+        primitiveReq.setContentType(contentType);
+        primitiveReq.setPrefer(prefer);
+        final ODataInvokeResponse<ODataProperty> primitiveRes = primitiveReq.execute();
+        assertNotNull(primitiveRes);
+
+        final ODataProperty property = primitiveRes.getBody();
+        assertNotNull(property);
+        assertEquals(Integer.valueOf(34), property.getPrimitiveValue().<Integer>toCastValue());
+
+        // feed operation
+        metadata = client.getRetrieveRequestFactory().getMetadataRequest(testDefaultServiceRootURL).execute().getBody();
+        assertNotNull(metadata);
+
+        container = metadata.getSchema(0).getEntityContainers().get(0);
+        imp = container.getFunctionImport("GetSpecificCustomer");
+
+        builder = client.getURIBuilder(testDefaultServiceRootURL).
+                appendFunctionImportSegment(URIUtils.rootFunctionImportURISegment(container, imp));
+
+        type = new EdmV3Type(imp.getParameters().get(0).getType());
+        argument = client.getPrimitiveValueBuilder().
+                setType(type.getSimpleType()).
+                setText(StringUtils.EMPTY).
+                build();
+        parameters = new LinkedHashMap<String, ODataValue>();
+        parameters.put(imp.getParameters().get(0).getName(), argument);
+
+        final ODataInvokeRequest<ODataEntitySet> feedReq =
+                client.getInvokeRequestFactory().getInvokeRequest(builder.build(), metadata, imp, parameters);
+        feedReq.setFormat(format);
+        feedReq.setContentType(contentType);
+        feedReq.setPrefer(prefer);
+        final ODataInvokeResponse<ODataEntitySet> feedRes = feedReq.execute();
+        assertNotNull(feedRes);
+
+        final ODataEntitySet feed = feedRes.getBody();
+        assertNotNull(feed);
+
+        final ODataProperty id = feed.getEntities().get(0).getProperty("CustomerId");
+        assertNotNull(id);
+    }
+    // get operation with parameters, format as JSON full metadata
+
+    @Test
+    public void invokeParamWithJSON() {
+        ODataPubFormat format = ODataPubFormat.JSON_FULL_METADATA;
+        String contentType = "application/json;odata=fullmetadata";
+        String prefer = "return-content";
+        try {
+            invokeOperationWithParameters(format, contentType, prefer);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        } catch (AssertionError e) {
+            fail(e.getMessage());
+        }
+    }
+    // get operation with parameters, format as ATOM 
+
+    @Test
+    public void invokeParamWithATOM() {
+        ODataPubFormat format = ODataPubFormat.ATOM;
+        String contentType = "application/atom+xml";
+        String prefer = "return-content";
+        try {
+            invokeOperationWithParameters(format, contentType, prefer);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        } catch (AssertionError e) {
+            fail(e.getMessage());
+        }
+    }
+
+    // create a product
+    private ODataEntity createProduct(
+            final ODataPubFormat format,
+            final String contentType, final int id) {
+        final ODataEntity product = client.getObjectFactory().newEntity(
+                "Microsoft.Test.OData.Services.AstoriaDefaultService.Product");
+        product.addProperty(client.getObjectFactory().newPrimitiveProperty("ProductId", client.
+                getPrimitiveValueBuilder().
+                setValue(id).setType(EdmSimpleType.Int32).build()));
+        product.addProperty(client.getObjectFactory().newPrimitiveProperty("Description", client.
+                getPrimitiveValueBuilder().
+                setText("Test Product").build()));
+        product.addProperty(client.getObjectFactory().newPrimitiveProperty("BaseConcurrency",
+                client.getPrimitiveValueBuilder().
+                setText("Test Base Concurrency").setType(EdmSimpleType.String).build()));
+
+        final ODataComplexValue dimensions = new ODataComplexValue(
+                "Microsoft.Test.OData.Services.AstoriaDefaultService.Dimensions");
+        dimensions.add(client.getObjectFactory().newPrimitiveProperty("Width",
+                client.getPrimitiveValueBuilder().setText("10.11").setType(EdmSimpleType.Decimal).build()));
+        dimensions.add(client.getObjectFactory().newPrimitiveProperty("Height",
+                client.getPrimitiveValueBuilder().setText("10.11").setType(EdmSimpleType.Decimal).build()));
+        dimensions.add(client.getObjectFactory().newPrimitiveProperty("Depth",
+                client.getPrimitiveValueBuilder().setText("10.11").setType(EdmSimpleType.Decimal).build()));
+
+        product.addProperty(client.getObjectFactory().newComplexProperty("Dimensions",
+                dimensions));
+
+        final URIBuilder uriBuilder = client.getURIBuilder(testDefaultServiceRootURL).
+                appendEntityTypeSegment("Product");
+
+        final ODataEntityCreateRequest createReq =
+                client.getCUDRequestFactory().getEntityCreateRequest(uriBuilder.build(), product);
+        createReq.setFormat(format);
+        createReq.setContentType(contentType);
+
+        final ODataEntityCreateResponse createRes = createReq.execute();
+        assertEquals(201, createRes.getStatusCode());
+
+        return createRes.getBody();
+    }
+    // delete the created feed
+
+    private void delete(final ODataPubFormat format, final String contentType, final Integer id, final String tag,
+            final String feed) {
+        final URIBuilder uriBuilder = client.getURIBuilder(testDefaultServiceRootURL).
+                appendEntityTypeSegment(feed).appendKeySegment(id);
+
+        final ODataDeleteRequest deleteReq = client.getCUDRequestFactory().getDeleteRequest(uriBuilder.build());
+        deleteReq.setFormat(format);
+        deleteReq.setContentType(contentType);
+        if (StringUtils.isNotBlank(tag)) {
+            deleteReq.setIfMatch(tag);
+        }
+        final ODataDeleteResponse deleteRes = deleteReq.execute();
+        assertEquals(204, deleteRes.getStatusCode());
+    }
+
+    // post operation with parameters
+    private void boundPostWithParameters(
+            final ODataPubFormat format,
+            final String contentType,
+            final String prefer) {
+        final ODataEntity created = createProduct(format, contentType, 1905);
+        assertNotNull(created);
+        final Integer createdId = created.getProperty("ProductId").getPrimitiveValue().<Integer>toCastValue();
+        assertNotNull(createdId);
+        final ODataOperation action = created.getOperations().get(0);
+
+        final EdmV3Metadata metadata =
+                client.getRetrieveRequestFactory().getMetadataRequest(testDefaultServiceRootURL).execute().getBody();
+        assertNotNull(metadata);
+        final EntityContainer container = metadata.getSchema(0).getEntityContainers().get(0);
+        final FunctionImport funcImp = container.getFunctionImport(action.getTitle());
+        final ODataComplexValue dimensions = new ODataComplexValue(
+                "Microsoft.Test.OData.Services.AstoriaDefaultService.Dimensions");
+        dimensions.add(client.getObjectFactory().newPrimitiveProperty("Width",
+                client.getPrimitiveValueBuilder().setType(EdmSimpleType.Decimal).setText("99.11").build()));
+        dimensions.add(client.getObjectFactory().newPrimitiveProperty("Height",
+                client.getPrimitiveValueBuilder().setType(EdmSimpleType.Decimal).setText("99.11").build()));
+        dimensions.add(client.getObjectFactory().newPrimitiveProperty("Depth",
+                client.getPrimitiveValueBuilder().setType(EdmSimpleType.Decimal).setText("99.11").build()));
+
+        Map<String, ODataValue> parameters = new LinkedHashMap<String, ODataValue>();
+        parameters.put(funcImp.getParameters().get(1).getName(), dimensions);
+
+        final ODataInvokeRequest<ODataNoContent> req = client.getInvokeRequestFactory().getInvokeRequest(
+                action.getTarget(), metadata, funcImp, parameters);
+        req.setFormat(format);
+        req.setContentType(contentType);
+        req.setPrefer(prefer);
+
+        final ODataInvokeResponse<ODataNoContent> res = req.execute();
+        assertNotNull(res);
+        assertEquals(204, res.getStatusCode());
+
+        final URIBuilder uriBuilder = client.getURIBuilder(testDefaultServiceRootURL).
+                appendEntityTypeSegment("Product").appendKeySegment(createdId);
+        final ODataEntityRequest retrieveRes = client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+        retrieveRes.setFormat(format);
+        retrieveRes.setContentType(contentType);
+        final ODataEntity read = retrieveRes.execute().getBody();
+
+        ODataComplexValue value = read.getProperty("Dimensions").getComplexValue();
+        assertEquals(dimensions.get("Depth").getValue(), value.get("Depth").getValue());
+        assertEquals(dimensions.get("Width").getValue(), value.get("Width").getValue());
+        assertEquals(dimensions.get("Height").getValue(), value.get("Height").getValue());
+        delete(format, contentType, createdId, created.getETag(), "Product");
+
+    }
+    // test post operation with parameters and with JSON header
+
+    @Test
+    public void invokeOperationParamWithJSON() {
+        final ODataPubFormat format = ODataPubFormat.JSON_FULL_METADATA;
+        final String contentType = "application/json;odata=fullmetadata";
+        final String prefer = "return-content";
+        try {
+            boundPostWithParameters(format, contentType, prefer);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        } catch (AssertionError e) {
+            fail(e.getMessage());
+        }
+    }
+    // test post operation with parameters and with ATOM header
+
+    @Test
+    public void invokeOperationParamWithATOM() {
+        final ODataPubFormat format = ODataPubFormat.ATOM;
+        final String contentType = "application/atom+xml";
+        final String prefer = "return-content";
+        try {
+            boundPostWithParameters(format, contentType, prefer);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        } catch (AssertionError e) {
+            fail(e.getMessage());
+        }
+    }
+    // create an employee
+
+    private ODataEntity createEmployee(final ODataPubFormat format, final String contentType, final String prefer,
+            final int id) {
+        final ODataEntity employee = client.getObjectFactory().newEntity(
+                "Microsoft.Test.OData.Services.AstoriaDefaultService.Employee");
+        employee.addProperty(client.getObjectFactory().newPrimitiveProperty("PersonId", client.
+                getPrimitiveValueBuilder().
+                setValue(id).setType(EdmSimpleType.Int32).build()));
+        employee.addProperty(client.getObjectFactory().newPrimitiveProperty("Name", client.getPrimitiveValueBuilder().
+                setText("Test employee").build()));
+        employee.addProperty(client.getObjectFactory().newPrimitiveProperty("ManagersPersonId", client.
+                getPrimitiveValueBuilder().
+                setText("1111").setType(EdmSimpleType.Int32).build()));
+        employee.addProperty(client.getObjectFactory().newPrimitiveProperty("Salary", client.getPrimitiveValueBuilder().
+                setText("5999").setType(EdmSimpleType.Int32).build()));
+        employee.addProperty(client.getObjectFactory().newPrimitiveProperty("Title", client.getPrimitiveValueBuilder().
+                setText("Developer").build()));
+
+        final URIBuilder uriBuilder = client.getURIBuilder(testDefaultServiceRootURL).
+                appendEntityTypeSegment("Person");
+
+        final ODataEntityCreateRequest createReq =
+                client.getCUDRequestFactory().getEntityCreateRequest(uriBuilder.build(), employee);
+        createReq.setFormat(format);
+        createReq.setContentType(contentType);
+        createReq.setPrefer(prefer);
+        final ODataEntityCreateResponse createRes = createReq.execute();
+        assertEquals(201, createRes.getStatusCode());
+        return createRes.getBody();
+    }
+    // post operation  
+
+    private void boundPost(
+            final ODataPubFormat format,
+            final String contentType,
+            final String prefer,
+            final int id) {
+        final ODataEntity created = createEmployee(format, contentType, prefer, id);
+        assertNotNull(created);
+        final Integer createdId = created.getProperty("PersonId").getPrimitiveValue().<Integer>toCastValue();
+        assertNotNull(createdId);
+
+        final ODataOperation action = created.getOperations().get(0);
+
+        final EdmV3Metadata metadata =
+                client.getRetrieveRequestFactory().getMetadataRequest(testDefaultServiceRootURL).execute().getBody();
+        assertNotNull(metadata);
+
+        final EntityContainer container = metadata.getSchema(0).getEntityContainers().get(0);
+        final FunctionImport funcImp = container.getFunctionImport(action.getTitle());
+
+        final ODataInvokeRequest<ODataNoContent> req = client.getInvokeRequestFactory().getInvokeRequest(
+                action.getTarget(), metadata, funcImp);
+        req.setFormat(format);
+        req.setContentType(contentType);
+        req.setPrefer(prefer);
+        final ODataInvokeResponse<ODataNoContent> res = req.execute();
+        assertNotNull(res);
+        assertEquals(204, res.getStatusCode());
+
+        final URIBuilder uriBuilder = client.getURIBuilder(testDefaultServiceRootURL).
+                appendEntityTypeSegment("Person").appendKeySegment(createdId);
+        final ODataEntityRequest retrieveRes = client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+        retrieveRes.setFormat(format);
+        retrieveRes.setContentType(contentType);
+        retrieveRes.setPrefer(prefer);
+        final ODataEntity read = retrieveRes.execute().getBody();
+        assertEquals("0", read.getProperty("Salary").getPrimitiveValue().toString());
+        assertTrue(read.getProperty("Title").getPrimitiveValue().toString().endsWith("[Sacked]"));
+
+        delete(format, contentType, createdId, created.getETag(), "Person");
+    }
+
+    // test post operation without parameters and with JSON header
+    @Test
+    public void invokeOperationWithJSON() {
+        final ODataPubFormat format = ODataPubFormat.JSON_FULL_METADATA;
+        final String contentType = "application/json;odata=fullmetadata";
+        final String prefer = "return-content";
+        try {
+            boundPost(format, contentType, prefer, 2222);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        } catch (AssertionError e) {
+            fail(e.getMessage());
+        }
+    }
+    // test post operation without parameters and with ATOM header
+
+    @Test
+    public void invokeOperationWithATOM() {
+        final ODataPubFormat format = ODataPubFormat.ATOM;
+        final String contentType = "application/atom+xml";
+        final String prefer = "return-content";
+        try {
+            boundPost(format, contentType, prefer, 2223);
+        } catch (Exception e) {
+            if (e.getMessage().equals("Unsupported media type requested. [HTTP/1.1 415 Unsupported Media Type]")) {
+                assertTrue(true);
+            } else {
+                fail(e.getMessage());
+            }
+        } catch (AssertionError e) {
+            fail(e.getMessage());
+        }
+    }
+    // create an entity under feed 'Computer detail'
+
+    private ODataEntity createComputerDetail(final ODataPubFormat format, final String contentType, final String prefer,
+            final int id) {
+        final ODataEntity entity =
+                client.getObjectFactory().
+                newEntity("Microsoft.Test.OData.Services.AstoriaDefaultService.ComputerDetail");
+        entity.addProperty(client.getObjectFactory().newPrimitiveProperty("Manufacturer",
+                client.getPrimitiveValueBuilder().setText("manufacturer name").setType(EdmSimpleType.String).build()));
+
+        entity.addProperty(client.getObjectFactory().newPrimitiveProperty("ComputerDetailId",
+                client.getPrimitiveValueBuilder().setText(String.valueOf(id)).setType(EdmSimpleType.Int32).build()));
+
+        entity.addProperty(client.getObjectFactory().newPrimitiveProperty("Model",
+                client.getPrimitiveValueBuilder().setText("Model Name").setType(EdmSimpleType.String).build()));
+
+        final URIBuilder uriBuilder = client.getURIBuilder(testDefaultServiceRootURL).
+                appendEntityTypeSegment("ComputerDetail");
+
+        final ODataEntityCreateRequest createReq =
+                client.getCUDRequestFactory().getEntityCreateRequest(uriBuilder.build(), entity);
+        createReq.setFormat(format);
+        createReq.setContentType(contentType);
+        createReq.setPrefer(prefer);
+        final ODataEntityCreateResponse createRes = createReq.execute();
+        assertEquals(201, createRes.getStatusCode());
+        return createRes.getBody();
+    }
+    // post operation with parameters
+
+    private void boundPostWithParametersComputer(
+            final ODataPubFormat format,
+            final String contentType,
+            final String prefer,
+            final int id) {
+        final ODataEntity created = createComputerDetail(format, contentType, prefer, id);
+        assertNotNull(created);
+        final Integer createdId = created.getProperty("ComputerDetailId").getPrimitiveValue().<Integer>toCastValue();
+        assertNotNull(createdId);
+
+        final ODataOperation action = created.getOperations().get(0);
+
+        final EdmV3Metadata metadata =
+                client.getRetrieveRequestFactory().getMetadataRequest(testDefaultServiceRootURL).execute().getBody();
+        assertNotNull(metadata);
+
+        final EntityContainer container = metadata.getSchema(0).getEntityContainers().get(0);
+        final FunctionImport funcImp = container.getFunctionImport(action.getTitle());
+        final ODataCollectionValue specification = new ODataCollectionValue(("Collection(Edm.String)"));
+        specification.add(client.getPrimitiveValueBuilder().setType(EdmSimpleType.String).setText("specification1").
+                build());
+        specification.add(client.getPrimitiveValueBuilder().setType(EdmSimpleType.String).setText("specification2").
+                build());
+        specification.add(client.getPrimitiveValueBuilder().setType(EdmSimpleType.String).setText("specification3").
+                build());
+
+        ODataValue argument = client.getPrimitiveValueBuilder().
+                setType(EdmSimpleType.DateTime).
+                setText("2011-11-11T23:59:59.9999999").
+                build();
+        Map<String, ODataValue> parameters = new LinkedHashMap<String, ODataValue>();
+        parameters.put(funcImp.getParameters().get(1).getName(), specification);
+        parameters.put(funcImp.getParameters().get(2).getName(), argument);
+
+        final ODataInvokeRequest<ODataNoContent> req = client.getInvokeRequestFactory().getInvokeRequest(
+                action.getTarget(), metadata, funcImp, parameters);
+        req.setFormat(format);
+        req.setContentType(contentType);
+        req.setPrefer(prefer);
+        final ODataInvokeResponse<ODataNoContent> res = req.execute();
+        assertNotNull(res);
+        assertEquals(204, res.getStatusCode());
+
+        final URIBuilder uriBuilder = client.getURIBuilder(testDefaultServiceRootURL).
+                appendEntityTypeSegment("ComputerDetail").appendKeySegment(createdId);
+        final ODataEntityRequest retrieveRes = client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+        retrieveRes.setFormat(format);
+        retrieveRes.setContentType(contentType);
+        retrieveRes.setPrefer(prefer);
+        final ODataEntity read = retrieveRes.execute().getBody();
+        assertEquals("2011-11-11T23:59:59.9999999", read.getProperty("PurchaseDate").getValue().toString());
+        delete(format, contentType, createdId, created.getETag(), "ComputerDetail");
+    }
+    // test with json
+
+    @Test
+    public void boundPostComputerDetailWithJSON() {
+        final ODataPubFormat format = ODataPubFormat.JSON_FULL_METADATA;
+        final String contentType = "application/json;odata=fullmetadata";
+        final String prefer = "return-content";
+        try {
+            boundPostWithParametersComputer(format, contentType, prefer, 2235);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        } catch (AssertionError e) {
+            fail(e.getMessage());
+        }
+    }
+    // test with atom
+
+    @Test
+    public void boundPostComputerDetailWithATOM() {
+        final ODataPubFormat format = ODataPubFormat.ATOM;
+        final String contentType = "application/atom+xml";
+        final String prefer = "return-content";
+        try {
+            boundPostWithParametersComputer(format, contentType, prefer, 2235);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        } catch (AssertionError e) {
+            fail(e.getMessage());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/7baecb90/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/InvokeTestITCase.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/InvokeTestITCase.java b/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/InvokeTestITCase.java
new file mode 100644
index 0000000..98ea727
--- /dev/null
+++ b/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/InvokeTestITCase.java
@@ -0,0 +1,308 @@
+/**
+ * Copyright © Microsoft Open Technologies, Inc.
+ *
+ * All Rights Reserved
+ *
+ * Licensed 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
+ *
+ * THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ * ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A
+ * PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT.
+ *
+ * See the Apache License, Version 2.0 for the specific language
+ * governing permissions and limitations under the License.
+ */
+package com.msopentech.odatajclient.engine.it;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.msopentech.odatajclient.engine.communication.request.cud.ODataDeleteRequest;
+import com.msopentech.odatajclient.engine.communication.request.cud.ODataEntityCreateRequest;
+import com.msopentech.odatajclient.engine.communication.request.invoke.ODataInvokeRequest;
+import com.msopentech.odatajclient.engine.communication.request.retrieve.ODataEntityRequest;
+import com.msopentech.odatajclient.engine.communication.response.ODataDeleteResponse;
+import com.msopentech.odatajclient.engine.communication.response.ODataEntityCreateResponse;
+import com.msopentech.odatajclient.engine.communication.response.ODataInvokeResponse;
+import com.msopentech.odatajclient.engine.data.ODataEntity;
+import com.msopentech.odatajclient.engine.data.ODataEntitySet;
+import com.msopentech.odatajclient.engine.data.ODataNoContent;
+import com.msopentech.odatajclient.engine.data.ODataOperation;
+import com.msopentech.odatajclient.engine.data.ODataPrimitiveValue;
+import com.msopentech.odatajclient.engine.data.ODataProperty;
+import com.msopentech.odatajclient.engine.uri.URIBuilder;
+import com.msopentech.odatajclient.engine.data.ODataValue;
+import com.msopentech.odatajclient.engine.metadata.EdmType;
+import com.msopentech.odatajclient.engine.metadata.EdmV3Metadata;
+import com.msopentech.odatajclient.engine.metadata.EdmV3Type;
+import com.msopentech.odatajclient.engine.metadata.edm.EdmSimpleType;
+import com.msopentech.odatajclient.engine.metadata.edm.v3.EntityContainer;
+import com.msopentech.odatajclient.engine.metadata.edm.v3.FunctionImport;
+import com.msopentech.odatajclient.engine.format.ODataPubFormat;
+import com.msopentech.odatajclient.engine.utils.URIUtils;
+import java.net.URI;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Test;
+
+public class InvokeTestITCase extends AbstractTestITCase {
+
+    private void getWithNoParams(final ODataPubFormat format) {
+        final EdmV3Metadata metadata =
+                client.getRetrieveRequestFactory().getMetadataRequest(testDefaultServiceRootURL).execute().getBody();
+        assertNotNull(metadata);
+
+        final EntityContainer container = metadata.getSchema(0).getEntityContainers().get(0);
+
+        // 1. get primitive value property
+        FunctionImport funcImp = container.getFunctionImport("GetPrimitiveString");
+
+        URIBuilder builder = client.getURIBuilder(testDefaultServiceRootURL).
+                appendFunctionImportSegment(URIUtils.rootFunctionImportURISegment(container, funcImp));
+
+        ODataInvokeRequest<ODataProperty> req =
+                client.getInvokeRequestFactory().getInvokeRequest(builder.build(), metadata, funcImp);
+        req.setFormat(format);
+        ODataInvokeResponse<ODataProperty> res = req.execute();
+        assertNotNull(res);
+
+        ODataProperty property = res.getBody();
+        assertNotNull(property);
+        assertEquals("Foo", property.getPrimitiveValue().<String>toCastValue());
+
+        // 2. get collection of complex type property
+        funcImp = container.getFunctionImport("EntityProjectionReturnsCollectionOfComplexTypes");
+
+        builder = client.getURIBuilder(testDefaultServiceRootURL).
+                appendFunctionImportSegment(URIUtils.rootFunctionImportURISegment(container, funcImp));
+
+        req = client.getInvokeRequestFactory().getInvokeRequest(builder.build(), metadata, funcImp);
+        req.setFormat(format);
+        res = req.execute();
+        assertNotNull(res);
+
+        property = res.getBody();
+        assertNotNull(property);
+        assertTrue(property.hasCollectionValue());
+        assertFalse(property.getCollectionValue().isEmpty());
+    }
+
+    @Test
+    public void getWithNoParamsAsAtom() {
+        getWithNoParams(ODataPubFormat.ATOM);
+    }
+
+    @Test
+    public void getWithNoParamsAsJSON() {
+        getWithNoParams(ODataPubFormat.JSON);
+    }
+
+    private void getWithParams(final ODataPubFormat format) {
+        // 1. primitive result
+        EdmV3Metadata metadata =
+                client.getRetrieveRequestFactory().getMetadataRequest(testDefaultServiceRootURL).execute().getBody();
+        assertNotNull(metadata);
+
+        EntityContainer container = metadata.getSchema(0).getEntityContainers().get(0);
+        FunctionImport funcImp = container.getFunctionImport("GetArgumentPlusOne");
+
+        URIBuilder builder = client.getURIBuilder(testDefaultServiceRootURL).
+                appendFunctionImportSegment(URIUtils.rootFunctionImportURISegment(container, funcImp));
+
+        EdmType type = new EdmV3Type(funcImp.getParameters().get(0).getType());
+        ODataPrimitiveValue argument = client.getPrimitiveValueBuilder().
+                setType(type.getSimpleType()).
+                setValue(154).
+                build();
+        Map<String, ODataValue> parameters = new HashMap<String, ODataValue>();
+        parameters.put(funcImp.getParameters().get(0).getName(), argument);
+
+        final ODataInvokeRequest<ODataProperty> primitiveReq =
+                client.getInvokeRequestFactory().getInvokeRequest(builder.build(), metadata, funcImp,
+                        parameters);
+        primitiveReq.setFormat(format);
+
+        final ODataInvokeResponse<ODataProperty> primitiveRes = primitiveReq.execute();
+        assertNotNull(primitiveRes);
+
+        final ODataProperty property = primitiveRes.getBody();
+        assertNotNull(property);
+        assertEquals(Integer.valueOf(155), property.getPrimitiveValue().<Integer>toCastValue());
+
+        // 2. feed result
+        metadata = client.getRetrieveRequestFactory().getMetadataRequest(testDefaultServiceRootURL).execute().getBody();
+        assertNotNull(metadata);
+
+        container = metadata.getSchema(0).getEntityContainers().get(0);
+        funcImp = container.getFunctionImport("GetSpecificCustomer");
+
+        builder = client.getURIBuilder(testDefaultServiceRootURL).
+                appendFunctionImportSegment(URIUtils.rootFunctionImportURISegment(container, funcImp));
+
+        type = new EdmV3Type(funcImp.getParameters().get(0).getType());
+        argument = client.getPrimitiveValueBuilder().
+                setType(type.getSimpleType()).
+                setText(StringUtils.EMPTY).
+                build();
+        parameters = new LinkedHashMap<String, ODataValue>();
+        parameters.put(funcImp.getParameters().get(0).getName(), argument);
+
+        final ODataInvokeRequest<ODataEntitySet> feedReq =
+                client.getInvokeRequestFactory().getInvokeRequest(builder.build(), metadata, funcImp, parameters);
+        feedReq.setFormat(format);
+
+        final ODataInvokeResponse<ODataEntitySet> feedRes = feedReq.execute();
+        assertNotNull(feedRes);
+
+        final ODataEntitySet feed = feedRes.getBody();
+        assertNotNull(feed);
+
+        final Set<Integer> customerIds = new HashSet<Integer>(feed.getEntities().size());
+        for (ODataEntity entity : feed.getEntities()) {
+            customerIds.add(entity.getProperty("CustomerId").getPrimitiveValue().<Integer>toCastValue());
+        }
+        assertTrue(customerIds.contains(-8));
+    }
+
+    @Test
+    public void getWithParamsAsAtom() {
+        getWithParams(ODataPubFormat.ATOM);
+    }
+
+    @Test
+    public void getWithParamsAsJSON() {
+        getWithParams(ODataPubFormat.JSON);
+    }
+
+    private ODataEntity createEmployee(final ODataPubFormat format) {
+        final ODataEntity employee = client.getObjectFactory().newEntity(
+                "Microsoft.Test.OData.Services.AstoriaDefaultService.Employee");
+
+        employee.addProperty(client.getObjectFactory().newPrimitiveProperty("PersonId", client.
+                getPrimitiveValueBuilder().
+                setText("1244").setType(EdmSimpleType.Int32).build()));
+        employee.addProperty(client.getObjectFactory().newPrimitiveProperty("Name", client.getPrimitiveValueBuilder().
+                setText("Test employee").build()));
+        employee.addProperty(client.getObjectFactory().newPrimitiveProperty("ManagersPersonId", client.
+                getPrimitiveValueBuilder().
+                setText("3777").setType(EdmSimpleType.Int32).build()));
+        employee.addProperty(client.getObjectFactory().newPrimitiveProperty("Salary", client.getPrimitiveValueBuilder().
+                setText("1000").setType(EdmSimpleType.Int32).build()));
+        employee.addProperty(client.getObjectFactory().newPrimitiveProperty("Title", client.getPrimitiveValueBuilder().
+                setText("CEO").build()));
+
+        final URIBuilder uriBuilder = client.getURIBuilder(testDefaultServiceRootURL).
+                appendEntityTypeSegment("Person");
+
+        final ODataEntityCreateRequest createReq =
+                client.getCUDRequestFactory().getEntityCreateRequest(uriBuilder.build(), employee);
+        createReq.setFormat(format);
+        final ODataEntityCreateResponse createRes = createReq.execute();
+        assertEquals(201, createRes.getStatusCode());
+
+        return createRes.getBody();
+    }
+
+    private void deleteEmployee(final ODataPubFormat format, final Integer id) {
+        final URIBuilder uriBuilder = client.getURIBuilder(testDefaultServiceRootURL).
+                appendEntityTypeSegment("Person").appendKeySegment(id);
+
+        final ODataDeleteRequest deleteReq = client.getCUDRequestFactory().getDeleteRequest(uriBuilder.build());
+        deleteReq.setFormat(format);
+        final ODataDeleteResponse deleteRes = deleteReq.execute();
+        assertEquals(204, deleteRes.getStatusCode());
+    }
+
+    @Test
+    public void boundPost() {
+        // 0. create an employee
+        final ODataEntity created = createEmployee(ODataPubFormat.JSON_FULL_METADATA);
+        assertNotNull(created);
+        final Integer createdId = created.getProperty("PersonId").getPrimitiveValue().<Integer>toCastValue();
+        assertNotNull(createdId);
+
+        // 1. invoke action bound with the employee just created
+        final ODataOperation action = created.getOperations().get(0);
+
+        final EdmV3Metadata metadata =
+                client.getRetrieveRequestFactory().getMetadataRequest(testDefaultServiceRootURL).execute().getBody();
+        assertNotNull(metadata);
+
+        final EntityContainer container = metadata.getSchema(0).getEntityContainers().get(0);
+        final FunctionImport funcImp = container.getFunctionImport(action.getTitle());
+
+        final ODataInvokeRequest<ODataNoContent> req = client.getInvokeRequestFactory().getInvokeRequest(
+                action.getTarget(), metadata, funcImp);
+        req.setFormat(ODataPubFormat.JSON_FULL_METADATA);
+        final ODataInvokeResponse<ODataNoContent> res = req.execute();
+        assertNotNull(res);
+        assertEquals(204, res.getStatusCode());
+
+        // 2. check that invoked action has effectively run
+        final URIBuilder uriBuilder = client.getURIBuilder(testDefaultServiceRootURL).
+                appendEntityTypeSegment("Person").appendKeySegment(createdId);
+        final ODataEntityRequest retrieveRes = client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+        retrieveRes.setFormat(ODataPubFormat.JSON_FULL_METADATA);
+        final ODataEntity read = retrieveRes.execute().getBody();
+        assertEquals("0", read.getProperty("Salary").getPrimitiveValue().toString());
+        assertTrue(read.getProperty("Title").getPrimitiveValue().toString().endsWith("[Sacked]"));
+
+        // 3. remove the test employee
+        deleteEmployee(ODataPubFormat.JSON_FULL_METADATA, createdId);
+    }
+
+    @Test
+    public void boundPostWithParams() {
+        // 1. read employees and store their current salary
+        final URIBuilder builder = client.getURIBuilder(testDefaultServiceRootURL).
+                appendEntitySetSegment("Person").
+                appendEntityTypeSegment("Microsoft.Test.OData.Services.AstoriaDefaultService.Employee");
+        final URI employeesURI = builder.build();
+        ODataEntitySet employees = client.getRetrieveRequestFactory().getEntitySetRequest(employeesURI).execute().
+                getBody();
+        assertFalse(employees.getEntities().isEmpty());
+        final Map<Integer, Integer> preSalaries = new HashMap<Integer, Integer>(employees.getCount());
+        for (ODataEntity employee : employees.getEntities()) {
+            preSalaries.put(employee.getProperty("PersonId").getPrimitiveValue().<Integer>toCastValue(),
+                    employee.getProperty("Salary").getPrimitiveValue().<Integer>toCastValue());
+        }
+        assertFalse(preSalaries.isEmpty());
+
+        // 2. invoke action bound, with additional parameter
+        final EdmV3Metadata metadata =
+                client.getRetrieveRequestFactory().getMetadataRequest(testDefaultServiceRootURL).execute().getBody();
+        assertNotNull(metadata);
+
+        final EntityContainer container = metadata.getSchema(0).getEntityContainers().get(0);
+        final FunctionImport funcImp = container.getFunctionImport("IncreaseSalaries");
+
+        final ODataInvokeRequest<ODataNoContent> req = client.getInvokeRequestFactory().getInvokeRequest(
+                builder.appendStructuralSegment(funcImp.getName()).build(), metadata, funcImp,
+                Collections.<String, ODataValue>singletonMap(
+                        "n", client.getPrimitiveValueBuilder().setValue(1).setType(EdmSimpleType.Int32).build()));
+        final ODataInvokeResponse<ODataNoContent> res = req.execute();
+        assertNotNull(res);
+        assertEquals(204, res.getStatusCode());
+
+        // 3. check whether salaries were incremented
+        employees = client.getRetrieveRequestFactory().getEntitySetRequest(employeesURI).execute().getBody();
+        assertFalse(employees.getEntities().isEmpty());
+        for (ODataEntity employee : employees.getEntities()) {
+            assertTrue(
+                    preSalaries.get(employee.getProperty("PersonId").getPrimitiveValue().<Integer>toCastValue())
+                    < employee.getProperty("Salary").getPrimitiveValue().<Integer>toCastValue());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/7baecb90/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/KeyAsSegmentTestITCase.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/KeyAsSegmentTestITCase.java b/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/KeyAsSegmentTestITCase.java
new file mode 100644
index 0000000..e823999
--- /dev/null
+++ b/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/KeyAsSegmentTestITCase.java
@@ -0,0 +1,111 @@
+/**
+ * Copyright © Microsoft Open Technologies, Inc.
+ *
+ * All Rights Reserved
+ *
+ * Licensed 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
+ *
+ * THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ * ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A
+ * PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT.
+ *
+ * See the Apache License, Version 2.0 for the specific language
+ * governing permissions and limitations under the License.
+ */
+package com.msopentech.odatajclient.engine.it;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+import com.msopentech.odatajclient.engine.communication.request.UpdateType;
+import com.msopentech.odatajclient.engine.communication.request.retrieve.ODataEntityRequest;
+import com.msopentech.odatajclient.engine.communication.response.ODataRetrieveResponse;
+import com.msopentech.odatajclient.engine.data.ODataEntity;
+import com.msopentech.odatajclient.engine.uri.URIBuilder;
+import com.msopentech.odatajclient.engine.format.ODataPubFormat;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class KeyAsSegmentTestITCase extends AbstractTestITCase {
+
+    @BeforeClass
+    public static void enableKeyAsSegment() {
+        client.getConfiguration().setKeyAsSegment(true);
+    }
+
+    private void read(final ODataPubFormat format) {
+        final URIBuilder uriBuilder = client.getURIBuilder(testKeyAsSegmentServiceRootURL).
+                appendEntityTypeSegment("Customer").appendKeySegment(-10);
+
+        final ODataEntityRequest req = client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+        req.setFormat(format);
+
+        final ODataRetrieveResponse<ODataEntity> res = req.execute();
+        final ODataEntity entity = res.getBody();
+        assertNotNull(entity);
+
+        assertFalse(entity.getEditLink().toASCIIString().contains("("));
+        assertFalse(entity.getEditLink().toASCIIString().contains(")"));
+    }
+
+    @Test
+    public void fromAtom() {
+        read(ODataPubFormat.ATOM);
+    }
+
+    @Test
+    public void fromJSON() {
+        read(ODataPubFormat.JSON_FULL_METADATA);
+    }
+
+    @Test
+    public void createODataEntityAsAtom() {
+        final ODataPubFormat format = ODataPubFormat.ATOM;
+        final int id = 1;
+        final ODataEntity original = getSampleCustomerProfile(id, "Sample customer", false);
+
+        createEntity(testKeyAsSegmentServiceRootURL, format, original, "Customer");
+        final ODataEntity actual = compareEntities(testKeyAsSegmentServiceRootURL, format, original, id, null);
+
+        cleanAfterCreate(format, actual, false, testKeyAsSegmentServiceRootURL);
+    }
+
+    @Test
+    public void createODataEntityAsJSON() {
+        final ODataPubFormat format = ODataPubFormat.JSON_FULL_METADATA;
+        final int id = 2;
+        final ODataEntity original = getSampleCustomerProfile(id, "Sample customer", false);
+
+        createEntity(testKeyAsSegmentServiceRootURL, format, original, "Customer");
+        final ODataEntity actual = compareEntities(testKeyAsSegmentServiceRootURL, format, original, id, null);
+
+        cleanAfterCreate(format, actual, false, testKeyAsSegmentServiceRootURL);
+    }
+
+    @Test
+    public void replaceODataEntityAsAtom() {
+        final ODataPubFormat format = ODataPubFormat.ATOM;
+        final ODataEntity changes = read(format, client.getURIBuilder(testKeyAsSegmentServiceRootURL).
+                appendEntityTypeSegment("Car").appendKeySegment(14).build());
+        updateEntityDescription(format, changes, UpdateType.REPLACE);
+    }
+
+    @Test
+    public void replaceODataEntityAsJSON() {
+        final ODataPubFormat format = ODataPubFormat.JSON_FULL_METADATA;
+        final ODataEntity changes = read(format, client.getURIBuilder(testKeyAsSegmentServiceRootURL).
+                appendEntityTypeSegment("Car").appendKeySegment(14).build());
+        updateEntityDescription(format, changes, UpdateType.REPLACE);
+    }
+
+    @AfterClass
+    public static void disableKeyAsSegment() {
+        client.getConfiguration().setKeyAsSegment(false);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/7baecb90/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/LinkTestITCase.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/LinkTestITCase.java b/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/LinkTestITCase.java
new file mode 100644
index 0000000..2899b80
--- /dev/null
+++ b/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/LinkTestITCase.java
@@ -0,0 +1,178 @@
+/**
+ * Copyright © Microsoft Open Technologies, Inc.
+ *
+ * All Rights Reserved
+ *
+ * Licensed 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
+ *
+ * THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ * ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A
+ * PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT.
+ *
+ * See the Apache License, Version 2.0 for the specific language
+ * governing permissions and limitations under the License.
+ */
+package com.msopentech.odatajclient.engine.it;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNotNull;
+
+import com.msopentech.odatajclient.engine.communication.request.UpdateType;
+import com.msopentech.odatajclient.engine.communication.request.cud.ODataLinkCreateRequest;
+import com.msopentech.odatajclient.engine.communication.request.cud.ODataLinkUpdateRequest;
+import com.msopentech.odatajclient.engine.communication.request.retrieve.ODataLinkCollectionRequest;
+import com.msopentech.odatajclient.engine.communication.response.ODataLinkOperationResponse;
+import com.msopentech.odatajclient.engine.communication.response.ODataRetrieveResponse;
+import com.msopentech.odatajclient.engine.data.ODataLink;
+import com.msopentech.odatajclient.engine.data.ODataLinkCollection;
+import com.msopentech.odatajclient.engine.uri.URIBuilder;
+import com.msopentech.odatajclient.engine.format.ODataFormat;
+import java.io.IOException;
+import java.net.URI;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Test;
+
+/**
+ * This is the unit test class to check basic link operations.
+ */
+public class LinkTestITCase extends AbstractTestITCase {
+
+    protected String getServiceRoot() {
+        return testDefaultServiceRootURL;
+    }
+
+    private ODataLinkCollection doRetrieveLinkURIs(final ODataFormat format, final String linkname) throws IOException {
+        final URIBuilder uriBuilder = client.getURIBuilder(getServiceRoot()).
+                appendEntityTypeSegment("Customer").appendKeySegment(-10);
+
+        final ODataLinkCollectionRequest req =
+                client.getRetrieveRequestFactory().getLinkCollectionRequest(uriBuilder.build(), linkname);
+        req.setFormat(format);
+
+        final ODataRetrieveResponse<ODataLinkCollection> res = req.execute();
+        assertEquals(200, res.getStatusCode());
+
+        return res.getBody();
+    }
+
+    private void retrieveLinkURIs(final ODataFormat format) throws IOException {
+        final List<URI> links = doRetrieveLinkURIs(format, "Logins").getLinks();
+        assertEquals(2, links.size());
+        assertTrue(links.contains(URI.create(getServiceRoot() + "/Login('1')")));
+        assertTrue(links.contains(URI.create(getServiceRoot() + "/Login('4')")));
+    }
+
+    @Test
+    public void retrieveXMLLinkURIsWithNext() throws IOException {
+        final ODataLinkCollection uris = doRetrieveLinkURIs(ODataFormat.XML, "Orders");
+        assertEquals(2, uris.getLinks().size());
+        assertNotNull(uris.getNext());
+    }
+
+    @Test
+    public void retrieveXMLLinkURIs() throws IOException {
+        retrieveLinkURIs(ODataFormat.XML);
+    }
+
+    @Test
+    public void retrieveJSONLinkURIs() throws IOException {
+        retrieveLinkURIs(ODataFormat.JSON);
+    }
+
+    private void createLink(final ODataFormat format) throws IOException {
+        // 1. read current Logins $links (for later usage)
+        final List<URI> before = doRetrieveLinkURIs(format, "Logins").getLinks();
+        assertEquals(2, before.size());
+
+        // 2. create new link
+        final ODataLink newLink = client.getObjectFactory().
+                newAssociationLink(null, URI.create(getServiceRoot() + "/Login('3')"));
+
+        final URIBuilder uriBuilder = client.getURIBuilder(getServiceRoot()).
+                appendEntityTypeSegment("Customer").appendKeySegment(-10).appendLinksSegment("Logins");
+
+        final ODataLinkCreateRequest req =
+                client.getCUDRequestFactory().getLinkCreateRequest(uriBuilder.build(), newLink);
+        req.setFormat(format);
+
+        final ODataLinkOperationResponse res = req.execute();
+        assertEquals(204, res.getStatusCode());
+
+        final List<URI> after = doRetrieveLinkURIs(format, "Logins").getLinks();
+        assertEquals(before.size() + 1, after.size());
+
+        // 3. reset Logins $links as before this test was run
+        after.removeAll(before);
+        assertEquals(Collections.singletonList(newLink.getLink()), after);
+
+        assertEquals(204, client.getCUDRequestFactory().getDeleteRequest(
+                client.getURIBuilder(getServiceRoot()).appendEntityTypeSegment("Customer").
+                appendKeySegment(-10).appendLinksSegment("Logins('3')").build()).execute().getStatusCode());
+    }
+
+    @Test
+    public void createXMLLink() throws IOException {
+        createLink(ODataFormat.XML);
+    }
+
+    @Test
+    public void createJSONLink() throws IOException {
+        createLink(ODataFormat.JSON);
+    }
+
+    private void updateLink(final ODataFormat format, final UpdateType updateType) throws IOException {
+        // 1. read what is the link before the test runs
+        final URI before = doRetrieveLinkURIs(format, "Info").getLinks().get(0);
+
+        // 2. update the link
+        ODataLink newLink =
+                client.getObjectFactory().newAssociationLink(null, URI.create(getServiceRoot() + "/CustomerInfo(12)"));
+
+        final URIBuilder uriBuilder = client.getURIBuilder(getServiceRoot());
+        uriBuilder.appendEntityTypeSegment("Customer").appendKeySegment(-10).appendLinksSegment("Info");
+
+        ODataLinkUpdateRequest req =
+                client.getCUDRequestFactory().getLinkUpdateRequest(uriBuilder.build(), updateType, newLink);
+        req.setFormat(format);
+
+        ODataLinkOperationResponse res = req.execute();
+        assertEquals(204, res.getStatusCode());
+
+        URI after = doRetrieveLinkURIs(format, "Info").getLinks().get(0);
+        assertNotEquals(before, after);
+        assertEquals(newLink.getLink(), after);
+
+        // 3. reset back the link value
+        newLink = client.getObjectFactory().newAssociationLink(null, before);
+        req = client.getCUDRequestFactory().getLinkUpdateRequest(uriBuilder.build(), updateType, newLink);
+        req.setFormat(format);
+
+        res = req.execute();
+        assertEquals(204, res.getStatusCode());
+
+        after = doRetrieveLinkURIs(format, "Info").getLinks().get(0);
+        assertEquals(before, after);
+    }
+
+    @Test
+    public void updateXMLLink() throws IOException {
+        updateLink(ODataFormat.XML, UpdateType.MERGE);
+        updateLink(ODataFormat.XML, UpdateType.PATCH);
+        updateLink(ODataFormat.XML, UpdateType.REPLACE);
+    }
+
+    @Test
+    public void updateJSONLink() throws IOException {
+        updateLink(ODataFormat.JSON, UpdateType.MERGE);
+        updateLink(ODataFormat.JSON, UpdateType.PATCH);
+        updateLink(ODataFormat.JSON, UpdateType.REPLACE);
+    }
+}