You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ar...@apache.org on 2018/04/02 11:32:02 UTC

[21/24] olingo-odata2 git commit: [OLINGO-1253]Client Module for Olingo v2

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/JsonSerializerDeserializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/JsonSerializerDeserializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/JsonSerializerDeserializer.java
new file mode 100644
index 0000000..aaba634
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/JsonSerializerDeserializer.java
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * 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.odata2.client.core.ep;
+
+import java.io.BufferedWriter;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.batch.BatchException;
+import org.apache.olingo.odata2.api.batch.BatchResponsePart;
+import org.apache.olingo.odata2.api.client.batch.BatchPart;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.api.processor.ODataErrorContext;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.client.api.ep.ContentTypeBasedDeserializer;
+import org.apache.olingo.odata2.client.api.ep.ContentTypeBasedSerializer;
+import org.apache.olingo.odata2.client.api.ep.Entity;
+import org.apache.olingo.odata2.client.api.ep.EntityCollection;
+import org.apache.olingo.odata2.client.api.ep.EntityCollectionSerializerProperties;
+import org.apache.olingo.odata2.client.api.ep.EntitySerializerProperties;
+import org.apache.olingo.odata2.client.api.ep.EntityStream;
+import org.apache.olingo.odata2.client.core.ep.deserializer.JsonEntityDeserializer;
+import org.apache.olingo.odata2.client.core.ep.serializer.JsonEntryEntitySerializer;
+import org.apache.olingo.odata2.client.core.ep.serializer.JsonFeedEntitySerializer;
+import org.apache.olingo.odata2.core.batch.BatchRequestWriter;
+import org.apache.olingo.odata2.core.batch.BatchResponseWriter;
+import org.apache.olingo.odata2.core.ep.EntityProviderProducerException;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.consumer.JsonErrorDocumentConsumer;
+import org.apache.olingo.odata2.core.ep.util.CircleStreamBuffer;
+
+/**
+ *  This class includes methods to serialize deserialize JSON Content type
+ */
+public class JsonSerializerDeserializer implements ContentTypeBasedSerializer, ContentTypeBasedDeserializer {
+
+  private static final String DEFAULT_CHARSET = "UTF-8";
+
+  @Override
+  public ODataResponse writeEntry(EdmEntitySet entitySet, Entity data) 
+      throws EntityProviderException {
+
+    final EntitySerializerProperties properties = data == null ? 
+        EntitySerializerProperties.serviceRoot(null).build() : data.getWriteProperties() == null ? 
+            EntitySerializerProperties.serviceRoot(null).build() : data.getWriteProperties();
+    final EntityInfoAggregator entityInfo = EntityInfoAggregator.create(entitySet, null);
+    CircleStreamBuffer buffer = new CircleStreamBuffer();
+
+    try {
+      BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(buffer.getOutputStream(), DEFAULT_CHARSET));
+      JsonEntryEntitySerializer producer = new JsonEntryEntitySerializer(properties);
+      producer.append(writer, entityInfo, data);
+      writer.flush();
+      buffer.closeWrite();
+
+      return ODataResponse.entity(buffer.getInputStream())
+          .idLiteral(producer.getLocation())
+          .build();
+    } catch (EntityProviderException e) {
+      buffer.close();
+      throw e;
+    } catch (Exception e) {
+      buffer.close();
+      throw new EntityProviderProducerException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+  
+  }
+
+  @Override
+  public ODataFeed readFeed(EdmEntitySet entitySet, EntityStream content) 
+      throws EntityProviderException {
+    return new JsonEntityDeserializer().readFeed(entitySet, content);
+  }
+
+  @Override
+  public ODataEntry readEntry(EdmEntitySet entitySet, EntityStream content) 
+      throws EntityProviderException {
+    return new JsonEntityDeserializer().readEntry(entitySet, content);
+  
+  }
+
+  @Override
+  public ODataErrorContext readErrorDocument(InputStream errorDocument) throws EntityProviderException {
+    return new JsonErrorDocumentConsumer().readError(errorDocument);
+  }
+
+  @Override
+  public ODataResponse writeFeed(EdmEntitySet entitySet, EntityCollection data) throws EntityProviderException {
+    final EntityCollectionSerializerProperties properties = data == null ? 
+        EntityCollectionSerializerProperties.serviceRoot(null).build() : data.getCollectionProperties() == null ? 
+            EntityCollectionSerializerProperties.serviceRoot(null).build() : data.getCollectionProperties();
+    final EntityInfoAggregator entityInfo = EntityInfoAggregator.create(entitySet, null);
+    CircleStreamBuffer buffer = new CircleStreamBuffer();
+
+    try {
+      BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(buffer.getOutputStream(), DEFAULT_CHARSET));
+      new JsonFeedEntitySerializer(properties).appendAsObject(writer, entityInfo, data);
+      writer.flush();
+      buffer.closeWrite();
+
+      return ODataResponse.entity(buffer.getInputStream()).build();
+    } catch (EntityProviderException e) {
+      buffer.close();
+      throw e;
+    } catch (Exception e) {
+      buffer.close();
+      throw new EntityProviderProducerException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+  }
+
+  @Override
+  public ODataResponse writeBatchResponse(List<BatchResponsePart> batchResponseParts) throws BatchException {
+    BatchResponseWriter batchWriter = new BatchResponseWriter();
+    return batchWriter.writeResponse(batchResponseParts);
+  }
+
+  @Override
+  public InputStream readBatchRequest(List<BatchPart> batchParts,
+      String boundary) {
+    BatchRequestWriter batchWriter = new BatchRequestWriter();
+    return batchWriter.writeBatchRequest(batchParts, boundary);
+  }
+
+  @Override
+  public Object readFunctionImport(EdmFunctionImport functionImport, EntityStream content)
+      throws EntityProviderException {
+    try {
+      if (functionImport.getReturnType().getType().getKind() == EdmTypeKind.ENTITY) {
+        return functionImport.getReturnType().getMultiplicity() == EdmMultiplicity.MANY
+            ? new JsonEntityDeserializer().readFeed(functionImport.getEntitySet(), content)
+            : new JsonEntityDeserializer().readEntry(functionImport.getEntitySet(), content);
+      } else {
+        final EntityPropertyInfo info = EntityInfoAggregator.create(functionImport);
+        return functionImport.getReturnType().getMultiplicity() == EdmMultiplicity.MANY ?
+            new JsonEntityDeserializer().readCollection(info, content) :
+            new JsonEntityDeserializer().readProperty(info, content).get(info.getName());
+      }
+    } catch (final EdmException e) {
+      throw new EntityProviderException(e.getMessageReference(), e);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntityDeserializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntityDeserializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntityDeserializer.java
new file mode 100644
index 0000000..49c61d7
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntityDeserializer.java
@@ -0,0 +1,218 @@
+/*******************************************************************************
+ * 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.odata2.client.core.ep.deserializer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataDeltaFeed;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.client.api.ep.EntityStream;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+
+import com.google.gson.stream.JsonReader;
+
+/**
+ *  This class includes method for deserialization of feed and entry data
+ */
+public class JsonEntityDeserializer {
+
+  /** Default used charset for reader */
+  private static final String DEFAULT_CHARSET = "UTF-8";
+
+  /**
+   * Returns an ODataEntry deserializing EntityStream
+   * @param entitySet
+   * @param entityStream
+   * @return ODataEntry
+   * @throws EntityProviderException
+   */
+  public ODataEntry readEntry(final EdmEntitySet entitySet, final EntityStream entityStream) 
+      throws EntityProviderException {
+    JsonReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      EntityInfoAggregator eia = EntityInfoAggregator.create(entitySet);
+      reader = createJsonReader(entityStream.getContent());
+
+      return new JsonEntryDeserializer(reader, eia, entityStream.getReadProperties()).readSingleEntry();
+    } catch (UnsupportedEncodingException e) {
+      cachedException =
+          new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+              .getSimpleName()), e);
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (IOException e) { //NOPMD  - suppressed
+          if (cachedException != null) { //NOSONAR
+            throw cachedException; //NOSONAR
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.//NOSONAR
+                addContent(e.getClass()
+                .getSimpleName()), e); 
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * Returns an ODataFeed deserializing EntityStream
+   * @param entitySet
+   * @param entityStream
+   * @return ODataFeed
+   * @throws EntityProviderException
+   */
+  public ODataFeed readFeed(final EdmEntitySet entitySet, final EntityStream entityStream) 
+      throws EntityProviderException {
+    return readDeltaFeed(entitySet, entityStream);
+  }
+
+  /**
+   * Returns an ODataDeltaFeed deserializing EntityStream
+   * @param entitySet
+   * @param entityStream
+   * @return ODataDeltaFeed
+   * @throws EntityProviderException
+   */
+  public ODataDeltaFeed readDeltaFeed(final EdmEntitySet entitySet, final EntityStream entityStream) 
+      throws EntityProviderException {
+
+    JsonReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      EntityInfoAggregator eia = EntityInfoAggregator.create(entitySet);
+      reader = createJsonReader(entityStream.getContent());
+
+      JsonFeedDeserializer jfc = new JsonFeedDeserializer(reader, eia, entityStream.getReadProperties());
+      return jfc.readFeedStandalone();
+    } catch (UnsupportedEncodingException e) {
+      cachedException =
+          new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+              .getSimpleName()), e);
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (IOException e) { //NOPMD  - suppressed
+          if (cachedException != null) { //NOSONAR
+            throw cachedException; //NOSONAR
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.//NOSONAR
+                addContent(e.getClass()
+                .getSimpleName()), e); 
+          }
+        }
+      }
+    }
+  }
+
+/**
+ * 
+ * @param content
+ * @return JsonReader
+ * @throws EntityProviderException
+ * @throws UnsupportedEncodingException
+ */
+  private JsonReader createJsonReader(final Object content) throws EntityProviderException,
+      UnsupportedEncodingException {
+
+    if (content == null) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT
+          .addContent("Got not supported NULL object as content to de-serialize."));
+    }
+
+    if (content instanceof InputStream) {
+      return new JsonReader(new InputStreamReader((InputStream) content, DEFAULT_CHARSET));
+    }
+    throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT
+        .addContent("Found not supported content of class '" + content.getClass() + "' to de-serialize."));
+  }
+  
+  public List<?> readCollection(final EntityPropertyInfo info, final EntityStream entityStream) 
+      throws EntityProviderException {
+    JsonReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      reader = createJsonReader(entityStream.getContent());
+      return new JsonPropertyDeserializer().readCollection(reader, info, entityStream.getReadProperties());
+    } catch (final UnsupportedEncodingException e) {
+      cachedException = new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED
+          .addContent(e.getClass().getSimpleName()), e);
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (final IOException e) {
+          if (cachedException != null) {
+            throw cachedException;
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED
+                .addContent(e.getClass().getSimpleName()), e);
+          }
+        }
+      }
+    }
+  }
+  
+  public Map<String, Object> readProperty(final EntityPropertyInfo propertyInfo, final EntityStream entityStream) 
+      throws EntityProviderException {
+    JsonReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      reader = createJsonReader(entityStream.getContent());
+      return new JsonPropertyDeserializer().readPropertyStandalone(reader, propertyInfo, 
+          entityStream.getReadProperties());
+    } catch (final UnsupportedEncodingException e) {
+      cachedException =
+          new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+              .getSimpleName()), e);
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (final IOException e) {
+          if (cachedException != null) {
+            throw cachedException;
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+                .getSimpleName()), e);
+          }
+        }
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntryDeserializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntryDeserializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntryDeserializer.java
new file mode 100644
index 0000000..f9fb915
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonEntryDeserializer.java
@@ -0,0 +1,451 @@
+/*******************************************************************************
+ * 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.odata2.client.core.ep.deserializer;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+import org.apache.olingo.odata2.client.api.ep.DeserializerProperties;
+import org.apache.olingo.odata2.client.api.ep.callback.OnDeserializeInlineContent;
+import org.apache.olingo.odata2.core.edm.EdmDateTimeOffset;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.aggregator.NavigationPropertyInfo;
+import org.apache.olingo.odata2.core.ep.entry.DeletedEntryMetadataImpl;
+import org.apache.olingo.odata2.core.ep.entry.EntryMetadataImpl;
+import org.apache.olingo.odata2.core.ep.entry.MediaMetadataImpl;
+import org.apache.olingo.odata2.core.ep.entry.ODataEntryImpl;
+import org.apache.olingo.odata2.core.ep.feed.JsonFeedEntry;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+
+/**
+ *  This class Deserializes JsonEntry payloads
+ */
+public class JsonEntryDeserializer {
+
+  private final EntityInfoAggregator eia;
+  private final JsonReader reader;
+  private final DeserializerProperties readProperties;
+
+  private ODataEntryImpl resultEntry;
+  private Map<String, Object> properties;
+  private MediaMetadataImpl mediaMetadata;
+  private EntryMetadataImpl entryMetadata;
+
+  private DeletedEntryMetadataImpl resultDeletedEntry;
+
+  /**
+   * 
+   * @param reader
+   * @param eia
+   * @param readProperties
+   */
+  public JsonEntryDeserializer(final JsonReader reader, final EntityInfoAggregator eia,
+      final DeserializerProperties readProperties) {
+    this.eia = eia;
+    this.readProperties = readProperties;
+    this.reader = reader;
+  }
+
+  /**
+   * Returns ODataEntry deserializing a single entry
+   * @return ODataEntry
+   * @throws EntityProviderException
+   */
+  public ODataEntry readSingleEntry() throws EntityProviderException {
+    try {
+      reader.beginObject();
+      String nextName = reader.nextName();
+      if (FormatJson.D.equals(nextName)) {
+        reader.beginObject();
+        readEntryContent();
+        reader.endObject();
+      } else {
+        handleName(nextName);
+        readEntryContent();
+      }
+      reader.endObject();
+
+      if (reader.peek() != JsonToken.END_DOCUMENT) {
+        throw new EntityProviderException(EntityProviderException.END_DOCUMENT_EXPECTED.addContent(reader.peek()
+            .toString()));
+      }
+    } catch (IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    } catch (IllegalStateException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+
+    return resultEntry;
+  }
+
+  /**
+   * Returns Feed deserializing feed entry
+   * @return JsonFeedEntry
+   * @throws EdmException
+   * @throws EntityProviderException
+   * @throws IOException
+   */
+  public JsonFeedEntry readFeedEntry() throws EdmException, EntityProviderException, IOException {//NOSONAR
+    reader.beginObject();
+    readEntryContent();
+    reader.endObject();
+
+    if (resultDeletedEntry == null) {
+      return new JsonFeedEntry(resultEntry);
+    } else {
+      return new JsonFeedEntry(resultDeletedEntry);
+    }
+  }
+
+  /**
+   * 
+   * @throws IOException
+   * @throws EdmException
+   * @throws EntityProviderException
+   */
+  private void readEntryContent() throws IOException, EdmException, EntityProviderException {
+    while (reader.hasNext()) {
+      final String name = reader.nextName();
+      handleName(name);
+    }
+  }
+
+  /**
+   * Ensure that instance field {@link #resultEntry} exists.
+   * If it not already exists create an instance (as well as all other necessary objects like: {@link #properties},
+   * {@link #mediaMetadata}, {@link #entryMetadata}, {@link #expandSelectTree}).
+   */
+  private void ensureODataEntryExists() {
+    if (resultEntry == null) {
+      properties = new HashMap<String, Object>();
+      mediaMetadata = new MediaMetadataImpl();
+      entryMetadata = new EntryMetadataImpl();
+      
+      resultEntry = new ODataEntryImpl(properties, mediaMetadata, entryMetadata, null);
+    }
+  }
+
+  /**
+   * Ensure that instance field {@link #resultDeletedEntry} exists.
+   * If it not already exists create an instance.
+   */
+  private void ensureDeletedEntryMetadataExists() {
+    if (resultDeletedEntry == null) {
+      resultDeletedEntry = new DeletedEntryMetadataImpl();
+    }
+  }
+
+  /**
+   * 
+   * @param name
+   * @throws IOException
+   * @throws EdmException
+   * @throws EntityProviderException
+   */
+  private void handleName(final String name) throws IOException, EdmException, EntityProviderException {
+    if (FormatJson.METADATA.equals(name)) {
+      ensureODataEntryExists();
+      readMetadata();
+      validateMetadata();
+    } else if (FormatJson.ODATA_CONTEXT.equals(name)) {
+      readODataContext();
+    } else {
+      ensureODataEntryExists();
+      EntityPropertyInfo propertyInfo = eia.getPropertyInfo(name);
+      if (propertyInfo != null) {
+        //TODO: put Type mapping instead of null
+        Object propertyValue = new JsonPropertyDeserializer()
+            .readPropertyValue(reader, propertyInfo, null, readProperties);
+        if (properties.containsKey(name)) {
+          throw new EntityProviderException(EntityProviderException.DOUBLE_PROPERTY.addContent(name));
+        }
+        properties.put(name, propertyValue);
+      } else {
+        readNavigationProperty(name);
+      }
+    }
+  }
+  /**
+   * 
+   * @throws IOException
+   * @throws EntityProviderException
+   */
+  private void readODataContext() throws IOException, EntityProviderException {
+    String contextValue = reader.nextString();
+    if (contextValue == null) {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent(FormatJson.ODATA_CONTEXT)
+          .addContent(FormatJson.RESULTS));
+    }
+
+    if (contextValue.startsWith(FormatJson.DELTA_CONTEXT_PREFIX)
+        && contextValue.endsWith(FormatJson.DELTA_CONTEXT_POSTFIX)) {
+      while (reader.hasNext()) {
+        ensureDeletedEntryMetadataExists();
+        String name = reader.nextName();
+        String value = reader.nextString();
+        if (FormatJson.ID.equals(name)) {
+          resultDeletedEntry.setUri(value);
+        } else if (FormatJson.DELTA_WHEN.equals(name)) {
+          Date when = parseWhen(value);
+          resultDeletedEntry.setWhen(when);
+        }
+      }
+    }
+  }
+
+  /**
+   * 
+   * @param value
+   * @return Date
+   * @throws EntityProviderException
+   */
+  private Date parseWhen(final String value) throws EntityProviderException {
+    try {
+      return EdmDateTimeOffset.getInstance().valueOfString(value, EdmLiteralKind.JSON, null, Date.class);
+    } catch (EdmSimpleTypeException e) {
+      throw new EntityProviderException(EntityProviderException.INVALID_DELETED_ENTRY_METADATA
+          .addContent("Unparsable format for when field value."), e);
+    }
+  }
+
+  /**
+   * 
+   * @throws IOException
+   * @throws EdmException
+   * @throws EntityProviderException
+   */
+  private void readMetadata() throws IOException, EdmException, EntityProviderException {//NOSONAR
+    String name = null;
+    String value = null;
+    reader.beginObject();
+    while (reader.hasNext()) {
+      name = reader.nextName();
+
+      if (FormatJson.PROPERTIES.equals(name)) {
+        reader.skipValue();
+        continue;
+      }
+
+      value = reader.nextString();
+      if (FormatJson.ID.equals(name)) {
+        entryMetadata.setId(value);
+      } else if (FormatJson.URI.equals(name)) {
+        entryMetadata.setUri(value);
+      } else if (FormatJson.TYPE.equals(name)) {
+        String fullQualifiedName = eia.getEntityType().getNamespace() + Edm.DELIMITER + eia.getEntityType().getName();
+        if (!fullQualifiedName.equals(value)) {
+          throw new EntityProviderException(EntityProviderException.INVALID_ENTITYTYPE.addContent(fullQualifiedName)
+              .addContent(value));
+        }
+      } else if (FormatJson.ETAG.equals(name)) {
+        entryMetadata.setEtag(value);
+      } else if (FormatJson.EDIT_MEDIA.equals(name)) {
+        mediaMetadata.setEditLink(value);
+      } else if (FormatJson.MEDIA_SRC.equals(name)) {
+        mediaMetadata.setSourceLink(value);
+      } else if (FormatJson.MEDIA_ETAG.equals(name)) {
+        mediaMetadata.setEtag(value);
+      } else if (FormatJson.CONTENT_TYPE.equals(name)) {
+        mediaMetadata.setContentType(value);
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(name).addContent(
+            FormatJson.METADATA));
+      }
+    }
+
+    reader.endObject();
+  }
+
+  /**
+   * 
+   * @throws EdmException
+   * @throws EntityProviderException
+   */
+  private void validateMetadata() throws EdmException, EntityProviderException {
+    if (eia.getEntityType().hasStream()) {
+      if (mediaMetadata.getSourceLink() == null) {
+        throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent(FormatJson.MEDIA_SRC)
+            .addContent(FormatJson.METADATA));
+      }
+      if (mediaMetadata.getContentType() == null) {
+        throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent(FormatJson.CONTENT_TYPE)
+            .addContent(FormatJson.METADATA));
+      }
+    } else {
+      if (mediaMetadata.getContentType() != null || mediaMetadata.getEditLink() != null
+          || mediaMetadata.getEtag() != null || mediaMetadata.getSourceLink() != null) {
+        throw new EntityProviderException(EntityProviderException.MEDIA_DATA_NOT_INITIAL);
+      }
+    }
+  }
+
+  /**
+   * 
+   * @param navigationPropertyName
+   * @throws IOException
+   * @throws EntityProviderException
+   * @throws EdmException
+   */
+  private void readNavigationProperty(final String navigationPropertyName) throws IOException, EntityProviderException,
+      EdmException {
+    NavigationPropertyInfo navigationPropertyInfo = eia.getNavigationPropertyInfo(navigationPropertyName);
+    if (navigationPropertyInfo == null) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent(navigationPropertyName));
+    }
+
+    JsonToken peek = reader.peek();
+    if (peek == JsonToken.BEGIN_OBJECT) {
+      reader.beginObject();
+      String name = reader.nextName();
+      if (FormatJson.DEFERRED.equals(name)) {
+        reader.beginObject();
+        String uri = reader.nextName();
+        if (FormatJson.URI.equals(uri)) {
+          String value = reader.nextString(); 
+          entryMetadata.putAssociationUri(navigationPropertyInfo.getName(), value);
+        } else {
+          throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent(uri));
+        }
+        reader.endObject();
+      } else {
+        handleInlineEntries(navigationPropertyName, name);
+      }
+      reader.endObject();
+    } else if (peek == JsonToken.NULL) {
+      reader.nextNull();
+    } else {
+      handleArray(navigationPropertyName);
+    }
+   }
+
+  /**
+   * @param navigationPropertyName
+   * @throws EdmException
+   * @throws EntityProviderException
+   * @throws IOException
+   */
+  private void handleArray(final String navigationPropertyName) throws EdmException, EntityProviderException,
+      IOException {
+    final EdmNavigationProperty navigationProperty =
+        (EdmNavigationProperty) eia.getEntityType().getProperty(navigationPropertyName);
+    final EdmEntitySet inlineEntitySet = eia.getEntitySet().getRelatedEntitySet(navigationProperty);
+    final EntityInfoAggregator inlineInfo = EntityInfoAggregator.create(inlineEntitySet);
+    OnDeserializeInlineContent callback = readProperties.getCallback();
+    DeserializerProperties inlineReadProperties;
+    try {
+      if (callback == null) {
+        inlineReadProperties =
+            DeserializerProperties.init()
+                .isValidatingFacets(readProperties.isValidatingFacets())
+                .build();
+
+      } else {
+        inlineReadProperties = callback.receiveReadProperties(readProperties, navigationProperty);
+      }
+    } catch (ODataApplicationException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+    
+    ODataFeed feed = new JsonFeedDeserializer(reader, inlineInfo, inlineReadProperties).readInlineFeedStandalone();
+    properties.put(navigationPropertyName, feed);
+    resultEntry.setContainsInlineEntry(true);
+  }
+
+  /**
+   * @param navigationPropertyName
+   * @param name
+   * @throws EdmException
+   * @throws EntityProviderException
+   * @throws IOException
+   */
+  private void handleInlineEntries(final String navigationPropertyName, String name) throws EdmException,
+      EntityProviderException, IOException {
+    EdmNavigationProperty navigationProperty =
+        (EdmNavigationProperty) eia.getEntityType().getProperty(navigationPropertyName);
+    EdmEntitySet inlineEntitySet = eia.getEntitySet().getRelatedEntitySet(navigationProperty);
+    EntityInfoAggregator inlineEia = EntityInfoAggregator.create(inlineEntitySet);
+    OnDeserializeInlineContent callback = readProperties.getCallback();
+    final DeserializerProperties inlineReadProperties;
+    try {
+      if (callback == null) {
+        inlineReadProperties =
+            DeserializerProperties.init()
+                .isValidatingFacets(readProperties.isValidatingFacets())
+                .build();
+
+      } else {
+        inlineReadProperties = callback.receiveReadProperties(readProperties, navigationProperty);
+      }
+    } catch (ODataApplicationException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+    if (navigationProperty.getMultiplicity() == EdmMultiplicity.MANY) {
+      JsonFeedDeserializer inlineConsumer = new JsonFeedDeserializer(reader, inlineEia, inlineReadProperties);
+      ODataFeed feed = inlineConsumer.readStartedInlineFeed(name);
+      properties.put(navigationPropertyName, feed);
+      resultEntry.setContainsInlineEntry(true);
+    } else {
+      JsonEntryDeserializer inlineConsumer = new JsonEntryDeserializer(reader, inlineEia, inlineReadProperties);
+      ODataEntry entry = inlineConsumer.readInlineEntry(name);
+      properties.put(navigationPropertyName, entry);
+      resultEntry.setContainsInlineEntry(true);
+    }
+  }
+  
+  /**
+   * 
+   * @param name
+   * @return ODataEntry
+   * @throws EdmException
+   * @throws EntityProviderException
+   * @throws IOException
+   */
+  private ODataEntry readInlineEntry(final String name) throws EdmException, EntityProviderException, IOException {
+    // consume the already started content
+    handleName(name);
+    // consume the rest of the entry content
+    readEntryContent();
+    return resultEntry;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonErrorDocumentDeserializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonErrorDocumentDeserializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonErrorDocumentDeserializer.java
new file mode 100644
index 0000000..8b5cc45
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonErrorDocumentDeserializer.java
@@ -0,0 +1,278 @@
+/*******************************************************************************
+ * 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.odata2.client.core.ep.deserializer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.processor.ODataErrorContext;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+
+/**
+ * Consuming (read / deserialization) for OData error document in JSON format.
+ */
+public class JsonErrorDocumentDeserializer {
+  /** Default used charset for reader */
+  private static final String DEFAULT_CHARSET = "UTF-8";
+  private static final String FOUND = "' found.";
+  /**
+   * Map containing language code (language - country) to Locale mapping
+   * based on Locale.getAvailableLocales()
+   * */
+  private static final Map<String, Locale> AVAILABLE_LOCALES = new HashMap<String, Locale>();
+  static {
+    Locale[] locales = Locale.getAvailableLocales();
+    for (Locale l : locales) {
+      AVAILABLE_LOCALES.put(l.getLanguage() + "-" + l.getCountry(), l);
+    }
+  }
+
+  /**
+   * Deserialize / read OData error document in ODataErrorContext.
+   * 
+   * @param errorDocument OData error document in JSON format
+   * @return created ODataErrorContext based on input stream content.
+   * @throws EntityProviderException if an exception during read / deserialization occurs.
+   */
+  public ODataErrorContext readError(final InputStream errorDocument) throws EntityProviderException {
+    JsonReader reader = createJsonReader(errorDocument);
+    try {
+      return parseJson(reader);
+    } catch (IOException e) {
+      throw new EntityProviderException(
+          EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getMessage()), e);
+    }
+  }
+
+  /**
+   * 
+   * @param reader
+   * @return ODataErrorContext
+   * @throws IOException
+   * @throws EntityProviderException
+   */
+  private ODataErrorContext parseJson(final JsonReader reader) throws IOException, EntityProviderException {
+    ODataErrorContext errorContext;
+
+    if (reader.hasNext()) {
+      reader.beginObject();
+      String currentName = reader.nextName();
+      if (FormatJson.ERROR.equals(currentName)) {
+        errorContext = parseError(reader);
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_STATE.addContent(
+            "Invalid object with name '" + currentName + FOUND));
+      }
+    } else {
+      throw new EntityProviderException(EntityProviderException.INVALID_STATE.addContent(
+          "No content to parse found."));
+    }
+
+    errorContext.setContentType(ContentType.APPLICATION_JSON.toContentTypeString());
+    return errorContext;
+  }
+
+  /**
+   * 
+   * @param reader
+   * @return ODataErrorContext
+   * @throws IOException
+   * @throws EntityProviderException
+   */
+  private ODataErrorContext parseError(final JsonReader reader) throws IOException, EntityProviderException {
+    ODataErrorContext errorContext = new ODataErrorContext();
+    String currentName;
+    reader.beginObject();
+    boolean messageFound = false;
+    boolean codeFound = false;
+
+    while (reader.hasNext()) {
+      currentName = reader.nextName();
+      if (FormatJson.CODE.equals(currentName)) {
+        codeFound = true;
+        errorContext.setErrorCode(getValue(reader));
+      } else if (FormatJson.MESSAGE.equals(currentName)) {
+        messageFound = true;
+        parseMessage(reader, errorContext);
+      } else if (FormatJson.INNER_ERROR.equals(currentName)) {
+        parseInnerError(reader, errorContext);
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_STATE.addContent(
+            "Invalid name '" + currentName + FOUND));
+      }
+    }
+
+    if (!codeFound) {
+      throw new EntityProviderException(
+          EntityProviderException.MISSING_PROPERTY.addContent("Mandatory 'code' property not found.'"));
+    }
+    if (!messageFound) {
+      throw new EntityProviderException(
+          EntityProviderException.MISSING_PROPERTY.addContent("Mandatory 'message' property not found.'"));
+    }
+
+    reader.endObject();
+    return errorContext;
+  }
+
+  /**
+   * 
+   * @param reader
+   * @param errorContext
+   * @throws IOException
+   */
+  private void parseInnerError(final JsonReader reader, final ODataErrorContext errorContext) throws IOException {
+    JsonToken token = reader.peek();
+    if (token == JsonToken.STRING) {
+      // implementation for parse content as provided by JsonErrorDocumentProducer
+      String innerError = reader.nextString();
+      errorContext.setInnerError(innerError);
+    } else if (token == JsonToken.BEGIN_OBJECT) {
+      // implementation for OData v2 Section 2.2.8.1.2 JSON Error Response
+      // (RFC4627 Section 2.2 -> https://www.ietf.org/rfc/rfc4627.txt))
+      // currently partial provided
+      errorContext.setInnerError(readJson(reader));
+    }
+  }
+
+  /**
+   * 
+   * @param reader
+   * @return String
+   * @throws IOException
+   */
+  private String readJson(final JsonReader reader) throws IOException {
+    StringBuilder sb = new StringBuilder();
+
+    while (reader.hasNext()) {
+      JsonToken token = reader.peek();
+      if (token == JsonToken.NAME) {
+        if (sb.length() > 0) {
+          sb.append(",");
+        }
+        String name = reader.nextName();
+        sb.append("\"").append(name).append("\"").append(":");
+      } else if (token == JsonToken.BEGIN_OBJECT) {
+        reader.beginObject();
+        sb.append("{")
+            .append(readJson(reader))
+            .append("}");
+        reader.endObject();
+      } else if (token == JsonToken.BEGIN_ARRAY) {
+        reader.beginArray();
+        sb.append("[")
+            .append(readJson(reader))
+            .append("]");
+        reader.endArray();
+      } else {
+        sb.append("\"")
+            .append(reader.nextString())
+            .append("\"");
+      }
+    }
+
+    return sb.toString();
+  }
+
+  /**
+   * 
+   * @param reader
+   * @param errorContext
+   * @throws IOException
+   * @throws EntityProviderException
+   */
+  private void parseMessage(final JsonReader reader, final ODataErrorContext errorContext)
+      throws IOException, EntityProviderException {
+
+    reader.beginObject();
+    boolean valueFound = false;
+    boolean langFound = false;
+    String currentName;
+
+    while (reader.hasNext()) {
+      currentName = reader.nextName();
+      if (FormatJson.LANG.equals(currentName)) {
+        langFound = true;
+        String langValue = getValue(reader);
+        if (langValue != null) {
+          errorContext.setLocale(getLocale(langValue));
+        }
+      } else if (FormatJson.VALUE.equals(currentName)) {
+        valueFound = true;
+        errorContext.setMessage(getValue(reader));
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_STATE.addContent("Invalid name '" +
+            currentName + FOUND));
+      }
+    }
+
+    if (!langFound) {
+      throw new EntityProviderException(
+          EntityProviderException.MISSING_PROPERTY.addContent("Mandatory 'lang' property not found.'"));
+    }
+    if (!valueFound) {
+      throw new EntityProviderException(
+          EntityProviderException.MISSING_PROPERTY.addContent("Mandatory 'value' property not found.'"));
+    }
+    reader.endObject();
+  }
+
+  private Locale getLocale(final String langValue) {
+    return AVAILABLE_LOCALES.get(langValue);
+  }
+
+  /**
+   * Read the string value from the JsonReader or 'null' if no value is available.
+   * 
+   * @param reader to read from
+   * @return the string value or 'null'
+   * @throws IOException if an exception occurs
+   */
+  private String getValue(final JsonReader reader) throws IOException {
+    JsonToken token = reader.peek();
+    if (JsonToken.NULL == token) {
+      reader.skipValue();
+      return null;
+    }
+    return reader.nextString();
+  }
+
+  private JsonReader createJsonReader(final InputStream in) throws EntityProviderException {
+    if (in == null) {
+      throw new EntityProviderException(EntityProviderException.INVALID_STATE
+          .addContent(("Got not supported NULL object as content to de-serialize.")));
+    }
+    try {
+      return new JsonReader(new InputStreamReader(in, DEFAULT_CHARSET));
+    } catch (final UnsupportedEncodingException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonFeedDeserializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonFeedDeserializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonFeedDeserializer.java
new file mode 100644
index 0000000..dd79c3a
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonFeedDeserializer.java
@@ -0,0 +1,255 @@
+/*******************************************************************************
+ * 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.odata2.client.core.ep.deserializer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.entry.DeletedEntryMetadata;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataDeltaFeed;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.client.api.ep.DeserializerProperties;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.feed.FeedMetadataImpl;
+import org.apache.olingo.odata2.core.ep.feed.JsonFeedEntry;
+import org.apache.olingo.odata2.core.ep.feed.ODataDeltaFeedImpl;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+
+/**
+ *  This class Deserializes JsonFeed payloads
+ */
+public class JsonFeedDeserializer {
+
+  private JsonReader reader;
+  private EntityInfoAggregator eia;
+  private DeserializerProperties readProperties;
+  private List<DeletedEntryMetadata> deletedEntries = new ArrayList<DeletedEntryMetadata>();
+  private List<ODataEntry> entries = new ArrayList<ODataEntry>();
+  private FeedMetadataImpl feedMetadata = new FeedMetadataImpl();
+  private boolean resultsArrayPresent = false;
+  private static final String JSONFEED = "JsonFeed";
+
+  /**
+   * 
+   * @param reader
+   * @param eia
+   * @param readProperties
+   */
+  public JsonFeedDeserializer(final JsonReader reader, final EntityInfoAggregator eia,
+      final DeserializerProperties readProperties) {
+    this.reader = reader;
+    this.eia = eia;
+    this.readProperties = readProperties;
+  }
+
+  /**
+   * 
+   * @return ODataDeltaFeed
+   * @throws EntityProviderException
+   */
+  public ODataDeltaFeed readFeedStandalone() throws EntityProviderException {
+    try {
+      readFeed();
+
+      if (reader.peek() != JsonToken.END_DOCUMENT) {
+
+        throw new EntityProviderException(EntityProviderException.END_DOCUMENT_EXPECTED.addContent(reader.peek()
+            .toString()));
+      }
+
+    } catch (IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    } catch (IllegalStateException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+    return new ODataDeltaFeedImpl(entries, feedMetadata, deletedEntries);
+  }
+
+  /**
+   * 
+   * @throws IOException
+   * @throws EdmException
+   * @throws EntityProviderException
+   */
+  private void readFeed() throws IOException, EdmException, EntityProviderException {
+    JsonToken peek = reader.peek();
+    if (peek == JsonToken.BEGIN_ARRAY) {
+      readArrayContent();
+    } else {
+      reader.beginObject();
+      final String nextName = reader.nextName();
+      if (FormatJson.D.equals(nextName)) {
+        if (reader.peek() == JsonToken.BEGIN_ARRAY) {
+          readArrayContent();
+        } else {
+          reader.beginObject();
+          readFeedContent();
+          reader.endObject();
+        }
+      } else {
+        handleName(nextName);
+        readFeedContent();
+      }
+
+      reader.endObject();
+    }
+  }
+
+  /**
+   * 
+   * @throws IOException
+   * @throws EdmException
+   * @throws EntityProviderException
+   */
+  private void readFeedContent() throws IOException, EdmException, EntityProviderException {
+    while (reader.hasNext()) {
+      final String nextName = reader.nextName();
+      handleName(nextName);
+    }
+
+    if (!resultsArrayPresent) {
+      throw new EntityProviderException(EntityProviderException.MISSING_RESULTS_ARRAY);
+    }
+  }
+
+  /**
+   * 
+   * @param nextName
+   * @throws IOException
+   * @throws EdmException
+   * @throws EntityProviderException
+   */
+  private void handleName(final String nextName) throws IOException, EdmException, EntityProviderException {
+    if (FormatJson.RESULTS.equals(nextName)) {
+      resultsArrayPresent = true;
+      readArrayContent();
+
+    } else if (FormatJson.COUNT.equals(nextName)) {
+      readInlineCount(reader, feedMetadata);
+
+    } else if (FormatJson.NEXT.equals(nextName)) {
+      if (reader.peek() == JsonToken.STRING && feedMetadata.getNextLink() == null) {
+        String nextLink = reader.nextString();
+        feedMetadata.setNextLink(nextLink);
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(nextName).addContent(
+            JSONFEED));
+      }
+
+    } else if (FormatJson.DELTA.equals(nextName)) {
+      if (reader.peek() == JsonToken.STRING && feedMetadata.getDeltaLink() == null) {
+        String deltaLink = reader.nextString();
+        feedMetadata.setDeltaLink(deltaLink);
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(nextName).addContent(
+            JSONFEED));
+      }
+    } else {
+      throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(nextName).addContent(
+          JSONFEED));
+    }
+  }
+
+  /**
+   * 
+   * @throws IOException
+   * @throws EdmException
+   * @throws EntityProviderException
+   */
+  private void readArrayContent() throws IOException, EdmException, EntityProviderException {
+    reader.beginArray();
+    while (reader.hasNext()) {
+      final JsonFeedEntry entry = new JsonEntryDeserializer(reader, eia, readProperties).readFeedEntry();
+      if (entry.isODataEntry()) {
+        entries.add(entry.getODataEntry());
+      } else {
+        deletedEntries.add(entry.getDeletedEntryMetadata());
+      }
+    }
+    reader.endArray();
+  }
+
+  /**
+   * 
+   * @param reader
+   * @param feedMetadata
+   * @throws IOException
+   * @throws EntityProviderException
+   */
+  protected static void readInlineCount(final JsonReader reader, final FeedMetadataImpl feedMetadata)
+      throws IOException, EntityProviderException {
+    if (reader.peek() == JsonToken.STRING && feedMetadata.getInlineCount() == null) {
+      int inlineCount;
+      try {
+        inlineCount = reader.nextInt();
+      } catch (final NumberFormatException e) {
+        throw new EntityProviderException(EntityProviderException.INLINECOUNT_INVALID.addContent(""), e);
+      }
+      if (inlineCount >= 0) {
+        feedMetadata.setInlineCount(inlineCount);
+      } else {
+        throw new EntityProviderException(EntityProviderException.INLINECOUNT_INVALID.addContent(inlineCount));
+      }
+    } else {
+      throw new EntityProviderException(EntityProviderException.INLINECOUNT_INVALID.addContent(reader.peek()));
+    }
+  }
+
+  /**
+   * 
+   * @param name
+   * @return ODataFeed
+   * @throws EdmException
+   * @throws EntityProviderException
+   * @throws IOException
+   */
+  protected ODataFeed readStartedInlineFeed(final String name) throws EdmException, EntityProviderException,
+      IOException {
+    // consume the already started content
+    handleName(name);
+    // consume the rest of the entry content
+    readFeedContent();
+    return new ODataDeltaFeedImpl(entries, feedMetadata);
+  }
+
+  /**
+   * 
+   * @return ODataFeed
+   * @throws EdmException
+   * @throws EntityProviderException
+   * @throws IOException
+   */
+  protected ODataFeed readInlineFeedStandalone() throws EdmException, EntityProviderException, IOException {
+    readFeed();
+    return new ODataDeltaFeedImpl(entries, feedMetadata);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonPropertyDeserializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonPropertyDeserializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonPropertyDeserializer.java
new file mode 100644
index 0000000..44d8d07
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/JsonPropertyDeserializer.java
@@ -0,0 +1,326 @@
+/*******************************************************************************
+ * 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.odata2.client.core.ep.deserializer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.client.api.ep.DeserializerProperties;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityComplexPropertyInfo;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+
+/**
+ * JSON property consumer.
+ */
+public class JsonPropertyDeserializer {
+
+  /**
+   * Deserializes Property
+   * @param reader
+   * @param edmProperty
+   * @param readProperties
+   * @return Map<String, Object>
+   * @throws EntityProviderException
+   */
+  public Map<String, Object> readPropertyStandalone(JsonReader reader, final EdmProperty edmProperty,
+      final DeserializerProperties readProperties) throws EntityProviderException {
+    return readPropertyStandalone(reader, EntityInfoAggregator.create(edmProperty), readProperties);
+  }
+
+  /**
+   * Deserializes Property
+   * @param reader
+   * @param propertyInfo
+   * @param readProperties
+   * @return Map<String, Object>
+   * @throws EntityProviderException
+   */
+  public Map<String, Object> readPropertyStandalone(final JsonReader reader, final EntityPropertyInfo propertyInfo,
+      final DeserializerProperties readProperties) throws EntityProviderException {
+    Map<String, Object> typeMappings  = null ;
+    Map<String, Object> result = new HashMap<String, Object>();
+
+    try {
+      reader.beginObject();
+      String nextName = reader.nextName();
+      if (FormatJson.D.equals(nextName)) {
+        reader.beginObject();
+        nextName = reader.nextName();
+        handleName(reader, typeMappings, propertyInfo, readProperties, result, nextName);
+        reader.endObject();
+      } else {
+        handleName(reader, typeMappings, propertyInfo, readProperties, result, nextName);
+      }
+      reader.endObject();
+
+      if (reader.peek() != JsonToken.END_DOCUMENT) {
+        throw new EntityProviderException(EntityProviderException.END_DOCUMENT_EXPECTED.addContent(reader.peek()
+            .toString()));
+      }
+
+      return result;
+    } catch (final IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    } catch (final IllegalStateException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+  }
+
+  /**
+   * This method reads through a collection of entities and deserializes each entry
+   * @param reader
+   * @param propertyInfo
+   * @param readProperties
+   * @return List<?>
+   * @throws EntityProviderException
+   */
+  public List<?> readCollection(JsonReader reader, final EntityPropertyInfo propertyInfo,
+        final DeserializerProperties readProperties) throws EntityProviderException {
+    final Object typeMapping =  null ;
+    List<Object> result = new ArrayList<Object>();
+    String name = null;
+    boolean wrapped = false;
+    boolean version2 = false;
+
+    try {
+      if (reader.peek() == JsonToken.BEGIN_OBJECT) {
+        reader.beginObject();
+        name = reader.nextName();
+        if (FormatJson.D.equals(name)) {
+          wrapped = true;
+          if (reader.peek() == JsonToken.BEGIN_OBJECT) {
+            reader.beginObject();
+            name = reader.nextName();
+          } else {
+            name = null;
+          }
+        }
+      }
+      if (name != null) {
+        version2 = true;
+        if (FormatJson.METADATA.equals(name)) {
+          readAndCheckTypeInfo(reader,
+              "Collection(" + propertyInfo.getType().getNamespace() + Edm.DELIMITER
+              + propertyInfo.getType().getName() + ")");
+          name = reader.nextName();
+        }
+        if (!FormatJson.RESULTS.equals(name)) {
+          throw new EntityProviderException(EntityProviderException.INVALID_PARENT_TAG
+              .addContent(FormatJson.RESULTS, name));
+        }
+      }
+      reader.beginArray();
+      while (reader.hasNext()) {
+        result.add(readPropertyValue(reader, propertyInfo, typeMapping, readProperties));
+      }
+      reader.endArray();
+      if (version2) {
+        reader.endObject();
+      }
+      if (wrapped) {
+        reader.endObject();
+      }
+
+      if (reader.peek() != JsonToken.END_DOCUMENT) {
+        throw new EntityProviderException(EntityProviderException.END_DOCUMENT_EXPECTED
+            .addContent(reader.peek().toString()));
+      }
+
+      return result;
+    } catch (final EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED
+          .addContent(e.getClass().getSimpleName()), e);
+    } catch (final IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED
+          .addContent(e.getClass().getSimpleName()), e);
+    } catch (final IllegalStateException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED
+          .addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  private void handleName(final JsonReader reader, final Map<String, Object> typeMappings,
+      final EntityPropertyInfo entityPropertyInfo, final DeserializerProperties readProperties,
+      final Map<String, Object> result, final String nextName) throws EntityProviderException {
+    if (!entityPropertyInfo.getName().equals(nextName)) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent(nextName));
+    }
+    final Object mapping = typeMappings == null ? null : typeMappings.get(nextName);
+    final Object propertyValue = readPropertyValue(reader, entityPropertyInfo, mapping, readProperties);
+    result.put(nextName, propertyValue);
+  }
+
+  protected Object readPropertyValue(final JsonReader reader, final EntityPropertyInfo entityPropertyInfo,
+      final Object typeMapping, final DeserializerProperties readProperties)
+          throws EntityProviderException {
+    try {
+      return entityPropertyInfo.isComplex() ?
+          readComplexProperty(reader, (EntityComplexPropertyInfo) entityPropertyInfo, typeMapping, readProperties) :
+          readSimpleProperty(reader, entityPropertyInfo, typeMapping, readProperties);
+    } catch (final EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    } catch (final IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+  }
+
+  private Object readSimpleProperty(final JsonReader reader, final EntityPropertyInfo entityPropertyInfo,
+      final Object typeMapping, final DeserializerProperties readProperties)
+      throws EdmException, EntityProviderException, IOException {
+    final EdmSimpleType type = (EdmSimpleType) entityPropertyInfo.getType();
+    Object value = null;
+    final JsonToken tokenType = reader.peek();
+    if (tokenType == JsonToken.NULL) {
+      reader.nextNull();
+    } else {
+      switch (EdmSimpleTypeKind.valueOf(type.getName())) {
+      case Boolean:
+        if (tokenType == JsonToken.BOOLEAN) {
+          value = reader.nextBoolean();
+          value = value.toString();
+        } else {
+          throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY_VALUE
+              .addContent(entityPropertyInfo.getName()));
+        }
+        break;
+      case Byte:
+      case SByte:
+      case Int16:
+      case Int32:
+        if (tokenType == JsonToken.NUMBER) {
+          value = reader.nextInt();
+          value = value.toString();
+        } else {
+          throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY_VALUE
+              .addContent(entityPropertyInfo.getName()));
+        }
+        break;
+      case Single:
+      case Double:
+        if (tokenType == JsonToken.STRING) {
+          value = reader.nextString();
+        } else if (tokenType == JsonToken.NUMBER) {
+          value = reader.nextDouble();
+          value = value.toString();
+        } else {
+          throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY_VALUE
+              .addContent(entityPropertyInfo.getName()));
+        }
+        break;
+      default:
+        if (tokenType == JsonToken.STRING) {
+          value = reader.nextString();
+        } else {
+          throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY_VALUE
+              .addContent(entityPropertyInfo.getName()));
+        }
+        break;
+      }
+    }
+
+    final Class<?> typeMappingClass = typeMapping == null ? type.getDefaultType() : (Class<?>) typeMapping;
+    final EdmFacets facets = readProperties == null || readProperties.isValidatingFacets() ?
+        entityPropertyInfo.getFacets() : null;
+    return type.valueOfString((String) value, EdmLiteralKind.JSON, facets, typeMappingClass);
+  }
+
+  @SuppressWarnings("unchecked")
+  private Object readComplexProperty(final JsonReader reader, final EntityComplexPropertyInfo complexPropertyInfo,
+      final Object typeMapping, final DeserializerProperties readProperties)
+      throws EdmException, EntityProviderException, IOException {
+    if (reader.peek().equals(JsonToken.NULL)) {
+      reader.nextNull();
+      if ((readProperties == null || readProperties.isValidatingFacets()) && complexPropertyInfo.isMandatory()) {
+        throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY_VALUE.addContent(complexPropertyInfo
+            .getName()));
+      }
+      return null;
+    }
+
+    reader.beginObject();
+    Map<String, Object> data = new HashMap<String, Object>();
+
+    Map<String, Object> mapping;
+    if (typeMapping != null) {
+      if (typeMapping instanceof Map) {
+        mapping = (Map<String, Object>) typeMapping;
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_MAPPING.addContent(complexPropertyInfo
+            .getName()));
+      }
+    } else {
+      mapping = new HashMap<String, Object>();
+    }
+
+    while (reader.hasNext()) {
+      final String childName = reader.nextName();
+      if (FormatJson.METADATA.equals(childName)) {
+        readAndCheckTypeInfo(reader,
+            complexPropertyInfo.getType().getNamespace() + Edm.DELIMITER + complexPropertyInfo.getType().getName());
+      } else {
+        EntityPropertyInfo childPropertyInfo = complexPropertyInfo.getPropertyInfo(childName);
+        if (childPropertyInfo == null) {
+          throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY.addContent(childName));
+        }
+        Object childData = readPropertyValue(reader, childPropertyInfo, mapping.get(childName), readProperties);
+        if (data.containsKey(childName)) {
+          throw new EntityProviderException(EntityProviderException.DOUBLE_PROPERTY.addContent(childName));
+        }
+        data.put(childName, childData);
+      }
+    }
+    reader.endObject();
+    return data;
+  }
+
+  protected void readAndCheckTypeInfo(final JsonReader reader, String expectedTypeName)
+          throws IOException, EntityProviderException {
+    reader.beginObject();
+    if (!FormatJson.TYPE.equals(reader.nextName())) {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent(FormatJson.TYPE)
+          .addContent(FormatJson.METADATA));
+    }
+    final String actualTypeName = reader.nextString();
+    if (!expectedTypeName.equals(actualTypeName)) {
+      throw new EntityProviderException(EntityProviderException.INVALID_ENTITYTYPE.addContent(expectedTypeName)
+          .addContent(actualTypeName));
+    }
+    reader.endObject();
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/9e949e40/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlEntityDeserializer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlEntityDeserializer.java b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlEntityDeserializer.java
new file mode 100644
index 0000000..ea3393c
--- /dev/null
+++ b/odata2-lib/odata-client-core/src/main/java/org/apache/olingo/odata2/client/core/ep/deserializer/XmlEntityDeserializer.java
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * 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.odata2.client.core.ep.deserializer;
+
+import java.util.Map;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataDeltaFeed;
+import org.apache.olingo.odata2.client.api.ep.EntityStream;
+import org.apache.olingo.odata2.core.commons.XmlHelper;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+
+/**
+ * Xml entity (content type dependent) consumer for reading input (from <code>content</code>).
+ * 
+ * 
+ */
+public class XmlEntityDeserializer {
+
+  /**
+   * 
+   * @throws EntityProviderException
+   */
+  public XmlEntityDeserializer() throws EntityProviderException {
+    super();
+  }
+
+  /**
+   * Returns an ODataDeltaFeed deserializing EntityStream
+   * @param entitySet
+   * @param entity
+   * @return ODataDeltaFeed
+   * @throws EntityProviderException
+   */
+  public ODataDeltaFeed readFeed(final EdmEntitySet entitySet, final EntityStream entity)
+      throws EntityProviderException {
+    XMLStreamReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      reader = XmlHelper.createStreamReader(entity.getContent());
+
+      EntityInfoAggregator eia = EntityInfoAggregator.create(entitySet);
+      XmlFeedDeserializer xfc = new XmlFeedDeserializer();
+      return xfc.readFeed(reader, eia, entity.getReadProperties());
+    } catch (EntityProviderException e) {
+      cachedException = e;
+      throw cachedException;
+    } finally { //NOPMD  - suppressed
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (XMLStreamException e) {
+          if (cachedException != null) {
+            throw cachedException; //NOSONAR
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.//NOSONAR
+                addContent(e.getClass() 
+                .getSimpleName()), e);
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * Returns an ODataEntry deserializing EntityStream
+   * @param entitySet
+   * @param entity
+   * @return ODataEntry
+   * @throws EntityProviderException
+   */
+  public ODataEntry readEntry(final EdmEntitySet entitySet, final EntityStream entity)
+      throws EntityProviderException {
+    XMLStreamReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      reader = XmlHelper.createStreamReader(entity.getContent());
+      EntityInfoAggregator eia = EntityInfoAggregator.create(entitySet);
+
+      return new XmlEntryDeserializer().readEntry(reader, eia, entity.getReadProperties(), false);
+    } catch (EntityProviderException e) {
+      cachedException = e;
+      throw cachedException;
+    } finally {//NOPMD  - suppressed
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (XMLStreamException e) {
+          if (cachedException != null) {
+            throw cachedException; //NOSONAR
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.//NOSONAR
+                addContent(e.getClass() 
+                .getSimpleName()), e); 
+          }
+        }
+      }
+    }
+  }
+  
+  /**
+   * 
+   * @param info
+   * @param entityStream
+   * @return
+   * @throws EntityProviderException
+   */
+  public Object readCollection(final EntityPropertyInfo info, EntityStream entityStream) 
+      throws EntityProviderException {
+    XMLStreamReader reader = null;
+    EntityProviderException cachedException = null;
+    try {
+      reader = XmlHelper.createStreamReader(entityStream.getContent());
+      return new XmlPropertyDeserializer().readCollection(reader, info, entityStream.getReadProperties());
+    } catch (final EntityProviderException e) {
+      cachedException = e;
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (final XMLStreamException e) {
+          if (cachedException != null) {
+            throw cachedException;
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED
+                .addContent(e.getClass().getSimpleName()), e);
+          }
+        }
+      }
+    }
+  }
+  
+  /**
+   * 
+   * @param propertyInfo
+   * @param entityStream
+   * @return
+   * @throws EntityProviderException
+   */
+  public Map<String, Object> readProperty(final EntityPropertyInfo propertyInfo, final EntityStream entityStream)
+      throws EntityProviderException {
+    XMLStreamReader reader = null;
+    EntityProviderException cachedException = null;
+    try {
+      reader = XmlHelper.createStreamReader(entityStream.getContent());
+      return new XmlPropertyDeserializer().readProperty(reader, propertyInfo, entityStream.getReadProperties());
+    } catch (EntityProviderException e) {
+      cachedException = e;
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (XMLStreamException e) {
+          if (cachedException != null) {
+            throw cachedException;
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+                .getSimpleName()), e);
+          }
+        }
+      }
+    }
+  }
+}