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:58 UTC
[46/52] [abbrv] [OLINGO-205, OLINGO-200, OLINGO-65] merge
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5b5576f8/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomDeserializer.java
----------------------------------------------------------------------
diff --cc lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomDeserializer.java
index 0000000,f42fe00..b8775d5
mode 000000,100644..100644
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomDeserializer.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomDeserializer.java
@@@ -1,0 -1,370 +1,368 @@@
+ /*
+ * 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/5b5576f8/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomPropertyDeserializer.java
----------------------------------------------------------------------
diff --cc lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomPropertyDeserializer.java
index 0000000,99231b4..91ad49a
mode 000000,100644..100644
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomPropertyDeserializer.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AtomPropertyDeserializer.java
@@@ -1,0 -1,214 +1,218 @@@
+ /*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+ package org.apache.olingo.commons.core.data;
+
+ 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.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.api.edm.constants.ODataServiceVersion;
+ import org.apache.olingo.commons.core.edm.EdmTypeInfo;
+
+ class AtomPropertyDeserializer extends AbstractAtomDealer {
+
+ private final AtomGeoValueDeserializer geoDeserializer;
+
+ public AtomPropertyDeserializer(final ODataServiceVersion version) {
+ super(version);
+ this.geoDeserializer = new AtomGeoValueDeserializer();
+ }
+
+ private Value fromPrimitive(final XMLEventReader reader, final StartElement start,
+ final EdmTypeInfo typeInfo) throws XMLStreamException {
+
+ Value value = null;
+
+ boolean foundEndProperty = false;
+ while (reader.hasNext() && !foundEndProperty) {
+ final XMLEvent event = reader.nextEvent();
+
+ if (event.isStartElement() && typeInfo != null && typeInfo.getPrimitiveTypeKind().isGeospatial()) {
+ final EdmPrimitiveTypeKind geoType = EdmPrimitiveTypeKind.valueOfFQN(
+ version, typeInfo.getFullQualifiedName().toString());
+ value = new GeospatialValueImpl(this.geoDeserializer.deserialize(reader, event.asStartElement(), geoType));
+ }
+
+ if (event.isCharacters() && !event.asCharacters().isWhiteSpace()
+ && (typeInfo == null || !typeInfo.getPrimitiveTypeKind().isGeospatial())) {
+
+ value = new PrimitiveValueImpl(event.asCharacters().getData());
+ }
+
+ if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
+ foundEndProperty = true;
+ }
+ }
+
+ return value;
+ }
+
+ private ComplexValue fromComplex(final XMLEventReader reader, final StartElement start)
+ throws XMLStreamException {
+
+ final ComplexValue value = new ComplexValueImpl();
+
+ boolean foundEndProperty = false;
+ while (reader.hasNext() && !foundEndProperty) {
+ final XMLEvent event = reader.nextEvent();
+
+ if (event.isStartElement()) {
+ value.get().add(deserialize(reader, event.asStartElement()));
+ }
+
+ if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
+ foundEndProperty = true;
+ }
+ }
+
+ return value;
+ }
+
+ private CollectionValue fromCollection(final XMLEventReader reader, final StartElement start,
+ final EdmTypeInfo typeInfo) throws XMLStreamException {
+
+ final CollectionValueImpl value = new CollectionValueImpl();
+
+ final EdmTypeInfo type = typeInfo == null
+ ? null
+ : new EdmTypeInfo.Builder().setTypeExpression(typeInfo.getFullQualifiedName().toString()).build();
+
+ boolean foundEndProperty = false;
+ while (reader.hasNext() && !foundEndProperty) {
+ final XMLEvent event = reader.nextEvent();
+
+ if (event.isStartElement()) {
+ switch (guessPropertyType(reader)) {
+ case COMPLEX:
+ value.get().add(fromComplex(reader, event.asStartElement()));
+ break;
+
+ case PRIMITIVE:
+ value.get().add(fromPrimitive(reader, event.asStartElement(), type));
+ break;
+
+ default:
+ // do not add null or empty values
+ }
+ }
+
+ if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
+ foundEndProperty = true;
+ }
+ }
+
+ return value;
+ }
+
+ private ODataPropertyType guessPropertyType(final XMLEventReader reader) throws XMLStreamException {
+ XMLEvent child = null;
+ while (reader.hasNext() && child == null) {
+ final XMLEvent event = reader.peek();
+ if (event.isCharacters() && event.asCharacters().isWhiteSpace()) {
+ reader.nextEvent();
+ } else {
+ child = event;
+ }
+ }
+
- ODataPropertyType type = null;
++ final ODataPropertyType type;
+ if (child == null) {
+ type = ODataPropertyType.PRIMITIVE;
+ } else {
+ if (child.isStartElement()) {
+ if (Constants.NS_GML.equals(child.asStartElement().getName().getNamespaceURI())) {
+ type = ODataPropertyType.PRIMITIVE;
+ } else if (elementQName.equals(child.asStartElement().getName())) {
+ type = ODataPropertyType.COLLECTION;
+ } else {
+ type = ODataPropertyType.COMPLEX;
+ }
+ } else if (child.isCharacters()) {
+ type = ODataPropertyType.PRIMITIVE;
+ } else {
+ type = ODataPropertyType.EMPTY;
+ }
+ }
+
+ return type;
+ }
+
+ public AtomPropertyImpl deserialize(final XMLEventReader reader, final StartElement start)
+ throws XMLStreamException {
+
+ final AtomPropertyImpl property = new AtomPropertyImpl();
+ property.setName(start.getName().getLocalPart());
+
+ final Attribute typeAttr = start.getAttributeByName(this.typeQName);
- if (typeAttr != null) {
- property.setType(typeAttr.getValue());
- }
+
+ Value value;
+ final Attribute nullAttr = start.getAttributeByName(this.nullQName);
++ final String typeAttrValue = typeAttr == null ? null : typeAttr.getValue();
++
+ if (nullAttr == null) {
- final EdmTypeInfo typeInfo = StringUtils.isBlank(property.getType())
++ final EdmTypeInfo typeInfo = StringUtils.isBlank(typeAttrValue)
+ ? null
- : new EdmTypeInfo.Builder().setTypeExpression(property.getType()).build();
++ : new EdmTypeInfo.Builder().setTypeExpression(typeAttrValue).build();
++
++ if (typeInfo != null) {
++ property.setType(typeInfo.getTypeExpression());
++ }
+
+ final ODataPropertyType propType = typeInfo == null
+ ? guessPropertyType(reader)
+ : typeInfo.isCollection()
+ ? ODataPropertyType.COLLECTION
+ : typeInfo.isPrimitiveType()
+ ? ODataPropertyType.PRIMITIVE
+ : ODataPropertyType.COMPLEX;
+
+ switch (propType) {
+ case COLLECTION:
+ value = fromCollection(reader, start, typeInfo);
+ break;
+
+ case COMPLEX:
+ value = fromComplex(reader, start);
+ break;
+
+ case PRIMITIVE:
+ value = fromPrimitive(reader, start, typeInfo);
+ break;
+
+ case EMPTY:
+ default:
+ value = new PrimitiveValueImpl(StringUtils.EMPTY);
+ }
+ } else {
+ value = new NullValueImpl();
+ }
++
+ property.setValue(value);
+
+ return property;
+ }
+ }
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5b5576f8/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONGeoValueDeserializer.java
----------------------------------------------------------------------
diff --cc lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONGeoValueDeserializer.java
index 0000000,f1863a7..c544f73
mode 000000,100644..100644
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONGeoValueDeserializer.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONGeoValueDeserializer.java
@@@ -1,0 -1,274 +1,273 @@@
+ /*
+ * 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 java.util.ArrayList;
+ import java.util.Collections;
+ import java.util.Iterator;
+ import java.util.List;
+ 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.constants.ODataServiceVersion;
+ 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.EdmTypeInfo;
+ import org.apache.olingo.commons.core.edm.primitivetype.EdmDouble;
+
+ class JSONGeoValueDeserializer {
+
+ private final ODataServiceVersion version;
+
+ public JSONGeoValueDeserializer(final ODataServiceVersion version) {
+ this.version = version;
+ }
+
+ private Point point(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type, final String crs) {
+ Point point = null;
+
+ if (itor.hasNext()) {
+ point = new Point(GeoUtils.getDimension(type), crs);
+ try {
+ point.setX(EdmDouble.getInstance().valueOfString(itor.next().asText(), null, null,
+ Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null, Double.class));
+ point.setY(EdmDouble.getInstance().valueOfString(itor.next().asText(), null, null,
+ Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null, Double.class));
+ } catch (EdmPrimitiveTypeException e) {
+ throw new IllegalArgumentException("While deserializing point coordinates as double", e);
+ }
+ }
+
+ return point;
+ }
+
+ private MultiPoint multipoint(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type,
+ final String crs) {
+
- MultiPoint multiPoint = null;
++ final MultiPoint multiPoint;
+
+ if (itor.hasNext()) {
+ final List<Point> points = new ArrayList<Point>();
+ while (itor.hasNext()) {
+ final Iterator<JsonNode> mpItor = itor.next().elements();
+ points.add(point(mpItor, type, crs));
+ }
+ multiPoint = new MultiPoint(GeoUtils.getDimension(type), crs, points);
+ } else {
+ multiPoint = new MultiPoint(GeoUtils.getDimension(type), crs, Collections.<Point>emptyList());
+ }
+
+ return multiPoint;
+ }
+
+ private LineString lineString(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type,
+ final String crs) {
+
- LineString lineString = null;
++ final LineString lineString;
+
+ if (itor.hasNext()) {
+ final List<Point> points = new ArrayList<Point>();
+ while (itor.hasNext()) {
+ final Iterator<JsonNode> mpItor = itor.next().elements();
+ points.add(point(mpItor, type, crs));
+ }
+ lineString = new LineString(GeoUtils.getDimension(type), crs, points);
+ } else {
+ lineString = new LineString(GeoUtils.getDimension(type), crs, Collections.<Point>emptyList());
+ }
+
+ return lineString;
+ }
+
+ private MultiLineString multiLineString(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type,
+ final String crs) {
+
- MultiLineString multiLineString = null;
++ final MultiLineString multiLineString;
+
+ if (itor.hasNext()) {
+ final List<LineString> lineStrings = new ArrayList<LineString>();
+ while (itor.hasNext()) {
+ final Iterator<JsonNode> mlsItor = itor.next().elements();
+ lineStrings.add(lineString(mlsItor, type, crs));
+ }
+ multiLineString = new MultiLineString(GeoUtils.getDimension(type), crs, lineStrings);
+ } else {
+ multiLineString = new MultiLineString(GeoUtils.getDimension(type), crs, Collections.<LineString>emptyList());
+ }
+
+ return multiLineString;
+ }
+
+ private Polygon polygon(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type,
+ final String crs) {
+
+ List<Point> extPoints = null;
+ if (itor.hasNext()) {
+ final Iterator<JsonNode> extItor = itor.next().elements();
+ if (extItor.hasNext()) {
+ extPoints = new ArrayList<Point>();
+ while (extItor.hasNext()) {
+ final Iterator<JsonNode> mpItor = extItor.next().elements();
+ extPoints.add(point(mpItor, type, crs));
+ }
+ }
+ }
+
+ List<Point> intPoints = null;
+ if (itor.hasNext()) {
+ final Iterator<JsonNode> intItor = itor.next().elements();
+ if (intItor.hasNext()) {
+ intPoints = new ArrayList<Point>();
+ while (intItor.hasNext()) {
+ final Iterator<JsonNode> mpItor = intItor.next().elements();
+ intPoints.add(point(mpItor, type, crs));
+ }
+ }
+ }
+
+ return new Polygon(GeoUtils.getDimension(type), crs, intPoints, extPoints);
+ }
+
+ private MultiPolygon multiPolygon(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type,
+ final String crs) {
+
- MultiPolygon multiPolygon = null;
++ final MultiPolygon multiPolygon;
+
+ if (itor.hasNext()) {
+ final List<Polygon> polygons = new ArrayList<Polygon>();
+ while (itor.hasNext()) {
+ final Iterator<JsonNode> mpItor = itor.next().elements();
+ polygons.add(polygon(mpItor, type, crs));
+ }
+ multiPolygon = new MultiPolygon(GeoUtils.getDimension(type), crs, polygons);
+ } else {
+ multiPolygon = new MultiPolygon(GeoUtils.getDimension(type), crs, Collections.<Polygon>emptyList());
+ }
+
+ return multiPolygon;
+ }
+
+ private GeospatialCollection collection(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type,
+ final String crs) {
+
- GeospatialCollection collection = null;
++ final GeospatialCollection collection;
+
+ if (itor.hasNext()) {
+ final List<Geospatial> geospatials = new ArrayList<Geospatial>();
+
+ while (itor.hasNext()) {
+ final JsonNode geo = itor.next();
+ final String collItemType = geo.get(Constants.ATTR_TYPE).asText();
+ final String callAsType;
+ if (EdmPrimitiveTypeKind.GeographyCollection.name().equals(collItemType)
+ || EdmPrimitiveTypeKind.GeometryCollection.name().equals(collItemType)) {
+
+ callAsType = collItemType;
+ } else {
+ callAsType = (type == EdmPrimitiveTypeKind.GeographyCollection ? "Geography" : "Geometry")
+ + collItemType;
+ }
+
+ geospatials.add(deserialize(geo, new EdmTypeInfo.Builder().setTypeExpression(callAsType).build()));
+ }
+
+ collection = new GeospatialCollection(GeoUtils.getDimension(type), crs, geospatials);
+ } else {
+ collection = new GeospatialCollection(GeoUtils.getDimension(type), crs, Collections.<Geospatial>emptyList());
+ }
+
+ return collection;
+ }
+
+ public Geospatial deserialize(final JsonNode node, final EdmTypeInfo typeInfo) {
+ final EdmPrimitiveTypeKind actualType;
+ if ((typeInfo.getPrimitiveTypeKind() == EdmPrimitiveTypeKind.Geography
+ || typeInfo.getPrimitiveTypeKind() == EdmPrimitiveTypeKind.Geometry)
+ && node.has(Constants.ATTR_TYPE)) {
+
+ String nodeType = node.get(Constants.ATTR_TYPE).asText();
+ if (nodeType.startsWith("Geo")) {
+ final int yIdx = nodeType.indexOf('y');
+ nodeType = nodeType.substring(yIdx + 1);
+ }
+ actualType = EdmPrimitiveTypeKind.valueOfFQN(version, typeInfo.getFullQualifiedName().toString() + nodeType);
+ } else {
+ actualType = typeInfo.getPrimitiveTypeKind();
+ }
+
+ final Iterator<JsonNode> cooItor = node.has(Constants.JSON_COORDINATES)
+ ? node.get(Constants.JSON_COORDINATES).elements()
+ : Collections.<JsonNode>emptyList().iterator();
+
+ String crs = null;
+ if (node.has(Constants.JSON_CRS)) {
+ crs = node.get(Constants.JSON_CRS).get(Constants.PROPERTIES).get(Constants.JSON_NAME).asText().split(":")[1];
+ }
+
+ Geospatial value = null;
+ switch (actualType) {
+ case GeographyPoint:
+ case GeometryPoint:
+ value = point(cooItor, actualType, crs);
+ break;
+
+ case GeographyMultiPoint:
+ case GeometryMultiPoint:
+ value = multipoint(cooItor, actualType, crs);
+ break;
+
+ case GeographyLineString:
+ case GeometryLineString:
+ value = lineString(cooItor, actualType, crs);
+ break;
+
+ case GeographyMultiLineString:
+ case GeometryMultiLineString:
+ value = multiLineString(cooItor, actualType, crs);
+ break;
+
+ case GeographyPolygon:
+ case GeometryPolygon:
+ value = polygon(cooItor, actualType, crs);
+ break;
+
+ case GeographyMultiPolygon:
+ case GeometryMultiPolygon:
+ value = multiPolygon(cooItor, actualType, crs);
+ break;
+
+ case GeographyCollection:
+ case GeometryCollection:
+ value = collection(node.get(Constants.JSON_GEOMETRIES).elements(), actualType, crs);
+ break;
+
+ default:
+ }
+
+ return value;
+ }
-
+ }
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5b5576f8/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmTypeInfo.java
----------------------------------------------------------------------
diff --cc lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmTypeInfo.java
index 0000000,567950d..09e70cb
mode 000000,100644..100644
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmTypeInfo.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmTypeInfo.java
@@@ -1,0 -1,172 +1,184 @@@
+ /*
+ * 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.edm;
+
+ import org.apache.commons.lang3.StringUtils;
+ import org.apache.olingo.commons.api.edm.Edm;
+ import org.apache.olingo.commons.api.edm.EdmComplexType;
+ import org.apache.olingo.commons.api.edm.EdmEntityType;
+ import org.apache.olingo.commons.api.edm.EdmEnumType;
++import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
+ import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
+ import org.apache.olingo.commons.api.edm.FullQualifiedName;
+ import org.slf4j.Logger;
+ import org.slf4j.LoggerFactory;
+
+ public class EdmTypeInfo {
+
+ private static final Logger LOG = LoggerFactory.getLogger(EdmTypeInfo.class);
+
+ public static class Builder {
+
+ private String typeExpression;
+
+ private String defaultNamespace;
+
+ private Edm edm;
+
+ public Builder setTypeExpression(final String typeExpression) {
+ this.typeExpression = typeExpression;
+ return this;
+ }
+
+ public Builder setDefaultNamespace(final String defaultNamespace) {
+ this.defaultNamespace = defaultNamespace;
+ return this;
+ }
+
+ public Builder setEdm(final Edm edm) {
+ this.edm = edm;
+ return this;
+ }
+
+ public EdmTypeInfo build() {
- return new EdmTypeInfo(edm, typeExpression.indexOf('.') == -1
++ return new EdmTypeInfo(edm, typeExpression.indexOf('.') == -1 && StringUtils.isNotBlank(defaultNamespace)
+ ? defaultNamespace + "." + typeExpression
+ : typeExpression);
+ }
+ }
-
+ private final Edm edm;
+
+ private final String typeExpression;
+
+ private final boolean collection;
+
+ private final FullQualifiedName fullQualifiedName;
+
+ private EdmPrimitiveTypeKind primitiveType;
+
+ private EdmEnumType enumType;
+
+ private EdmComplexType complexType;
+
+ private EdmEntityType entityType;
+
+ private EdmTypeInfo(final Edm edm, final String typeExpression) {
+ this.edm = edm;
- this.typeExpression = typeExpression;
+
+ String baseType;
+ final int collStartIdx = typeExpression.indexOf("Collection(");
+ final int collEndIdx = typeExpression.lastIndexOf(')');
+ if (collStartIdx == -1) {
+ baseType = typeExpression;
+ this.collection = false;
+ } else {
+ if (collEndIdx == -1) {
+ throw new IllegalArgumentException("Malformed type: " + typeExpression);
+ }
+
+ this.collection = true;
+ baseType = typeExpression.substring(collStartIdx + 11, collEndIdx);
+ }
+
++
++ baseType = baseType.replaceAll("^#", "");
++
++ final String typeName;
++ final String namespace;
++
+ final int lastDotIdx = baseType.lastIndexOf('.');
+ if (lastDotIdx == -1) {
- throw new IllegalArgumentException("Cannot find namespace or alias in " + typeExpression);
++ namespace = EdmPrimitiveType.EDM_NAMESPACE;
++ typeName = baseType;
++ baseType = new FullQualifiedName(EdmPrimitiveType.EDM_NAMESPACE, baseType).toString();
++ } else {
++ namespace = baseType.substring(0, lastDotIdx);
++ typeName = baseType.substring(lastDotIdx + 1);
+ }
- final String namespace = baseType.substring(0, lastDotIdx);
- final String typeName = baseType.substring(lastDotIdx + 1);
++
+ if (StringUtils.isBlank(typeName)) {
+ throw new IllegalArgumentException("Null or empty type name in " + typeExpression);
+ }
+
++ final StringBuilder exp = new StringBuilder();
++ exp.append(baseType);
++
++ this.typeExpression = (this.collection ? exp.insert(0, "Collection(").append(")") : exp).toString();
+ this.fullQualifiedName = new FullQualifiedName(namespace, typeName);
+
+ try {
+ this.primitiveType = EdmPrimitiveTypeKind.valueOf(this.fullQualifiedName.getName());
+ } catch (IllegalArgumentException e) {
+ LOG.debug("{} does not appear to refer to an Edm primitive type", this.fullQualifiedName);
+ }
+ if (this.primitiveType == null && this.edm != null) {
+ this.enumType = this.edm.getEnumType(this.fullQualifiedName);
+ if (this.enumType == null) {
+ this.complexType = this.edm.getComplexType(this.fullQualifiedName);
+ if (this.complexType == null) {
+ this.entityType = this.edm.getEntityType(this.fullQualifiedName);
+ }
+ }
+ }
+ }
+
+ public String getTypeExpression() {
+ return typeExpression;
+ }
+
+ public boolean isCollection() {
+ return collection;
+ }
+
+ public FullQualifiedName getFullQualifiedName() {
+ return fullQualifiedName;
+ }
+
+ public boolean isPrimitiveType() {
+ return this.primitiveType != null;
+ }
+
+ public EdmPrimitiveTypeKind getPrimitiveTypeKind() {
+ return primitiveType;
+ }
+
+ public boolean isEnumType() {
+ return this.enumType != null;
+ }
+
+ public EdmEnumType getEnumType() {
+ return enumType;
+ }
+
+ public boolean isComplexType() {
+ return this.complexType != null;
+ }
+
+ public EdmComplexType getComplexType() {
+ return complexType;
+ }
+
+ public boolean isEntityType() {
+ return this.entityType != null;
+ }
+
+ public EdmEntityType getEntityType() {
+ return entityType;
+ }
-
+ }
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5b5576f8/lib/commons-core/src/main/java/org/apache/olingo/commons/core/op/AbstractODataDeserializer.java
----------------------------------------------------------------------
diff --cc lib/commons-core/src/main/java/org/apache/olingo/commons/core/op/AbstractODataDeserializer.java
index 0000000,94c43da..991e723
mode 000000,100644..100644
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/op/AbstractODataDeserializer.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/op/AbstractODataDeserializer.java
@@@ -1,0 -1,107 +1,106 @@@
+ /*
+ * 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.op;
+
+ import java.io.InputStream;
+ import org.apache.olingo.commons.api.data.Entry;
+ import org.apache.olingo.commons.api.domain.ODataError;
+ import org.apache.olingo.commons.api.data.Feed;
+ import org.apache.olingo.commons.api.data.Property;
+ import org.apache.olingo.commons.api.format.ODataFormat;
+ import org.apache.olingo.commons.api.format.ODataPubFormat;
+ import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
+ import org.apache.olingo.commons.api.op.CommonODataDeserializer;
+ import org.apache.olingo.commons.core.data.AtomDeserializer;
+ import org.apache.olingo.commons.core.data.AtomEntryImpl;
+ import org.apache.olingo.commons.core.data.AtomFeedImpl;
+ import org.apache.olingo.commons.core.data.AtomPropertyImpl;
+ import org.apache.olingo.commons.core.data.JSONEntryImpl;
+ import org.apache.olingo.commons.core.data.JSONErrorBundle;
+ import org.apache.olingo.commons.core.data.JSONFeedImpl;
+ import org.apache.olingo.commons.core.data.JSONPropertyImpl;
+ import org.apache.olingo.commons.core.data.XMLErrorImpl;
+
+ public abstract class AbstractODataDeserializer extends AbstractJacksonTool implements CommonODataDeserializer {
+
+ private static final long serialVersionUID = -4244158979195609909L;
+
+ private final AtomDeserializer atomDeserializer;
+
+ public AbstractODataDeserializer(final ODataServiceVersion version) {
+ super(version);
+
+ this.atomDeserializer = new AtomDeserializer(version);
+ }
+
+ @Override
+ public Feed toFeed(final InputStream input, final ODataPubFormat format) {
+ return format == ODataPubFormat.ATOM
+ ? atom(input, AtomFeedImpl.class)
+ : json(input, JSONFeedImpl.class);
+ }
+
+ @Override
+ public Entry toEntry(final InputStream input, final ODataPubFormat format) {
+ return format == ODataPubFormat.ATOM
+ ? atom(input, AtomEntryImpl.class)
+ : json(input, JSONEntryImpl.class);
+ }
+
+ @Override
+ public Property toProperty(final InputStream input, final ODataFormat format) {
+ return format == ODataFormat.XML
+ ? atom(input, AtomPropertyImpl.class)
+ : json(input, JSONPropertyImpl.class);
+ }
+
+ @Override
+ public ODataError toError(final InputStream input, final boolean isXML) {
+ return isXML
+ ? xml(input, XMLErrorImpl.class)
+ : json(input, JSONErrorBundle.class).getError();
+ }
+
+ /*
+ * ------------------ Protected methods ------------------
+ */
+ protected <T> T xml(final InputStream input, final Class<T> reference) {
+ try {
+ return getXmlMapper().readValue(input, reference);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("While deserializing " + reference.getName(), e);
+ }
+ }
+
+ protected <T> T atom(final InputStream input, final Class<T> reference) {
+ try {
+ return atomDeserializer.read(input, reference);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("While deserializing " + reference.getName(), e);
+ }
+ }
+
+ protected <T> T json(final InputStream input, final Class<T> reference) {
+ try {
+ return getObjectMapper().readValue(input, reference);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("While deserializing " + reference.getName(), e);
+ }
+ }
-
+ }