You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by il...@apache.org on 2014/04/28 17:00:41 UTC

[2/5] [OLINGO-259] Delta response content parsing (including new domain objects)

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/118b779b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomDeserializer.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomDeserializer.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomDeserializer.java
index 72d8d76..080b4aa 100644
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomDeserializer.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomDeserializer.java
@@ -18,7 +18,6 @@
  */
 package org.apache.olingo.commons.core.data;
 
-import org.apache.olingo.commons.api.data.ResWrap;
 import java.io.InputStream;
 import java.net.URI;
 import java.text.ParseException;
@@ -32,6 +31,8 @@ import javax.xml.stream.events.XMLEvent;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.olingo.commons.api.Constants;
 import org.apache.olingo.commons.api.data.CollectionValue;
+import org.apache.olingo.commons.api.data.EntitySet;
+import org.apache.olingo.commons.api.data.ResWrap;
 import org.apache.olingo.commons.api.data.Value;
 import org.apache.olingo.commons.api.domain.ODataOperation;
 import org.apache.olingo.commons.api.domain.ODataPropertyType;
@@ -228,7 +229,7 @@ public class AtomDeserializer extends AbstractAtomDealer {
 
     final AtomPropertyImpl property = new AtomPropertyImpl();
 
-    if (ODataServiceVersion.V40 == version && v4PropertyValueQName.equals(start.getName())) {
+    if (ODataServiceVersion.V40 == version && propertyValueQName.equals(start.getName())) {
       // retrieve name from context
       final Attribute context = start.getAttributeByName(contextQName);
       if (context != null) {
@@ -352,10 +353,10 @@ public class AtomDeserializer extends AbstractAtomDealer {
         }
         if (inline != null) {
           if (Constants.QNAME_ATOM_ELEM_ENTRY.equals(inline.getName())) {
-            link.setInlineEntry(entry(reader, inline));
+            link.setInlineEntity(entity(reader, inline));
           }
           if (Constants.QNAME_ATOM_ELEM_FEED.equals(inline.getName())) {
-            link.setInlineFeed(feed(reader, inline));
+            link.setInlineEntitySet(entitySet(reader, inline));
           }
         }
       }
@@ -366,6 +367,102 @@ public class AtomDeserializer extends AbstractAtomDealer {
     }
   }
 
+  private ResWrap<AtomDeltaImpl> delta(final InputStream input) throws XMLStreamException {
+    final XMLEventReader reader = getReader(input);
+    final StartElement start = skipBeforeFirstStartElement(reader);
+    return getContainer(start, delta(reader, start));
+  }
+
+  private AtomDeltaImpl delta(final XMLEventReader reader, final StartElement start) throws XMLStreamException {
+    if (!Constants.QNAME_ATOM_ELEM_FEED.equals(start.getName())) {
+      return null;
+    }
+    final AtomDeltaImpl delta = new AtomDeltaImpl();
+    final Attribute xmlBase = start.getAttributeByName(Constants.QNAME_ATTR_XML_BASE);
+    if (xmlBase != null) {
+      delta.setBaseURI(xmlBase.getValue());
+    }
+
+    boolean foundEndFeed = false;
+    while (reader.hasNext() && !foundEndFeed) {
+      final XMLEvent event = reader.nextEvent();
+      if (event.isStartElement()) {
+        if (countQName.equals(event.asStartElement().getName())) {
+          count(reader, event.asStartElement(), delta);
+        } else if (Constants.QNAME_ATOM_ELEM_ID.equals(event.asStartElement().getName())) {
+          common(reader, event.asStartElement(), delta, "id");
+        } else if (Constants.QNAME_ATOM_ELEM_TITLE.equals(event.asStartElement().getName())) {
+          common(reader, event.asStartElement(), delta, "title");
+        } else if (Constants.QNAME_ATOM_ELEM_SUMMARY.equals(event.asStartElement().getName())) {
+          common(reader, event.asStartElement(), delta, "summary");
+        } else if (Constants.QNAME_ATOM_ELEM_UPDATED.equals(event.asStartElement().getName())) {
+          common(reader, event.asStartElement(), delta, "updated");
+        } else if (Constants.QNAME_ATOM_ELEM_LINK.equals(event.asStartElement().getName())) {
+          final Attribute rel = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATTR_REL));
+          if (rel != null) {
+            if (Constants.NEXT_LINK_REL.equals(rel.getValue())) {
+              final Attribute href = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATTR_HREF));
+              if (href != null) {
+                delta.setNext(URI.create(href.getValue()));
+              }
+            }
+            if (Constants.DELTA_LINK_REL.equals(rel.getValue())) {
+              final Attribute href = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATTR_HREF));
+              if (href != null) {
+                delta.setDeltaLink(URI.create(href.getValue()));
+              }
+            }
+          }
+        } else if (Constants.QNAME_ATOM_ELEM_ENTRY.equals(event.asStartElement().getName())) {
+          delta.getEntities().add(entity(reader, event.asStartElement()));
+        } else if (deletedEntryQName.equals(event.asStartElement().getName())) {
+          final DeletedEntityImpl deletedEntity = new DeletedEntityImpl();
+
+          final Attribute ref = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATTR_REF));
+          if (ref != null) {
+            deletedEntity.setId(ref.getValue());
+          }
+          final Attribute reason = event.asStartElement().getAttributeByName(reasonQName);
+          if (reason != null) {
+            deletedEntity.setReason(reason.getValue());
+          }
+
+          delta.getDeletedEntities().add(deletedEntity);
+        } else if (linkQName.equals(event.asStartElement().getName())
+                || deletedLinkQName.equals(event.asStartElement().getName())) {
+
+          final DeltaLinkImpl link = new DeltaLinkImpl();
+
+          final Attribute source = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATTR_SOURCE));
+          if (source != null) {
+            link.setSource(URI.create(source.getValue()));
+          }
+          final Attribute relationship = 
+                  event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATTR_RELATIONSHIP));
+          if (relationship != null) {
+            link.setRelationship(relationship.getValue());
+          }
+          final Attribute target = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATTR_TARGET));
+          if (target != null) {
+            link.setTarget(URI.create(target.getValue()));
+          }
+
+          if (linkQName.equals(event.asStartElement().getName())) {
+            delta.getAddedLinks().add(link);
+          } else {
+            delta.getDeletedLinks().add(link);
+          }
+        }
+      }
+
+      if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
+        foundEndFeed = true;
+      }
+    }
+
+    return delta;
+  }
+
   private ResWrap<XMLLinkCollectionImpl> linkCollection(final InputStream input) throws XMLStreamException {
     final XMLEventReader reader = getReader(input);
     final StartElement start = skipBeforeFirstStartElement(reader);
@@ -400,14 +497,14 @@ public class AtomDeserializer extends AbstractAtomDealer {
     return linkCollection;
   }
 
-  private void properties(final XMLEventReader reader, final StartElement start, final AtomEntryImpl entry)
+  private void properties(final XMLEventReader reader, final StartElement start, final AtomEntityImpl entity)
           throws XMLStreamException {
     boolean foundEndProperties = false;
     while (reader.hasNext() && !foundEndProperties) {
       final XMLEvent event = reader.nextEvent();
 
       if (event.isStartElement()) {
-        entry.getProperties().add(property(reader, event.asStartElement()));
+        entity.getProperties().add(property(reader, event.asStartElement()));
       }
 
       if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
@@ -416,31 +513,31 @@ public class AtomDeserializer extends AbstractAtomDealer {
     }
   }
 
-  private AtomEntryImpl entryRef(final StartElement start) throws XMLStreamException {
-    final AtomEntryImpl entry = new AtomEntryImpl();
+  private AtomEntityImpl entityRef(final StartElement start) throws XMLStreamException {
+    final AtomEntityImpl entity = new AtomEntityImpl();
 
-    final Attribute entryRefId = start.getAttributeByName(Constants.QNAME_ATOM_ATTR_ID);
-    if (entryRefId != null) {
-      entry.setId(entryRefId.getValue());
+    final Attribute entityRefId = start.getAttributeByName(Constants.QNAME_ATOM_ATTR_ID);
+    if (entityRefId != null) {
+      entity.setId(entityRefId.getValue());
     }
 
-    return entry;
+    return entity;
   }
 
-  private AtomEntryImpl entry(final XMLEventReader reader, final StartElement start) throws XMLStreamException {
-    final AtomEntryImpl entry;
+  private AtomEntityImpl entity(final XMLEventReader reader, final StartElement start) throws XMLStreamException {
+    final AtomEntityImpl entity;
     if (entryRefQName.equals(start.getName())) {
-      entry = entryRef(start);
+      entity = entityRef(start);
     } else if (Constants.QNAME_ATOM_ELEM_ENTRY.equals(start.getName())) {
-      entry = new AtomEntryImpl();
+      entity = new AtomEntityImpl();
       final Attribute xmlBase = start.getAttributeByName(Constants.QNAME_ATTR_XML_BASE);
       if (xmlBase != null) {
-        entry.setBaseURI(xmlBase.getValue());
+        entity.setBaseURI(xmlBase.getValue());
       }
 
       final Attribute etag = start.getAttributeByName(etagQName);
       if (etag != null) {
-        entry.setETag(etag.getValue());
+        entity.setETag(etag.getValue());
       }
 
       boolean foundEndEntry = false;
@@ -449,17 +546,17 @@ public class AtomDeserializer extends AbstractAtomDealer {
 
         if (event.isStartElement()) {
           if (Constants.QNAME_ATOM_ELEM_ID.equals(event.asStartElement().getName())) {
-            common(reader, event.asStartElement(), entry, "id");
+            common(reader, event.asStartElement(), entity, "id");
           } else if (Constants.QNAME_ATOM_ELEM_TITLE.equals(event.asStartElement().getName())) {
-            common(reader, event.asStartElement(), entry, "title");
+            common(reader, event.asStartElement(), entity, "title");
           } else if (Constants.QNAME_ATOM_ELEM_SUMMARY.equals(event.asStartElement().getName())) {
-            common(reader, event.asStartElement(), entry, "summary");
+            common(reader, event.asStartElement(), entity, "summary");
           } else if (Constants.QNAME_ATOM_ELEM_UPDATED.equals(event.asStartElement().getName())) {
-            common(reader, event.asStartElement(), entry, "updated");
+            common(reader, event.asStartElement(), entity, "updated");
           } else if (Constants.QNAME_ATOM_ELEM_CATEGORY.equals(event.asStartElement().getName())) {
             final Attribute term = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATOM_ATTR_TERM));
             if (term != null) {
-              entry.setType(new EdmTypeInfo.Builder().setTypeExpression(term.getValue()).build().internal());
+              entity.setType(new EdmTypeInfo.Builder().setTypeExpression(term.getValue()).build().internal());
             }
           } else if (Constants.QNAME_ATOM_ELEM_LINK.equals(event.asStartElement().getName())) {
             final LinkImpl link = new LinkImpl();
@@ -481,22 +578,22 @@ public class AtomDeserializer extends AbstractAtomDealer {
             }
 
             if (Constants.SELF_LINK_REL.equals(link.getRel())) {
-              entry.setSelfLink(link);
+              entity.setSelfLink(link);
             } else if (Constants.EDIT_LINK_REL.equals(link.getRel())) {
-              entry.setEditLink(link);
+              entity.setEditLink(link);
             } else if (Constants.EDITMEDIA_LINK_REL.equals(link.getRel())) {
               final Attribute mediaETag = event.asStartElement().getAttributeByName(etagQName);
               if (mediaETag != null) {
-                entry.setMediaETag(mediaETag.getValue());
+                entity.setMediaETag(mediaETag.getValue());
               }
             } else if (link.getRel().startsWith(
                     version.getNamespaceMap().get(ODataServiceVersion.NAVIGATION_LINK_REL))) {
-              entry.getNavigationLinks().add(link);
+              entity.getNavigationLinks().add(link);
               inline(reader, event.asStartElement(), link);
             } else if (link.getRel().startsWith(
                     version.getNamespaceMap().get(ODataServiceVersion.ASSOCIATION_LINK_REL))) {
 
-              entry.getAssociationLinks().add(link);
+              entity.getAssociationLinks().add(link);
             } else if (link.getRel().startsWith(
                     version.getNamespaceMap().get(ODataServiceVersion.MEDIA_EDIT_LINK_REL))) {
 
@@ -504,7 +601,7 @@ public class AtomDeserializer extends AbstractAtomDealer {
               if (metag != null) {
                 link.setMediaETag(metag.getValue());
               }
-              entry.getMediaEditLinks().add(link);
+              entity.getMediaEditLinks().add(link);
             }
           } else if (actionQName.equals(event.asStartElement().getName())) {
             final ODataOperation operation = new ODataOperation();
@@ -522,20 +619,20 @@ public class AtomDeserializer extends AbstractAtomDealer {
               operation.setTarget(URI.create(target.getValue()));
             }
 
-            entry.getOperations().add(operation);
+            entity.getOperations().add(operation);
           } else if (Constants.QNAME_ATOM_ELEM_CONTENT.equals(event.asStartElement().getName())) {
             final Attribute type = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATTR_TYPE));
             if (type == null || ContentType.APPLICATION_XML.equals(type.getValue())) {
-              properties(reader, skipBeforeFirstStartElement(reader), entry);
+              properties(reader, skipBeforeFirstStartElement(reader), entity);
             } else {
-              entry.setMediaContentType(type.getValue());
+              entity.setMediaContentType(type.getValue());
               final Attribute src = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATOM_ATTR_SRC));
               if (src != null) {
-                entry.setMediaContentSource(src.getValue());
+                entity.setMediaContentSource(src.getValue());
               }
             }
           } else if (propertiesQName.equals(event.asStartElement().getName())) {
-            properties(reader, event.asStartElement(), entry);
+            properties(reader, event.asStartElement(), entity);
           }
         }
 
@@ -544,21 +641,21 @@ public class AtomDeserializer extends AbstractAtomDealer {
         }
       }
 
-      return entry;
+      return entity;
     } else {
-      entry = null;
+      entity = null;
     }
 
-    return entry;
+    return entity;
   }
 
