You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by fm...@apache.org on 2013/07/26 13:22:22 UTC

[17/51] [partial] initial commit

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityPropertyInfo.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityPropertyInfo.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityPropertyInfo.java
new file mode 100644
index 0000000..283d81a
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityPropertyInfo.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * 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.core.ep.aggregator;
+
+import org.apache.olingo.odata2.api.edm.EdmCustomizableFeedMappings;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmType;
+
+/**
+ * Collects informations about a property of an entity.
+ * @author SAP AG
+ */
+public class EntityPropertyInfo {
+  private String name;
+  private EdmType type;
+  private EdmFacets facets;
+  private EdmCustomizableFeedMappings customMapping;
+  private String mimeType;
+  private EdmMapping mapping;
+
+  EntityPropertyInfo(final String name, final EdmType type, final EdmFacets facets, final EdmCustomizableFeedMappings customizableFeedMapping, final String mimeType, final EdmMapping mapping) {
+    this.name = name;
+    this.type = type;
+    this.facets = facets;
+    customMapping = customizableFeedMapping;
+    this.mimeType = mimeType;
+    this.mapping = mapping;
+  }
+
+  static EntityPropertyInfo create(final EdmProperty property) throws EdmException {
+    return new EntityPropertyInfo(
+        property.getName(),
+        property.getType(),
+        property.getFacets(),
+        property.getCustomizableFeedMappings(),
+        property.getMimeType(),
+        property.getMapping());
+  }
+
+  public boolean isMandatory() {
+    if (facets == null) {
+      return false;
+    } else if (facets.isNullable() == null) {
+      return false;
+    } else {
+      return !facets.isNullable();
+    }
+  }
+
+  public boolean isComplex() {
+    return false;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public EdmType getType() {
+    return type;
+  }
+
+  public EdmFacets getFacets() {
+    return facets;
+  }
+
+  public EdmCustomizableFeedMappings getCustomMapping() {
+    return customMapping;
+  }
+
+  public String getMimeType() {
+    return mimeType;
+  }
+
+  public EdmMapping getMapping() {
+    return mapping;
+  }
+
+  @Override
+  public String toString() {
+    return name;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityTypeMapping.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityTypeMapping.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityTypeMapping.java
new file mode 100644
index 0000000..ba82f30
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityTypeMapping.java
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * 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.core.ep.aggregator;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+
+/**
+ * @author SAP AG
+ */
+public class EntityTypeMapping {
+  private static final EntityTypeMapping ENTITY_TYPE_MAPPING = new EntityTypeMapping();
+  final String propertyName;
+  final Class<?> mapping;
+  final List<EntityTypeMapping> mappings;
+
+  private EntityTypeMapping() {
+    this(null, Object.class);
+  }
+
+  private EntityTypeMapping(final String name, final Class<?> mappingClass) {
+    propertyName = name;
+    mapping = mappingClass;
+    mappings = Collections.emptyList();
+  }
+
+  private EntityTypeMapping(final String name, final List<EntityTypeMapping> typeMappings) {
+    propertyName = name;
+    mapping = EntityTypeMapping.class;
+    List<EntityTypeMapping> tmp = new ArrayList<EntityTypeMapping>();
+    for (EntityTypeMapping typeMapping : typeMappings) {
+      tmp.add(typeMapping);
+    }
+    mappings = Collections.unmodifiableList(tmp);
+  }
+
+  public static EntityTypeMapping create(final Map<String, Object> mappings) throws EntityProviderException {
+    return create(null, mappings);
+  }
+
+  @SuppressWarnings("unchecked")
+  public static EntityTypeMapping create(final String name, final Map<String, Object> mappings) throws EntityProviderException {
+    if (mappings == null) {
+      return ENTITY_TYPE_MAPPING;
+    }
+    List<EntityTypeMapping> typeMappings = new ArrayList<EntityTypeMapping>();
+    Set<Entry<String, Object>> entries = mappings.entrySet();
+    for (Entry<String, Object> entry : entries) {
+      EntityTypeMapping typeMapping;
+      Object value = entry.getValue();
+      if (value instanceof Map) {
+        typeMapping = create(entry.getKey(), (Map<String, Object>) value);
+      } else if (value instanceof Class) {
+        typeMapping = new EntityTypeMapping(entry.getKey(), (Class<?>) value);
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_MAPPING.addContent(entry.getKey()));
+      }
+      typeMappings.add(typeMapping);
+    }
+
+    return new EntityTypeMapping(name, typeMappings);
+  }
+
+  boolean isComplex() {
+    return mappings != null && mapping == EntityTypeMapping.class;
+  }
+
+  /**
+   * If this {@link EntityTypeMapping} is complex the mapping for the property
+   * with the given <code>name</code> is returned; otherwise an empty
+   * {@link EntityTypeMapping} is returned.
+   * @param name
+   * @return the mapping for this entity type
+   */
+  public EntityTypeMapping getEntityTypeMapping(final String name) {
+    if (isComplex()) {
+      for (EntityTypeMapping mapping : mappings) {
+        if (mapping.propertyName.equals(name)) {
+          return mapping;
+        }
+      }
+    }
+    return ENTITY_TYPE_MAPPING;
+  }
+
+  /**
+   * If this {@link EntityTypeMapping} is complex the mapping {@link Class} for the property
+   * with the given <code>name</code> is returned; otherwise <code>NULL</code> is returned.
+   * @param name
+   * @return mapping {@link Class} for the property with given <code>name</code> or <code>NULL</code>.
+   */
+  public Class<?> getMappingClass(final String name) {
+    if (isComplex()) {
+      for (EntityTypeMapping mapping : mappings) {
+        if (mapping.propertyName.equals(name)) {
+          return mapping.mapping;
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public String toString() {
+    if (isComplex()) {
+      return "{'" + propertyName + "'->" + mappings.toString() + "}";
+    }
+    return "{'" + propertyName + "' as " + (mapping == null ? "NULL" : mapping.getSimpleName()) + "}";
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/NavigationPropertyInfo.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/NavigationPropertyInfo.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/NavigationPropertyInfo.java
new file mode 100644
index 0000000..7918a69
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/NavigationPropertyInfo.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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.core.ep.aggregator;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+
+public final class NavigationPropertyInfo {
+  private String name;
+  private EdmMultiplicity multiplicity;
+
+  static NavigationPropertyInfo create(final EdmNavigationProperty property) throws EdmException {
+    NavigationPropertyInfo info = new NavigationPropertyInfo();
+    info.name = property.getName();
+    info.multiplicity = property.getMultiplicity();
+    return info;
+  }
+
+  @Override
+  public String toString() {
+    return name + "; multiplicity=" + multiplicity;
+  }
+
+  public EdmMultiplicity getMultiplicity() {
+    return multiplicity;
+  }
+
+  public String getName() {
+    return name;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/AtomServiceDocumentConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/AtomServiceDocumentConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/AtomServiceDocumentConsumer.java
new file mode 100644
index 0000000..716c4bb
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/AtomServiceDocumentConsumer.java
@@ -0,0 +1,312 @@
+/*******************************************************************************
+ * 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.core.ep.consumer;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.servicedocument.Accept;
+import org.apache.olingo.odata2.api.servicedocument.Categories;
+import org.apache.olingo.odata2.api.servicedocument.Category;
+import org.apache.olingo.odata2.api.servicedocument.Collection;
+import org.apache.olingo.odata2.api.servicedocument.ExtensionAttribute;
+import org.apache.olingo.odata2.api.servicedocument.ExtensionElement;
+import org.apache.olingo.odata2.api.servicedocument.Fixed;
+import org.apache.olingo.odata2.api.servicedocument.Workspace;
+import org.apache.olingo.odata2.core.ep.util.FormatXml;
+import org.apache.olingo.odata2.core.servicedocument.AcceptImpl;
+import org.apache.olingo.odata2.core.servicedocument.AtomInfoImpl;
+import org.apache.olingo.odata2.core.servicedocument.CategoriesImpl;
+import org.apache.olingo.odata2.core.servicedocument.CategoryImpl;
+import org.apache.olingo.odata2.core.servicedocument.CollectionImpl;
+import org.apache.olingo.odata2.core.servicedocument.CommonAttributesImpl;
+import org.apache.olingo.odata2.core.servicedocument.ExtensionAttributeImpl;
+import org.apache.olingo.odata2.core.servicedocument.ExtensionElementImpl;
+import org.apache.olingo.odata2.core.servicedocument.ServiceDocumentImpl;
+import org.apache.olingo.odata2.core.servicedocument.TitleImpl;
+import org.apache.olingo.odata2.core.servicedocument.WorkspaceImpl;
+
+public class AtomServiceDocumentConsumer {
+  private String currentHandledStartTagName;
+  private static final String DEFAULT_PREFIX = "";
+
+  public ServiceDocumentImpl readServiceDokument(final XMLStreamReader reader) throws EntityProviderException {
+    AtomInfoImpl atomInfo = new AtomInfoImpl();
+    ServiceDocumentImpl serviceDocument = new ServiceDocumentImpl();
+    List<Workspace> workspaces = new ArrayList<Workspace>();
+    List<ExtensionElement> extElements = new ArrayList<ExtensionElement>();
+    CommonAttributesImpl attributes = new CommonAttributesImpl();
+    try {
+      while (reader.hasNext()
+          && !(reader.isEndElement() && Edm.NAMESPACE_APP_2007.equals(reader.getNamespaceURI()) && FormatXml.APP_SERVICE.equals(reader.getLocalName()))) {
+        reader.next();
+        if (reader.isStartElement()) {
+          currentHandledStartTagName = reader.getLocalName();
+          if (FormatXml.APP_SERVICE.equals(currentHandledStartTagName)) {
+            attributes = parseCommonAttribute(reader);
+          } else if (FormatXml.APP_WORKSPACE.equals(currentHandledStartTagName)) {
+            workspaces.add(parseWorkspace(reader));
+          } else {
+            ExtensionElementImpl extElement = parseExtensionElement(reader);
+            if (extElement != null) {
+              extElements.add(extElement);
+            }
+          }
+        }
+      }
+      if (workspaces.isEmpty()) {
+        throw new EntityProviderException(EntityProviderException.INVALID_STATE.addContent("Service element must contain at least one workspace element"));
+      }
+      reader.close();
+      atomInfo.setWorkspaces(workspaces).setCommonAttributes(attributes).setExtesionElements(extElements);
+
+      serviceDocument.setAtomInfo(atomInfo);
+      serviceDocument.setEntitySetsInfo(atomInfo.getEntitySetsInfo());
+      return serviceDocument;
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  private CommonAttributesImpl parseCommonAttribute(final XMLStreamReader reader) {
+    CommonAttributesImpl attribute = new CommonAttributesImpl();
+    List<ExtensionAttribute> extAttributes = new ArrayList<ExtensionAttribute>();
+    attribute.setBase(reader.getAttributeValue(null, FormatXml.XML_BASE));
+    attribute.setLang(reader.getAttributeValue(null, FormatXml.XML_LANG));
+    for (int i = 0; i < reader.getAttributeCount(); i++) {
+      if (!(FormatXml.XML_BASE.equals(reader.getAttributeLocalName(i)) && Edm.PREFIX_XML.equals(reader.getAttributePrefix(i))
+          || (FormatXml.XML_LANG.equals(reader.getAttributeLocalName(i)) && Edm.PREFIX_XML.equals(reader.getAttributePrefix(i)))
+          || ("local".equals(reader.getAttributeNamespace(i)) || DEFAULT_PREFIX.equals(reader.getAttributePrefix(i))))) {
+        extAttributes.add(new ExtensionAttributeImpl()
+            .setName(reader.getAttributeLocalName(i))
+            .setNamespace(reader.getAttributeNamespace(i))
+            .setPrefix(reader.getAttributePrefix(i))
+            .setText(reader.getAttributeValue(i)));
+      }
+    }
+
+    return attribute.setAttributes(extAttributes);
+  }
+
+  private WorkspaceImpl parseWorkspace(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_APP_2007, FormatXml.APP_WORKSPACE);
+
+    TitleImpl title = null;
+    List<Collection> collections = new ArrayList<Collection>();
+    List<ExtensionElement> extElements = new ArrayList<ExtensionElement>();
+    CommonAttributesImpl attributes = parseCommonAttribute(reader);
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_APP_2007.equals(reader.getNamespaceURI()) && FormatXml.APP_WORKSPACE.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        currentHandledStartTagName = reader.getLocalName();
+        if (FormatXml.APP_COLLECTION.equals(currentHandledStartTagName)) {
+          collections.add(parseCollection(reader));
+        } else if (FormatXml.ATOM_TITLE.equals(currentHandledStartTagName)) {
+          title = parseTitle(reader);
+        } else {
+          extElements.add(parseExtensionSansTitleElement(reader));
+        }
+      }
+    }
+    if (title == null) {
+      throw new EntityProviderException(EntityProviderException.INVALID_STATE.addContent("Missing element title for workspace"));
+    }
+    return new WorkspaceImpl().setTitle(title).setCollections(collections).setAttributes(attributes).setExtesionElements(extElements);
+  }
+
+  private CollectionImpl parseCollection(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_APP_2007, FormatXml.APP_COLLECTION);
+    TitleImpl title = null;
+    String resourceIdentifier = reader.getAttributeValue(null, FormatXml.ATOM_HREF);
+    CommonAttributesImpl attributes = parseCommonAttribute(reader);
+    List<ExtensionElement> extElements = new ArrayList<ExtensionElement>();
+    List<Accept> acceptList = new ArrayList<Accept>();
+    List<Categories> categories = new ArrayList<Categories>();
+    if (resourceIdentifier == null) {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent("href"));
+    }
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_APP_2007.equals(reader.getNamespaceURI()) && FormatXml.APP_COLLECTION.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        currentHandledStartTagName = reader.getLocalName();
+        if (FormatXml.ATOM_TITLE.equals(currentHandledStartTagName)) {
+          title = parseTitle(reader);
+        } else if (FormatXml.APP_ACCEPT.equals(currentHandledStartTagName)) {
+          acceptList.add(parseAccept(reader));
+        } else if (FormatXml.APP_CATEGORIES.equals(currentHandledStartTagName)) {
+          categories.add(parseCategories(reader));
+        } else {
+          extElements.add(parseExtensionSansTitleElement(reader));
+        }
+      }
+    }
+    return new CollectionImpl().setHref(resourceIdentifier).setTitle(title).setCommonAttributes(attributes).setExtesionElements(extElements).setAcceptElements(acceptList).setCategories(categories);
+  }
+
+  private TitleImpl parseTitle(final XMLStreamReader reader) throws XMLStreamException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_TITLE);
+    String text = "";
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_ATOM_2005.equals(reader.getNamespaceURI()) && FormatXml.ATOM_TITLE.equals(reader.getLocalName()))) {
+      if (reader.isCharacters()) {
+        text += reader.getText();
+      }
+      reader.next();
+    }
+    return new TitleImpl().setText(text);
+  }
+
+  private AcceptImpl parseAccept(final XMLStreamReader reader) throws XMLStreamException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_APP_2007, FormatXml.APP_ACCEPT);
+    CommonAttributesImpl commonAttributes = parseCommonAttribute(reader);
+    String text = "";
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_APP_2007.equals(reader.getNamespaceURI()) && FormatXml.APP_ACCEPT.equals(reader.getLocalName()))) {
+      if (reader.isCharacters()) {
+        text += reader.getText();
+      }
+      reader.next();
+    }
+    return new AcceptImpl().setCommonAttributes(commonAttributes).setText(text);
+  }
+
+  private CategoriesImpl parseCategories(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_APP_2007, FormatXml.APP_CATEGORIES);
+    CategoriesImpl categories = new CategoriesImpl();
+    String href = reader.getAttributeValue(null, FormatXml.ATOM_HREF);
+    String fixed = reader.getAttributeValue(null, FormatXml.APP_CATEGORIES_FIXED);
+    categories.setScheme(reader.getAttributeValue(null, FormatXml.APP_CATEGORIES_SCHEME));
+    categories.setHref(href);
+    if (href == null) {
+      for (int i = 0; i < Fixed.values().length; i++) {
+        if (Fixed.values()[i].name().equalsIgnoreCase(fixed)) {
+          categories.setFixed(Fixed.values()[i]);
+        }
+      }
+      if (categories.getFixed() == null) {
+        categories.setFixed(Fixed.NO);
+      }
+      List<Category> categoriesList = new ArrayList<Category>();
+      while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_APP_2007.equals(reader.getNamespaceURI()) && FormatXml.APP_CATEGORIES.equals(reader.getLocalName()))) {
+        reader.next();
+        if (reader.isStartElement()) {
+          currentHandledStartTagName = reader.getLocalName();
+          if (FormatXml.ATOM_CATEGORY.equals(currentHandledStartTagName)) {
+            categoriesList.add(parseCategory(reader));
+          }
+        }
+      }
+      categories.setCategoryList(categoriesList);
+    }
+    if ((href != null && fixed != null && categories.getScheme() != null) ||
+        (href == null && fixed == null && categories.getScheme() == null)) {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent("for the element categories"));
+    }
+    return categories;
+  }
+
+  private CategoryImpl parseCategory(final XMLStreamReader reader) throws XMLStreamException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_CATEGORY);
+    CategoryImpl category = new CategoryImpl();
+    category.setScheme(reader.getAttributeValue(null, FormatXml.ATOM_CATEGORY_SCHEME));
+    category.setTerm(reader.getAttributeValue(null, FormatXml.ATOM_CATEGORY_TERM));
+    category.setLabel(reader.getAttributeValue(null, FormatXml.ATOM_CATEGORY_LABEL));
+    CommonAttributesImpl attributes = parseCommonAttribute(reader);
+    return category.setCommonAttributes(attributes);
+  }
+
+  private ExtensionElementImpl parseExtensionSansTitleElement(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    ExtensionElementImpl extElement = new ExtensionElementImpl();
+    if (!(Edm.NAMESPACE_APP_2007.equals(reader.getNamespaceURI())
+    || (FormatXml.ATOM_TITLE.equals(reader.getLocalName()) && Edm.NAMESPACE_ATOM_2005.equals(reader.getNamespaceURI())))) {
+      extElement = parseElement(reader);
+    }
+    return extElement;
+  }
+
+  private ExtensionElementImpl parseExtensionElement(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    ExtensionElementImpl extElement = null;
+    if (!Edm.NAMESPACE_APP_2007.equals(reader.getNamespaceURI())) {
+      extElement = parseElement(reader);
+    }
+    return extElement;
+  }
+
+  private ExtensionElementImpl parseElement(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    List<ExtensionElement> extensionElements = new ArrayList<ExtensionElement>();
+    ExtensionElementImpl extElement = new ExtensionElementImpl().setName(reader.getLocalName()).setNamespace(reader.getNamespaceURI()).setPrefix(reader.getPrefix());
+    extElement.setAttributes(parseAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && extElement.getName() != null && extElement.getName().equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isCharacters()) {
+        extElement.setText(reader.getText());
+      } else if (reader.isStartElement()) {
+        extensionElements.add(parseExtensionElement(reader));
+      }
+    }
+    extElement.setElements(extensionElements);
+    if (extElement.getText() == null && extElement.getAttributes().isEmpty() && extElement.getElements().isEmpty()) {
+      throw new EntityProviderException(EntityProviderException.INVALID_STATE.addContent("Invalid extension element"));
+    }
+    return extElement;
+  }
+
+  private List<ExtensionAttribute> parseAttribute(final XMLStreamReader reader) {
+    List<ExtensionAttribute> extAttributes = new ArrayList<ExtensionAttribute>();
+    for (int i = 0; i < reader.getAttributeCount(); i++) {
+      {
+        extAttributes.add(new ExtensionAttributeImpl()
+            .setName(reader.getAttributeLocalName(i))
+            .setNamespace(reader.getAttributeNamespace(i))
+            .setPrefix(reader.getAttributePrefix(i))
+            .setText(reader.getAttributeValue(i)));
+      }
+    }
+
+    return extAttributes;
+  }
+
+  public ServiceDocumentImpl parseXml(final InputStream in) throws EntityProviderException {
+    return readServiceDokument(createStreamReader(in));
+  }
+
+  private XMLStreamReader createStreamReader(final InputStream in) throws EntityProviderException {
+    if (in != null) {
+      XMLInputFactory factory = XMLInputFactory.newInstance();
+      factory.setProperty(XMLInputFactory.IS_VALIDATING, false);
+      factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
+      XMLStreamReader streamReader;
+      try {
+        streamReader = factory.createXMLStreamReader(in);
+      } catch (XMLStreamException e) {
+        throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+      }
+      return streamReader;
+    } else {
+      throw new EntityProviderException(EntityProviderException.INVALID_STATE.addContent("Null InputStream"));
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntityConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntityConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntityConsumer.java
new file mode 100644
index 0000000..9185ad0
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntityConsumer.java
@@ -0,0 +1,192 @@
+/*******************************************************************************
+ * 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.core.ep.consumer;
+
+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 com.google.gson.stream.JsonReader;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+
+/**
+ * @author SAP AG
+ */
+public class JsonEntityConsumer {
+
+  /** Default used charset for reader */
+  private static final String DEFAULT_CHARSET = "UTF-8";
+
+  public ODataEntry readEntry(final EdmEntitySet entitySet, final InputStream content, final EntityProviderReadProperties properties) throws EntityProviderException {
+    JsonReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      EntityInfoAggregator eia = EntityInfoAggregator.create(entitySet);
+      reader = createJsonReader(content);
+
+      JsonEntryConsumer jec = new JsonEntryConsumer(reader, eia, properties);
+      ODataEntry result = jec.readSingleEntry();
+      return result;
+    } 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) {
+          if (cachedException != null) {
+            throw cachedException;
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+          }
+        }
+      }
+    }
+  }
+
+  public ODataFeed readFeed(final EdmEntitySet entitySet, final InputStream content, final EntityProviderReadProperties readProperties) throws EntityProviderException {
+    JsonReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      EntityInfoAggregator eia = EntityInfoAggregator.create(entitySet);
+      reader = createJsonReader(content);
+
+      JsonFeedConsumer jfc = new JsonFeedConsumer(reader, eia, readProperties);
+      ODataFeed result = jfc.readFeedStandalone();
+
+      return result;
+    } 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) {
+          if (cachedException != null) {
+            throw cachedException;
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+          }
+        }
+      }
+    }
+  }
+
+  public Map<String, Object> readProperty(final EdmProperty property, final InputStream content, final EntityProviderReadProperties readProperties) throws EntityProviderException {
+    JsonReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      reader = createJsonReader(content);
+      return new JsonPropertyConsumer().readPropertyStandalone(reader, property, readProperties);
+    } 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 String readLink(final EdmEntitySet entitySet, final Object content) throws EntityProviderException {
+    JsonReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      reader = createJsonReader(content);
+      return new JsonLinkConsumer().readLink(reader, entitySet);
+    } 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 List<String> readLinks(final EdmEntitySet entitySet, final Object content) throws EntityProviderException {
+    JsonReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      reader = createJsonReader(content);
+      return new JsonLinkConsumer().readLinks(reader, entitySet);
+    } 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);
+          }
+        }
+      }
+    }
+  }
+
+  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."));
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntryConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntryConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntryConsumer.java
new file mode 100644
index 0000000..6d54f5c
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntryConsumer.java
@@ -0,0 +1,311 @@
+/*******************************************************************************
+ * 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.core.ep.consumer;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+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.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
+import org.apache.olingo.odata2.api.ep.callback.OnReadInlineContent;
+import org.apache.olingo.odata2.api.ep.callback.ReadEntryResult;
+import org.apache.olingo.odata2.api.ep.callback.ReadFeedResult;
+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.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.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.util.FormatJson;
+import org.apache.olingo.odata2.core.uri.ExpandSelectTreeNodeImpl;
+
+/**
+ * @author SAP AG
+ */
+public class JsonEntryConsumer {
+
+  private final Map<String, Object> properties = new HashMap<String, Object>();
+  private final MediaMetadataImpl mediaMetadata = new MediaMetadataImpl();
+  private final EntryMetadataImpl entryMetadata = new EntryMetadataImpl();
+  private final ExpandSelectTreeNodeImpl expandSelectTree = new ExpandSelectTreeNodeImpl();
+  private final Map<String, Object> typeMappings;
+  private final EntityInfoAggregator eia;
+  private final JsonReader reader;
+  private final EntityProviderReadProperties readProperties;
+  private final ODataEntryImpl entryResult;
+
+  public JsonEntryConsumer(final JsonReader reader, final EntityInfoAggregator eia, final EntityProviderReadProperties readProperties) {
+    typeMappings = readProperties.getTypeMappings();
+    this.eia = eia;
+    this.readProperties = readProperties;
+    this.reader = reader;
+    entryResult = new ODataEntryImpl(properties, mediaMetadata, entryMetadata, expandSelectTree);
+  }
+
+  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 entryResult;
+  }
+
+  public ODataEntry readFeedEntry() throws EdmException, EntityProviderException, IOException {
+    reader.beginObject();
+    readEntryContent();
+    reader.endObject();
+    return entryResult;
+  }
+
+  private void readEntryContent() throws IOException, EdmException, EntityProviderException {
+    while (reader.hasNext()) {
+      String name = reader.nextName();
+      handleName(name);
+    }
+
+    //TODO: validate created entry
+  }
+
+  private void handleName(final String name) throws IOException, EdmException, EntityProviderException {
+    if (FormatJson.METADATA.equals(name)) {
+      readMetadata();
+      validateMetadata();
+    } else {
+      EntityPropertyInfo propertyInfo = eia.getPropertyInfo(name);
+      if (propertyInfo != null) {
+        JsonPropertyConsumer jpc = new JsonPropertyConsumer();
+        Object propertyValue = jpc.readPropertyValue(reader, propertyInfo, typeMappings.get(name));
+        if (properties.containsKey(name)) {
+          throw new EntityProviderException(EntityProviderException.DOUBLE_PROPERTY.addContent(name));
+        }
+        properties.put(name, propertyValue);
+      } else {
+        readNavigationProperty(name);
+      }
+    }
+  }
+
+  private void readMetadata() throws IOException, EdmException, EntityProviderException {
+    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();
+  }
+
+  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));
+      }
+      //TODO Mime Type Mapping
+    } else {
+      if (mediaMetadata.getContentType() != null || mediaMetadata.getEditLink() != null
+          || mediaMetadata.getEtag() != null || mediaMetadata.getSourceLink() != null) {
+        throw new EntityProviderException(EntityProviderException.MEDIA_DATA_NOT_INITIAL);
+      }
+    }
+  }
+
+  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));
+    }
+
+    if (reader.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 {
+        EdmNavigationProperty navigationProperty = (EdmNavigationProperty) eia.getEntityType().getProperty(navigationPropertyName);
+        EdmEntitySet inlineEntitySet = eia.getEntitySet().getRelatedEntitySet(navigationProperty);
+        EntityInfoAggregator inlineEia = EntityInfoAggregator.create(inlineEntitySet);
+        EntityProviderReadProperties inlineReadProperties;
+        OnReadInlineContent callback = readProperties.getCallback();
+        try {
+          if (callback == null) {
+            inlineReadProperties = EntityProviderReadProperties.init().mergeSemantic(readProperties.getMergeSemantic()).build();
+
+          } else {
+            inlineReadProperties = callback.receiveReadProperties(readProperties, navigationProperty);
+          }
+
+          if (navigationProperty.getMultiplicity() == EdmMultiplicity.MANY) {
+            JsonFeedConsumer inlineConsumer = new JsonFeedConsumer(reader, inlineEia, inlineReadProperties);
+            ODataFeed feed = inlineConsumer.readStartedInlineFeed(name);
+            updateExpandSelectTree(navigationPropertyName, feed);
+            if (callback == null) {
+              properties.put(navigationPropertyName, feed);
+              entryResult.setContainsInlineEntry(true);
+            } else {
+              ReadFeedResult result = new ReadFeedResult(inlineReadProperties, navigationProperty, feed);
+              callback.handleReadFeed(result);
+            }
+          } else {
+            JsonEntryConsumer inlineConsumer = new JsonEntryConsumer(reader, inlineEia, inlineReadProperties);
+            ODataEntry entry = inlineConsumer.readInlineEntry(name);
+            updateExpandSelectTree(navigationPropertyName, entry);
+            if (callback == null) {
+              properties.put(navigationPropertyName, entry);
+              entryResult.setContainsInlineEntry(true);
+            } else {
+              ReadEntryResult result = new ReadEntryResult(inlineReadProperties, navigationProperty, entry);
+              callback.handleReadEntry(result);
+            }
+          }
+
+        } catch (ODataApplicationException e) {
+          throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+        }
+      }
+      reader.endObject();
+    } else {
+      final EdmNavigationProperty navigationProperty = (EdmNavigationProperty) eia.getEntityType().getProperty(navigationPropertyName);
+      final EdmEntitySet inlineEntitySet = eia.getEntitySet().getRelatedEntitySet(navigationProperty);
+      final EntityInfoAggregator inlineInfo = EntityInfoAggregator.create(inlineEntitySet);
+      OnReadInlineContent callback = readProperties.getCallback();
+      EntityProviderReadProperties inlineReadProperties;
+      if (callback == null) {
+        inlineReadProperties = EntityProviderReadProperties.init().mergeSemantic(readProperties.getMergeSemantic()).build();
+      } else {
+        try {
+          inlineReadProperties = callback.receiveReadProperties(readProperties, navigationProperty);
+        } catch (final ODataApplicationException e) {
+          throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+        }
+      }
+      ODataFeed feed = new JsonFeedConsumer(reader, inlineInfo, inlineReadProperties).readInlineFeedStandalone();
+      updateExpandSelectTree(navigationPropertyName, feed);
+      if (callback == null) {
+        properties.put(navigationPropertyName, feed);
+        entryResult.setContainsInlineEntry(true);
+      } else {
+        ReadFeedResult result = new ReadFeedResult(inlineReadProperties, navigationProperty, feed);
+        try {
+          callback.handleReadFeed(result);
+        } catch (final ODataApplicationException e) {
+          throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+        }
+      }
+    }
+  }
+
+  private void updateExpandSelectTree(final String navigationPropertyName, final ODataFeed feed) {
+    List<ODataEntry> entries = feed.getEntries();
+    if (entries.size() > 0) {
+      updateExpandSelectTree(navigationPropertyName, entries.get(0));
+    } else {
+      expandSelectTree.setExpanded();
+      expandSelectTree.setExplicitlySelected();
+      expandSelectTree.putLink(navigationPropertyName, new ExpandSelectTreeNodeImpl());
+    }
+  }
+
+  private void updateExpandSelectTree(final String navigationPropertyName, final ODataEntry entry) {
+    expandSelectTree.setExpanded();
+    expandSelectTree.setExplicitlySelected();
+    expandSelectTree.putLink(navigationPropertyName, (ExpandSelectTreeNodeImpl) entry.getExpandSelectTree());
+  }
+
+  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 entryResult;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonFeedConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonFeedConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonFeedConsumer.java
new file mode 100644
index 0000000..4da0420
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonFeedConsumer.java
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * 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.core.ep.consumer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+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.ODataFeedImpl;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+
+/**
+ * @author SAP AG
+ */
+public class JsonFeedConsumer {
+
+  private JsonReader reader;
+  private EntityInfoAggregator eia;
+  private EntityProviderReadProperties readProperties;
+  private List<ODataEntry> entries = new ArrayList<ODataEntry>();
+  private FeedMetadataImpl feedMetadata = new FeedMetadataImpl();
+  private boolean resultsArrayPresent = false;
+
+  public JsonFeedConsumer(final JsonReader reader, final EntityInfoAggregator eia, final EntityProviderReadProperties readProperties) {
+    this.reader = reader;
+    this.eia = eia;
+    this.readProperties = readProperties;
+  }
+
+  public ODataFeed 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 ODataFeedImpl(entries, feedMetadata);
+  }
+
+  private void readFeed() throws IOException, EdmException, EntityProviderException {
+    if (reader.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();
+    }
+  }
+
+  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);
+    }
+  }
+
+  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"));
+    }
+  }
+
+  private void readArrayContent() throws IOException, EdmException, EntityProviderException {
+    reader.beginArray();
+    while (reader.hasNext()) {
+      final ODataEntry entry = new JsonEntryConsumer(reader, eia, readProperties).readFeedEntry();
+      entries.add(entry);
+    }
+    reader.endArray();
+  }
+
+  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()));
+    }
+  }
+
+  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 ODataFeedImpl(entries, feedMetadata);
+  }
+
+  protected ODataFeed readInlineFeedStandalone() throws EdmException, EntityProviderException, IOException {
+    readFeed();
+    return new ODataFeedImpl(entries, feedMetadata);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonLinkConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonLinkConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonLinkConsumer.java
new file mode 100644
index 0000000..f82328c
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonLinkConsumer.java
@@ -0,0 +1,155 @@
+/*******************************************************************************
+ * 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.core.ep.consumer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.core.ep.feed.FeedMetadataImpl;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+
+/**
+ * @author SAP AG
+ */
+public class JsonLinkConsumer {
+
+  /**
+   * Reads single link with format <code>{"d":{"uri":"http://somelink"}}</code>
+   * or <code>{"uri":"http://somelink"}</code>.
+   * @param reader
+   * @param entitySet
+   * @return link as string object
+   * @throws EntityProviderException
+   */
+  public String readLink(final JsonReader reader, final EdmEntitySet entitySet) throws EntityProviderException {
+    try {
+      String result;
+      reader.beginObject();
+      String nextName = reader.nextName();
+      final boolean wrapped = FormatJson.D.equals(nextName);
+      if (wrapped) {
+        reader.beginObject();
+        nextName = reader.nextName();
+      }
+      if (FormatJson.URI.equals(nextName) && reader.peek() == JsonToken.STRING) {
+        result = reader.nextString();
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(FormatJson.D + " or " + FormatJson.URI).addContent(nextName));
+      }
+      reader.endObject();
+      if (wrapped) {
+        reader.endObject();
+      }
+
+      reader.peek(); // to assert end of structure or document
+
+      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);
+    }
+  }
+
+  /**
+   * Reads a collection of links, optionally wrapped in a "d" object,
+   * and optionally wrapped in an "results" object, where an additional "__count"
+   * object could appear on the same level as the "results".
+   * @param reader
+   * @param entitySet
+   * @return links as List of Strings
+   * @throws EntityProviderException
+   */
+  public List<String> readLinks(final JsonReader reader, final EdmEntitySet entitySet) throws EntityProviderException {
+    List<String> links = null;
+    int openedObjects = 0;
+
+    try {
+      String nextName;
+      if (reader.peek() == JsonToken.BEGIN_ARRAY) {
+        nextName = FormatJson.RESULTS;
+      } else {
+        reader.beginObject();
+        openedObjects++;
+        nextName = reader.nextName();
+      }
+      if (FormatJson.D.equals(nextName)) {
+        if (reader.peek() == JsonToken.BEGIN_ARRAY) {
+          nextName = FormatJson.RESULTS;
+        } else {
+          reader.beginObject();
+          openedObjects++;
+          nextName = reader.nextName();
+        }
+      }
+      FeedMetadataImpl feedMetadata = new FeedMetadataImpl();
+      if (FormatJson.COUNT.equals(nextName)) {
+        JsonFeedConsumer.readInlineCount(reader, feedMetadata);
+        nextName = reader.nextName();
+      }
+      if (FormatJson.RESULTS.equals(nextName)) {
+        links = readLinksArray(reader);
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(FormatJson.RESULTS).addContent(nextName));
+      }
+      if (reader.hasNext() && reader.peek() == JsonToken.NAME) {
+        if (FormatJson.COUNT.equals(reader.nextName())) {
+          JsonFeedConsumer.readInlineCount(reader, feedMetadata);
+        } else {
+          throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(FormatJson.COUNT).addContent(nextName));
+        }
+      }
+      for (; openedObjects > 0; openedObjects--) {
+        reader.endObject();
+      }
+
+      reader.peek(); // to assert end of document
+    } 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);
+    }
+
+    return links;
+  }
+
+  private List<String> readLinksArray(final JsonReader reader) throws IOException, EntityProviderException {
+    List<String> links = new ArrayList<String>();
+
+    reader.beginArray();
+    while (reader.hasNext()) {
+      reader.beginObject();
+      String nextName = reader.nextName();
+      if (FormatJson.URI.equals(nextName) && reader.peek() == JsonToken.STRING) {
+        links.add(reader.nextString());
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(FormatJson.URI).addContent(nextName));
+      }
+      reader.endObject();
+    }
+    reader.endArray();
+
+    return links;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonPropertyConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonPropertyConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonPropertyConsumer.java
new file mode 100644
index 0000000..2a3327c
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonPropertyConsumer.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.core.ep.consumer;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmException;
+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.api.ep.EntityProviderReadProperties;
+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;
+
+/**
+ * @author SAP AG
+ */
+public class JsonPropertyConsumer {
+
+  public Map<String, Object> readPropertyStandalone(final JsonReader reader, final EdmProperty property, final EntityProviderReadProperties readProperties) throws EntityProviderException {
+    try {
+      EntityPropertyInfo entityPropertyInfo = EntityInfoAggregator.create(property);
+      Map<String, Object> typeMappings = readProperties == null ? null : readProperties.getTypeMappings();
+      Map<String, Object> result = new HashMap<String, Object>();
+
+      reader.beginObject();
+      String nextName = reader.nextName();
+      if (FormatJson.D.equals(nextName)) {
+        reader.beginObject();
+        nextName = reader.nextName();
+        handleName(reader, typeMappings, entityPropertyInfo, result, nextName);
+        reader.endObject();
+      } else {
+        handleName(reader, typeMappings, entityPropertyInfo, 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);
+    }
+  }
+
+  private void handleName(final JsonReader reader, final Map<String, Object> typeMappings, final EntityPropertyInfo entityPropertyInfo, final Map<String, Object> result, final String nextName) throws EntityProviderException {
+    if (!entityPropertyInfo.getName().equals(nextName)) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent(nextName));
+    }
+    Object mapping = null;
+    if (typeMappings != null) {
+      mapping = typeMappings.get(nextName);
+    }
+    Object propertyValue = readPropertyValue(reader, entityPropertyInfo, mapping);
+    result.put(nextName, propertyValue);
+  }
+
+  protected Object readPropertyValue(final JsonReader reader, final EntityPropertyInfo entityPropertyInfo, final Object typeMapping) throws EntityProviderException {
+    try {
+      return entityPropertyInfo.isComplex() ?
+          readComplexProperty(reader, (EntityComplexPropertyInfo) entityPropertyInfo, typeMapping) :
+          readSimpleProperty(reader, entityPropertyInfo, typeMapping);
+    } 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) 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;
+      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;
+    return type.valueOfString((String) value, EdmLiteralKind.JSON, entityPropertyInfo.getFacets(), typeMappingClass);
+  }
+
+  @SuppressWarnings("unchecked")
+  private Object readComplexProperty(final JsonReader reader, final EntityComplexPropertyInfo complexPropertyInfo, final Object typeMapping) throws EdmException, EntityProviderException, IOException {
+    if (reader.peek().equals(JsonToken.NULL)) {
+      reader.nextNull();
+      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()) {
+      String childName = reader.nextName();
+      if (FormatJson.METADATA.equals(childName)) {
+        reader.beginObject();
+        childName = reader.nextName();
+        if (!FormatJson.TYPE.equals(childName)) {
+          throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent(FormatJson.TYPE).addContent(FormatJson.METADATA));
+        }
+        String actualTypeName = reader.nextString();
+        String expectedTypeName = complexPropertyInfo.getType().getNamespace() + Edm.DELIMITER + complexPropertyInfo.getType().getName();
+        if (!expectedTypeName.equals(actualTypeName)) {
+          throw new EntityProviderException(EntityProviderException.INVALID_ENTITYTYPE.addContent(expectedTypeName).addContent(actualTypeName));
+        }
+        reader.endObject();
+      } 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));
+        if (data.containsKey(childName)) {
+          throw new EntityProviderException(EntityProviderException.DOUBLE_PROPERTY.addContent(childName));
+        }
+        data.put(childName, childData);
+      }
+    }
+    reader.endObject();
+    return data;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonServiceDocumentConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonServiceDocumentConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonServiceDocumentConsumer.java
new file mode 100644
index 0000000..b0fbb25
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonServiceDocumentConsumer.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * 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.core.ep.consumer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.gson.stream.JsonReader;
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySetInfo;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.provider.EntityContainerInfo;
+import org.apache.olingo.odata2.api.edm.provider.EntitySet;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.core.edm.provider.EdmEntitySetInfoImplProv;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+import org.apache.olingo.odata2.core.servicedocument.ServiceDocumentImpl;
+
+/**
+ * Reads the OData service document (JSON).
+ * @author SAP AG
+ */
+public class JsonServiceDocumentConsumer {
+  private static final String DEFAULT_CHARSET = "UTF-8";
+  List<EdmEntitySetInfo> entitySets = new ArrayList<EdmEntitySetInfo>();
+  private String currentHandledObjectName;
+
+  public ServiceDocumentImpl parseJson(final InputStream in) throws EntityProviderException {
+    return readServiceDocument(createJsonReader(in));
+  }
+
+  private ServiceDocumentImpl readServiceDocument(final JsonReader reader) throws EntityProviderException {
+    try {
+      reader.beginObject();
+      currentHandledObjectName = reader.nextName();
+      if (FormatJson.D.equals(currentHandledObjectName)) {
+        reader.beginObject();
+        readContent(reader);
+        reader.endObject();
+      }
+      reader.endObject();
+      reader.peek();
+      reader.close();
+    } 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);
+    } catch (final EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+    return new ServiceDocumentImpl().setEntitySetsInfo(entitySets);
+  }
+
+  private void readContent(final JsonReader reader) throws IOException, EdmException, EntityProviderException {
+    currentHandledObjectName = reader.nextName();
+    if (FormatJson.ENTITY_SETS.equals(currentHandledObjectName)) {
+      reader.beginArray();
+      readEntitySets(reader);
+      reader.endArray();
+    }
+  }
+
+  private void readEntitySets(final JsonReader reader) throws IOException, EntityProviderException, EdmException {
+    while (reader.hasNext()) {
+      currentHandledObjectName = reader.nextString();
+      if (currentHandledObjectName != null) {
+        // Looking for the last dot: "\\.(?=[^.]+$)"
+        String[] names = currentHandledObjectName.split("\\" + Edm.DELIMITER + "(?=[^" + Edm.DELIMITER + "]+$)");
+        if (names.length == 1) {
+          EntitySet entitySet = new EntitySet().setName(names[0]);
+          EntityContainerInfo container = new EntityContainerInfo().setDefaultEntityContainer(true);
+          EdmEntitySetInfo entitySetInfo = new EdmEntitySetInfoImplProv(entitySet, container);
+          entitySets.add(entitySetInfo);
+        } else {
+          EntitySet entitySet = new EntitySet().setName(names[1]);
+          EntityContainerInfo container = new EntityContainerInfo().setName(names[0]).setDefaultEntityContainer(false);
+          EdmEntitySetInfo entitySetInfo = new EdmEntitySetInfoImplProv(entitySet, container);
+          entitySets.add(entitySetInfo);
+        }
+      }
+    }
+  }
+
+  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.")));
+    }
+    InputStreamReader isReader;
+    try {
+      isReader = new InputStreamReader(in, DEFAULT_CHARSET);
+    } catch (final UnsupportedEncodingException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+    return new JsonReader(isReader);
+  }
+}