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

[34/52] [abbrv] [OLINGO-200] Moving Atom and JSON (de)serializer to commons

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/fac84b3e/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/Link.java
----------------------------------------------------------------------
diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/Link.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/Link.java
new file mode 100644
index 0000000..f0a35a5
--- /dev/null
+++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/Link.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.api.data;
+
+public interface Link {
+
+  /**
+   * Gets rel info.
+   *
+   * @return rel info.
+   */
+  String getRel();
+
+  /**
+   * Sets rel info.
+   *
+   * @param rel rel info.
+   */
+  void setRel(String rel);
+
+  /**
+   * Gets type.
+   *
+   * @return type.
+   */
+  String getType();
+
+  /**
+   * Sets type.
+   *
+   * @param type type.
+   */
+  void setType(String type);
+
+  /**
+   * Gets title.
+   *
+   * @return title.
+   */
+  String getTitle();
+
+  /**
+   * Sets title.
+   *
+   * @param title title.
+   */
+  void setTitle(String title);
+
+  /**
+   * Gets href.
+   *
+   * @return href.
+   */
+  String getHref();
+
+  /**
+   * Sets href.
+   *
+   * @param href href.
+   */
+  void setHref(String href);
+
+  /**
+   * Gets Media ETag.
+   *
+   * @return media ETag
+   */
+  String getMediaETag();
+
+  /**
+   * Sets Media ETag.
+   *
+   * @param etag media ETag
+   */
+  void setMediaETag(String etag);
+
+  /**
+   * Gets in-line entry.
+   *
+   * @return in-line entry.
+   */
+  Entry getInlineEntry();
+
+  /**
+   * Sets in-line entry.
+   *
+   * @param entry entry.
+   */
+  void setInlineEntry(Entry entry);
+
+  /**
+   * Gets in-line feed.
+   *
+   * @return in-line feed.
+   */
+  Feed getInlineFeed();
+
+  /**
+   * Sets in-line feed.
+   *
+   * @param feed feed.
+   */
+  void setInlineFeed(Feed feed);
+
+}

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

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

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/fac84b3e/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/Property.java
----------------------------------------------------------------------
diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/Property.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/Property.java
new file mode 100644
index 0000000..feb8f71
--- /dev/null
+++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/Property.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.api.data;
+
+public interface Property {
+
+  String getName();
+
+  void setName(String name);
+
+  String getType();
+
+  void setType(String type);
+
+  Value getValue();
+
+  void setValue(Value value);
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/fac84b3e/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/Value.java
----------------------------------------------------------------------
diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/Value.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/Value.java
new file mode 100644
index 0000000..045751d
--- /dev/null
+++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/Value.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.api.data;
+
+public interface Value {
+
+  boolean isNull();
+
+  boolean isSimple();
+
+  boolean isGeospatial();
+
+  boolean isComplex();
+
+  boolean isCollection();
+
+  Object get();
+
+  NullValue asNull();
+
+  PrimitiveValue asSimple();
+
+  GeospatialValue asGeospatial();
+
+  ComplexValue asComplex();
+
+  CollectionValue asCollection();
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/fac84b3e/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/v3/LinkCollection.java
----------------------------------------------------------------------
diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/v3/LinkCollection.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/v3/LinkCollection.java
new file mode 100644
index 0000000..72186fc
--- /dev/null
+++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/v3/LinkCollection.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.api.data.v3;
+
+import java.net.URI;
+import java.util.List;
+
+/**
+ * REST resource for an <tt>ODataLinkCollection</tt>.
+ *
+ * @see org.apache.olingo.client.api.domain.ODataLinkCollection
+ */
+public interface LinkCollection {
+
+  /**
+   * Smart management of different JSON format produced by OData services when
+   * <tt>$links</tt> is a single or a collection property.
+   *
+   * @return list of URIs for <tt>$links</tt>
+   */
+  List<URI> getLinks();
+
+  /**
+   * Sets next link.
+   *
+   * @param next next link.
+   */
+  void setNext(final URI next);
+
+  /**
+   * Gets next link if exists.
+   *
+   * @return next link if exists; null otherwise.
+   */
+  URI getNext();
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/fac84b3e/lib/commons-core/pom.xml
----------------------------------------------------------------------
diff --git a/lib/commons-core/pom.xml b/lib/commons-core/pom.xml
index a767566..f025fd0 100644
--- a/lib/commons-core/pom.xml
+++ b/lib/commons-core/pom.xml
@@ -46,6 +46,27 @@
     </dependency>
     
     <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-databind</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-annotations</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.dataformat</groupId>
+      <artifactId>jackson-dataformat-xml</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml</groupId>
+      <artifactId>aalto-xml</artifactId>
+    </dependency>
+        
+    <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
     </dependency>

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/fac84b3e/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractAtomDealer.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractAtomDealer.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractAtomDealer.java
new file mode 100644
index 0000000..940d8a5
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractAtomDealer.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.core.data;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.olingo.commons.api.Constants;
+import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
+
+abstract class AbstractAtomDealer {
+
+  protected static final String TYPE_TEXT = "text";
+
+  protected final ODataServiceVersion version;
+
+  protected final QName etagQName;
+
+  protected final QName inlineQName;
+
+  protected final QName actionQName;
+
+  protected final QName propertiesQName;
+
+  protected final QName typeQName;
+
+  protected final QName nullQName;
+
+  protected final QName elementQName;
+
+  protected final QName countQName;
+
+  protected final QName uriQName;
+  protected final QName nextQName;
+
+  public AbstractAtomDealer(final ODataServiceVersion version) {
+    this.version = version;
+
+    this.etagQName =
+            new QName(version.getNamespaceMap().get(ODataServiceVersion.NS_METADATA), Constants.ATOM_ATTR_ETAG);
+    this.inlineQName =
+            new QName(version.getNamespaceMap().get(ODataServiceVersion.NS_METADATA), Constants.ATOM_ELEM_INLINE);
+    this.actionQName =
+            new QName(version.getNamespaceMap().get(ODataServiceVersion.NS_METADATA), Constants.ATOM_ELEM_ACTION);
+    this.propertiesQName =
+            new QName(version.getNamespaceMap().get(ODataServiceVersion.NS_METADATA), Constants.PROPERTIES);
+    this.typeQName = new QName(version.getNamespaceMap().get(ODataServiceVersion.NS_METADATA), Constants.ATTR_TYPE);
+    this.nullQName = new QName(version.getNamespaceMap().get(ODataServiceVersion.NS_METADATA), Constants.ATTR_NULL);
+    this.elementQName =
+            new QName(version.getNamespaceMap().get(ODataServiceVersion.NS_DATASERVICES), Constants.ELEM_ELEMENT);
+    this.countQName =
+            new QName(version.getNamespaceMap().get(ODataServiceVersion.NS_METADATA), Constants.ATOM_ELEM_COUNT);
+    this.uriQName =
+            new QName(version.getNamespaceMap().get(ODataServiceVersion.NS_DATASERVICES), Constants.ELEM_URI);
+    this.nextQName =
+            new QName(version.getNamespaceMap().get(ODataServiceVersion.NS_DATASERVICES), Constants.NEXT_LINK_REL);
+  }
+
+  protected void namespaces(final XMLStreamWriter writer) throws XMLStreamException {
+    writer.writeNamespace(StringUtils.EMPTY, Constants.NS_ATOM);
+    writer.writeNamespace(XMLConstants.XML_NS_PREFIX, XMLConstants.XML_NS_URI);
+    writer.writeNamespace(Constants.PREFIX_METADATA, version.getNamespaceMap().get(ODataServiceVersion.NS_METADATA));
+    writer.writeNamespace(
+            Constants.PREFIX_DATASERVICES, version.getNamespaceMap().get(ODataServiceVersion.NS_DATASERVICES));
+    writer.writeNamespace(Constants.PREFIX_GML, Constants.NS_GML);
+    writer.writeNamespace(Constants.PREFIX_GEORSS, Constants.NS_GEORSS);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/fac84b3e/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractAtomObject.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractAtomObject.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractAtomObject.java
new file mode 100644
index 0000000..f09de40
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractAtomObject.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.core.data;
+
+import com.fasterxml.jackson.databind.util.ISO8601DateFormat;
+import java.net.URI;
+import java.text.ParseException;
+import java.util.Date;
+
+abstract class AbstractAtomObject extends AbstractPayloadObject {
+
+  private static final long serialVersionUID = -4391162864875546927L;
+
+  private static final ISO8601DateFormat ISO_DATEFORMAT = new ISO8601DateFormat();
+
+  private URI baseURI;
+
+  private String id;
+
+  private String title;
+
+  private String summary;
+
+  private Date updated;
+
+  public URI getBaseURI() {
+    return baseURI;
+  }
+
+  public void setBaseURI(final String baseURI) {
+    this.baseURI = URI.create(baseURI);
+  }
+
+  public String getId() {
+    return id;
+  }
+
+  public String getTitle() {
+    return title;
+  }
+
+  public String getSummary() {
+    return summary;
+  }
+
+  public Date getUpdated() {
+    return updated;
+  }
+
+  public void setCommonProperty(final String key, final String value) throws ParseException {
+    if ("id".equals(key)) {
+      this.id = value;
+    } else if ("title".equals(key)) {
+      this.title = value;
+    } else if ("summary".equals(key)) {
+      this.summary = value;
+    } else if ("updated".equals(key)) {
+      this.updated = ISO_DATEFORMAT.parse(value);
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/fac84b3e/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractEntry.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractEntry.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractEntry.java
new file mode 100644
index 0000000..29a4a75
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractEntry.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.core.data;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.olingo.commons.api.data.Entry;
+import org.apache.olingo.commons.api.data.Link;
+import org.apache.olingo.commons.api.data.Property;
+import org.apache.olingo.commons.api.domain.ODataOperation;
+
+/**
+ * Abstract base for classes implementing an OData entry in Atom and JSON.
+ */
+public abstract class AbstractEntry extends AbstractAtomObject implements Entry {
+
+  private static final long serialVersionUID = 2127764552600969783L;
+
+  private String eTag;
+
+  private String type;
+
+  private Link readLink;
+
+  private Link editLink;
+
+  private final List<Link> associationLinks = new ArrayList<Link>();
+
+  private final List<Link> navigationLinks = new ArrayList<Link>();
+
+  private final List<Link> mediaEditLinks = new ArrayList<Link>();
+
+  private final List<ODataOperation> operations = new ArrayList<ODataOperation>();
+
+  private final List<Property> properties = new ArrayList<Property>();
+
+  private String mediaContentSource;
+
+  private String mediaContentType;
+
+  @Override
+  public String getETag() {
+    return eTag;
+  }
+
+  public void setETag(final String eTag) {
+    this.eTag = eTag;
+  }
+
+  @Override
+  public String getType() {
+    return type;
+  }
+
+  @Override
+  public void setType(final String type) {
+    this.type = type;
+  }
+
+  @Override
+  public Link getSelfLink() {
+    return readLink;
+  }
+
+  @Override
+  public void setSelfLink(final Link readLink) {
+    this.readLink = readLink;
+  }
+
+  @Override
+  public Link getEditLink() {
+    return editLink;
+  }
+
+  @Override
+  public void setEditLink(final Link editLink) {
+    this.editLink = editLink;
+  }
+
+  @Override
+  public List<Link> getAssociationLinks() {
+    return associationLinks;
+  }
+
+  @Override
+  public List<Link> getNavigationLinks() {
+    return navigationLinks;
+  }
+
+  @Override
+  public List<Link> getMediaEditLinks() {
+    return mediaEditLinks;
+  }
+
+  @Override
+  public List<ODataOperation> getOperations() {
+    return operations;
+  }
+
+  @Override
+  public List<Property> getProperties() {
+    return properties;
+  }
+
+  @Override
+  public Property getProperty(final String name) {
+    Property result = null;
+
+    for (Property property : properties) {
+      if (name.equals(property.getName())) {
+        result = property;
+      }
+    }
+
+    return result;
+  }
+
+  @Override
+  public String getMediaContentType() {
+    return this.mediaContentType;
+  }
+
+  @Override
+  public void setMediaContentType(final String mediaContentType) {
+    this.mediaContentType = mediaContentType;
+  }
+
+  @Override
+  public String getMediaContentSource() {
+    return this.mediaContentSource;
+  }
+
+  @Override
+  public void setMediaContentSource(final String mediaContentSource) {
+    this.mediaContentSource = mediaContentSource;
+  }
+
+  @Override
+  public boolean isMediaEntry() {
+    return StringUtils.isNotBlank(this.mediaContentSource);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/fac84b3e/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractJsonDeserializer.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractJsonDeserializer.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractJsonDeserializer.java
new file mode 100644
index 0000000..2d865ce
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractJsonDeserializer.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.commons.core.data;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.util.Iterator;
+import java.util.Map;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.olingo.commons.api.Constants;
+import org.apache.olingo.commons.api.data.CollectionValue;
+import org.apache.olingo.commons.api.data.ComplexValue;
+import org.apache.olingo.commons.api.data.Value;
+import org.apache.olingo.commons.api.domain.ODataPropertyType;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
+import org.apache.olingo.commons.core.edm.EdmTypeInfo;
+
+abstract class AbstractJsonDeserializer<T> extends ODataJacksonDeserializer<T> {
+
+  private JSONGeoValueDeserializer geoDeserializer;
+
+  private JSONGeoValueDeserializer getGeoDeserializer() {
+    if (geoDeserializer == null) {
+      geoDeserializer = new JSONGeoValueDeserializer(version);
+    }
+    return geoDeserializer;
+  }
+
+  protected EdmPrimitiveTypeKind getPrimitiveType(final JsonNode node) {
+    EdmPrimitiveTypeKind result = EdmPrimitiveTypeKind.String;
+
+    if (node.isIntegralNumber()) {
+      result = EdmPrimitiveTypeKind.Int32;
+    } else if (node.isBoolean()) {
+      result = EdmPrimitiveTypeKind.Boolean;
+    } else if (node.isFloatingPointNumber()) {
+      result = EdmPrimitiveTypeKind.Double;
+    }
+
+    return result;
+  }
+
+  private ODataPropertyType guessPropertyType(final JsonNode node) {
+    ODataPropertyType type = null;
+
+    if (node.isValueNode() || node.isNull()) {
+      type = ODataPropertyType.PRIMITIVE;
+    } else if (node.isArray()) {
+      type = ODataPropertyType.COLLECTION;
+    } else if (node.isObject()) {
+      type = ODataPropertyType.COMPLEX;
+    } else {
+      type = ODataPropertyType.EMPTY;
+    }
+
+    return type;
+  }
+
+  private Value fromPrimitive(final JsonNode node, final EdmTypeInfo typeInfo) {
+    Value value = null;
+
+    if (node.isNull()) {
+      value = new NullValueImpl();
+    } else {
+      if (typeInfo != null && typeInfo.getPrimitiveTypeKind().isGeospatial()) {
+        value = new GeospatialValueImpl(getGeoDeserializer().deserialize(node, typeInfo));
+      } else {
+        value = new PrimitiveValueImpl(node.asText());
+      }
+    }
+
+    return value;
+  }
+
+  private ComplexValue fromComplex(final JsonNode node) {
+    final ComplexValue value = new ComplexValueImpl();
+
+    String type = null;
+    for (final Iterator<Map.Entry<String, JsonNode>> itor = node.fields(); itor.hasNext();) {
+      final Map.Entry<String, JsonNode> field = itor.next();
+
+      if (type == null && field.getKey().endsWith(Constants.JSON_TYPE_SUFFIX)) {
+        type = field.getValue().asText();
+      } else {
+        final JSONPropertyImpl property = new JSONPropertyImpl();
+        property.setName(field.getKey());
+        property.setType(type);
+        type = null;
+
+        value(property, field.getValue());
+        value.get().add(property);
+      }
+    }
+
+    return value;
+  }
+
+  private CollectionValue fromCollection(final Iterator<JsonNode> nodeItor, final EdmTypeInfo typeInfo) {
+    final CollectionValueImpl value = new CollectionValueImpl();
+
+    final EdmTypeInfo type = typeInfo == null
+            ? null
+            : new EdmTypeInfo.Builder().setTypeExpression(typeInfo.getFullQualifiedName().toString()).build();
+
+    while (nodeItor.hasNext()) {
+      final JsonNode child = nodeItor.next();
+
+      if (child.isValueNode()) {
+        value.get().add(fromPrimitive(child, type));
+      } else if (child.isContainerNode()) {
+        if (child.has(Constants.JSON_TYPE)) {
+          ((ObjectNode) child).remove(Constants.JSON_TYPE);
+        }
+        value.get().add(fromComplex(child));
+      }
+    }
+
+    return value;
+  }
+
+  protected void value(final JSONPropertyImpl property, final JsonNode node) {
+    final EdmTypeInfo typeInfo = StringUtils.isBlank(property.getType())
+            ? null
+            : new EdmTypeInfo.Builder().setTypeExpression(property.getType()).build();
+
+    final ODataPropertyType propType = typeInfo == null
+            ? guessPropertyType(node)
+            : typeInfo.isCollection()
+            ? ODataPropertyType.COLLECTION
+            : typeInfo.isPrimitiveType()
+            ? ODataPropertyType.PRIMITIVE
+            : ODataPropertyType.COMPLEX;
+
+    switch (propType) {
+      case COLLECTION:
+        property.setValue(fromCollection(node.elements(), typeInfo));
+        break;
+
+      case COMPLEX:
+        if (node.has(Constants.JSON_TYPE)) {
+          property.setType(node.get(Constants.JSON_TYPE).asText());
+          ((ObjectNode) node).remove(Constants.JSON_TYPE);
+        }
+        property.setValue(fromComplex(node));
+        break;
+
+      case PRIMITIVE:
+        if (property.getType() == null) {
+          property.setType(getPrimitiveType(node).getFullQualifiedName().toString());
+        }
+        property.setValue(fromPrimitive(node, typeInfo));
+        break;
+
+      case EMPTY:
+      default:
+        property.setValue(new PrimitiveValueImpl(StringUtils.EMPTY));
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/fac84b3e/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractJsonSerializer.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractJsonSerializer.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractJsonSerializer.java
new file mode 100644
index 0000000..1380dd5
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractJsonSerializer.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.core.data;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import java.io.IOException;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.apache.olingo.commons.api.data.CollectionValue;
+import org.apache.olingo.commons.api.data.Property;
+import org.apache.olingo.commons.api.data.Value;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
+import org.apache.olingo.commons.core.edm.EdmTypeInfo;
+
+abstract class AbstractJsonSerializer<T> extends ODataJacksonSerializer<T> {
+
+  private static final EdmPrimitiveTypeKind[] NUMBER_TYPES = {
+    EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte,
+    EdmPrimitiveTypeKind.Single, EdmPrimitiveTypeKind.Double,
+    EdmPrimitiveTypeKind.Int16, EdmPrimitiveTypeKind.Int32, EdmPrimitiveTypeKind.Int64
+  };
+
+  private final JSONGeoValueSerializer geoSerializer = new JSONGeoValueSerializer();
+
+  private void collection(final JsonGenerator jgen, final String itemType, final CollectionValue value)
+          throws IOException {
+
+    jgen.writeStartArray();
+    for (Value item : value.get()) {
+      value(jgen, itemType, item);
+    }
+    jgen.writeEndArray();
+  }
+
+  private void value(final JsonGenerator jgen, final String type, final Value value) throws IOException {
+    final EdmTypeInfo typeInfo = type == null
+            ? null
+            : new EdmTypeInfo.Builder().setTypeExpression(type).build();
+
+    if (value.isNull()) {
+      jgen.writeNull();
+    } else if (value.isSimple()) {
+      final boolean isNumber = typeInfo == null
+              ? NumberUtils.isNumber(value.asSimple().get())
+              : ArrayUtils.contains(NUMBER_TYPES, typeInfo.getPrimitiveTypeKind());
+      final boolean isBoolean = typeInfo == null
+              ? (value.asSimple().get().equalsIgnoreCase(Boolean.TRUE.toString())
+              || value.asSimple().get().equalsIgnoreCase(Boolean.FALSE.toString()))
+              : typeInfo.getPrimitiveTypeKind() == EdmPrimitiveTypeKind.Boolean;
+
+      if (isNumber) {
+        jgen.writeNumber(value.asSimple().get());
+      } else if (isBoolean) {
+        jgen.writeBoolean(BooleanUtils.toBoolean(value.asSimple().get()));
+      } else {
+        jgen.writeString(value.asSimple().get());
+      }
+    } else if (value.isGeospatial()) {
+      jgen.writeStartObject();
+      geoSerializer.serialize(jgen, value.asGeospatial().get());
+      jgen.writeEndObject();
+    } else if (value.isCollection()) {
+      collection(jgen, typeInfo == null ? null : typeInfo.getFullQualifiedName().toString(), value.asCollection());
+    } else if (value.isComplex()) {
+      jgen.writeStartObject();
+      for (Property property : value.asComplex().get()) {
+        property(jgen, property, property.getName());
+      }
+      jgen.writeEndObject();
+    }
+  }
+
+  protected void property(final JsonGenerator jgen, final Property property, final String name) throws IOException {
+    jgen.writeFieldName(name);
+    value(jgen, property.getType(), property.getValue());
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/fac84b3e/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractPayloadObject.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractPayloadObject.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractPayloadObject.java
new file mode 100644
index 0000000..bad009d
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractPayloadObject.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.commons.core.data;
+
+import java.io.Serializable;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * Abstract representation of a payload (Atom, JSON) object.
+ */
+public abstract class AbstractPayloadObject implements Serializable {
+
+  private static final long serialVersionUID = 1634654241914156675L;
+
+  @Override
+  public boolean equals(final Object obj) {
+    return EqualsBuilder.reflectionEquals(this, obj);
+  }
+
+  @Override
+  public int hashCode() {
+    return HashCodeBuilder.reflectionHashCode(this);
+  }
+
+  @Override
+  public String toString() {
+    return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/fac84b3e/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractPropertyImpl.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractPropertyImpl.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractPropertyImpl.java
new file mode 100644
index 0000000..e005f98
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractPropertyImpl.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.core.data;
+
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import org.apache.olingo.commons.api.data.Property;
+import org.apache.olingo.commons.api.data.Value;
+
+public abstract class AbstractPropertyImpl implements Property {
+
+  private String name;
+
+  private String type;
+
+  private Value value;
+
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public void setName(final String name) {
+    this.name = name;
+  }
+
+  @Override
+  public String getType() {
+    return type;
+  }
+
+  @Override
+  public void setType(final String type) {
+    this.type = type;
+  }
+
+  @Override
+  public Value getValue() {
+    return value;
+  }
+
+  @Override
+  public void setValue(final Value value) {
+    this.value = value;
+  }
+
+  @Override
+  public boolean equals(final Object obj) {
+    return EqualsBuilder.reflectionEquals(this, obj);
+  }
+
+  @Override
+  public int hashCode() {
+    return HashCodeBuilder.reflectionHashCode(this);
+  }
+
+  @Override
+  public String toString() {
+    return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/fac84b3e/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractValue.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractValue.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractValue.java
new file mode 100644
index 0000000..31629e2
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractValue.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.core.data;
+
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import org.apache.olingo.commons.api.data.CollectionValue;
+import org.apache.olingo.commons.api.data.ComplexValue;
+import org.apache.olingo.commons.api.data.GeospatialValue;
+import org.apache.olingo.commons.api.data.NullValue;
+import org.apache.olingo.commons.api.data.PrimitiveValue;
+import org.apache.olingo.commons.api.data.Value;
+
+public abstract class AbstractValue implements Value {
+
+  @Override
+  public boolean isNull() {
+    return false;
+  }
+
+  @Override
+  public boolean isSimple() {
+    return false;
+  }
+
+  @Override
+  public boolean isGeospatial() {
+    return false;
+  }
+
+  @Override
+  public boolean isComplex() {
+    return false;
+  }
+
+  @Override
+  public boolean isCollection() {
+    return false;
+  }
+
+  @Override
+  public NullValue asNull() {
+    return isNull() ? (NullValue) this : null;
+  }
+
+  @Override
+  public PrimitiveValue asSimple() {
+    return isSimple() ? (PrimitiveValue) this : null;
+  }
+
+  @Override
+  public GeospatialValue asGeospatial() {
+    return isGeospatial() ? (GeospatialValue) this : null;
+  }
+
+  @Override
+  public ComplexValue asComplex() {
+    return isComplex() ? (ComplexValue) this : null;
+  }
+
+  @Override
+  public CollectionValue asCollection() {
+    return isCollection() ? (CollectionValue) this : null;
+  }
+
+  @Override
+  public boolean equals(final Object obj) {
+    return EqualsBuilder.reflectionEquals(this, obj);
+  }
+
+  @Override
+  public int hashCode() {
+    return HashCodeBuilder.reflectionHashCode(this);
+  }
+
+  @Override
+  public String toString() {
+    return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/fac84b3e/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomDeserializer.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomDeserializer.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomDeserializer.java
new file mode 100644
index 0000000..f42fe00
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomDeserializer.java
@@ -0,0 +1,370 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.core.data;
+
+import java.io.InputStream;
+import java.net.URI;
+import java.text.ParseException;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Attribute;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+import org.apache.olingo.commons.api.Constants;
+import org.apache.olingo.commons.api.domain.ODataOperation;
+import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
+import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.commons.core.data.v3.XMLLinkCollectionImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class AtomDeserializer extends AbstractAtomDealer {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AtomDeserializer.class);
+
+  private static final XMLInputFactory FACTORY = XMLInputFactory.newInstance();
+
+  private final AtomPropertyDeserializer propDeserializer;
+
+  public AtomDeserializer(final ODataServiceVersion version) {
+    super(version);
+    this.propDeserializer = new AtomPropertyDeserializer(version);
+  }
+
+  private AtomPropertyImpl property(final InputStream input) throws XMLStreamException {
+    final XMLEventReader reader = FACTORY.createXMLEventReader(input);
+    return propDeserializer.deserialize(reader, skipBeforeFirstStartElement(reader));
+  }
+
+  private StartElement skipBeforeFirstStartElement(final XMLEventReader reader) throws XMLStreamException {
+    StartElement startEvent = null;
+    while (reader.hasNext() && startEvent == null) {
+      final XMLEvent event = reader.nextEvent();
+      if (event.isStartElement()) {
+        startEvent = event.asStartElement();
+      }
+    }
+    if (startEvent == null) {
+      throw new IllegalArgumentException("Cannot find any XML start element");
+    }
+
+    return startEvent;
+  }
+
+  private void common(final XMLEventReader reader, final StartElement start,
+          final AbstractAtomObject object, final String key) throws XMLStreamException {
+
+    boolean foundEndElement = false;
+    while (reader.hasNext() && !foundEndElement) {
+      final XMLEvent event = reader.nextEvent();
+
+      if (event.isCharacters() && !event.asCharacters().isWhiteSpace()) {
+        try {
+          object.setCommonProperty(key, event.asCharacters().getData());
+        } catch (ParseException e) {
+          throw new XMLStreamException("While parsing Atom entry or feed common elements", e);
+        }
+      }
+
+      if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
+        foundEndElement = true;
+      }
+    }
+  }
+
+  private void inline(final XMLEventReader reader, final StartElement start, final LinkImpl link)
+          throws XMLStreamException {
+
+    boolean foundEndElement = false;
+    while (reader.hasNext() && !foundEndElement) {
+      final XMLEvent event = reader.nextEvent();
+
+      if (event.isStartElement() && inlineQName.equals(event.asStartElement().getName())) {
+        StartElement inline = null;
+        while (reader.hasNext() && inline == null) {
+          final XMLEvent innerEvent = reader.peek();
+          if (innerEvent.isCharacters() && innerEvent.asCharacters().isWhiteSpace()) {
+            reader.nextEvent();
+          } else if (innerEvent.isStartElement()) {
+            inline = innerEvent.asStartElement();
+          }
+        }
+        if (inline != null) {
+          if (Constants.QNAME_ATOM_ELEM_ENTRY.equals(inline.getName())) {
+            link.setInlineEntry(entry(reader, inline));
+          }
+          if (Constants.QNAME_ATOM_ELEM_FEED.equals(inline.getName())) {
+            link.setInlineFeed(feed(reader, inline));
+          }
+        }
+      }
+
+      if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
+        foundEndElement = true;
+      }
+    }
+  }
+
+  private XMLLinkCollectionImpl linkCollection(final InputStream input) throws XMLStreamException {
+    final XMLEventReader reader = FACTORY.createXMLEventReader(input);
+
+    final XMLLinkCollectionImpl linkCollection = new XMLLinkCollectionImpl();
+
+    boolean isURI = false;
+    boolean isNext = false;
+    while (reader.hasNext()) {
+      final XMLEvent event = reader.nextEvent();
+      if (event.isStartElement()) {
+        isURI = uriQName.equals(event.asStartElement().getName());
+        isNext = nextQName.equals(event.asStartElement().getName());
+      }
+
+      if (event.isCharacters() && !event.asCharacters().isWhiteSpace()) {
+        if (isURI) {
+          linkCollection.getLinks().add(URI.create(event.asCharacters().getData()));
+          isURI = false;
+        } else if (isNext) {
+          linkCollection.setNext(URI.create(event.asCharacters().getData()));
+          isNext = false;
+        }
+      }
+    }
+
+    return linkCollection;
+  }
+
+  private void properties(final XMLEventReader reader, final StartElement start, final AtomEntryImpl entry)
+          throws XMLStreamException {
+
+    boolean foundEndProperties = false;
+    while (reader.hasNext() && !foundEndProperties) {
+      final XMLEvent event = reader.nextEvent();
+
+      if (event.isStartElement()) {
+        entry.getProperties().add(propDeserializer.deserialize(reader, event.asStartElement()));
+      }
+
+      if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
+        foundEndProperties = true;
+      }
+    }
+  }
+
+  private AtomEntryImpl entry(final XMLEventReader reader, final StartElement start) throws XMLStreamException {
+    if (!Constants.QNAME_ATOM_ELEM_ENTRY.equals(start.getName())) {
+      return null;
+    }
+
+    final AtomEntryImpl entry = new AtomEntryImpl();
+    final Attribute xmlBase = start.getAttributeByName(Constants.QNAME_ATTR_XML_BASE);
+    if (xmlBase != null) {
+      entry.setBaseURI(xmlBase.getValue());
+    }
+    final Attribute etag = start.getAttributeByName(etagQName);
+    if (etag != null) {
+      entry.setETag(etag.getValue());
+    }
+
+    boolean foundEndEntry = false;
+    while (reader.hasNext() && !foundEndEntry) {
+      final XMLEvent event = reader.nextEvent();
+
+      if (event.isStartElement()) {
+        if (Constants.QNAME_ATOM_ELEM_ID.equals(event.asStartElement().getName())) {
+          common(reader, event.asStartElement(), entry, "id");
+        } else if (Constants.QNAME_ATOM_ELEM_TITLE.equals(event.asStartElement().getName())) {
+          common(reader, event.asStartElement(), entry, "title");
+        } else if (Constants.QNAME_ATOM_ELEM_SUMMARY.equals(event.asStartElement().getName())) {
+          common(reader, event.asStartElement(), entry, "summary");
+        } else if (Constants.QNAME_ATOM_ELEM_UPDATED.equals(event.asStartElement().getName())) {
+          common(reader, event.asStartElement(), entry, "updated");
+        } else if (Constants.QNAME_ATOM_ELEM_CATEGORY.equals(event.asStartElement().getName())) {
+          final Attribute term = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATOM_ATTR_TERM));
+          if (term != null) {
+            entry.setType(term.getValue());
+          }
+        } else if (Constants.QNAME_ATOM_ELEM_LINK.equals(event.asStartElement().getName())) {
+          final LinkImpl link = new LinkImpl();
+          final Attribute rel = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATTR_REL));
+          if (rel != null) {
+            link.setRel(rel.getValue());
+          }
+          final Attribute title = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATTR_TITLE));
+          if (title != null) {
+            link.setTitle(title.getValue());
+          }
+          final Attribute href = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATTR_HREF));
+          if (href != null) {
+            link.setHref(href.getValue());
+          }
+          final Attribute type = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATTR_TYPE));
+          if (type != null) {
+            link.setType(type.getValue());
+          }
+
+          if (Constants.SELF_LINK_REL.equals(link.getRel())) {
+            entry.setSelfLink(link);
+          } else if (Constants.EDIT_LINK_REL.equals(link.getRel())) {
+            entry.setEditLink(link);
+          } else if (link.getRel().startsWith(version.getNamespaceMap().get(ODataServiceVersion.NAVIGATION_LINK_REL))) {
+            entry.getNavigationLinks().add(link);
+            inline(reader, event.asStartElement(), link);
+          } else if (link.getRel().startsWith(
+                  version.getNamespaceMap().get(ODataServiceVersion.ASSOCIATION_LINK_REL))) {
+
+            entry.getAssociationLinks().add(link);
+          } else if (link.getRel().startsWith(
+                  version.getNamespaceMap().get(ODataServiceVersion.MEDIA_EDIT_LINK_REL))) {
+
+            final Attribute metag = event.asStartElement().getAttributeByName(etagQName);
+            if (metag != null) {
+              link.setMediaETag(metag.getValue());
+            }
+            entry.getMediaEditLinks().add(link);
+          }
+        } else if (actionQName.equals(event.asStartElement().getName())) {
+          final ODataOperation operation = new ODataOperation();
+          final Attribute metadata = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATTR_METADATA));
+          if (metadata != null) {
+            operation.setMetadataAnchor(metadata.getValue());
+          }
+          final Attribute title = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATTR_TITLE));
+          if (title != null) {
+            operation.setTitle(title.getValue());
+          }
+          final Attribute target = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATTR_TARGET));
+          if (target != null) {
+            operation.setTarget(URI.create(target.getValue()));
+          }
+
+          entry.getOperations().add(operation);
+        } else if (Constants.QNAME_ATOM_ELEM_CONTENT.equals(event.asStartElement().getName())) {
+          final Attribute type = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATTR_TYPE));
+          if (type == null || ContentType.APPLICATION_XML.equals(type.getValue())) {
+            properties(reader, skipBeforeFirstStartElement(reader), entry);
+          } else {
+            entry.setMediaContentType(type.getValue());
+            final Attribute src = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATOM_ATTR_SRC));
+            if (src != null) {
+              entry.setMediaContentSource(src.getValue());
+            }
+          }
+        } else if (propertiesQName.equals(event.asStartElement().getName())) {
+          properties(reader, event.asStartElement(), entry);
+        }
+      }
+
+      if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
+        foundEndEntry = true;
+      }
+    }
+
+    return entry;
+  }
+
+  private AtomEntryImpl entry(final InputStream input) throws XMLStreamException {
+    final XMLEventReader reader = FACTORY.createXMLEventReader(input);
+    return entry(reader, skipBeforeFirstStartElement(reader));
+  }
+
+  private void count(final XMLEventReader reader, final StartElement start, final AtomFeedImpl feed)
+          throws XMLStreamException {
+
+    boolean foundEndElement = false;
+    while (reader.hasNext() && !foundEndElement) {
+      final XMLEvent event = reader.nextEvent();
+
+      if (event.isCharacters() && !event.asCharacters().isWhiteSpace()) {
+        feed.setCount(Integer.valueOf(event.asCharacters().getData()));
+      }
+
+      if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
+        foundEndElement = true;
+      }
+    }
+  }
+
+  private AtomFeedImpl feed(final XMLEventReader reader, final StartElement start) throws XMLStreamException {
+    if (!Constants.QNAME_ATOM_ELEM_FEED.equals(start.getName())) {
+      return null;
+    }
+
+    final AtomFeedImpl feed = new AtomFeedImpl();
+    final Attribute xmlBase = start.getAttributeByName(Constants.QNAME_ATTR_XML_BASE);
+    if (xmlBase != null) {
+      feed.setBaseURI(xmlBase.getValue());
+    }
+
+    boolean foundEndFeed = false;
+    while (reader.hasNext() && !foundEndFeed) {
+      final XMLEvent event = reader.nextEvent();
+
+      if (event.isStartElement()) {
+        if (countQName.equals(event.asStartElement().getName())) {
+          count(reader, event.asStartElement(), feed);
+        } else if (Constants.QNAME_ATOM_ELEM_ID.equals(event.asStartElement().getName())) {
+          common(reader, event.asStartElement(), feed, "id");
+        } else if (Constants.QNAME_ATOM_ELEM_TITLE.equals(event.asStartElement().getName())) {
+          common(reader, event.asStartElement(), feed, "title");
+        } else if (Constants.QNAME_ATOM_ELEM_SUMMARY.equals(event.asStartElement().getName())) {
+          common(reader, event.asStartElement(), feed, "summary");
+        } else if (Constants.QNAME_ATOM_ELEM_UPDATED.equals(event.asStartElement().getName())) {
+          common(reader, event.asStartElement(), feed, "updated");
+        } else if (Constants.QNAME_ATOM_ELEM_LINK.equals(event.asStartElement().getName())) {
+          final Attribute rel = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATTR_REL));
+          if (rel != null && Constants.NEXT_LINK_REL.equals(rel.getValue())) {
+            final Attribute href = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATTR_HREF));
+            if (href != null) {
+              feed.setNext(URI.create(href.getValue()));
+            }
+          }
+        } else if (Constants.QNAME_ATOM_ELEM_ENTRY.equals(event.asStartElement().getName())) {
+          feed.getEntries().add(entry(reader, event.asStartElement()));
+        }
+      }
+
+      if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
+        foundEndFeed = true;
+      }
+    }
+
+    return feed;
+  }
+
+  private AtomFeedImpl feed(final InputStream input) throws XMLStreamException {
+    final XMLEventReader reader = FACTORY.createXMLEventReader(input);
+    return feed(reader, skipBeforeFirstStartElement(reader));
+  }
+
+  @SuppressWarnings("unchecked")
+  public <T> T read(final InputStream input, final Class<T> reference) throws XMLStreamException {
+    if (AtomFeedImpl.class.equals(reference)) {
+      return (T) feed(input);
+    } else if (AtomEntryImpl.class.equals(reference)) {
+      return (T) entry(input);
+    } else if (AtomPropertyImpl.class.equals(reference)) {
+      return (T) property(input);
+    } else if (XMLLinkCollectionImpl.class.equals(reference)) {
+      return (T) linkCollection(input);
+    }
+    return null;
+  }
+}

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

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

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/fac84b3e/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomGeoValueDeserializer.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomGeoValueDeserializer.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomGeoValueDeserializer.java
new file mode 100644
index 0000000..458e4cc
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomGeoValueDeserializer.java
@@ -0,0 +1,261 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.core.data;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Attribute;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.olingo.commons.api.Constants;
+import org.apache.olingo.commons.api.data.GeoUtils;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
+import org.apache.olingo.commons.api.edm.geo.Geospatial;
+import org.apache.olingo.commons.api.edm.geo.GeospatialCollection;
+import org.apache.olingo.commons.api.edm.geo.LineString;
+import org.apache.olingo.commons.api.edm.geo.MultiLineString;
+import org.apache.olingo.commons.api.edm.geo.MultiPoint;
+import org.apache.olingo.commons.api.edm.geo.MultiPolygon;
+import org.apache.olingo.commons.api.edm.geo.Point;
+import org.apache.olingo.commons.api.edm.geo.Polygon;
+import org.apache.olingo.commons.core.edm.primitivetype.EdmDouble;
+
+class AtomGeoValueDeserializer {
+
+  private List<Point> points(final XMLEventReader reader, final StartElement start,
+          final EdmPrimitiveTypeKind type, final String crs) throws XMLStreamException {
+
+    final List<Point> result = new ArrayList<Point>();
+
+    boolean foundEndProperty = false;
+    while (reader.hasNext() && !foundEndProperty) {
+      final XMLEvent event = reader.nextEvent();
+
+      if (event.isCharacters() && !event.asCharacters().isWhiteSpace()) {
+        final String[] pointInfo = event.asCharacters().getData().split(" ");
+
+        final Point point = new Point(GeoUtils.getDimension(type), crs);
+        try {
+          point.setX(EdmDouble.getInstance().valueOfString(pointInfo[0], null, null,
+                  Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null, Double.class));
+          point.setY(EdmDouble.getInstance().valueOfString(pointInfo[1], null, null,
+                  Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null, Double.class));
+        } catch (EdmPrimitiveTypeException e) {
+          throw new XMLStreamException("While deserializing point coordinates as double", e);
+        }
+        result.add(point);
+      }
+
+      if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
+        foundEndProperty = true;
+      }
+    }
+
+    return result;
+  }
+
+  private MultiPoint multipoint(final XMLEventReader reader, final StartElement start,
+          final EdmPrimitiveTypeKind type, final String crs) throws XMLStreamException {
+
+    List<Point> points = Collections.<Point>emptyList();
+
+    boolean foundEndProperty = false;
+    while (reader.hasNext() && !foundEndProperty) {
+      final XMLEvent event = reader.nextEvent();
+
+      if (event.isStartElement() && event.asStartElement().getName().equals(Constants.QNAME_POINTMEMBERS)) {
+        points = points(reader, event.asStartElement(), type, null);
+      }
+
+      if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
+        foundEndProperty = true;
+      }
+    }
+
+    return new MultiPoint(GeoUtils.getDimension(type), crs, points);
+  }
+
+  private LineString lineString(final XMLEventReader reader, final StartElement start,
+          final EdmPrimitiveTypeKind type, final String crs) throws XMLStreamException {
+
+    return new LineString(GeoUtils.getDimension(type), crs, points(reader, start, type, null));
+  }
+
+  private Polygon polygon(final XMLEventReader reader, final StartElement start,
+          final EdmPrimitiveTypeKind type, final String crs) throws XMLStreamException {
+
+    List<Point> extPoints = null;
+    List<Point> intPoints = null;
+
+    boolean foundEndProperty = false;
+    while (reader.hasNext() && !foundEndProperty) {
+      final XMLEvent event = reader.nextEvent();
+
+      if (event.isStartElement()) {
+        if (event.asStartElement().getName().equals(Constants.QNAME_POLYGON_EXTERIOR)) {
+          extPoints = points(reader, event.asStartElement(), type, null);
+        }
+        if (event.asStartElement().getName().equals(Constants.QNAME_POLYGON_INTERIOR)) {
+          intPoints = points(reader, event.asStartElement(), type, null);
+        }
+      }
+
+      if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
+        foundEndProperty = true;
+      }
+    }
+
+    return new Polygon(GeoUtils.getDimension(type), crs, intPoints, extPoints);
+  }
+
+  private MultiLineString multiLineString(final XMLEventReader reader, final StartElement start,
+          final EdmPrimitiveTypeKind type, final String crs) throws XMLStreamException {
+
+    final List<LineString> lineStrings = new ArrayList<LineString>();
+
+    boolean foundEndProperty = false;
+    while (reader.hasNext() && !foundEndProperty) {
+      final XMLEvent event = reader.nextEvent();
+
+      if (event.isStartElement() && event.asStartElement().getName().equals(Constants.QNAME_LINESTRING)) {
+        lineStrings.add(lineString(reader, event.asStartElement(), type, null));
+      }
+
+      if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
+        foundEndProperty = true;
+      }
+    }
+
+    return new MultiLineString(GeoUtils.getDimension(type), crs, lineStrings);
+  }
+
+  private MultiPolygon multiPolygon(final XMLEventReader reader, final StartElement start,
+          final EdmPrimitiveTypeKind type, final String crs) throws XMLStreamException {
+
+    final List<Polygon> polygons = new ArrayList<Polygon>();
+
+    boolean foundEndProperty = false;
+    while (reader.hasNext() && !foundEndProperty) {
+      final XMLEvent event = reader.nextEvent();
+
+      if (event.isStartElement() && event.asStartElement().getName().equals(Constants.QNAME_POLYGON)) {
+        polygons.add(polygon(reader, event.asStartElement(), type, null));
+      }
+
+      if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
+        foundEndProperty = true;
+      }
+    }
+
+    return new MultiPolygon(GeoUtils.getDimension(type), crs, polygons);
+  }
+
+  private GeospatialCollection collection(final XMLEventReader reader, final StartElement start,
+          final EdmPrimitiveTypeKind type, final String crs) throws XMLStreamException {
+
+    final List<Geospatial> geospatials = new ArrayList<Geospatial>();
+
+    boolean foundEndCollection = false;
+    while (reader.hasNext() && !foundEndCollection) {
+      final XMLEvent event = reader.nextEvent();
+
+      if (event.isStartElement() && event.asStartElement().getName().equals(Constants.QNAME_GEOMEMBERS)) {
+        boolean foundEndMembers = false;
+        while (reader.hasNext() && !foundEndMembers) {
+          final XMLEvent subevent = reader.nextEvent();
+
+          if (subevent.isStartElement()) {
+            geospatials.add(deserialize(reader, subevent.asStartElement(),
+                    GeoUtils.getType(GeoUtils.getDimension(type), subevent.asStartElement().getName().getLocalPart())));
+          }
+
+          if (subevent.isEndElement() && Constants.QNAME_GEOMEMBERS.equals(subevent.asEndElement().getName())) {
+            foundEndMembers = true;
+          }
+        }
+      }
+
+      if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
+        foundEndCollection = true;
+      }
+    }
+
+    return new GeospatialCollection(GeoUtils.getDimension(type), crs, geospatials);
+  }
+
+  public Geospatial deserialize(final XMLEventReader reader, final StartElement start,
+          final EdmPrimitiveTypeKind type) throws XMLStreamException {
+
+    String crs = null;
+    final Attribute srsName = start.getAttributeByName(Constants.QNAME_ATTR_SRSNAME);
+    if (srsName != null) {
+      crs = StringUtils.substringAfterLast(srsName.getValue(), "/");
+    }
+
+    Geospatial value;
+
+    switch (type) {
+      case GeographyPoint:
+      case GeometryPoint:
+        value = points(reader, start, type, crs).get(0);
+        break;
+
+      case GeographyMultiPoint:
+      case GeometryMultiPoint:
+        value = multipoint(reader, start, type, crs);
+        break;
+
+      case GeographyLineString:
+      case GeometryLineString:
+        value = lineString(reader, start, type, crs);
+        break;
+
+      case GeographyMultiLineString:
+      case GeometryMultiLineString:
+        value = multiLineString(reader, start, type, crs);
+        break;
+
+      case GeographyPolygon:
+      case GeometryPolygon:
+        value = polygon(reader, start, type, crs);
+        break;
+
+      case GeographyMultiPolygon:
+      case GeometryMultiPolygon:
+        value = multiPolygon(reader, start, type, crs);
+        break;
+
+      case GeographyCollection:
+      case GeometryCollection:
+        value = collection(reader, start, type, crs);
+        break;
+
+      default:
+        value = null;
+    }
+
+    return value;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/fac84b3e/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomGeoValueSerializer.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomGeoValueSerializer.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomGeoValueSerializer.java
new file mode 100644
index 0000000..624bcfa
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomGeoValueSerializer.java
@@ -0,0 +1,221 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.commons.core.data;
+
+import java.util.Collections;
+import java.util.Iterator;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import org.apache.olingo.commons.api.Constants;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
+import org.apache.olingo.commons.api.edm.geo.Geospatial;
+import org.apache.olingo.commons.api.edm.geo.GeospatialCollection;
+import org.apache.olingo.commons.api.edm.geo.LineString;
+import org.apache.olingo.commons.api.edm.geo.MultiLineString;
+import org.apache.olingo.commons.api.edm.geo.MultiPoint;
+import org.apache.olingo.commons.api.edm.geo.MultiPolygon;
+import org.apache.olingo.commons.api.edm.geo.Point;
+import org.apache.olingo.commons.api.edm.geo.Polygon;
+import org.apache.olingo.commons.core.edm.primitivetype.EdmDouble;
+
+class AtomGeoValueSerializer {
+
+  private void points(final XMLStreamWriter writer, final Iterator<Point> itor, final boolean wrap)
+          throws XMLStreamException {
+
+    while (itor.hasNext()) {
+      final Point point = itor.next();
+
+      if (wrap) {
+        writer.writeStartElement(Constants.PREFIX_GML, Constants.ELEM_POINT, Constants.NS_GML);
+      }
+
+      writer.writeStartElement(Constants.PREFIX_GML, Constants.ELEM_POS, Constants.NS_GML);
+      try {
+        writer.writeCharacters(EdmDouble.getInstance().valueToString(point.getX(), null, null,
+                Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null)
+                + " "
+                + EdmDouble.getInstance().valueToString(point.getY(), null, null,
+                        Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null));
+      } catch (EdmPrimitiveTypeException e) {
+        throw new XMLStreamException("While serializing point coordinates as double", e);
+      }
+      writer.writeEndElement();
+
+      if (wrap) {
+        writer.writeEndElement();
+      }
+    }
+  }
+
+  private void lineStrings(final XMLStreamWriter writer, final Iterator<LineString> itor, final boolean wrap)
+          throws XMLStreamException {
+
+    while (itor.hasNext()) {
+      final LineString lineString = itor.next();
+
+      if (wrap) {
+        writer.writeStartElement(Constants.PREFIX_GML, Constants.ELEM_LINESTRING, Constants.NS_GML);
+      }
+
+      points(writer, lineString.iterator(), false);
+
+      if (wrap) {
+        writer.writeEndElement();
+      }
+    }
+  }
+
+  private void polygons(final XMLStreamWriter writer, final Iterator<Polygon> itor, final boolean wrap)
+          throws XMLStreamException {
+
+    while (itor.hasNext()) {
+      final Polygon polygon = itor.next();
+
+      if (wrap) {
+        writer.writeStartElement(Constants.PREFIX_GML, Constants.ELEM_POLYGON, Constants.NS_GML);
+      }
+
+      if (!polygon.getExterior().isEmpty()) {
+        writer.writeStartElement(Constants.PREFIX_GML, Constants.ELEM_POLYGON_EXTERIOR, Constants.NS_GML);
+        writer.writeStartElement(Constants.PREFIX_GML, Constants.ELEM_POLYGON_LINEARRING, Constants.NS_GML);
+
+        points(writer, polygon.getExterior().iterator(), false);
+
+        writer.writeEndElement();
+        writer.writeEndElement();
+      }
+      if (!polygon.getInterior().isEmpty()) {
+        writer.writeStartElement(Constants.PREFIX_GML, Constants.ELEM_POLYGON_INTERIOR, Constants.NS_GML);
+        writer.writeStartElement(Constants.PREFIX_GML, Constants.ELEM_POLYGON_LINEARRING, Constants.NS_GML);
+
+        points(writer, polygon.getInterior().iterator(), false);
+
+        writer.writeEndElement();
+        writer.writeEndElement();
+      }
+
+      if (wrap) {
+        writer.writeEndElement();
+      }
+    }
+  }
+
+  private void writeSrsName(final XMLStreamWriter writer, final Geospatial value) throws XMLStreamException {
+    if (value.getCrs() != null) {
+      writer.writeAttribute(Constants.PREFIX_GML, Constants.NS_GML, Constants.ATTR_SRSNAME,
+              Constants.SRS_URLPREFIX + value.getCrs());
+    }
+  }
+
+  public void serialize(final XMLStreamWriter writer, final Geospatial value) throws XMLStreamException {
+    switch (value.getEdmPrimitiveTypeKind()) {
+      case GeographyPoint:
+      case GeometryPoint:
+        writer.writeStartElement(Constants.PREFIX_GML, Constants.ELEM_POINT, Constants.NS_GML);
+        writeSrsName(writer, value);
+
+        points(writer, Collections.singleton((Point) value).iterator(), false);
+
+        writer.writeEndElement();
+        break;
+
+      case GeometryMultiPoint:
+      case GeographyMultiPoint:
+        writer.writeStartElement(Constants.PREFIX_GML, Constants.ELEM_MULTIPOINT, Constants.NS_GML);
+        writeSrsName(writer, value);
+
+        if (!((MultiPoint) value).isEmpty()) {
+          writer.writeStartElement(Constants.PREFIX_GML, Constants.ELEM_POINTMEMBERS, Constants.NS_GML);
+          points(writer, ((MultiPoint) value).iterator(), true);
+          writer.writeEndElement();
+        }
+
+        writer.writeEndElement();
+        break;
+
+      case GeometryLineString:
+      case GeographyLineString:
+        writer.writeStartElement(Constants.PREFIX_GML, Constants.ELEM_LINESTRING, Constants.NS_GML);
+        writeSrsName(writer, value);
+
+        lineStrings(writer, Collections.singleton((LineString) value).iterator(), false);
+
+        writer.writeEndElement();
+        break;
+
+      case GeometryMultiLineString:
+      case GeographyMultiLineString:
+        writer.writeStartElement(Constants.PREFIX_GML, Constants.ELEM_MULTILINESTRING, Constants.NS_GML);
+        writeSrsName(writer, value);
+
+        if (!((MultiLineString) value).isEmpty()) {
+          writer.writeStartElement(Constants.PREFIX_GML, Constants.ELEM_LINESTRINGMEMBERS, Constants.NS_GML);
+          lineStrings(writer, ((MultiLineString) value).iterator(), true);
+          writer.writeEndElement();
+        }
+
+        writer.writeEndElement();
+        break;
+
+      case GeographyPolygon:
+      case GeometryPolygon:
+        writer.writeStartElement(Constants.PREFIX_GML, Constants.ELEM_POLYGON, Constants.NS_GML);
+        writeSrsName(writer, value);
+
+        polygons(writer, Collections.singleton(((Polygon) value)).iterator(), false);
+
+        writer.writeEndElement();
+        break;
+
+      case GeographyMultiPolygon:
+      case GeometryMultiPolygon:
+        writer.writeStartElement(Constants.PREFIX_GML, Constants.ELEM_MULTIPOLYGON, Constants.NS_GML);
+        writeSrsName(writer, value);
+
+        if (!((MultiPolygon) value).isEmpty()) {
+          writer.writeStartElement(Constants.PREFIX_GML, Constants.ELEM_SURFACEMEMBERS, Constants.NS_GML);
+          polygons(writer, ((MultiPolygon) value).iterator(), true);
+          writer.writeEndElement();
+        }
+
+        writer.writeEndElement();
+        break;
+
+      case GeographyCollection:
+      case GeometryCollection:
+        writer.writeStartElement(Constants.PREFIX_GML, Constants.ELEM_GEOCOLLECTION, Constants.NS_GML);
+        writeSrsName(writer, value);
+
+        if (!((GeospatialCollection) value).isEmpty()) {
+          writer.writeStartElement(Constants.PREFIX_GML, Constants.ELEM_GEOMEMBERS, Constants.NS_GML);
+          for (final Iterator<Geospatial> itor = ((GeospatialCollection) value).iterator(); itor.hasNext();) {
+            serialize(writer, itor.next());
+          }
+          writer.writeEndElement();
+        }
+
+        writer.writeEndElement();
+        break;
+
+      default:
+    }
+  }
+
+}