-  private ResWrap<AtomEntryImpl> entry(final InputStream input) throws XMLStreamException {
+  private ResWrap<AtomEntityImpl> entity(final InputStream input) throws XMLStreamException {
     final XMLEventReader reader = getReader(input);
     final StartElement start = skipBeforeFirstStartElement(reader);
-    return getContainer(start, entry(reader, start));
+    return getContainer(start, entity(reader, start));
   }
 
-  private void count(final XMLEventReader reader, final StartElement start, final AtomFeedImpl feed)
+  private void count(final XMLEventReader reader, final StartElement start, final EntitySet entitySet)
           throws XMLStreamException {
 
     boolean foundEndElement = false;
@@ -566,7 +663,7 @@ public class AtomDeserializer extends AbstractAtomDealer {
       final XMLEvent event = reader.nextEvent();
 
       if (event.isCharacters() && !event.asCharacters().isWhiteSpace()) {
-        feed.setCount(Integer.valueOf(event.asCharacters().getData()));
+        entitySet.setCount(Integer.valueOf(event.asCharacters().getData()));
       }
 
       if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
@@ -575,14 +672,14 @@ public class AtomDeserializer extends AbstractAtomDealer {
     }
   }
 
-  private AtomFeedImpl feed(final XMLEventReader reader, final StartElement start) throws XMLStreamException {
+  private AtomEntitySetImpl entitySet(final XMLEventReader reader, final StartElement start) throws XMLStreamException {
     if (!Constants.QNAME_ATOM_ELEM_FEED.equals(start.getName())) {
       return null;
     }
-    final AtomFeedImpl feed = new AtomFeedImpl();
+    final AtomEntitySetImpl entitySet = new AtomEntitySetImpl();
     final Attribute xmlBase = start.getAttributeByName(Constants.QNAME_ATTR_XML_BASE);
     if (xmlBase != null) {
-      feed.setBaseURI(xmlBase.getValue());
+      entitySet.setBaseURI(xmlBase.getValue());
     }
 
     boolean foundEndFeed = false;
@@ -590,27 +687,27 @@ public class AtomDeserializer extends AbstractAtomDealer {
       final XMLEvent event = reader.nextEvent();
       if (event.isStartElement()) {
         if (countQName.equals(event.asStartElement().getName())) {
-          count(reader, event.asStartElement(), feed);
+          count(reader, event.asStartElement(), entitySet);
         } else if (Constants.QNAME_ATOM_ELEM_ID.equals(event.asStartElement().getName())) {
-          common(reader, event.asStartElement(), feed, "id");
+          common(reader, event.asStartElement(), entitySet, "id");
         } else if (Constants.QNAME_ATOM_ELEM_TITLE.equals(event.asStartElement().getName())) {
-          common(reader, event.asStartElement(), feed, "title");
+          common(reader, event.asStartElement(), entitySet, "title");
         } else if (Constants.QNAME_ATOM_ELEM_SUMMARY.equals(event.asStartElement().getName())) {
-          common(reader, event.asStartElement(), feed, "summary");
+          common(reader, event.asStartElement(), entitySet, "summary");
         } else if (Constants.QNAME_ATOM_ELEM_UPDATED.equals(event.asStartElement().getName())) {
-          common(reader, event.asStartElement(), feed, "updated");
+          common(reader, event.asStartElement(), entitySet, "updated");
         } else if (Constants.QNAME_ATOM_ELEM_LINK.equals(event.asStartElement().getName())) {
           final Attribute rel = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATTR_REL));
           if (rel != null && Constants.NEXT_LINK_REL.equals(rel.getValue())) {
             final Attribute href = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATTR_HREF));
             if (href != null) {
-              feed.setNext(URI.create(href.getValue()));
+              entitySet.setNext(URI.create(href.getValue()));
             }
           }
         } else if (Constants.QNAME_ATOM_ELEM_ENTRY.equals(event.asStartElement().getName())) {
-          feed.getEntries().add(entry(reader, event.asStartElement()));
+          entitySet.getEntities().add(entity(reader, event.asStartElement()));
         } else if (entryRefQName.equals(event.asStartElement().getName())) {
-          feed.getEntries().add(entryRef(event.asStartElement()));
+          entitySet.getEntities().add(entityRef(event.asStartElement()));
         }
       }
 
@@ -619,13 +716,13 @@ public class AtomDeserializer extends AbstractAtomDealer {
       }
     }
 
