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:21 UTC

[45/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/main/java/com/msopentech/odatajclient/engine/data/ODataBinder.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataBinder.java b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataBinder.java
new file mode 100644
index 0000000..6589d04
--- /dev/null
+++ b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataBinder.java
@@ -0,0 +1,129 @@
+/**
+ * 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.data;
+
+import java.io.Serializable;
+import java.net.URI;
+import org.w3c.dom.Element;
+
+public interface ODataBinder extends Serializable {
+
+    /**
+     * Gets <tt>ODataServiceDocument</tt> from the given service document resource.
+     *
+     * @param resource service document resource.
+     * @return <tt>ODataServiceDocument</tt> object.
+     */
+    ODataServiceDocument getODataServiceDocument(ServiceDocument resource);
+
+    /**
+     * Gets a <tt>FeedResource</tt> from the given OData entity set.
+     *
+     * @param <T> feed resource type.
+     * @param feed OData entity set.
+     * @param reference reference class.
+     * @return <tt>FeedResource</tt> object.
+     */
+    <T extends Feed> T getFeed(ODataEntitySet feed, Class<T> reference);
+
+    /**
+     * Gets an <tt>EntryResource</tt> from the given OData entity.
+     *
+     * @param <T> entry resource type.
+     * @param entity OData entity.
+     * @param reference reference class.
+     * @return <tt>EntryResource</tt> object.
+     */
+    <T extends Entry> T getEntry(ODataEntity entity, Class<T> reference);
+
+    /**
+     * Gets an <tt>EntryResource</tt> from the given OData entity.
+     *
+     * @param <T> entry resource type.
+     * @param entity OData entity.
+     * @param reference reference class.
+     * @param setType whether to explicitly output type information.
+     * @return <tt>EntryResource</tt> object.
+     */
+    <T extends Entry> T getEntry(ODataEntity entity, Class<T> reference, boolean setType);
+
+    /**
+     * Gets the given OData property as DOM element.
+     *
+     * @param prop OData property.
+     * @return <tt>Element</tt> object.
+     */
+    Element toDOMElement(ODataProperty prop);
+
+    ODataLinkCollection getLinkCollection(LinkCollection linkCollection);
+
+    /**
+     * Gets <tt>ODataEntitySet</tt> from the given feed resource.
+     *
+     * @param resource feed resource.
+     * @return <tt>ODataEntitySet</tt> object.
+     */
+    ODataEntitySet getODataEntitySet(Feed resource);
+
+    /**
+     * Gets <tt>ODataEntitySet</tt> from the given feed resource.
+     *
+     * @param resource feed resource.
+     * @param defaultBaseURI default base URI.
+     * @return <tt>ODataEntitySet</tt> object.
+     */
+    ODataEntitySet getODataEntitySet(Feed resource, URI defaultBaseURI);
+
+    /**
+     * Gets <tt>ODataEntity</tt> from the given entry resource.
+     *
+     * @param resource entry resource.
+     * @return <tt>ODataEntity</tt> object.
+     */
+    ODataEntity getODataEntity(Entry resource);
+
+    /**
+     * Gets <tt>ODataEntity</tt> from the given entry resource.
+     *
+     * @param resource entry resource.
+     * @param defaultBaseURI default base URI.
+     * @return <tt>ODataEntity</tt> object.
+     */
+    ODataEntity getODataEntity(Entry resource, URI defaultBaseURI);
+
+    /**
+     * Gets a <tt>LinkResource</tt> from the given OData link.
+     *
+     * @param <T> link resource type.
+     * @param link OData link.
+     * @param reference reference class.
+     * @return <tt>LinkResource</tt> object.
+     */
+    @SuppressWarnings("unchecked")
+    <T extends Link> T getLinkResource(ODataLink link, Class<T> reference);
+
+    /**
+     * Gets an <tt>ODataProperty</tt> from the given DOM element.
+     *
+     * @param property content.
+     * @return <tt>ODataProperty</tt> object.
+     */
+    ODataProperty getProperty(Element property);
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/7baecb90/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataCollectionValue.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataCollectionValue.java b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataCollectionValue.java
new file mode 100644
index 0000000..f3fd183
--- /dev/null
+++ b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataCollectionValue.java
@@ -0,0 +1,99 @@
+/**
+ * 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.data;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * OData collection property value.
+ */
+public class ODataCollectionValue extends ODataValue implements Iterable<ODataValue> {
+
+    private static final long serialVersionUID = -3665659846001987187L;
+
+    /**
+     * Type name;
+     */
+    private final String typeName;
+
+    /**
+     * Values.
+     */
+    private final List<ODataValue> values = new ArrayList<ODataValue>();
+
+    /**
+     * Constructor.
+     *
+     * @param typeName type name.
+     */
+    public ODataCollectionValue(final String typeName) {
+        this.typeName = typeName;
+    }
+
+    /**
+     * Adds a value to the collection.
+     *
+     * @param value value to be added.
+     */
+    public void add(final ODataValue value) {
+        if (value.isPrimitive() || value.isComplex()) {
+            values.add(value);
+        }
+    }
+
+    /**
+     * Value iterator.
+     *
+     * @return value iterator.
+     */
+    @Override
+    public Iterator<ODataValue> iterator() {
+        return values.iterator();
+    }
+
+    /**
+     * Gets value type name.
+     *
+     * @return value type name.
+     */
+    public String getTypeName() {
+        return typeName;
+    }
+
+    /**
+     * Gets collection size.
+     *
+     * @return collection size.
+     */
+    public int size() {
+        return values.size();
+    }
+
+    /**
+     * Checks if collection is empty.
+     *
+     * @return 'TRUE' if empty; 'FALSE' otherwise.
+     */
+    public boolean isEmpty() {
+        return values.isEmpty();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/7baecb90/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataComplexValue.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataComplexValue.java b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataComplexValue.java
new file mode 100644
index 0000000..98d3c45
--- /dev/null
+++ b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataComplexValue.java
@@ -0,0 +1,98 @@
+/**
+ * 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.data;
+
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * OData complex property value.
+ */
+public class ODataComplexValue extends ODataValue implements Iterable<ODataProperty> {
+
+    private static final long serialVersionUID = -1878555027714020431L;
+
+    /**
+     * Type name.
+     */
+    private final String typeName;
+
+    /**
+     * Complex type fields.
+     */
+    private final Map<String, ODataProperty> fields = new LinkedHashMap<String, ODataProperty>();
+
+    /**
+     * Constructor.
+     *
+     * @param typeName type name.
+     */
+    public ODataComplexValue(final String typeName) {
+        this.typeName = typeName;
+    }
+
+    /**
+     * Adds field to the complex type.
+     *
+     * @param field field to be added.
+     */
+    public void add(final ODataProperty field) {
+        fields.put(field.getName(), field);
+    }
+
+    /**
+     * Gets field.
+     *
+     * @param name name of the field to be retrieved.
+     * @return requested field.
+     */
+    public ODataProperty get(final String name) {
+        return fields.get(name);
+    }
+
+    /**
+     * Complex property fields iterator.
+     *
+     * @return fields iterator.
+     */
+    @Override
+    public Iterator<ODataProperty> iterator() {
+        return fields.values().iterator();
+    }
+
+    /**
+     * Gest value type name.
+     *
+     * @return value type name.
+     */
+    public String getTypeName() {
+        return typeName;
+    }
+
+    /**
+     * Gets number of fields.
+     *
+     * @return number of fields.
+     */
+    public int size() {
+        return fields.size();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/7baecb90/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataDeserializer.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataDeserializer.java b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataDeserializer.java
new file mode 100644
index 0000000..ef19822
--- /dev/null
+++ b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataDeserializer.java
@@ -0,0 +1,98 @@
+/**
+ * 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.data;
+
+import com.msopentech.odatajclient.engine.metadata.edm.AbstractEdmx;
+import com.msopentech.odatajclient.engine.format.ODataFormat;
+import java.io.InputStream;
+import java.io.Serializable;
+import org.w3c.dom.Element;
+
+/**
+ * Utility class for serialization.
+ */
+public interface ODataDeserializer extends Serializable {
+
+    AbstractEdmx<?, ?, ?, ?, ?, ?> toMetadata(InputStream input);
+
+    /**
+     * Gets the ServiceDocumentResource object represented by the given InputStream.
+     *
+     * @param input stream to be de-serialized.
+     * @param format OData service document format.
+     * @return ServiceDocumentResource object.
+     */
+    ServiceDocument toServiceDocument(InputStream input, ODataFormat format);
+
+    /**
+     * Gets a feed object from the given InputStream.
+     *
+     * @param <T> reference class type
+     * @param input stream to be de-serialized.
+     * @param reference reference class (AtomFeed.class, JSONFeed.class).
+     * @return FeedResource instance.
+     */
+    <T extends Feed> T toFeed(InputStream input, Class<T> reference);
+
+    /**
+     * Gets an entry object from the given InputStream.
+     *
+     * @param <T> reference class type
+     * @param input stream to be de-serialized.
+     * @param reference reference class (AtomEntry.class, JSONV3Entry.class).
+     * @return EntryResource instance.
+     */
+    <T extends Entry> T toEntry(InputStream input, Class<T> reference);
+
+    /**
+     * Gets a DOM representation of the given InputStream.
+     *
+     * @param input stream to be de-serialized.
+     * @param format OData format.
+     * @return DOM.
+     */
+    Element toPropertyDOM(InputStream input, ODataFormat format);
+
+    /**
+     * Gets a list of links from the given InputStream.
+     *
+     * @param input stream to be de-serialized.
+     * @param format OData format.
+     * @return de-serialized links.
+     */
+    LinkCollection toLinkCollection(InputStream input, ODataFormat format);
+
+    /**
+     * Gets the ODataError object represented by the given InputStream.
+     *
+     * @param input stream to be parsed and de-serialized.
+     * @param isXML 'TRUE' if the error is represented by XML; 'FALSE' otherwise.
+     * @return
+     */
+    ODataError toODataError(InputStream input, boolean isXML);
+
+    /**
+     * Parses the given input into a DOM tree.
+     *
+     * @param input stream to be parsed and de-serialized.
+     * @return DOM tree
+     */
+    Element toDOM(InputStream input);
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/7baecb90/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataDuration.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataDuration.java b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataDuration.java
new file mode 100644
index 0000000..44cd7fc
--- /dev/null
+++ b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataDuration.java
@@ -0,0 +1,81 @@
+/**
+ * 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.data;
+
+import java.io.Serializable;
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.Duration;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+
+/**
+ * Helper class for handling time (as duration) primitive values.
+ *
+ * @see com.msopentech.odatajclient.engine.data.metadata.edm.EdmSimpleType#TIME
+ * @see Duration
+ */
+public final class ODataDuration implements Serializable {
+
+    private static final long serialVersionUID = 778404231943967899L;
+
+    private final Duration duration;
+
+    public ODataDuration(final String input) {
+        try {
+            final DatatypeFactory dtFactory = DatatypeFactory.newInstance();
+            this.duration = dtFactory.newDuration(input);
+        } catch (DatatypeConfigurationException e) {
+            throw new IllegalArgumentException("Could not parse '" + input + "' as Duration", e);
+        }
+    }
+
+    public ODataDuration(final Duration duration) {
+        this.duration = duration;
+    }
+
+    public Duration getDuration() {
+        return duration;
+    }
+
+    /**
+     * {@inheritDoc }
+     */
+    @Override
+    public boolean equals(final Object obj) {
+        return EqualsBuilder.reflectionEquals(this, obj);
+    }
+
+    /**
+     * {@inheritDoc }
+     */
+    @Override
+    public int hashCode() {
+        return HashCodeBuilder.reflectionHashCode(this);
+    }
+
+    /**
+     * {@inheritDoc }
+     */
+    @Override
+    public String toString() {
+        return this.duration.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/7baecb90/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataEntity.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataEntity.java b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataEntity.java
new file mode 100644
index 0000000..79e2c74
--- /dev/null
+++ b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataEntity.java
@@ -0,0 +1,362 @@
+/**
+ * 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.data;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * OData entity.
+ */
+public class ODataEntity extends ODataItem implements ODataInvokeResult {
+
+    private static final long serialVersionUID = 8360640095932811034L;
+
+    /**
+     * ETag.
+     */
+    private String eTag;
+
+    /**
+     * Media entity flag.
+     */
+    private boolean mediaEntity = false;
+
+    /**
+     * In case of media entity, media content type.
+     */
+    private String mediaContentType;
+
+    /**
+     * In case of media entity, media content source.
+     */
+    private String mediaContentSource;
+
+    /**
+     * Edit link.
+     */
+    protected URI editLink;
+
+    /**
+     * Navigation links (might contain in-line entities or feeds).
+     */
+    protected final List<ODataLink> navigationLinks = new ArrayList<ODataLink>();
+
+    /**
+     * Association links.
+     */
+    protected final List<ODataLink> associationLinks = new ArrayList<ODataLink>();
+
+    /**
+     * Media edit links.
+     */
+    protected final List<ODataLink> editMediaLinks = new ArrayList<ODataLink>();
+
+    /**
+     * Operations (legacy, functions, actions).
+     */
+    protected final List<ODataOperation> operations = new ArrayList<ODataOperation>();
+
+    /**
+     * Entity properties.
+     */
+    protected final List<ODataProperty> properties = new ArrayList<ODataProperty>();
+
+    /**
+     * Constructor.
+     *
+     * @param name OData entity name.
+     */
+    ODataEntity(final String name) {
+        super(name);
+    }
+
+    /**
+     * Gets ETag.
+     *
+     * @return ETag.
+     */
+    public String getETag() {
+        return eTag;
+    }
+
+    /**
+     * Sets ETag.
+     *
+     * @param eTag ETag.
+     */
+    public void setETag(final String eTag) {
+        this.eTag = eTag;
+    }
+
+    /**
+     * Adds an operation.
+     *
+     * @param operation to be added.
+     * @return whether operation was actually added or not.
+     */
+    public boolean addOperation(final ODataOperation operation) {
+        return this.operations.add(operation);
+    }
+
+    /**
+     * Sets operations.
+     *
+     * @param operations operations.
+     */
+    public void setOperations(final List<ODataOperation> operations) {
+        this.operations.clear();
+        if (operations != null && !operations.isEmpty()) {
+            this.operations.addAll(operations);
+        }
+    }
+
+    /**
+     * Searches for operation with given title.
+     *
+     * @param title operation to look for
+     * @return operation if found with given title, <tt>null</tt> otherwise
+     */
+    public ODataOperation getOperation(final String title) {
+        ODataOperation result = null;
+        for (ODataOperation operation : operations) {
+            if (title.equals(operation.getTitle())) {
+                result = operation;
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Gets operations.
+     *
+     * @return operations.
+     */
+    public List<ODataOperation> getOperations() {
+        return this.operations;
+    }
+
+    /**
+     * Searches for property with given name.
+     *
+     * @param name property to look for
+     * @return property if found with given name, <tt>null</tt> otherwise
+     */
+    public ODataProperty getProperty(final String name) {
+        ODataProperty result = null;
+
+        if (StringUtils.isNotBlank(name)) {
+            for (ODataProperty property : properties) {
+                if (name.equals(property.getName())) {
+                    result = property;
+                }
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Returns OData entity properties.
+     *
+     * @return OData entity properties.
+     */
+    public List<ODataProperty> getProperties() {
+        return properties;
+    }
+
+    /**
+     * Adds new property.
+     *
+     * @param property property to be added.
+     */
+    public boolean addProperty(final ODataProperty property) {
+        return properties.contains(property) ? false : properties.add(property);
+    }
+
+    /**
+     * Removes given property.
+     *
+     * @param property property to be removed.
+     */
+    public boolean removeProperty(final ODataProperty property) {
+        return properties.remove(property);
+    }
+
+    /**
+     * Puts the given link into one of available lists, based on its type.
+     *
+     * @param link to be added
+     * @return <tt>true</tt> if the given link was added in one of available lists
+     */
+    public boolean addLink(final ODataLink link) {
+        boolean result = false;
+
+        switch (link.getType()) {
+            case ASSOCIATION:
+                result = associationLinks.contains(link) ? false : associationLinks.add(link);
+                break;
+
+            case ENTITY_NAVIGATION:
+            case ENTITY_SET_NAVIGATION:
+                result = navigationLinks.contains(link) ? false : navigationLinks.add(link);
+                break;
+
+            case MEDIA_EDIT:
+                result = editMediaLinks.contains(link) ? false : editMediaLinks.add(link);
+                break;
+
+            default:
+        }
+
+        return result;
+    }
+
+    /**
+     * Removes the given link from any list (association, navigation, edit-media).
+     *
+     * @param link to be removed
+     * @return <tt>true</tt> if the given link was contained in one of available lists
+     */
+    public boolean removeLink(final ODataLink link) {
+        return associationLinks.remove(link) || navigationLinks.remove(link) || editMediaLinks.remove(link);
+    }
+
+    /**
+     * Returns all entity navigation links (including inline entities / feeds).
+     *
+     * @return OData entity links.
+     */
+    public List<ODataLink> getNavigationLinks() {
+        return navigationLinks;
+    }
+
+    /**
+     * Returns all entity association links.
+     *
+     * @return OData entity links.
+     */
+    public List<ODataLink> getAssociationLinks() {
+        return associationLinks;
+    }
+
+    /**
+     * Returns all entity media edit links.
+     *
+     * @return OData entity links.
+     */
+    public List<ODataLink> getEditMediaLinks() {
+        return editMediaLinks;
+    }
+
+    /**
+     * Returns OData entity edit link.
+     *
+     * @return entity edit link.
+     */
+    public URI getEditLink() {
+        return editLink;
+    }
+
+    /**
+     * Sets OData entity edit link.
+     *
+     * @param editLink edit link.
+     */
+    public void setEditLink(final URI editLink) {
+        this.editLink = editLink;
+    }
+
+    /**
+     * {@inheritDoc }
+     * <p>
+     * If null the edit link will be returned.
+     */
+    @Override
+    public URI getLink() {
+        return super.getLink() == null ? getEditLink() : super.getLink();
+    }
+
+    /**
+     * TRUE if read-only entity.
+     *
+     * @return TRUE if read-only; FALSE otherwise.
+     */
+    public boolean isReadOnly() {
+        return super.getLink() != null;
+    }
+
+    /**
+     * Checks if the current entity is a media entity.
+     *
+     * @return 'TRUE' if media entity; 'FALSE' otherwise.
+     */
+    public boolean isMediaEntity() {
+        return mediaEntity;
+    }
+
+    /**
+     * Sets media entity flag.
+     *
+     * @param isMediaEntity media entity flag value.
+     */
+    public void setMediaEntity(final boolean isMediaEntity) {
+        this.mediaEntity = isMediaEntity;
+    }
+
+    /**
+     * Gets media content type.
+     *
+     * @return media content type.
+     */
+    public String getMediaContentType() {
+        return mediaContentType;
+    }
+
+    /**
+     * Sets media content type.
+     *
+     * @param mediaContentType media content type.
+     */
+    public void setMediaContentType(final String mediaContentType) {
+        this.mediaContentType = mediaContentType;
+    }
+
+    /**
+     * Gets media content source.
+     *
+     * @return media content source.
+     */
+    public String getMediaContentSource() {
+        return mediaContentSource;
+    }
+
+    /**
+     * Sets media content source.
+     *
+     * @param mediaContentSource media content source.
+     */
+    public void setMediaContentSource(final String mediaContentSource) {
+        this.mediaContentSource = mediaContentSource;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/7baecb90/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataEntitySet.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataEntitySet.java b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataEntitySet.java
new file mode 100644
index 0000000..77d615a
--- /dev/null
+++ b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataEntitySet.java
@@ -0,0 +1,122 @@
+/**
+ * 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.data;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * OData entity collection.
+ * If pagination was used to get this instance, forward page navigation URI will be available.
+ */
+public class ODataEntitySet extends ODataItem implements ODataInvokeResult {
+
+    private static final long serialVersionUID = 9039605899821494024L;
+
+    /**
+     * Link to the next page.
+     */
+    protected URI next;
+
+    /**
+     * Number of ODataEntities contained in this feed.
+     * If <tt>$inlinecount</tt> was requested, this value comes from there.
+     */
+    protected Integer count;
+
+    /**
+     * OData entities contained in this feed.
+     */
+    protected List<ODataEntity> entities = new ArrayList<ODataEntity>();
+
+    /**
+     * Constructor.
+     */
+    ODataEntitySet() {
+        super(null);
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param next next link.
+     */
+    ODataEntitySet(final URI next) {
+        super(null);
+        this.next = next;
+    }
+
+    /**
+     * Gets next page link.
+     *
+     * @return next page link; null value if single page or last page reached.
+     */
+    public URI getNext() {
+        return next;
+    }
+
+    /**
+     * Sets in-line count.
+     *
+     * @param count in-line count value.
+     */
+    public void setCount(final int count) {
+        this.count = count;
+    }
+
+    /**
+     * Gets in-line count.
+     *
+     * @return in-line count value.
+     */
+    public int getCount() {
+        return count == null ? entities.size() : count;
+    }
+
+    /**
+     * Adds entity to the current feed.
+     *
+     * @param entity entity to be added.
+     * @return 'FALSE' if already exists; 'TRUE' otherwise.
+     */
+    public boolean addEntity(final ODataEntity entity) {
+        return entities.contains(entity) ? false : entities.add(entity);
+    }
+
+    /**
+     * Removes an entity.
+     *
+     * @param entity entity to be removed.
+     * @return 'TRUE' in case of success; 'FALSE' otherwise.
+     */
+    public boolean removeEntity(final ODataEntity entity) {
+        return entities.remove(entity);
+    }
+
+    /**
+     * Gets contained entities.
+     *
+     * @return feed entries.
+     */
+    public List<ODataEntity> getEntities() {
+        return entities;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/7baecb90/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataEntitySetIterator.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataEntitySetIterator.java b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataEntitySetIterator.java
new file mode 100644
index 0000000..8ab8b37
--- /dev/null
+++ b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataEntitySetIterator.java
@@ -0,0 +1,320 @@
+/**
+ * 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.data;
+
+import com.msopentech.odatajclient.engine.client.ODataClient;
+import com.msopentech.odatajclient.engine.data.impl.v3.AtomEntry;
+import com.msopentech.odatajclient.engine.data.impl.v3.JSONEntry;
+import com.msopentech.odatajclient.engine.format.ODataPubFormat;
+import com.msopentech.odatajclient.engine.utils.ODataConstants;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * OData entity set iterator class.
+ */
+public class ODataEntitySetIterator implements Iterator<ODataEntity> {
+
+    /**
+     * Logger.
+     */
+    private static final Logger LOG = LoggerFactory.getLogger(ODataEntitySetIterator.class);
+
+    private static final long serialVersionUID = 9039605899821494025L;
+
+    private final ODataClient odataClient;
+
+    private final InputStream stream;
+
+    private final ODataPubFormat format;
+
+    private Entry cached;
+
+    private ODataEntitySet entitySet;
+
+    private final ByteArrayOutputStream osFeed;
+
+    private final String namespaces;
+
+    private boolean available = true;
+
+    /**
+     * Constructor.
+     *
+     * @param odataClient client instance getting this request
+     * @param stream source stream.
+     * @param format OData format.
+     */
+    public ODataEntitySetIterator(final ODataClient odataClient,
+            final InputStream stream, final ODataPubFormat format) {
+
+        this.odataClient = odataClient;
+        this.stream = stream;
+        this.format = format;
+        this.osFeed = new ByteArrayOutputStream();
+
+        if (format == ODataPubFormat.ATOM) {
+            namespaces = getAllElementAttributes(stream, "feed", osFeed);
+        } else {
+            namespaces = null;
+            try {
+                if (consume(stream, "\"value\":", osFeed, true) >= 0) {
+                    int c = 0;
+                    while (c != '[' && (c = stream.read()) >= 0) {
+                        osFeed.write(c);
+                    }
+                }
+            } catch (IOException e) {
+                LOG.error("Error parsing feed", e);
+                throw new IllegalStateException(e);
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc }
+     */
+    @Override
+    public boolean hasNext() {
+        if (available && cached == null) {
+            if (format == ODataPubFormat.ATOM) {
+                cached = nextAtomEntryFromFeed(stream, osFeed, namespaces);
+            } else {
+                cached = nextJsonEntryFromFeed(stream, osFeed);
+            }
+
+            if (cached == null) {
+                available = false;
+                entitySet = odataClient.getReader().
+                        readEntitySet(new ByteArrayInputStream(osFeed.toByteArray()), format);
+                close();
+            }
+        }
+
+        return available;
+    }
+
+    /**
+     * {@inheritDoc }
+     */
+    @Override
+    public ODataEntity next() {
+        if (hasNext()) {
+            final ODataEntity res = odataClient.getBinder().getODataEntity(cached);
+            cached = null;
+            return res;
+        }
+
+        throw new NoSuchElementException("No entity found");
+    }
+
+    /**
+     * Unsupported operation.
+     */
+    @Override
+    public void remove() {
+        throw new UnsupportedOperationException("Operation not supported");
+    }
+
+    /**
+     * Closes the current iterator.
+     */
+    public void close() {
+        IOUtils.closeQuietly(stream);
+        IOUtils.closeQuietly(osFeed);
+    }
+
+    /**
+     * Gets the next link if exists.
+     *
+     * @return next link if exists; null otherwise.
+     */
+    public URI getNext() {
+        if (entitySet == null) {
+            throw new IllegalStateException("Iteration must be completed in order to retrieve the link for next page");
+        }
+        return entitySet.getNext();
+    }
+
+    /**
+     * Finalize object closing all managed resources.
+     *
+     * @throws Throwable
+     */
+    @Override
+    protected void finalize() throws Throwable {
+        close();
+        super.finalize();
+    }
+
+    private JSONEntry nextJsonEntryFromFeed(final InputStream input, final OutputStream osFeed) {
+        final ByteArrayOutputStream entry = new ByteArrayOutputStream();
+
+        JSONEntry entity = null;
+        try {
+            int c = 0;
+
+            boolean foundNewOne = false;
+
+            do {
+                c = input.read();
+                if (c == '{') {
+                    entry.write(c);
+                    c = -1;
+                    foundNewOne = true;
+                }
+                if (c == ']') {
+                    osFeed.write(c);
+                    c = -1;
+                }
+            } while (c >= 0);
+
+            if (foundNewOne) {
+                int count = 1;
+                c = 0;
+
+                while (count > 0 && c >= 0) {
+                    c = input.read();
+                    if (c == '{') {
+                        count++;
+                    } else if (c == '}') {
+                        count--;
+                    }
+                    entry.write(c);
+                }
+
+                if (c >= 0) {
+                    entity = odataClient.getDeserializer().toEntry(
+                            new ByteArrayInputStream(entry.toByteArray()), JSONEntry.class);
+                }
+            } else {
+                while ((c = input.read()) >= 0) {
+                    osFeed.write(c);
+                }
+            }
+        } catch (Exception e) {
+            LOG.error("Error retrieving entities from EntitySet", e);
+        }
+
+        return entity;
+    }
+
+    /**
+     * De-Serializes a stream into an OData entity set.
+     *
+     * @param input stream to de-serialize.
+     * @param format de-serialize as AtomFeed or JSONFeed
+     * @return de-serialized entity set.
+     */
+    private AtomEntry nextAtomEntryFromFeed(final InputStream input, final OutputStream osFeed, final String namespaces) {
+        final ByteArrayOutputStream entry = new ByteArrayOutputStream();
+
+        AtomEntry entity = null;
+
+        try {
+            if (consume(input, "<entry>", osFeed, false) >= 0) {
+                entry.write("<entry ".getBytes(ODataConstants.UTF8));
+                entry.write(namespaces.getBytes(ODataConstants.UTF8));
+                entry.write(">".getBytes(ODataConstants.UTF8));
+
+                if (consume(input, "</entry>", entry, true) >= 0) {
+                    entity = odataClient.getDeserializer().
+                            toEntry(new ByteArrayInputStream(entry.toByteArray()), AtomEntry.class);
+                }
+            }
+        } catch (Exception e) {
+            LOG.error("Error retrieving entities from EntitySet", e);
+        }
+
+        return entity;
+    }
+
+    private String getAllElementAttributes(final InputStream input, final String name, final OutputStream os) {
+        final ByteArrayOutputStream attrs = new ByteArrayOutputStream();
+
+        String res;
+
+        try {
+            byte[] attrsDeclaration = null;
+
+            final String key = "<" + name + " ";
+            if (consume(input, key, os, true) >= 0 && consume(input, ">", attrs, false) >= 0) {
+                attrsDeclaration = attrs.toByteArray();
+                os.write(attrsDeclaration);
+                os.write('>');
+            }
+
+            res = attrsDeclaration == null
+                    ? StringUtils.EMPTY
+                    : new String(attrsDeclaration, ODataConstants.UTF8).trim();
+        } catch (Exception e) {
+            LOG.error("Error retrieving entities from EntitySet", e);
+            res = StringUtils.EMPTY;
+        }
+
+        return res.endsWith("/") ? res.substring(0, res.length() - 1) : res;
+    }
+
+    private int consume(
+            final InputStream input, final String end, final OutputStream os, final boolean includeEndKey)
+            throws IOException {
+
+        final char[] endKey = end.toCharArray();
+        final char[] endLowerKey = end.toLowerCase().toCharArray();
+        final char[] endUpperKey = end.toUpperCase().toCharArray();
+
+        int pos = 0;
+        int c = 0;
+        while (pos < endKey.length && (c = input.read()) >= 0) {
+            if (c == endLowerKey[pos] || c == endUpperKey[pos]) {
+                pos++;
+                if (includeEndKey && os != null) {
+                    os.write(c);
+                }
+            } else if (pos > 0) {
+                if (!includeEndKey && os != null) {
+                    for (int i = 0; i < pos; i++) {
+                        os.write(endKey[i]);
+                    }
+                }
+                if (os != null) {
+                    os.write(c);
+                }
+                pos = 0;
+            } else {
+                if (os != null) {
+                    os.write(c);
+                }
+            }
+        }
+
+        return c;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/7baecb90/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataError.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataError.java b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataError.java
new file mode 100644
index 0000000..3e1726b
--- /dev/null
+++ b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataError.java
@@ -0,0 +1,68 @@
+/**
+ * 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.data;
+
+/**
+ * OData error.
+ */
+public interface ODataError {
+
+    /**
+     * Gets error code.
+     *
+     * @return error code.
+     */
+    String getCode();
+
+    /**
+     * Gets error message language.
+     *
+     * @return error message language.
+     */
+    String getMessageLang();
+
+    /**
+     * Gets error message.
+     *
+     * @return error message.
+     */
+    String getMessageValue();
+
+    /**
+     * Gets inner error message.
+     *
+     * @return inner error message.
+     */
+    String getInnerErrorMessage();
+
+    /**
+     * Gets inner error type.
+     *
+     * @return inner error type.
+     */
+    String getInnerErrorType();
+
+    /**
+     * Gets inner error stack-trace.
+     *
+     * @return inner error stack-trace
+     */
+    String getInnerErrorStacktrace();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/7baecb90/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataGeospatialValue.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataGeospatialValue.java b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataGeospatialValue.java
new file mode 100644
index 0000000..ba58047
--- /dev/null
+++ b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataGeospatialValue.java
@@ -0,0 +1,489 @@
+/**
+ * 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.data;
+
+import com.msopentech.odatajclient.engine.client.ODataClient;
+import com.msopentech.odatajclient.engine.metadata.edm.EdmSimpleType;
+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.Point;
+import com.msopentech.odatajclient.engine.metadata.edm.geospatial.Polygon;
+import com.msopentech.odatajclient.engine.utils.ODataConstants;
+import com.msopentech.odatajclient.engine.utils.XMLUtils;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.ParserConfigurationException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class ODataGeospatialValue extends ODataPrimitiveValue {
+
+    private static final long serialVersionUID = -3984105137562291082L;
+
+    /**
+     * Geospatial value builder.
+     */
+    public static class Builder extends AbstractBuilder {
+
+        private final ODataGeospatialValue ogv;
+
+        /**
+         * Constructor.
+         */
+        public Builder(final ODataClient client) {
+            super(client);
+            this.ogv = new ODataGeospatialValue(client);
+        }
+
+        /**
+         * Sets the given value provided as a DOM tree.
+         *
+         * @param tree value.
+         * @return the current builder.
+         */
+        public Builder setTree(final Element tree) {
+            this.ogv.tree = tree;
+            return this;
+        }
+
+        /**
+         * Sets the actual object value.
+         *
+         * @param value value.
+         * @return the current builder.
+         */
+        public <T extends Geospatial> Builder setValue(final T value) {
+            this.ogv.value = value;
+            return this;
+        }
+
+        /**
+         * Sets actual value type.
+         *
+         * @param type type.
+         * @return the current builder.
+         */
+        public Builder setType(final EdmSimpleType type) {
+            isSupported(type);
+
+            if (!type.isGeospatial()) {
+                throw new IllegalArgumentException(
+                        "Use " + ODataPrimitiveValue.class.getSimpleName() + " for non-geospatial types");
+            }
+
+            if (type == EdmSimpleType.Geography || type == EdmSimpleType.Geometry) {
+                throw new IllegalArgumentException(
+                        type + "is not an instantiable type. "
+                        + "An entity can declare a property to be of type Geometry. "
+                        + "An instance of an entity MUST NOT have a value of type Geometry. "
+                        + "Each value MUST be of some subtype.");
+            }
+            this.ogv.type = type;
+            return this;
+        }
+
+        /**
+         * Builds the geospatial value.
+         *
+         * @return <tt>ODataGeospatialValue</tt> object.
+         */
+        public ODataGeospatialValue build() {
+            if (this.ogv.tree == null && this.ogv.value == null) {
+                throw new IllegalArgumentException("Must provide either tree or value");
+            }
+            if (this.ogv.tree != null && this.ogv.value != null) {
+                throw new IllegalArgumentException("Cannot provide both tree and value");
+            }
+
+            if (this.ogv.type == null) {
+                throw new IllegalArgumentException("Must provide geospatial type");
+            }
+
+            if (this.ogv.tree != null) {
+                this.ogv.value = this.ogv.parseTree(this.ogv.tree, this.ogv.type);
+            }
+            if (this.ogv.value != null) {
+                this.ogv.tree = this.ogv.parseGeospatial((Geospatial) this.ogv.value);
+            }
+
+            return this.ogv;
+        }
+    }
+
+    /**
+     * DOM tree.
+     */
+    private Element tree;
+
+    /**
+     * Protected constructor, need to use the builder to instantiate this class.
+     *
+     * @see Builder
+     */
+    protected ODataGeospatialValue(final ODataClient client) {
+        super(client);
+    }
+
+    private Geospatial.Dimension getDimension() {
+        Geospatial.Dimension dimension;
+
+        switch (this.type) {
+            case Geography:
+            case GeographyCollection:
+            case GeographyLineString:
+            case GeographyMultiLineString:
+            case GeographyPoint:
+            case GeographyMultiPoint:
+            case GeographyPolygon:
+            case GeographyMultiPolygon:
+                dimension = Geospatial.Dimension.GEOGRAPHY;
+                break;
+
+            default:
+                dimension = Geospatial.Dimension.GEOMETRY;
+        }
+
+        return dimension;
+    }
+
+    private List<Point> parsePoints(final NodeList posList) {
+        final List<Point> result = new ArrayList<Point>();
+        for (int i = 0; i < posList.getLength(); i++) {
+            final String[] pointInfo = posList.item(i).getTextContent().split(" ");
+            final Point point = new Point(getDimension());
+            point.setX(Double.valueOf(pointInfo[0]));
+            point.setY(Double.valueOf(pointInfo[1]));
+
+            result.add(point);
+        }
+        return result;
+    }
+
+    private LineString parseLineString(final Element element) {
+        return new LineString(getDimension(),
+                parsePoints(element.getElementsByTagName(ODataConstants.ELEM_POS)));
+    }
+
+    private Polygon parsePolygon(final Element element) {
+        List<Point> extPoints = null;
+        final Element exterior =
+                (Element) element.getElementsByTagName(ODataConstants.ELEM_POLYGON_EXTERIOR).item(0);
+        if (exterior != null) {
+            extPoints = parsePoints(
+                    ((Element) exterior.getElementsByTagName(ODataConstants.ELEM_POLYGON_LINEARRING).item(0)).
+                    getElementsByTagName(ODataConstants.ELEM_POS));
+        }
+        List<Point> intPoints = null;
+        final Element interior =
+                (Element) element.getElementsByTagName(ODataConstants.ELEM_POLYGON_INTERIOR).item(0);
+        if (interior != null) {
+            intPoints = parsePoints(
+                    ((Element) interior.getElementsByTagName(ODataConstants.ELEM_POLYGON_LINEARRING).item(0)).
+                    getElementsByTagName(ODataConstants.ELEM_POS));
+        }
+
+        return new Polygon(getDimension(), intPoints, extPoints);
+    }
+
+    /**
+     * Parses given tree as geospatial value.
+     */
+    private Geospatial parseTree(final Element tree, final EdmSimpleType type) {
+        Geospatial value;
+
+        switch (type) {
+            case GeographyPoint:
+            case GeometryPoint:
+                value = parsePoints(tree.getElementsByTagName(ODataConstants.ELEM_POS)).get(0);
+                break;
+
+            case GeographyMultiPoint:
+            case GeometryMultiPoint:
+                final Element pMembs =
+                        (Element) tree.getElementsByTagName(ODataConstants.ELEM_POINTMEMBERS).item(0);
+                final List<Point> points = pMembs == null
+                        ? Collections.<Point>emptyList()
+                        : parsePoints(pMembs.getElementsByTagName(ODataConstants.ELEM_POS));
+                value = new MultiPoint(getDimension(), points);
+                break;
+
+            case GeographyLineString:
+            case GeometryLineString:
+                value = parseLineString(tree);
+                break;
+
+            case GeographyMultiLineString:
+            case GeometryMultiLineString:
+                final Element mlMembs =
+                        (Element) tree.getElementsByTagName(ODataConstants.ELEM_LINESTRINGMEMBERS).item(0);
+                final List<LineString> lineStrings;
+                if (mlMembs == null) {
+                    lineStrings = Collections.<LineString>emptyList();
+                } else {
+                    lineStrings = new ArrayList<LineString>();
+                    final NodeList lineStringNodes = mlMembs.getElementsByTagName(ODataConstants.ELEM_LINESTRING);
+                    for (int i = 0; i < lineStringNodes.getLength(); i++) {
+                        lineStrings.add(parseLineString((Element) lineStringNodes.item(i)));
+                    }
+                }
+                value = new MultiLineString(getDimension(), lineStrings);
+                break;
+
+            case GeographyPolygon:
+            case GeometryPolygon:
+                value = parsePolygon(tree);
+                break;
+
+            case GeographyMultiPolygon:
+            case GeometryMultiPolygon:
+                final Element mpMembs =
+                        (Element) tree.getElementsByTagName(ODataConstants.ELEM_SURFACEMEMBERS).item(0);
+                final List<Polygon> polygons;
+                if (mpMembs == null) {
+                    polygons = Collections.<Polygon>emptyList();
+                } else {
+                    polygons = new ArrayList<Polygon>();
+                    final NodeList polygonNodes = mpMembs.getElementsByTagName(ODataConstants.ELEM_POLYGON);
+                    for (int i = 0; i < polygonNodes.getLength(); i++) {
+                        polygons.add(parsePolygon((Element) polygonNodes.item(i)));
+                    }
+                }
+                value = new MultiPolygon(getDimension(), polygons);
+                break;
+
+            case GeographyCollection:
+            case GeometryCollection:
+                final Element cMembs =
+                        (Element) tree.getElementsByTagName(ODataConstants.ELEM_GEOMEMBERS).item(0);
+                final List<Geospatial> geospatials;
+                if (cMembs == null) {
+                    geospatials = Collections.<Geospatial>emptyList();
+                } else {
+                    geospatials = new ArrayList<Geospatial>();
+                    for (Node geom : XMLUtils.getChildNodes(cMembs, Node.ELEMENT_NODE)) {
+                        geospatials.add(
+                                parseTree((Element) geom, XMLUtils.simpleTypeForNode(getDimension(), geom)));
+                    }
+                }
+                value = new GeospatialCollection(getDimension(), geospatials);
+                break;
+
+            default:
+                value = null;
+        }
+
+        return value;
+    }
+
+    private void parsePoints(final Element parent, final Iterator<Point> itor, final boolean wrap) {
+        while (itor.hasNext()) {
+            final Point point = itor.next();
+
+            final Element pos = parent.getOwnerDocument().
+                    createElementNS(ODataConstants.NS_GML, ODataConstants.ELEM_POS);
+            pos.appendChild(parent.getOwnerDocument().createTextNode(
+                    Double.toString(point.getX()) + " " + point.getY()));
+
+            final Element appendable;
+            if (wrap) {
+                final Element epoint = parent.getOwnerDocument().
+                        createElementNS(ODataConstants.NS_GML, ODataConstants.ELEM_POINT);
+                parent.appendChild(epoint);
+                appendable = epoint;
+            } else {
+                appendable = parent;
+            }
+            appendable.appendChild(pos);
+        }
+    }
+
+    private void parseLineStrings(final Element parent, final Iterator<LineString> itor, final boolean wrap) {
+        while (itor.hasNext()) {
+            final LineString lineString = itor.next();
+
+            final Element appendable;
+            if (wrap) {
+                final Element eLineString = parent.getOwnerDocument().
+                        createElementNS(ODataConstants.NS_GML, ODataConstants.ELEM_LINESTRING);
+                parent.appendChild(eLineString);
+                appendable = eLineString;
+            } else {
+                appendable = parent;
+            }
+            parsePoints(appendable, lineString.iterator(), false);
+        }
+    }
+
+    private void parsePolygons(final Element parent, final Iterator<Polygon> itor, final boolean wrap) {
+        while (itor.hasNext()) {
+            final Polygon polygon = itor.next();
+
+            final Element appendable;
+            if (wrap) {
+                final Element ePolygon = parent.getOwnerDocument().createElementNS(
+                        ODataConstants.NS_GML, ODataConstants.ELEM_POLYGON);
+                parent.appendChild(ePolygon);
+                appendable = ePolygon;
+            } else {
+                appendable = parent;
+            }
+
+            if (!polygon.getExterior().isEmpty()) {
+                final Element exterior = parent.getOwnerDocument().createElementNS(
+                        ODataConstants.NS_GML, ODataConstants.ELEM_POLYGON_EXTERIOR);
+                appendable.appendChild(exterior);
+                final Element linearRing = parent.getOwnerDocument().createElementNS(
+                        ODataConstants.NS_GML, ODataConstants.ELEM_POLYGON_LINEARRING);
+                exterior.appendChild(linearRing);
+
+                parsePoints(linearRing, polygon.getExterior().iterator(), false);
+            }
+            if (!polygon.getInterior().isEmpty()) {
+                final Element interior = parent.getOwnerDocument().createElementNS(
+                        ODataConstants.NS_GML, ODataConstants.ELEM_POLYGON_INTERIOR);
+                appendable.appendChild(interior);
+                final Element linearRing = parent.getOwnerDocument().createElementNS(
+                        ODataConstants.NS_GML, ODataConstants.ELEM_POLYGON_LINEARRING);
+                interior.appendChild(linearRing);
+
+                parsePoints(linearRing, polygon.getInterior().iterator(), false);
+            }
+        }
+    }
+
+    private Element parseGeospatial(final Geospatial value) {
+        final DocumentBuilder builder;
+        try {
+            builder = XMLUtils.DOC_BUILDER_FACTORY.newDocumentBuilder();
+        } catch (ParserConfigurationException e) {
+            throw new IllegalStateException("Failure initializing Geospatial DOM tree", e);
+        }
+        final Document doc = builder.newDocument();
+
+        final Element tree;
+
+        switch (value.getEdmSimpleType()) {
+            case GeographyPoint:
+            case GeometryPoint:
+                tree = doc.createElementNS(ODataConstants.NS_GML, ODataConstants.ELEM_POINT);
+
+                parsePoints(tree, Collections.singleton((Point) value).iterator(), false);
+                break;
+
+            case GeometryMultiPoint:
+            case GeographyMultiPoint:
+                tree = doc.createElementNS(ODataConstants.NS_GML, ODataConstants.ELEM_MULTIPOINT);
+
+                final Element pMembs = doc.createElementNS(ODataConstants.NS_GML, ODataConstants.ELEM_POINTMEMBERS);
+                tree.appendChild(pMembs);
+
+                parsePoints(pMembs, ((MultiPoint) value).iterator(), true);
+                break;
+
+            case GeometryLineString:
+            case GeographyLineString:
+                tree = doc.createElementNS(ODataConstants.NS_GML, ODataConstants.ELEM_LINESTRING);
+
+                parseLineStrings(tree, Collections.singleton((LineString) value).iterator(), false);
+                break;
+
+            case GeometryMultiLineString:
+            case GeographyMultiLineString:
+                tree = doc.createElementNS(ODataConstants.NS_GML, ODataConstants.ELEM_MULTILINESTRING);
+
+                final Element mlMembs =
+                        doc.createElementNS(ODataConstants.NS_GML, ODataConstants.ELEM_LINESTRINGMEMBERS);
+                tree.appendChild(mlMembs);
+
+                parseLineStrings(mlMembs, ((MultiLineString) value).iterator(), true);
+                break;
+
+            case GeographyPolygon:
+            case GeometryPolygon:
+                tree = doc.createElementNS(ODataConstants.NS_GML, ODataConstants.ELEM_POLYGON);
+                parsePolygons(tree, Collections.singleton(((Polygon) value)).iterator(), false);
+                break;
+
+            case GeographyMultiPolygon:
+            case GeometryMultiPolygon:
+                tree = doc.createElementNS(ODataConstants.NS_GML, ODataConstants.ELEM_MULTIPOLYGON);
+
+                final Element mpMembs =
+                        doc.createElementNS(ODataConstants.NS_GML, ODataConstants.ELEM_SURFACEMEMBERS);
+                tree.appendChild(mpMembs);
+
+                parsePolygons(mpMembs, ((MultiPolygon) value).iterator(), true);
+                break;
+
+            case GeographyCollection:
+            case GeometryCollection:
+                tree = doc.createElementNS(ODataConstants.NS_GML, ODataConstants.ELEM_GEOCOLLECTION);
+
+                final Element gMembs =
+                        doc.createElementNS(ODataConstants.NS_GML, ODataConstants.ELEM_GEOMEMBERS);
+                tree.appendChild(gMembs);
+
+                final Iterator<Geospatial> itor = ((GeospatialCollection) value).iterator();
+                while (itor.hasNext()) {
+                    final Geospatial geospatial = itor.next();
+                    gMembs.appendChild(doc.importNode(parseGeospatial(geospatial), true));
+                }
+                break;
+
+            default:
+                tree = null;
+        }
+
+        return tree;
+    }
+
+    public Element toTree() {
+        return this.tree;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final ODataGeospatialValue other = (ODataGeospatialValue) obj;
+        return this.tree.isEqualNode(other.tree);
+    }
+
+    @Override
+    public String toString() {
+        final StringWriter writer = new StringWriter();
+        client.getSerializer().dom(this.tree, writer);
+        return writer.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/7baecb90/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataInlineEntity.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataInlineEntity.java b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataInlineEntity.java
new file mode 100644
index 0000000..e4b2133
--- /dev/null
+++ b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataInlineEntity.java
@@ -0,0 +1,73 @@
+/**
+ * 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.data;
+
+import com.msopentech.odatajclient.engine.client.ODataClient;
+import java.net.URI;
+
+/**
+ * OData in-line entity.
+ */
+public class ODataInlineEntity extends ODataLink {
+
+    private static final long serialVersionUID = -4763341581843700743L;
+
+    private final ODataEntity entity;
+
+    /**
+     * Constructor.
+     *
+     * @param uri edit link.
+     * @param type type.
+     * @param title title.
+     * @param entity entity.
+     */
+    ODataInlineEntity(final ODataClient client,
+            final URI uri, final ODataLinkType type, final String title, final ODataEntity entity) {
+
+        super(client, uri, type, title);
+        this.entity = entity;
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param baseURI base URI.
+     * @param href href.
+     * @param type type.
+     * @param title title.
+     * @param entity entity.
+     */
+    ODataInlineEntity(final ODataClient client, final URI baseURI, final String href, final ODataLinkType type,
+            final String title, final ODataEntity entity) {
+
+        super(client, baseURI, href, type, title);
+        this.entity = entity;
+    }
+
+    /**
+     * Gets wrapped entity.
+     *
+     * @return wrapped entity.
+     */
+    public ODataEntity getEntity() {
+        return entity;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/7baecb90/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataInlineEntitySet.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataInlineEntitySet.java b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataInlineEntitySet.java
new file mode 100644
index 0000000..5582580
--- /dev/null
+++ b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataInlineEntitySet.java
@@ -0,0 +1,75 @@
+/**
+ * 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.data;
+
+import com.msopentech.odatajclient.engine.client.ODataClient;
+import java.net.URI;
+
+/**
+ * OData in-line entity set.
+ */
+public class ODataInlineEntitySet extends ODataLink {
+
+    private static final long serialVersionUID = -77628001615355449L;
+
+    private ODataEntitySet entitySet;
+
+    /**
+     * Constructor.
+     *
+     * @param client OData client.
+     * @param uri edit link.
+     * @param type type.
+     * @param title title.
+     * @param entitySet entity set.
+     */
+    ODataInlineEntitySet(final ODataClient client, final URI uri, final ODataLinkType type, final String title,
+            final ODataEntitySet entitySet) {
+
+        super(client, uri, type, title);
+        this.entitySet = entitySet;
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param client OData client.
+     * @param baseURI base URI.
+     * @param href href.
+     * @param type type.
+     * @param title title.
+     * @param entitySet entity set.
+     */
+    ODataInlineEntitySet(final ODataClient client, final URI baseURI, final String href, final ODataLinkType type,
+            final String title, final ODataEntitySet entitySet) {
+
+        super(client, baseURI, href, type, title);
+        this.entitySet = entitySet;
+    }
+
+    /**
+     * Gets wrapped entity set.
+     *
+     * @return wrapped entity set.
+     */
+    public ODataEntitySet getEntitySet() {
+        return entitySet;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/7baecb90/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataInvokeResult.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataInvokeResult.java b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataInvokeResult.java
new file mode 100644
index 0000000..a2501df
--- /dev/null
+++ b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataInvokeResult.java
@@ -0,0 +1,31 @@
+/**
+ * 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.data;
+
+/**
+ * Marker interface for any OData domain object that can be returned by an operation invocation.
+ *
+ * @see ODataEntitySet
+ * @see ODataEntity
+ * @see ODataProperty
+ * @see ODataNoContent
+ */
+public interface ODataInvokeResult {
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/7baecb90/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataItem.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataItem.java b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataItem.java
new file mode 100644
index 0000000..0b2a891
--- /dev/null
+++ b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataItem.java
@@ -0,0 +1,112 @@
+/**
+ * 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.data;
+
+import java.io.Serializable;
+import java.net.URI;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Abstract representation of OData entities and links.
+ */
+public abstract class ODataItem implements Serializable {
+
+    private static final long serialVersionUID = -2600707722689304686L;
+
+    /**
+     * Logger.
+     */
+    protected static final Logger LOG = LoggerFactory.getLogger(ODataItem.class);
+
+    /**
+     * OData item self link.
+     */
+    protected URI link;
+
+    /**
+     * OData entity name/type.
+     */
+    private final String name;
+
+    /**
+     * Constructor.
+     *
+     * @param name OData entity name.
+     */
+    public ODataItem(final String name) {
+        this.name = name;
+    }
+
+    /**
+     * Returns self link.
+     *
+     * @return entity edit link.
+     */
+    public URI getLink() {
+        return link;
+    }
+
+    /**
+     * Sets self link.
+     *
+     * @param link link.
+     */
+    public void setLink(final URI link) {
+        this.link = link;
+    }
+
+    /**
+     * Returns OData entity name.
+     *
+     * @return entity name.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * {@inheritDoc }
+     */
+    @Override
+    public boolean equals(final Object obj) {
+        return EqualsBuilder.reflectionEquals(this, obj);
+    }
+
+    /**
+     * {@inheritDoc }
+     */
+    @Override
+    public int hashCode() {
+        return HashCodeBuilder.reflectionHashCode(this);
+    }
+
+    /**
+     * {@inheritDoc }
+     */
+    @Override
+    public String toString() {
+        return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/7baecb90/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataLink.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataLink.java b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataLink.java
new file mode 100644
index 0000000..770d39d
--- /dev/null
+++ b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataLink.java
@@ -0,0 +1,110 @@
+/**
+ * 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.data;
+
+import com.msopentech.odatajclient.engine.client.ODataClient;
+import com.msopentech.odatajclient.engine.utils.ODataVersion;
+import com.msopentech.odatajclient.engine.utils.URIUtils;
+import java.net.URI;
+
+/**
+ * OData link.
+ */
+public class ODataLink extends ODataItem {
+
+    private static final long serialVersionUID = 7274966414277952124L;
+
+    protected final ODataClient client;
+
+    /**
+     * Link type.
+     */
+    protected final ODataLinkType type;
+
+    /**
+     * Link rel.
+     */
+    protected final String rel;
+
+    /**
+     * Constructor.
+     *
+     * @param client OData client.
+     * @param uri URI.
+     * @param type type.
+     * @param title title.
+     */
+    ODataLink(final ODataClient client, final URI uri, final ODataLinkType type, final String title) {
+        super(title);
+        this.client = client;
+        this.link = uri;
+
+        this.type = type;
+
+        switch (this.type) {
+            case ASSOCIATION:
+                this.rel = client.getWorkingVersion().getNamespaceMap().get(ODataVersion.ASSOCIATION_LINK_REL) + title;
+                break;
+
+            case ENTITY_NAVIGATION:
+            case ENTITY_SET_NAVIGATION:
+                this.rel = client.getWorkingVersion().getNamespaceMap().get(ODataVersion.NAVIGATION_LINK_REL) + title;
+                break;
+
+            case MEDIA_EDIT:
+            default:
+                this.rel = client.getWorkingVersion().getNamespaceMap().get(ODataVersion.MEDIA_EDIT_LINK_REL) + title;
+                break;
+        }
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param client OData client.
+     * @param baseURI base URI.
+     * @param href href.
+     * @param type type.
+     * @param title title.
+     */
+    ODataLink(
+            final ODataClient client, final URI baseURI, final String href, final ODataLinkType type, final String title) {
+
+        this(client, URIUtils.getURI(baseURI, href), type, title);
+    }
+
+    /**
+     * Gets link type.
+     *
+     * @return link type;
+     */
+    public ODataLinkType getType() {
+        return type;
+    }
+
+    /**
+     * Gets link rel.
+     *
+     * @return link rel
+     */
+    public String getRel() {
+        return rel;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/7baecb90/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataLinkCollection.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataLinkCollection.java b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataLinkCollection.java
new file mode 100644
index 0000000..abd6a68
--- /dev/null
+++ b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataLinkCollection.java
@@ -0,0 +1,101 @@
+/**
+ * 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.data;
+
+import java.net.URI;
+import java.util.List;
+
+/**
+ * Link collection wrapper.
+ */
+public class ODataLinkCollection {
+
+    /**
+     * Link to the next page.
+     */
+    private URI next;
+
+    /**
+     * Contained links.
+     */
+    private List<URI> links;
+
+    /**
+     * Constructor.
+     */
+    public ODataLinkCollection() {
+    }
+
+    /**
+     * Adds link to the collection.
+     *
+     * @param link link to be added.
+     * @return 'TRUE' in case of success; 'FALSE' otherwise.
+     */
+    public boolean addLink(final URI link) {
+        return links.add(link);
+    }
+
+    /**
+     * Removes a link.
+     *
+     * @param link link to be removed.
+     * @return 'TRUE' in case of success; 'FALSE' otherwise.
+     */
+    public boolean removeLink(final URI link) {
+        return links.remove(link);
+    }
+
+    /**
+     * Set links.
+     *
+     * @param links links.
+     */
+    public void setLinks(final List<URI> links) {
+        this.links = links;
+    }
+
+    /**
+     * Gets contained links.
+     *
+     * @return list of links.
+     */
+    public List<URI> getLinks() {
+        return links;
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param next next page link.
+     */
+    public ODataLinkCollection(final URI next) {
+        this.next = next;
+    }
+
+    /**
+     * Gets next page link.
+     *
+     * @return next page link; null value if single page or last page reached.
+     */
+    public URI getNext() {
+        return next;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/7baecb90/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataLinkType.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataLinkType.java b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataLinkType.java
new file mode 100644
index 0000000..a424e0f
--- /dev/null
+++ b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataLinkType.java
@@ -0,0 +1,99 @@
+/**
+ * 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.data;
+
+import com.msopentech.odatajclient.engine.client.ODataClient;
+import com.msopentech.odatajclient.engine.format.ODataPubFormat;
+import com.msopentech.odatajclient.engine.utils.ODataVersion;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.entity.ContentType;
+
+/**
+ * OData link types.
+ */
+public enum ODataLinkType {
+
+    /**
+     * Entity navigation link.
+     */
+    ENTITY_NAVIGATION(ODataPubFormat.ATOM + ";type=entry"),
+    /**
+     * Entity set navigation link.
+     */
+    ENTITY_SET_NAVIGATION(ODataPubFormat.ATOM + ";type=feed"),
+    /**
+     * Association link.
+     */
+    ASSOCIATION(ContentType.APPLICATION_XML.getMimeType()),
+    /**
+     * Media-edit link.
+     */
+    MEDIA_EDIT("*/*");
+
+    private String type;
+
+    private ODataLinkType(final String type) {
+        this.type = type;
+    }
+
+    private ODataLinkType setType(final String type) {
+        this.type = type;
+        return this;
+    }
+
+    /**
+     * Gets
+     * <code>ODataLinkType</code> instance from the given rel and type.
+     *
+     * @param client OData client.
+     * @param rel rel.
+     * @param type type.
+     * @return <code>ODataLinkType</code> object.
+     */
+    public static ODataLinkType fromString(final ODataClient client, final String rel, final String type) {
+        if (StringUtils.isNotBlank(rel)
+                && rel.startsWith(client.getWorkingVersion().getNamespaceMap().get(ODataVersion.MEDIA_EDIT_LINK_REL))) {
+
+            return MEDIA_EDIT.setType(StringUtils.isBlank(type) ? "*/*" : type);
+        }
+
+        if (ODataLinkType.ENTITY_NAVIGATION.type.equals(type)) {
+            return ENTITY_NAVIGATION;
+        }
+
+        if (ODataLinkType.ENTITY_SET_NAVIGATION.type.equals(type)) {
+            return ENTITY_SET_NAVIGATION;
+        }
+
+        if (ODataLinkType.ASSOCIATION.type.equals(type)) {
+            return ASSOCIATION;
+        }
+
+        throw new IllegalArgumentException("Invalid link type: " + type);
+    }
+
+    /**
+     * {@inheritDoc }
+     */
+    @Override
+    public String toString() {
+        return type;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/7baecb90/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataNoContent.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataNoContent.java b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataNoContent.java
new file mode 100644
index 0000000..254c8f4
--- /dev/null
+++ b/ODataJClient/engine/src/main/java/com/msopentech/odatajclient/engine/data/ODataNoContent.java
@@ -0,0 +1,31 @@
+/**
+ * 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.data;
+
+import java.io.Serializable;
+
+/**
+ * Marker class for invoke with no return type.
+ */
+public class ODataNoContent implements Serializable, ODataInvokeResult {
+
+    private static final long serialVersionUID = 2780193571934253136L;
+
+}