-    return feed;
+    return entitySet;
   }
 
-  private ResWrap<AtomFeedImpl> feed(final InputStream input) throws XMLStreamException {
+  private ResWrap<AtomEntitySetImpl> entitySet(final InputStream input) throws XMLStreamException {
     final XMLEventReader reader = getReader(input);
     final StartElement start = skipBeforeFirstStartElement(reader);
-    return getContainer(start, feed(reader, start));
+    return getContainer(start, entitySet(reader, start));
   }
 
   private XMLODataErrorImpl error(final XMLEventReader reader, final StartElement start) throws XMLStreamException {
@@ -700,14 +797,16 @@ public class AtomDeserializer extends AbstractAtomDealer {
 
     if (XMLODataErrorImpl.class.equals(reference)) {
       return (ResWrap<T>) error(input);
-    } else if (AtomFeedImpl.class.equals(reference)) {
-      return (ResWrap<T>) feed(input);
-    } else if (AtomEntryImpl.class.equals(reference)) {
-      return (ResWrap<T>) entry(input);
+    } else if (AtomEntitySetImpl.class.equals(reference)) {
+      return (ResWrap<T>) entitySet(input);
+    } else if (AtomEntityImpl.class.equals(reference)) {
+      return (ResWrap<T>) entity(input);
     } else if (AtomPropertyImpl.class.equals(reference)) {
       return (ResWrap<T>) property(input);
     } else if (XMLLinkCollectionImpl.class.equals(reference)) {
       return (ResWrap<T>) linkCollection(input);
+    } else if (AtomDeltaImpl.class.equals(reference)) {
+      return (ResWrap<T>) delta(input);
     }
     return null;
   }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/118b779b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomEntityImpl.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomEntityImpl.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomEntityImpl.java
new file mode 100644
index 0000000..6c7fb13
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomEntityImpl.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.core.data;
+
+public class AtomEntityImpl extends AbstractEntity {
+
+  private static final long serialVersionUID = 6973729343868293279L;
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/118b779b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomEntitySetImpl.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomEntitySetImpl.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomEntitySetImpl.java
new file mode 100644
index 0000000..397b18e
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomEntitySetImpl.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.core.data;
+
+/**
+ * List of entries, represented via Atom.
+ */
+public class AtomEntitySetImpl extends AbstractEntitySet {
+
+  private static final long serialVersionUID = 5466590540021319153L;
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/118b779b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomEntryImpl.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomEntryImpl.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomEntryImpl.java
deleted file mode 100644
index 8eef97a..0000000
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomEntryImpl.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.olingo.commons.core.data;
-
-public class AtomEntryImpl extends AbstractEntry {
-
-  private static final long serialVersionUID = 6973729343868293279L;
-
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/118b779b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomFeedImpl.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomFeedImpl.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomFeedImpl.java
deleted file mode 100644
index 09dfdcf..0000000
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomFeedImpl.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.olingo.commons.core.data;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.olingo.commons.api.data.Entry;
-import org.apache.olingo.commons.api.data.Feed;
-
-/**
- * List of entries, represented via Atom.
- *
- * @see AtomEntry
- */
-public class AtomFeedImpl extends AbstractODataObject implements Feed {
-
-  private static final long serialVersionUID = 5466590540021319153L;
-
-  private Integer count;
-
-  private final List<Entry> entries = new ArrayList<Entry>();
-
-  private URI next;
-
-  @Override
-  public void setCount(final Integer count) {
-    this.count = count;
-  }
-
-  @Override
-  public Integer getCount() {
-    return count;
-  }
-
-  @Override
-  public List<Entry> getEntries() {
-    return entries;
-  }
-
-  @Override
-  public void setNext(final URI next) {
-    this.next = next;
-  }
-
-  @Override
-  public URI getNext() {
-    return next;
-  }
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/118b779b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomSerializer.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomSerializer.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomSerializer.java
index aba3d16..279e3fe 100644
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomSerializer.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomSerializer.java
@@ -29,8 +29,8 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.olingo.commons.api.Constants;
 import org.apache.olingo.commons.api.data.CollectionValue;
 import org.apache.olingo.commons.api.data.ResWrap;
-import org.apache.olingo.commons.api.data.Entry;
-import org.apache.olingo.commons.api.data.Feed;
+import org.apache.olingo.commons.api.data.Entity;
+import org.apache.olingo.commons.api.data.EntitySet;
 import org.apache.olingo.commons.api.data.Link;
 import org.apache.olingo.commons.api.data.Property;
 import org.apache.olingo.commons.api.data.Value;
@@ -166,18 +166,18 @@ public class AtomSerializer extends AbstractAtomDealer {
         writer.writeAttribute(Constants.ATTR_TYPE, link.getType());
       }
 
-      if (link.getInlineEntry() != null || link.getInlineFeed() != null) {
+      if (link.getInlineEntity() != null || link.getInlineEntitySet() != null) {
         writer.writeStartElement(Constants.PREFIX_METADATA, Constants.ATOM_ELEM_INLINE,
                 version.getNamespaceMap().get(ODataServiceVersion.NS_METADATA));
 
-        if (link.getInlineEntry() != null) {
+        if (link.getInlineEntity() != null) {
           writer.writeStartElement(Constants.ATOM_ELEM_ENTRY);
-          entry(writer, link.getInlineEntry());
+          entity(writer, link.getInlineEntity());
           writer.writeEndElement();
         }
-        if (link.getInlineFeed() != null) {
+        if (link.getInlineEntitySet() != null) {
           writer.writeStartElement(Constants.ATOM_ELEM_FEED);
-          feed(writer, link.getInlineFeed());
+          entitySet(writer, link.getInlineEntitySet());
           writer.writeEndElement();
         }
 
@@ -210,51 +210,51 @@ public class AtomSerializer extends AbstractAtomDealer {
     }
   }
 
-  private void entry(final XMLStreamWriter writer, final Entry entry) throws XMLStreamException {
-    if (entry.getBaseURI() != null) {
-      writer.writeAttribute(XMLConstants.XML_NS_URI, Constants.ATTR_XML_BASE, entry.getBaseURI().toASCIIString());
+  private void entity(final XMLStreamWriter writer, final Entity entity) throws XMLStreamException {
+    if (entity.getBaseURI() != null) {
+      writer.writeAttribute(XMLConstants.XML_NS_URI, Constants.ATTR_XML_BASE, entity.getBaseURI().toASCIIString());
     }
 
-    if (serverMode && StringUtils.isNotBlank(entry.getETag())) {
+    if (serverMode && StringUtils.isNotBlank(entity.getETag())) {
       writer.writeAttribute(
               version.getNamespaceMap().get(ODataServiceVersion.NS_METADATA),
-              Constants.ATOM_ATTR_ETAG, entry.getETag());
+              Constants.ATOM_ATTR_ETAG, entity.getETag());
     }
 
-    if (StringUtils.isNotBlank(entry.getId())) {
+    if (StringUtils.isNotBlank(entity.getId())) {
       writer.writeStartElement(Constants.ATOM_ELEM_ID);
-      writer.writeCharacters(entry.getId());
+      writer.writeCharacters(entity.getId());
       writer.writeEndElement();
     }
 
     writer.writeStartElement(Constants.ATOM_ELEM_CATEGORY);
     writer.writeAttribute(Constants.ATOM_ATTR_SCHEME, version.getNamespaceMap().get(ODataServiceVersion.NS_SCHEME));
-    if (StringUtils.isNotBlank(entry.getType())) {
+    if (StringUtils.isNotBlank(entity.getType())) {
       writer.writeAttribute(Constants.ATOM_ATTR_TERM,
-              new EdmTypeInfo.Builder().setTypeExpression(entry.getType()).build().external(version));
+              new EdmTypeInfo.Builder().setTypeExpression(entity.getType()).build().external(version));
     }
     writer.writeEndElement();
 
-    if (entry instanceof AbstractODataObject) {
-      common(writer, (AbstractODataObject) entry);
+    if (entity instanceof AbstractODataObject) {
+      common(writer, (AbstractODataObject) entity);
     }
 
     if (serverMode) {
-      if (entry.getEditLink() != null) {
-        links(writer, Collections.singletonList(entry.getEditLink()));
+      if (entity.getEditLink() != null) {
+        links(writer, Collections.singletonList(entity.getEditLink()));
       }
 
-      if (entry.getSelfLink() != null) {
-        links(writer, Collections.singletonList(entry.getSelfLink()));
+      if (entity.getSelfLink() != null) {
+        links(writer, Collections.singletonList(entity.getSelfLink()));
       }
     }
 
-    links(writer, entry.getAssociationLinks());
-    links(writer, entry.getNavigationLinks());
-    links(writer, entry.getMediaEditLinks());
+    links(writer, entity.getAssociationLinks());
+    links(writer, entity.getNavigationLinks());
+    links(writer, entity.getMediaEditLinks());
 
     if (serverMode) {
-      for (ODataOperation operation : entry.getOperations()) {
+      for (ODataOperation operation : entity.getOperations()) {
         writer.writeStartElement(
                 version.getNamespaceMap().get(ODataServiceVersion.NS_METADATA), Constants.ATOM_ELEM_ACTION);        
         writer.writeAttribute(Constants.ATTR_METADATA, operation.getMetadataAnchor());
@@ -265,51 +265,51 @@ public class AtomSerializer extends AbstractAtomDealer {
     }
 
     writer.writeStartElement(Constants.ATOM_ELEM_CONTENT);
-    if (entry.isMediaEntry()) {
-      if (StringUtils.isNotBlank(entry.getMediaContentType())) {
-        writer.writeAttribute(Constants.ATTR_TYPE, entry.getMediaContentType());
+    if (entity.isMediaEntity()) {
+      if (StringUtils.isNotBlank(entity.getMediaContentType())) {
+        writer.writeAttribute(Constants.ATTR_TYPE, entity.getMediaContentType());
       }
-      if (StringUtils.isNotBlank(entry.getMediaContentSource())) {
-        writer.writeAttribute(Constants.ATOM_ATTR_SRC, entry.getMediaContentSource());
+      if (StringUtils.isNotBlank(entity.getMediaContentSource())) {
+        writer.writeAttribute(Constants.ATOM_ATTR_SRC, entity.getMediaContentSource());
       }
       writer.writeEndElement();
 
       writer.writeStartElement(version.getNamespaceMap().get(ODataServiceVersion.NS_METADATA), Constants.PROPERTIES);
-      properties(writer, entry.getProperties());
+      properties(writer, entity.getProperties());
     } else {
       writer.writeAttribute(Constants.ATTR_TYPE, ContentType.APPLICATION_XML);
       writer.writeStartElement(version.getNamespaceMap().get(ODataServiceVersion.NS_METADATA), Constants.PROPERTIES);
-      properties(writer, entry.getProperties());
+      properties(writer, entity.getProperties());
       writer.writeEndElement();
     }
     writer.writeEndElement();
   }
 
-  private void entryRef(final XMLStreamWriter writer, final Entry entry) throws XMLStreamException {
+  private void entityRef(final XMLStreamWriter writer, final Entity entity) throws XMLStreamException {
     writer.writeStartElement(Constants.ATOM_ELEM_ENTRY_REF);
     writer.writeNamespace(StringUtils.EMPTY, version.getNamespaceMap().get(ODataServiceVersion.NS_METADATA));
-    writer.writeAttribute(Constants.ATOM_ATTR_ID, entry.getId());
+    writer.writeAttribute(Constants.ATOM_ATTR_ID, entity.getId());
   }
 
-  private void entryRef(final XMLStreamWriter writer, final ResWrap<Entry> container) throws XMLStreamException {
+  private void entityRef(final XMLStreamWriter writer, final ResWrap<Entity> container) throws XMLStreamException {
     writer.writeStartElement(Constants.ATOM_ELEM_ENTRY_REF);
     writer.writeNamespace(StringUtils.EMPTY, version.getNamespaceMap().get(ODataServiceVersion.NS_METADATA));
     addContextInfo(writer, container);
     writer.writeAttribute(Constants.ATOM_ATTR_ID, container.getPayload().getId());
   }
 
-  private void entry(final Writer outWriter, final Entry entry) throws XMLStreamException {
+  private void entity(final Writer outWriter, final Entity entity) throws XMLStreamException {
     final XMLStreamWriter writer = FACTORY.createXMLStreamWriter(outWriter);
 
-    if (entry.getType() == null && entry.getProperties().isEmpty()) {
+    if (entity.getType() == null && entity.getProperties().isEmpty()) {
       writer.writeStartDocument();
       writer.setDefaultNamespace(version.getNamespaceMap().get(ODataServiceVersion.NS_METADATA));
 
-      entryRef(writer, entry);
+      entityRef(writer, entity);
     } else {
       startDocument(writer, Constants.ATOM_ELEM_ENTRY);
 
-      entry(writer, entry);
+      entity(writer, entity);
     }
 
     writer.writeEndElement();
@@ -317,22 +317,22 @@ public class AtomSerializer extends AbstractAtomDealer {
     writer.flush();
   }
 
-  private void entry(final Writer outWriter, final ResWrap<Entry> container) throws XMLStreamException {
-    final Entry entry = container.getPayload();
+  private void entity(final Writer outWriter, final ResWrap<Entity> container) throws XMLStreamException {
+    final Entity entity = container.getPayload();
 
     final XMLStreamWriter writer = FACTORY.createXMLStreamWriter(outWriter);
 
-    if (entry.getType() == null && entry.getProperties().isEmpty()) {
+    if (entity.getType() == null && entity.getProperties().isEmpty()) {
       writer.writeStartDocument();
       writer.setDefaultNamespace(version.getNamespaceMap().get(ODataServiceVersion.NS_METADATA));
 
-      entryRef(writer, container);
+      entityRef(writer, container);
     } else {
       startDocument(writer, Constants.ATOM_ELEM_ENTRY);
 
       addContextInfo(writer, container);
 
-      entry(writer, entry);
+      entity(writer, entity);
     }
 
     writer.writeEndElement();
@@ -340,68 +340,68 @@ public class AtomSerializer extends AbstractAtomDealer {
     writer.flush();
   }
 
-  private void feed(final XMLStreamWriter writer, final Feed feed) throws XMLStreamException {
-    if (feed.getBaseURI() != null) {
-      writer.writeAttribute(XMLConstants.XML_NS_URI, Constants.ATTR_XML_BASE, feed.getBaseURI().toASCIIString());
+  private void entitySet(final XMLStreamWriter writer, final EntitySet entitySet) throws XMLStreamException {
+    if (entitySet.getBaseURI() != null) {
+      writer.writeAttribute(XMLConstants.XML_NS_URI, Constants.ATTR_XML_BASE, entitySet.getBaseURI().toASCIIString());
     }
 
-    if (feed.getCount() != null) {
+    if (entitySet.getCount() != null) {
       writer.writeStartElement(
               version.getNamespaceMap().get(ODataServiceVersion.NS_METADATA), Constants.ATOM_ELEM_COUNT);
-      writer.writeCharacters(Integer.toString(feed.getCount()));
+      writer.writeCharacters(Integer.toString(entitySet.getCount()));
       writer.writeEndElement();
     }
 
-    if (StringUtils.isNotBlank(feed.getId())) {
+    if (StringUtils.isNotBlank(entitySet.getId())) {
       writer.writeStartElement(Constants.ATOM_ELEM_ID);
-      writer.writeCharacters(feed.getId());
+      writer.writeCharacters(entitySet.getId());
       writer.writeEndElement();
     }
 
-    if (feed instanceof AbstractODataObject) {
-      common(writer, (AbstractODataObject) feed);
+    if (entitySet instanceof AbstractODataObject) {
+      common(writer, (AbstractODataObject) entitySet);
     }
 
-    for (Entry entry : feed.getEntries()) {
-      if (entry.getType() == null && entry.getProperties().isEmpty()) {
-        entryRef(writer, entry);
+    for (Entity entity : entitySet.getEntities()) {
+      if (entity.getType() == null && entity.getProperties().isEmpty()) {
+        entityRef(writer, entity);
         writer.writeEndElement();
       } else {
         writer.writeStartElement(Constants.ATOM_ELEM_ENTRY);
-        entry(writer, entry);
+        entity(writer, entity);
         writer.writeEndElement();
       }
     }
 
-    if (feed.getNext() != null) {
+    if (entitySet.getNext() != null) {
       final LinkImpl next = new LinkImpl();
       next.setRel(Constants.NEXT_LINK_REL);
-      next.setHref(feed.getNext().toASCIIString());
+      next.setHref(entitySet.getNext().toASCIIString());
 
       links(writer, Collections.<Link>singletonList(next));
     }
   }
 
-  private void feed(final Writer outWriter, final Feed feed) throws XMLStreamException {
+  private void entitySet(final Writer outWriter, final EntitySet entitySet) throws XMLStreamException {
     final XMLStreamWriter writer = FACTORY.createXMLStreamWriter(outWriter);
 
     startDocument(writer, Constants.ATOM_ELEM_FEED);
 
-    feed(writer, feed);
+    entitySet(writer, entitySet);
 
     writer.writeEndElement();
     writer.writeEndDocument();
     writer.flush();
   }
 
-  private void feed(final Writer outWriter, final ResWrap<Feed> feed) throws XMLStreamException {
+  private void entitySet(final Writer outWriter, final ResWrap<EntitySet> entitySet) throws XMLStreamException {
     final XMLStreamWriter writer = FACTORY.createXMLStreamWriter(outWriter);
 
     startDocument(writer, Constants.ATOM_ELEM_FEED);
 
-    addContextInfo(writer, feed);
+    addContextInfo(writer, entitySet);
 
-    feed(writer, feed.getPayload());
+    entitySet(writer, entitySet.getPayload());
 
     writer.writeEndElement();
     writer.writeEndDocument();
@@ -427,10 +427,10 @@ public class AtomSerializer extends AbstractAtomDealer {
   }
 
   public <T> void write(final Writer writer, final T obj) throws XMLStreamException {
-    if (obj instanceof Feed) {
-      feed(writer, (Feed) obj);
-    } else if (obj instanceof Entry) {
-      entry(writer, (Entry) obj);
+    if (obj instanceof EntitySet) {
+      entitySet(writer, (EntitySet) obj);
+    } else if (obj instanceof Entity) {
+      entity(writer, (Entity) obj);
     } else if (obj instanceof Property) {
       property(writer, (Property) obj);
     } else if (obj instanceof Link) {
@@ -442,10 +442,10 @@ public class AtomSerializer extends AbstractAtomDealer {
   public <T> void write(final Writer writer, final ResWrap<T> container) throws XMLStreamException {
     final T obj = container == null ? null : container.getPayload();
 
-    if (obj instanceof Feed) {
-      this.feed(writer, (ResWrap<Feed>) container);
-    } else if (obj instanceof Entry) {
-      entry(writer, (ResWrap<Entry>) container);
+    if (obj instanceof EntitySet) {
+      this.entitySet(writer, (ResWrap<EntitySet>) container);
+    } else if (obj instanceof Entity) {
+      entity(writer, (ResWrap<Entity>) container);
     } else if (obj instanceof Property) {
       property(writer, (Property) obj);
     } else if (obj instanceof Link) {
@@ -458,11 +458,11 @@ public class AtomSerializer extends AbstractAtomDealer {
 
     if (container.getContextURL() != null) {
       String base = container.getContextURL().getServiceRoot().toASCIIString();
-      if (container.getPayload() instanceof AtomFeedImpl) {
-        ((AtomFeedImpl) container.getPayload()).setBaseURI(base);
+      if (container.getPayload() instanceof AtomEntitySetImpl) {
+        ((AtomEntitySetImpl) container.getPayload()).setBaseURI(base);
       }
-      if (container.getPayload() instanceof AtomEntryImpl) {
-        ((AtomEntryImpl) container.getPayload()).setBaseURI(base);
+      if (container.getPayload() instanceof AtomEntityImpl) {
+        ((AtomEntityImpl) container.getPayload()).setBaseURI(base);
       }
 
       writer.writeAttribute(

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/118b779b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/DeletedEntityImpl.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/DeletedEntityImpl.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/DeletedEntityImpl.java
new file mode 100644
index 0000000..0c97e9a
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/DeletedEntityImpl.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.core.data;
+
+import org.apache.olingo.commons.api.data.DeletedEntity;
+
+public class DeletedEntityImpl extends AbstractPayloadObject implements DeletedEntity {
+
+  private static final long serialVersionUID = -3841730551749114664L;
+
+  private String id;
+
+  private String reason;
+
+  @Override
+  public String getId() {
+    return id;
+  }
+
+  public void setId(final String id) {
+    this.id = id;
+  }
+
+  @Override
+  public String getReason() {
+    return reason;
+  }
+
+  public void setReason(final String reason) {
+    this.reason = reason;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/118b779b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/DeltaLinkImpl.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/DeltaLinkImpl.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/DeltaLinkImpl.java
new file mode 100644
index 0000000..972c6c6
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/DeltaLinkImpl.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.core.data;
+
+import java.net.URI;
+import org.apache.olingo.commons.api.data.DeltaLink;
+
+public class DeltaLinkImpl extends AbstractPayloadObject implements DeltaLink {
+
+  private static final long serialVersionUID = -6686550836508873044L;
+
+  private URI source;
+
+  private String relationship;
+
+  private URI target;
+
+  @Override
+  public URI getSource() {
+    return source;
+  }
+
+  @Override
+  public void setSource(final URI source) {
+    this.source = source;
+  }
+
+  @Override
+  public String getRelationship() {
+    return relationship;
+  }
+
+  @Override
+  public void setRelationship(String relationship) {
+    this.relationship = relationship;
+  }
+
+  @Override
+  public URI getTarget() {
+    return target;
+  }
+
+  @Override
+  public void setTarget(URI target) {
+    this.target = target;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/118b779b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONDeltaDeserializer.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONDeltaDeserializer.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONDeltaDeserializer.java
new file mode 100644
index 0000000..a141111
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONDeltaDeserializer.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.core.data;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import java.net.URI;
+import java.util.Iterator;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.olingo.commons.api.Constants;
+import org.apache.olingo.commons.api.data.ContextURL;
+import org.apache.olingo.commons.api.data.ResWrap;
+
+public class JSONDeltaDeserializer extends AbstractJsonDeserializer<JSONDeltaImpl> {
+
+  @Override
+  protected ResWrap<JSONDeltaImpl> doDeserialize(final JsonParser parser, final DeserializationContext ctxt)
+          throws IOException, JsonProcessingException {
+
+    final ObjectNode tree = parser.getCodec().readTree(parser);
+
+    final JSONDeltaImpl delta = new JSONDeltaImpl();
+
+    final URI contextURL;
+    if (tree.hasNonNull(Constants.JSON_CONTEXT)) {
+      contextURL = URI.create(tree.get(Constants.JSON_CONTEXT).textValue());
+    } else {
+      contextURL = null;
+    }
+    if (contextURL != null) {
+      delta.setBaseURI(StringUtils.substringBefore(contextURL.toASCIIString(), Constants.METADATA));
+    }
+
+    if (tree.hasNonNull(jsonCount)) {
+      delta.setCount(tree.get(jsonCount).asInt());
+    }
+    if (tree.hasNonNull(jsonNextLink)) {
+      delta.setNext(URI.create(tree.get(jsonNextLink).textValue()));
+    }
+    if (tree.hasNonNull(jsonDeltaLink)) {
+      delta.setDeltaLink(URI.create(tree.get(jsonDeltaLink).textValue()));
+    }
+
+    if (tree.hasNonNull(Constants.VALUE)) {
+      for (final Iterator<JsonNode> itor = tree.get(Constants.VALUE).iterator(); itor.hasNext();) {
+        final ObjectNode item = (ObjectNode) itor.next();
+        final ContextURL itemContextURL = item.hasNonNull(Constants.JSON_CONTEXT)
+                ? ContextURL.getInstance(URI.create(item.get(Constants.JSON_CONTEXT).textValue())) : null;
+        item.remove(Constants.JSON_CONTEXT);
+
+        if (itemContextURL == null || itemContextURL.isEntity()) {
+          final ResWrap<JSONEntityImpl> entity = item.traverse(parser.getCodec()).
+                  readValueAs(new TypeReference<JSONEntityImpl>() {
+                  });
+          delta.getEntities().add(entity.getPayload());
+        } else if (itemContextURL.isDeltaDeletedEntity()) {
+          delta.getDeletedEntities().
+                  add(parser.getCodec().treeToValue(item, DeletedEntityImpl.class));
+        } else if (itemContextURL.isDeltaLink()) {
+          delta.getAddedLinks().
+                  add(parser.getCodec().treeToValue(item, DeltaLinkImpl.class));
+        } else if (itemContextURL.isDeltaDeletedLink()) {
+          delta.getDeletedLinks().
+                  add(parser.getCodec().treeToValue(item, DeltaLinkImpl.class));
+        }
+      }
+    }
+
+    return new ResWrap<JSONDeltaImpl>(contextURL, null, delta);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/118b779b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONDeltaImpl.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONDeltaImpl.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONDeltaImpl.java
new file mode 100644
index 0000000..d684069
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONDeltaImpl.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.core.data;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+
+@JsonDeserialize(using = JSONDeltaDeserializer.class)
+public class JSONDeltaImpl extends AbstractDelta {
+
+  private static final long serialVersionUID = -7948494801560470246L;
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/118b779b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntityDeserializer.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntityDeserializer.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntityDeserializer.java
new file mode 100644
index 0000000..4fd7ace
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntityDeserializer.java
@@ -0,0 +1,200 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.core.data;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import java.net.URI;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.olingo.commons.api.Constants;
+import org.apache.olingo.commons.api.data.ResWrap;
+import org.apache.olingo.commons.api.data.Link;
+import org.apache.olingo.commons.api.domain.ODataLinkType;
+import org.apache.olingo.commons.api.domain.ODataOperation;
+import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
+import org.apache.olingo.commons.core.edm.EdmTypeInfo;
+
+/**
+ * Reads JSON string into an entity.
+ * <br/>
+ * If metadata information is available, the corresponding entity fields and content will be populated.
+ */
+public class JSONEntityDeserializer extends AbstractJsonDeserializer<JSONEntityImpl> {
+
+  @Override
+  protected ResWrap<JSONEntityImpl> doDeserialize(final JsonParser parser, final DeserializationContext ctxt)
+          throws IOException, JsonProcessingException {
+
+    final ObjectNode tree = parser.getCodec().readTree(parser);
+
+    if (tree.has(Constants.VALUE) && tree.get(Constants.VALUE).isArray()) {
+      throw new JsonParseException("Expected OData Entity, found EntitySet", parser.getCurrentLocation());
+    }
+
+    final JSONEntityImpl entity = new JSONEntityImpl();
+
+    final URI contextURL;
+    if (tree.hasNonNull(Constants.JSON_CONTEXT)) {
+      contextURL = URI.create(tree.get(Constants.JSON_CONTEXT).textValue());
+      tree.remove(Constants.JSON_CONTEXT);
+    } else if (tree.hasNonNull(Constants.JSON_METADATA)) {
+      contextURL = URI.create(tree.get(Constants.JSON_METADATA).textValue());
+      tree.remove(Constants.JSON_METADATA);
+    } else {
+      contextURL = null;
+    }
+    if (contextURL != null) {
+      entity.setBaseURI(StringUtils.substringBefore(contextURL.toASCIIString(), Constants.METADATA));
+    }
+
+    final String metadataETag;
+    if (tree.hasNonNull(Constants.JSON_METADATA_ETAG)) {
+      metadataETag = tree.get(Constants.JSON_METADATA_ETAG).textValue();
+      tree.remove(Constants.JSON_METADATA_ETAG);
+    } else {
+      metadataETag = null;
+    }
+
+    if (tree.hasNonNull(jsonETag)) {
+      entity.setETag(tree.get(jsonETag).textValue());
+      tree.remove(jsonETag);
+    }
+
+    if (tree.hasNonNull(jsonType)) {
+      entity.setType(new EdmTypeInfo.Builder().setTypeExpression(tree.get(jsonType).textValue()).build().internal());
+      tree.remove(jsonType);
+    }
+
+    if (tree.hasNonNull(jsonId)) {
+      entity.setId(tree.get(jsonId).textValue());
+      tree.remove(jsonId);
+    }
+
+    if (tree.hasNonNull(jsonReadLink)) {
+      final LinkImpl link = new LinkImpl();
+      link.setRel(Constants.SELF_LINK_REL);
+      link.setHref(tree.get(jsonReadLink).textValue());
+      entity.setSelfLink(link);
+
+      tree.remove(jsonReadLink);
+    }
+
+    if (tree.hasNonNull(jsonEditLink)) {
+      final LinkImpl link = new LinkImpl();
+      // Server mode
+      if (serverMode) {
+        link.setRel(Constants.EDIT_LINK_REL);
+      }
+      link.setHref(tree.get(jsonEditLink).textValue());
+      entity.setEditLink(link);
+
+      tree.remove(jsonEditLink);
+    }
+
+    if (tree.hasNonNull(jsonMediaReadLink)) {
+      entity.setMediaContentSource(tree.get(jsonMediaReadLink).textValue());
+      tree.remove(jsonMediaReadLink);
+    }
+    if (tree.hasNonNull(jsonMediaEditLink)) {
+      entity.setMediaContentSource(tree.get(jsonMediaEditLink).textValue());
+      tree.remove(jsonMediaEditLink);
+    }
+    if (tree.hasNonNull(jsonMediaContentType)) {
+      entity.setMediaContentType(tree.get(jsonMediaContentType).textValue());
+      tree.remove(jsonMediaContentType);
+    }
+    if (tree.hasNonNull(jsonMediaETag)) {
+      entity.setMediaETag(tree.get(jsonMediaETag).textValue());
+      tree.remove(jsonMediaETag);
+    }
+
+    final Set<String> toRemove = new HashSet<String>();
+    for (final Iterator<Map.Entry<String, JsonNode>> itor = tree.fields(); itor.hasNext();) {
+      final Map.Entry<String, JsonNode> field = itor.next();
+
+      links(field, entity, toRemove, tree, parser.getCodec());
+      if (field.getKey().endsWith(getJSONAnnotation(jsonMediaEditLink))) {
+        final LinkImpl link = new LinkImpl();
+        link.setTitle(getTitle(field));
+        link.setRel(version.getNamespaceMap().get(ODataServiceVersion.MEDIA_EDIT_LINK_REL) + getTitle(field));
+        link.setHref(field.getValue().textValue());
+        link.setType(ODataLinkType.MEDIA_EDIT.toString());
+        entity.getMediaEditLinks().add(link);
+
+        if (tree.has(link.getTitle() + getJSONAnnotation(jsonMediaETag))) {
+          link.setMediaETag(tree.get(link.getTitle() + getJSONAnnotation(jsonMediaETag)).asText());
+          toRemove.add(link.getTitle() + getJSONAnnotation(jsonMediaETag));
+        }
+
+        toRemove.add(field.getKey());
+        toRemove.add(setInline(field.getKey(), getJSONAnnotation(jsonMediaEditLink), tree, parser.getCodec(), link));
+      } else if (field.getKey().endsWith(getJSONAnnotation(jsonMediaContentType))) {
+        final String linkTitle = getTitle(field);
+        for (Link link : entity.getMediaEditLinks()) {
+          if (linkTitle.equals(link.getTitle())) {
+            ((LinkImpl) link).setType(field.getValue().asText());
+          }
+        }
+        toRemove.add(field.getKey());
+      } else if (field.getKey().charAt(0) == '#') {
+        final ODataOperation operation = new ODataOperation();
+        operation.setMetadataAnchor(field.getKey());
+
+        final ObjectNode opNode = (ObjectNode) tree.get(field.getKey());
+        operation.setTitle(opNode.get(Constants.ATTR_TITLE).asText());
+        operation.setTarget(URI.create(opNode.get(Constants.ATTR_TARGET).asText()));
+
+        entity.getOperations().add(operation);
+
+        toRemove.add(field.getKey());
+      }
+    }
+    tree.remove(toRemove);
+
+    String type = null;
+    for (final Iterator<Map.Entry<String, JsonNode>> itor = tree.fields(); itor.hasNext();) {
+      final Map.Entry<String, JsonNode> field = itor.next();
+
+      if (type == null && field.getKey().endsWith(getJSONAnnotation(jsonType))) {
+        type = field.getValue().asText();
+      } else {
+        final JSONPropertyImpl property = new JSONPropertyImpl();
+        property.setName(field.getKey());
+        property.setType(type == null
+                ? null
+                : new EdmTypeInfo.Builder().setTypeExpression(type).build().internal());
+        type = null;
+
+        value(property, field.getValue(), parser.getCodec());
+        entity.getProperties().add(property);
+      }
+    }
+    
+    return new ResWrap<JSONEntityImpl>(contextURL, metadataETag, entity);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/118b779b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntityImpl.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntityImpl.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntityImpl.java
new file mode 100644
index 0000000..57db805
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntityImpl.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.core.data;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+/**
+ * A single entity, represented via JSON.
+ */
+@JsonSerialize(using = JSONEntitySerializer.class)
+@JsonDeserialize(using = JSONEntityDeserializer.class)
+public class JSONEntityImpl extends AbstractEntity {
+
+  private static final long serialVersionUID = -5275365545400797758L;
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/118b779b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntitySerializer.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntitySerializer.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntitySerializer.java
new file mode 100644
index 0000000..0439783
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntitySerializer.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.core.data;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import java.io.IOException;
+import java.net.URI;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.olingo.commons.api.Constants;
+import org.apache.olingo.commons.api.data.ResWrap;
+import org.apache.olingo.commons.api.data.Entity;
+import org.apache.olingo.commons.api.data.Link;
+import org.apache.olingo.commons.api.data.Property;
+import org.apache.olingo.commons.api.domain.ODataOperation;
+import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
+import org.apache.olingo.commons.core.edm.EdmTypeInfo;
+
+/**
+ * Writes out JSON string from an entity.
+ */
+public class JSONEntitySerializer extends AbstractJsonSerializer<JSONEntityImpl> {
+
+  @Override
+  protected void doSerialize(final JSONEntityImpl entity, final JsonGenerator jgen, final SerializerProvider provider)
+          throws IOException, JsonProcessingException {
+
+    doContainerSerialize(new ResWrap<JSONEntityImpl>((URI) null, null, entity), jgen, provider);
+  }
+
+  @Override
+  protected void doContainerSerialize(
+          final ResWrap<JSONEntityImpl> container, final JsonGenerator jgen, final SerializerProvider provider)
+          throws IOException, JsonProcessingException {
+
+    final Entity entity = container.getPayload();
+
+    jgen.writeStartObject();
+
+    if (serverMode) {
+      if (container.getContextURL() != null) {
+        jgen.writeStringField(version.compareTo(ODataServiceVersion.V40) >= 0
+                ? Constants.JSON_CONTEXT : Constants.JSON_METADATA,
+                container.getContextURL().getURI().toASCIIString());
+      }
+      if (version.compareTo(ODataServiceVersion.V40) >= 0 && StringUtils.isNotBlank(container.getMetadataETag())) {
+        jgen.writeStringField(Constants.JSON_METADATA_ETAG, container.getMetadataETag());
+      }
+
+      if (StringUtils.isNotBlank(entity.getETag())) {
+        jgen.writeStringField(version.getJSONMap().get(ODataServiceVersion.JSON_ETAG), entity.getETag());
+      }
+    }
+
+    if (StringUtils.isNotBlank(entity.getType())) {
+      jgen.writeStringField(version.getJSONMap().get(ODataServiceVersion.JSON_TYPE),
+              new EdmTypeInfo.Builder().setTypeExpression(entity.getType()).build().external(version));
+    }
+
+    if (entity.getId() != null) {
+      jgen.writeStringField(version.getJSONMap().get(ODataServiceVersion.JSON_ID), entity.getId());
+    }
+
+    for (Property property : entity.getProperties()) {
+      property(jgen, property, property.getName());
+    }
+
+    if (serverMode && entity.getEditLink() != null && StringUtils.isNotBlank(entity.getEditLink().getHref())) {
+      final URI link = URI.create(entity.getEditLink().getHref());
+      final String editLink = link.isAbsolute() ? link.toASCIIString()
+              : URI.create(entity.getBaseURI() + "/" + link.toASCIIString()).normalize().toASCIIString();
+
+      jgen.writeStringField(version.getJSONMap().get(ODataServiceVersion.JSON_EDIT_LINK), editLink);
+    }
+
+    links(entity, jgen);
+
+    for (Link link : entity.getMediaEditLinks()) {
+      if (link.getTitle() == null) {
+        jgen.writeStringField(version.getJSONMap().get(ODataServiceVersion.JSON_MEDIAEDIT_LINK), link.getHref());
+      }
+
+      if (link.getInlineEntity() != null) {
+        jgen.writeObjectField(link.getTitle(), link.getInlineEntity());
+      }
+      if (link.getInlineEntitySet() != null) {
+        jgen.writeArrayFieldStart(link.getTitle());
+        for (Entity subEntry : link.getInlineEntitySet().getEntities()) {
+          jgen.writeObject(subEntry);
+        }
+        jgen.writeEndArray();
+      }
+    }
+
+    if (serverMode) {
+      for (ODataOperation operation : entity.getOperations()) {
+        jgen.writeObjectFieldStart("#" + StringUtils.substringAfterLast(operation.getMetadataAnchor(), "#"));
+        jgen.writeStringField(Constants.ATTR_TITLE, operation.getTitle());
+        jgen.writeStringField(Constants.ATTR_TARGET, operation.getTarget().toASCIIString());
+        jgen.writeEndObject();
+      }
+    }
+
+    jgen.writeEndObject();
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/118b779b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntitySetDeserializer.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntitySetDeserializer.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntitySetDeserializer.java
new file mode 100644
index 0000000..044e269
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntitySetDeserializer.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.core.data;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import java.net.URI;
+import java.util.Iterator;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.olingo.commons.api.Constants;
+import org.apache.olingo.commons.api.data.ResWrap;
+
+/**
+ * Reads JSON string into an entity set.
+ * <br/>
+ * If metadata information is available, the corresponding entity fields and content will be populated.
+ */
+public class JSONEntitySetDeserializer extends AbstractJsonDeserializer<JSONEntitySetImpl> {
+
+  @Override
+  protected ResWrap<JSONEntitySetImpl> doDeserialize(final JsonParser parser, final DeserializationContext ctxt)
+          throws IOException, JsonProcessingException {
+
+    final ObjectNode tree = (ObjectNode) parser.getCodec().readTree(parser);
+
+    if (!tree.has(Constants.VALUE)) {
+      return null;
+    }
+
+    final JSONEntitySetImpl entitySet = new JSONEntitySetImpl();
+
+    final URI contextURL;
+    if (tree.hasNonNull(Constants.JSON_CONTEXT)) {
+      contextURL = URI.create(tree.get(Constants.JSON_CONTEXT).textValue());
+      tree.remove(Constants.JSON_CONTEXT);
+    } else if (tree.hasNonNull(Constants.JSON_METADATA)) {
+      contextURL = URI.create(tree.get(Constants.JSON_METADATA).textValue());
+      tree.remove(Constants.JSON_METADATA);
+    } else {
+      contextURL = null;
+    }
+    if (contextURL != null) {
+      entitySet.setBaseURI(StringUtils.substringBefore(contextURL.toASCIIString(), Constants.METADATA));
+    }
+
+    final String metadataETag;
+    if (tree.hasNonNull(Constants.JSON_METADATA_ETAG)) {
+      metadataETag = tree.get(Constants.JSON_METADATA_ETAG).textValue();
+      tree.remove(Constants.JSON_METADATA_ETAG);
+    } else {
+      metadataETag = null;
+    }
+
+    if (tree.hasNonNull(jsonCount)) {
+      entitySet.setCount(tree.get(jsonCount).asInt());
+    }
+    if (tree.hasNonNull(jsonNextLink)) {
+      entitySet.setNext(URI.create(tree.get(jsonNextLink).textValue()));
+    }
+
+    if (tree.hasNonNull(Constants.VALUE)) {
+      for (final Iterator<JsonNode> itor = tree.get(Constants.VALUE).iterator(); itor.hasNext();) {
+        entitySet.getEntities().add(
+                itor.next().traverse(parser.getCodec()).<ResWrap<JSONEntityImpl>>readValueAs(
+                        new TypeReference<JSONEntityImpl>() {
+                        }).getPayload());
+      }
+    }
+
+    return new ResWrap<JSONEntitySetImpl>(contextURL, metadataETag, entitySet);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/118b779b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntitySetImpl.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntitySetImpl.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntitySetImpl.java
new file mode 100644
index 0000000..dac67cd
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntitySetImpl.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.core.data;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+/**
+ * List of entries, represented via JSON.
+ *
+ * @see JSONEntry
+ */
+@JsonDeserialize(using = JSONEntitySetDeserializer.class)
+@JsonSerialize(using = JSONEntitySetSerializer.class)
+public class JSONEntitySetImpl extends AbstractEntitySet {
+
+  private static final long serialVersionUID = -3576372289800799417L;
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/118b779b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntitySetSerializer.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntitySetSerializer.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntitySetSerializer.java
new file mode 100644
index 0000000..1e16fa8
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntitySetSerializer.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.core.data;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import java.io.IOException;
+import java.net.URI;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.olingo.commons.api.Constants;
+import org.apache.olingo.commons.api.data.ResWrap;
+import org.apache.olingo.commons.api.data.Entity;
+import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
+
+public class JSONEntitySetSerializer extends AbstractJsonSerializer<JSONEntitySetImpl> {
+
+  @Override
+  protected void doSerialize(
+          final JSONEntitySetImpl entitySet, final JsonGenerator jgen, final SerializerProvider provider)
+          throws IOException, JsonProcessingException {
+
+    doContainerSerialize(new ResWrap<JSONEntitySetImpl>((URI) null, null, entitySet), jgen, provider);
+  }
+
+  @Override
+  protected void doContainerSerialize(
+          final ResWrap<JSONEntitySetImpl> container, final JsonGenerator jgen, final SerializerProvider provider)
+          throws IOException, JsonProcessingException {
+
+    final JSONEntitySetImpl entitySet = container.getPayload();
+
+    jgen.writeStartObject();
+
+    if (serverMode) {
+      if (container.getContextURL() != null) {
+        jgen.writeStringField(version.compareTo(ODataServiceVersion.V40) >= 0
+                ? Constants.JSON_CONTEXT : Constants.JSON_METADATA,
+                container.getContextURL().getURI().toASCIIString());
+      }
+
+      if (version.compareTo(ODataServiceVersion.V40) >= 0 && StringUtils.isNotBlank(container.getMetadataETag())) {
+        jgen.writeStringField(
+                Constants.JSON_METADATA_ETAG,
+                container.getMetadataETag());
+      }
+    }
+
+    if (entitySet.getId() != null) {
+      jgen.writeStringField(version.getJSONMap().get(ODataServiceVersion.JSON_ID), entitySet.getId());
+    }
+    jgen.writeNumberField(version.getJSONMap().get(ODataServiceVersion.JSON_COUNT),
+            entitySet.getCount() == null ? entitySet.getEntities().size() : entitySet.getCount());
+    if (entitySet.getNext() != null) {
+      jgen.writeStringField(
+              version.getJSONMap().get(ODataServiceVersion.JSON_NEXT_LINK), entitySet.getNext().toASCIIString());
+    }
+
+    jgen.writeArrayFieldStart(Constants.VALUE);
+    for (Entity entity : entitySet.getEntities()) {
+      jgen.writeObject(entity);
+    }
+
+    jgen.writeEndArray();
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/118b779b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntryDeserializer.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntryDeserializer.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntryDeserializer.java
deleted file mode 100644
index dce4b74..0000000
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONEntryDeserializer.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.olingo.commons.core.data;
-
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import java.io.IOException;
-import java.net.URI;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.olingo.commons.api.Constants;
-import org.apache.olingo.commons.api.data.ResWrap;
-import org.apache.olingo.commons.api.data.Link;
-import org.apache.olingo.commons.api.domain.ODataLinkType;
-import org.apache.olingo.commons.api.domain.ODataOperation;
-import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
-import org.apache.olingo.commons.core.edm.EdmTypeInfo;
-
-/**
- * Reads JSON string into an entry.
- * <br/>
- * If metadata information is available, the corresponding entry fields and content will be populated.
- */
-public class JSONEntryDeserializer extends AbstractJsonDeserializer<JSONEntryImpl> {
-
-  @Override
-  protected ResWrap<JSONEntryImpl> doDeserialize(final JsonParser parser, final DeserializationContext ctxt)
-          throws IOException, JsonProcessingException {
-
-    final ObjectNode tree = parser.getCodec().readTree(parser);
-
-    if (tree.has(Constants.VALUE) && tree.get(Constants.VALUE).isArray()) {
-      throw new JsonParseException("Expected OData Entity, found EntitySet", parser.getCurrentLocation());
-    }
-
-    final JSONEntryImpl entry = new JSONEntryImpl();
-
-    final URI contextURL;
-    if (tree.hasNonNull(Constants.JSON_CONTEXT)) {
-      contextURL = URI.create(tree.get(Constants.JSON_CONTEXT).textValue());
-      tree.remove(Constants.JSON_CONTEXT);
-    } else if (tree.hasNonNull(Constants.JSON_METADATA)) {
-      contextURL = URI.create(tree.get(Constants.JSON_METADATA).textValue());
-      tree.remove(Constants.JSON_METADATA);
-    } else {
-      contextURL = null;
-    }
-    if (contextURL != null) {
-      entry.setBaseURI(StringUtils.substringBefore(contextURL.toASCIIString(), Constants.METADATA));
-    }
-
-    final String metadataETag;
-    if (tree.hasNonNull(Constants.JSON_METADATA_ETAG)) {
-      metadataETag = tree.get(Constants.JSON_METADATA_ETAG).textValue();
-      tree.remove(Constants.JSON_METADATA_ETAG);
-    } else {
-      metadataETag = null;
-    }
-
-    if (tree.hasNonNull(jsonETag)) {
-      entry.setETag(tree.get(jsonETag).textValue());
-      tree.remove(jsonETag);
-    }
-
-    if (tree.hasNonNull(jsonType)) {
-      entry.setType(new EdmTypeInfo.Builder().setTypeExpression(tree.get(jsonType).textValue()).build().internal());
-      tree.remove(jsonType);
-    }
-
-    if (tree.hasNonNull(jsonId)) {
-      entry.setId(tree.get(jsonId).textValue());
-      tree.remove(jsonId);
-    }
-
-    if (tree.hasNonNull(jsonReadLink)) {
-      final LinkImpl link = new LinkImpl();
-      link.setRel(Constants.SELF_LINK_REL);
-      link.setHref(tree.get(jsonReadLink).textValue());
-      entry.setSelfLink(link);
-
-      tree.remove(jsonReadLink);
-    }
-
-    if (tree.hasNonNull(jsonEditLink)) {
-      final LinkImpl link = new LinkImpl();
-      // Server mode
-      if (serverMode) {
-        link.setRel(Constants.EDIT_LINK_REL);
-      }
-      link.setHref(tree.get(jsonEditLink).textValue());
-      entry.setEditLink(link);
-
-      tree.remove(jsonEditLink);
-    }
-
-    if (tree.hasNonNull(jsonMediaReadLink)) {
-      entry.setMediaContentSource(tree.get(jsonMediaReadLink).textValue());
-      tree.remove(jsonMediaReadLink);
-    }
-    if (tree.hasNonNull(jsonMediaEditLink)) {
-      entry.setMediaContentSource(tree.get(jsonMediaEditLink).textValue());
-      tree.remove(jsonMediaEditLink);
-    }
-    if (tree.hasNonNull(jsonMediaContentType)) {
-      entry.setMediaContentType(tree.get(jsonMediaContentType).textValue());
-      tree.remove(jsonMediaContentType);
-    }
-    if (tree.hasNonNull(jsonMediaETag)) {
-      entry.setMediaETag(tree.get(jsonMediaETag).textValue());
-      tree.remove(jsonMediaETag);
-    }
-
-    final Set<String> toRemove = new HashSet<String>();
-    for (final Iterator<Map.Entry<String, JsonNode>> itor = tree.fields(); itor.hasNext();) {
-      final Map.Entry<String, JsonNode> field = itor.next();
-
-      links(field, entry, toRemove, tree, parser.getCodec());
-      if (field.getKey().endsWith(getJSONAnnotation(jsonMediaEditLink))) {
-        final LinkImpl link = new LinkImpl();
-        link.setTitle(getTitle(field));
-        link.setRel(version.getNamespaceMap().get(ODataServiceVersion.MEDIA_EDIT_LINK_REL) + getTitle(field));
-        link.setHref(field.getValue().textValue());
-        link.setType(ODataLinkType.MEDIA_EDIT.toString());
-        entry.getMediaEditLinks().add(link);
-
-        if (tree.has(link.getTitle() + getJSONAnnotation(jsonMediaETag))) {
-          link.setMediaETag(tree.get(link.getTitle() + getJSONAnnotation(jsonMediaETag)).asText());
-          toRemove.add(link.getTitle() + getJSONAnnotation(jsonMediaETag));
-        }
-
-        toRemove.add(field.getKey());
-        toRemove.add(setInline(field.getKey(), getJSONAnnotation(jsonMediaEditLink), tree, parser.getCodec(), link));
-      } else if (field.getKey().endsWith(getJSONAnnotation(jsonMediaContentType))) {
-        final String linkTitle = getTitle(field);
-        for (Link link : entry.getMediaEditLinks()) {
-          if (linkTitle.equals(link.getTitle())) {
-            ((LinkImpl) link).setType(field.getValue().asText());
-          }
-        }
-        toRemove.add(field.getKey());
-      } else if (field.getKey().charAt(0) == '#') {
-        final ODataOperation operation = new ODataOperation();
-        operation.setMetadataAnchor(field.getKey());
-
-        final ObjectNode opNode = (ObjectNode) tree.get(field.getKey());
-        operation.setTitle(opNode.get(Constants.ATTR_TITLE).asText());
-        operation.setTarget(URI.create(opNode.get(Constants.ATTR_TARGET).asText()));
-
-        entry.getOperations().add(operation);
-
-        toRemove.add(field.getKey());
-      }
-    }
-    tree.remove(toRemove);
-
-    String type = null;
-    for (final Iterator<Map.Entry<String, JsonNode>> itor = tree.fields(); itor.hasNext();) {
-      final Map.Entry<String, JsonNode> field = itor.next();
-
-      if (type == null && field.getKey().endsWith(getJSONAnnotation(jsonType))) {
-        type = field.getValue().asText();
-      } else {
-        final JSONPropertyImpl property = new JSONPropertyImpl();
-        property.setName(field.getKey());
-        property.setType(type == null
-                ? null
-                : new EdmTypeInfo.Builder().setTypeExpression(type).build().internal());
-        type = null;
-
-        value(property, field.getValue(), parser.getCodec());
-        entry.getProperties().add(property);
-      }
-    }
-
-    return new ResWrap<JSONEntryImpl>(contextURL, metadataETag, entry);
-  }
-}