You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by fm...@apache.org on 2013/07/26 13:22:22 UTC
[17/51] [partial] initial commit
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityPropertyInfo.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityPropertyInfo.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityPropertyInfo.java
new file mode 100644
index 0000000..283d81a
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityPropertyInfo.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.ep.aggregator;
+
+import org.apache.olingo.odata2.api.edm.EdmCustomizableFeedMappings;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmType;
+
+/**
+ * Collects informations about a property of an entity.
+ * @author SAP AG
+ */
+public class EntityPropertyInfo {
+ private String name;
+ private EdmType type;
+ private EdmFacets facets;
+ private EdmCustomizableFeedMappings customMapping;
+ private String mimeType;
+ private EdmMapping mapping;
+
+ EntityPropertyInfo(final String name, final EdmType type, final EdmFacets facets, final EdmCustomizableFeedMappings customizableFeedMapping, final String mimeType, final EdmMapping mapping) {
+ this.name = name;
+ this.type = type;
+ this.facets = facets;
+ customMapping = customizableFeedMapping;
+ this.mimeType = mimeType;
+ this.mapping = mapping;
+ }
+
+ static EntityPropertyInfo create(final EdmProperty property) throws EdmException {
+ return new EntityPropertyInfo(
+ property.getName(),
+ property.getType(),
+ property.getFacets(),
+ property.getCustomizableFeedMappings(),
+ property.getMimeType(),
+ property.getMapping());
+ }
+
+ public boolean isMandatory() {
+ if (facets == null) {
+ return false;
+ } else if (facets.isNullable() == null) {
+ return false;
+ } else {
+ return !facets.isNullable();
+ }
+ }
+
+ public boolean isComplex() {
+ return false;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public EdmType getType() {
+ return type;
+ }
+
+ public EdmFacets getFacets() {
+ return facets;
+ }
+
+ public EdmCustomizableFeedMappings getCustomMapping() {
+ return customMapping;
+ }
+
+ public String getMimeType() {
+ return mimeType;
+ }
+
+ public EdmMapping getMapping() {
+ return mapping;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityTypeMapping.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityTypeMapping.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityTypeMapping.java
new file mode 100644
index 0000000..ba82f30
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityTypeMapping.java
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.ep.aggregator;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+
+/**
+ * @author SAP AG
+ */
+public class EntityTypeMapping {
+ private static final EntityTypeMapping ENTITY_TYPE_MAPPING = new EntityTypeMapping();
+ final String propertyName;
+ final Class<?> mapping;
+ final List<EntityTypeMapping> mappings;
+
+ private EntityTypeMapping() {
+ this(null, Object.class);
+ }
+
+ private EntityTypeMapping(final String name, final Class<?> mappingClass) {
+ propertyName = name;
+ mapping = mappingClass;
+ mappings = Collections.emptyList();
+ }
+
+ private EntityTypeMapping(final String name, final List<EntityTypeMapping> typeMappings) {
+ propertyName = name;
+ mapping = EntityTypeMapping.class;
+ List<EntityTypeMapping> tmp = new ArrayList<EntityTypeMapping>();
+ for (EntityTypeMapping typeMapping : typeMappings) {
+ tmp.add(typeMapping);
+ }
+ mappings = Collections.unmodifiableList(tmp);
+ }
+
+ public static EntityTypeMapping create(final Map<String, Object> mappings) throws EntityProviderException {
+ return create(null, mappings);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static EntityTypeMapping create(final String name, final Map<String, Object> mappings) throws EntityProviderException {
+ if (mappings == null) {
+ return ENTITY_TYPE_MAPPING;
+ }
+ List<EntityTypeMapping> typeMappings = new ArrayList<EntityTypeMapping>();
+ Set<Entry<String, Object>> entries = mappings.entrySet();
+ for (Entry<String, Object> entry : entries) {
+ EntityTypeMapping typeMapping;
+ Object value = entry.getValue();
+ if (value instanceof Map) {
+ typeMapping = create(entry.getKey(), (Map<String, Object>) value);
+ } else if (value instanceof Class) {
+ typeMapping = new EntityTypeMapping(entry.getKey(), (Class<?>) value);
+ } else {
+ throw new EntityProviderException(EntityProviderException.INVALID_MAPPING.addContent(entry.getKey()));
+ }
+ typeMappings.add(typeMapping);
+ }
+
+ return new EntityTypeMapping(name, typeMappings);
+ }
+
+ boolean isComplex() {
+ return mappings != null && mapping == EntityTypeMapping.class;
+ }
+
+ /**
+ * If this {@link EntityTypeMapping} is complex the mapping for the property
+ * with the given <code>name</code> is returned; otherwise an empty
+ * {@link EntityTypeMapping} is returned.
+ * @param name
+ * @return the mapping for this entity type
+ */
+ public EntityTypeMapping getEntityTypeMapping(final String name) {
+ if (isComplex()) {
+ for (EntityTypeMapping mapping : mappings) {
+ if (mapping.propertyName.equals(name)) {
+ return mapping;
+ }
+ }
+ }
+ return ENTITY_TYPE_MAPPING;
+ }
+
+ /**
+ * If this {@link EntityTypeMapping} is complex the mapping {@link Class} for the property
+ * with the given <code>name</code> is returned; otherwise <code>NULL</code> is returned.
+ * @param name
+ * @return mapping {@link Class} for the property with given <code>name</code> or <code>NULL</code>.
+ */
+ public Class<?> getMappingClass(final String name) {
+ if (isComplex()) {
+ for (EntityTypeMapping mapping : mappings) {
+ if (mapping.propertyName.equals(name)) {
+ return mapping.mapping;
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ if (isComplex()) {
+ return "{'" + propertyName + "'->" + mappings.toString() + "}";
+ }
+ return "{'" + propertyName + "' as " + (mapping == null ? "NULL" : mapping.getSimpleName()) + "}";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/NavigationPropertyInfo.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/NavigationPropertyInfo.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/NavigationPropertyInfo.java
new file mode 100644
index 0000000..7918a69
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/NavigationPropertyInfo.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.ep.aggregator;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+
+public final class NavigationPropertyInfo {
+ private String name;
+ private EdmMultiplicity multiplicity;
+
+ static NavigationPropertyInfo create(final EdmNavigationProperty property) throws EdmException {
+ NavigationPropertyInfo info = new NavigationPropertyInfo();
+ info.name = property.getName();
+ info.multiplicity = property.getMultiplicity();
+ return info;
+ }
+
+ @Override
+ public String toString() {
+ return name + "; multiplicity=" + multiplicity;
+ }
+
+ public EdmMultiplicity getMultiplicity() {
+ return multiplicity;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/AtomServiceDocumentConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/AtomServiceDocumentConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/AtomServiceDocumentConsumer.java
new file mode 100644
index 0000000..716c4bb
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/AtomServiceDocumentConsumer.java
@@ -0,0 +1,312 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.ep.consumer;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.servicedocument.Accept;
+import org.apache.olingo.odata2.api.servicedocument.Categories;
+import org.apache.olingo.odata2.api.servicedocument.Category;
+import org.apache.olingo.odata2.api.servicedocument.Collection;
+import org.apache.olingo.odata2.api.servicedocument.ExtensionAttribute;
+import org.apache.olingo.odata2.api.servicedocument.ExtensionElement;
+import org.apache.olingo.odata2.api.servicedocument.Fixed;
+import org.apache.olingo.odata2.api.servicedocument.Workspace;
+import org.apache.olingo.odata2.core.ep.util.FormatXml;
+import org.apache.olingo.odata2.core.servicedocument.AcceptImpl;
+import org.apache.olingo.odata2.core.servicedocument.AtomInfoImpl;
+import org.apache.olingo.odata2.core.servicedocument.CategoriesImpl;
+import org.apache.olingo.odata2.core.servicedocument.CategoryImpl;
+import org.apache.olingo.odata2.core.servicedocument.CollectionImpl;
+import org.apache.olingo.odata2.core.servicedocument.CommonAttributesImpl;
+import org.apache.olingo.odata2.core.servicedocument.ExtensionAttributeImpl;
+import org.apache.olingo.odata2.core.servicedocument.ExtensionElementImpl;
+import org.apache.olingo.odata2.core.servicedocument.ServiceDocumentImpl;
+import org.apache.olingo.odata2.core.servicedocument.TitleImpl;
+import org.apache.olingo.odata2.core.servicedocument.WorkspaceImpl;
+
+public class AtomServiceDocumentConsumer {
+ private String currentHandledStartTagName;
+ private static final String DEFAULT_PREFIX = "";
+
+ public ServiceDocumentImpl readServiceDokument(final XMLStreamReader reader) throws EntityProviderException {
+ AtomInfoImpl atomInfo = new AtomInfoImpl();
+ ServiceDocumentImpl serviceDocument = new ServiceDocumentImpl();
+ List<Workspace> workspaces = new ArrayList<Workspace>();
+ List<ExtensionElement> extElements = new ArrayList<ExtensionElement>();
+ CommonAttributesImpl attributes = new CommonAttributesImpl();
+ try {
+ while (reader.hasNext()
+ && !(reader.isEndElement() && Edm.NAMESPACE_APP_2007.equals(reader.getNamespaceURI()) && FormatXml.APP_SERVICE.equals(reader.getLocalName()))) {
+ reader.next();
+ if (reader.isStartElement()) {
+ currentHandledStartTagName = reader.getLocalName();
+ if (FormatXml.APP_SERVICE.equals(currentHandledStartTagName)) {
+ attributes = parseCommonAttribute(reader);
+ } else if (FormatXml.APP_WORKSPACE.equals(currentHandledStartTagName)) {
+ workspaces.add(parseWorkspace(reader));
+ } else {
+ ExtensionElementImpl extElement = parseExtensionElement(reader);
+ if (extElement != null) {
+ extElements.add(extElement);
+ }
+ }
+ }
+ }
+ if (workspaces.isEmpty()) {
+ throw new EntityProviderException(EntityProviderException.INVALID_STATE.addContent("Service element must contain at least one workspace element"));
+ }
+ reader.close();
+ atomInfo.setWorkspaces(workspaces).setCommonAttributes(attributes).setExtesionElements(extElements);
+
+ serviceDocument.setAtomInfo(atomInfo);
+ serviceDocument.setEntitySetsInfo(atomInfo.getEntitySetsInfo());
+ return serviceDocument;
+ } catch (XMLStreamException e) {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ }
+ }
+
+ private CommonAttributesImpl parseCommonAttribute(final XMLStreamReader reader) {
+ CommonAttributesImpl attribute = new CommonAttributesImpl();
+ List<ExtensionAttribute> extAttributes = new ArrayList<ExtensionAttribute>();
+ attribute.setBase(reader.getAttributeValue(null, FormatXml.XML_BASE));
+ attribute.setLang(reader.getAttributeValue(null, FormatXml.XML_LANG));
+ for (int i = 0; i < reader.getAttributeCount(); i++) {
+ if (!(FormatXml.XML_BASE.equals(reader.getAttributeLocalName(i)) && Edm.PREFIX_XML.equals(reader.getAttributePrefix(i))
+ || (FormatXml.XML_LANG.equals(reader.getAttributeLocalName(i)) && Edm.PREFIX_XML.equals(reader.getAttributePrefix(i)))
+ || ("local".equals(reader.getAttributeNamespace(i)) || DEFAULT_PREFIX.equals(reader.getAttributePrefix(i))))) {
+ extAttributes.add(new ExtensionAttributeImpl()
+ .setName(reader.getAttributeLocalName(i))
+ .setNamespace(reader.getAttributeNamespace(i))
+ .setPrefix(reader.getAttributePrefix(i))
+ .setText(reader.getAttributeValue(i)));
+ }
+ }
+
+ return attribute.setAttributes(extAttributes);
+ }
+
+ private WorkspaceImpl parseWorkspace(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+ reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_APP_2007, FormatXml.APP_WORKSPACE);
+
+ TitleImpl title = null;
+ List<Collection> collections = new ArrayList<Collection>();
+ List<ExtensionElement> extElements = new ArrayList<ExtensionElement>();
+ CommonAttributesImpl attributes = parseCommonAttribute(reader);
+ while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_APP_2007.equals(reader.getNamespaceURI()) && FormatXml.APP_WORKSPACE.equals(reader.getLocalName()))) {
+ reader.next();
+ if (reader.isStartElement()) {
+ currentHandledStartTagName = reader.getLocalName();
+ if (FormatXml.APP_COLLECTION.equals(currentHandledStartTagName)) {
+ collections.add(parseCollection(reader));
+ } else if (FormatXml.ATOM_TITLE.equals(currentHandledStartTagName)) {
+ title = parseTitle(reader);
+ } else {
+ extElements.add(parseExtensionSansTitleElement(reader));
+ }
+ }
+ }
+ if (title == null) {
+ throw new EntityProviderException(EntityProviderException.INVALID_STATE.addContent("Missing element title for workspace"));
+ }
+ return new WorkspaceImpl().setTitle(title).setCollections(collections).setAttributes(attributes).setExtesionElements(extElements);
+ }
+
+ private CollectionImpl parseCollection(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+ reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_APP_2007, FormatXml.APP_COLLECTION);
+ TitleImpl title = null;
+ String resourceIdentifier = reader.getAttributeValue(null, FormatXml.ATOM_HREF);
+ CommonAttributesImpl attributes = parseCommonAttribute(reader);
+ List<ExtensionElement> extElements = new ArrayList<ExtensionElement>();
+ List<Accept> acceptList = new ArrayList<Accept>();
+ List<Categories> categories = new ArrayList<Categories>();
+ if (resourceIdentifier == null) {
+ throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent("href"));
+ }
+ while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_APP_2007.equals(reader.getNamespaceURI()) && FormatXml.APP_COLLECTION.equals(reader.getLocalName()))) {
+ reader.next();
+ if (reader.isStartElement()) {
+ currentHandledStartTagName = reader.getLocalName();
+ if (FormatXml.ATOM_TITLE.equals(currentHandledStartTagName)) {
+ title = parseTitle(reader);
+ } else if (FormatXml.APP_ACCEPT.equals(currentHandledStartTagName)) {
+ acceptList.add(parseAccept(reader));
+ } else if (FormatXml.APP_CATEGORIES.equals(currentHandledStartTagName)) {
+ categories.add(parseCategories(reader));
+ } else {
+ extElements.add(parseExtensionSansTitleElement(reader));
+ }
+ }
+ }
+ return new CollectionImpl().setHref(resourceIdentifier).setTitle(title).setCommonAttributes(attributes).setExtesionElements(extElements).setAcceptElements(acceptList).setCategories(categories);
+ }
+
+ private TitleImpl parseTitle(final XMLStreamReader reader) throws XMLStreamException {
+ reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_TITLE);
+ String text = "";
+ while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_ATOM_2005.equals(reader.getNamespaceURI()) && FormatXml.ATOM_TITLE.equals(reader.getLocalName()))) {
+ if (reader.isCharacters()) {
+ text += reader.getText();
+ }
+ reader.next();
+ }
+ return new TitleImpl().setText(text);
+ }
+
+ private AcceptImpl parseAccept(final XMLStreamReader reader) throws XMLStreamException {
+ reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_APP_2007, FormatXml.APP_ACCEPT);
+ CommonAttributesImpl commonAttributes = parseCommonAttribute(reader);
+ String text = "";
+ while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_APP_2007.equals(reader.getNamespaceURI()) && FormatXml.APP_ACCEPT.equals(reader.getLocalName()))) {
+ if (reader.isCharacters()) {
+ text += reader.getText();
+ }
+ reader.next();
+ }
+ return new AcceptImpl().setCommonAttributes(commonAttributes).setText(text);
+ }
+
+ private CategoriesImpl parseCategories(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+ reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_APP_2007, FormatXml.APP_CATEGORIES);
+ CategoriesImpl categories = new CategoriesImpl();
+ String href = reader.getAttributeValue(null, FormatXml.ATOM_HREF);
+ String fixed = reader.getAttributeValue(null, FormatXml.APP_CATEGORIES_FIXED);
+ categories.setScheme(reader.getAttributeValue(null, FormatXml.APP_CATEGORIES_SCHEME));
+ categories.setHref(href);
+ if (href == null) {
+ for (int i = 0; i < Fixed.values().length; i++) {
+ if (Fixed.values()[i].name().equalsIgnoreCase(fixed)) {
+ categories.setFixed(Fixed.values()[i]);
+ }
+ }
+ if (categories.getFixed() == null) {
+ categories.setFixed(Fixed.NO);
+ }
+ List<Category> categoriesList = new ArrayList<Category>();
+ while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_APP_2007.equals(reader.getNamespaceURI()) && FormatXml.APP_CATEGORIES.equals(reader.getLocalName()))) {
+ reader.next();
+ if (reader.isStartElement()) {
+ currentHandledStartTagName = reader.getLocalName();
+ if (FormatXml.ATOM_CATEGORY.equals(currentHandledStartTagName)) {
+ categoriesList.add(parseCategory(reader));
+ }
+ }
+ }
+ categories.setCategoryList(categoriesList);
+ }
+ if ((href != null && fixed != null && categories.getScheme() != null) ||
+ (href == null && fixed == null && categories.getScheme() == null)) {
+ throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent("for the element categories"));
+ }
+ return categories;
+ }
+
+ private CategoryImpl parseCategory(final XMLStreamReader reader) throws XMLStreamException {
+ reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_CATEGORY);
+ CategoryImpl category = new CategoryImpl();
+ category.setScheme(reader.getAttributeValue(null, FormatXml.ATOM_CATEGORY_SCHEME));
+ category.setTerm(reader.getAttributeValue(null, FormatXml.ATOM_CATEGORY_TERM));
+ category.setLabel(reader.getAttributeValue(null, FormatXml.ATOM_CATEGORY_LABEL));
+ CommonAttributesImpl attributes = parseCommonAttribute(reader);
+ return category.setCommonAttributes(attributes);
+ }
+
+ private ExtensionElementImpl parseExtensionSansTitleElement(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+ ExtensionElementImpl extElement = new ExtensionElementImpl();
+ if (!(Edm.NAMESPACE_APP_2007.equals(reader.getNamespaceURI())
+ || (FormatXml.ATOM_TITLE.equals(reader.getLocalName()) && Edm.NAMESPACE_ATOM_2005.equals(reader.getNamespaceURI())))) {
+ extElement = parseElement(reader);
+ }
+ return extElement;
+ }
+
+ private ExtensionElementImpl parseExtensionElement(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+ ExtensionElementImpl extElement = null;
+ if (!Edm.NAMESPACE_APP_2007.equals(reader.getNamespaceURI())) {
+ extElement = parseElement(reader);
+ }
+ return extElement;
+ }
+
+ private ExtensionElementImpl parseElement(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+ List<ExtensionElement> extensionElements = new ArrayList<ExtensionElement>();
+ ExtensionElementImpl extElement = new ExtensionElementImpl().setName(reader.getLocalName()).setNamespace(reader.getNamespaceURI()).setPrefix(reader.getPrefix());
+ extElement.setAttributes(parseAttribute(reader));
+ while (reader.hasNext() && !(reader.isEndElement() && extElement.getName() != null && extElement.getName().equals(reader.getLocalName()))) {
+ reader.next();
+ if (reader.isCharacters()) {
+ extElement.setText(reader.getText());
+ } else if (reader.isStartElement()) {
+ extensionElements.add(parseExtensionElement(reader));
+ }
+ }
+ extElement.setElements(extensionElements);
+ if (extElement.getText() == null && extElement.getAttributes().isEmpty() && extElement.getElements().isEmpty()) {
+ throw new EntityProviderException(EntityProviderException.INVALID_STATE.addContent("Invalid extension element"));
+ }
+ return extElement;
+ }
+
+ private List<ExtensionAttribute> parseAttribute(final XMLStreamReader reader) {
+ List<ExtensionAttribute> extAttributes = new ArrayList<ExtensionAttribute>();
+ for (int i = 0; i < reader.getAttributeCount(); i++) {
+ {
+ extAttributes.add(new ExtensionAttributeImpl()
+ .setName(reader.getAttributeLocalName(i))
+ .setNamespace(reader.getAttributeNamespace(i))
+ .setPrefix(reader.getAttributePrefix(i))
+ .setText(reader.getAttributeValue(i)));
+ }
+ }
+
+ return extAttributes;
+ }
+
+ public ServiceDocumentImpl parseXml(final InputStream in) throws EntityProviderException {
+ return readServiceDokument(createStreamReader(in));
+ }
+
+ private XMLStreamReader createStreamReader(final InputStream in) throws EntityProviderException {
+ if (in != null) {
+ XMLInputFactory factory = XMLInputFactory.newInstance();
+ factory.setProperty(XMLInputFactory.IS_VALIDATING, false);
+ factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
+ XMLStreamReader streamReader;
+ try {
+ streamReader = factory.createXMLStreamReader(in);
+ } catch (XMLStreamException e) {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ }
+ return streamReader;
+ } else {
+ throw new EntityProviderException(EntityProviderException.INVALID_STATE.addContent("Null InputStream"));
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntityConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntityConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntityConsumer.java
new file mode 100644
index 0000000..9185ad0
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntityConsumer.java
@@ -0,0 +1,192 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.ep.consumer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+import java.util.Map;
+
+import com.google.gson.stream.JsonReader;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+
+/**
+ * @author SAP AG
+ */
+public class JsonEntityConsumer {
+
+ /** Default used charset for reader */
+ private static final String DEFAULT_CHARSET = "UTF-8";
+
+ public ODataEntry readEntry(final EdmEntitySet entitySet, final InputStream content, final EntityProviderReadProperties properties) throws EntityProviderException {
+ JsonReader reader = null;
+ EntityProviderException cachedException = null;
+
+ try {
+ EntityInfoAggregator eia = EntityInfoAggregator.create(entitySet);
+ reader = createJsonReader(content);
+
+ JsonEntryConsumer jec = new JsonEntryConsumer(reader, eia, properties);
+ ODataEntry result = jec.readSingleEntry();
+ return result;
+ } catch (UnsupportedEncodingException e) {
+ cachedException = new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ throw cachedException;
+ } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException e) {
+ if (cachedException != null) {
+ throw cachedException;
+ } else {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ }
+ }
+ }
+ }
+ }
+
+ public ODataFeed readFeed(final EdmEntitySet entitySet, final InputStream content, final EntityProviderReadProperties readProperties) throws EntityProviderException {
+ JsonReader reader = null;
+ EntityProviderException cachedException = null;
+
+ try {
+ EntityInfoAggregator eia = EntityInfoAggregator.create(entitySet);
+ reader = createJsonReader(content);
+
+ JsonFeedConsumer jfc = new JsonFeedConsumer(reader, eia, readProperties);
+ ODataFeed result = jfc.readFeedStandalone();
+
+ return result;
+ } catch (UnsupportedEncodingException e) {
+ cachedException = new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ throw cachedException;
+ } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException e) {
+ if (cachedException != null) {
+ throw cachedException;
+ } else {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ }
+ }
+ }
+ }
+ }
+
+ public Map<String, Object> readProperty(final EdmProperty property, final InputStream content, final EntityProviderReadProperties readProperties) throws EntityProviderException {
+ JsonReader reader = null;
+ EntityProviderException cachedException = null;
+
+ try {
+ reader = createJsonReader(content);
+ return new JsonPropertyConsumer().readPropertyStandalone(reader, property, readProperties);
+ } catch (final UnsupportedEncodingException e) {
+ cachedException = new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ throw cachedException;
+ } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (final IOException e) {
+ if (cachedException != null) {
+ throw cachedException;
+ } else {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ }
+ }
+ }
+ }
+ }
+
+ public String readLink(final EdmEntitySet entitySet, final Object content) throws EntityProviderException {
+ JsonReader reader = null;
+ EntityProviderException cachedException = null;
+
+ try {
+ reader = createJsonReader(content);
+ return new JsonLinkConsumer().readLink(reader, entitySet);
+ } catch (final UnsupportedEncodingException e) {
+ cachedException = new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ throw cachedException;
+ } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (final IOException e) {
+ if (cachedException != null) {
+ throw cachedException;
+ } else {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ }
+ }
+ }
+ }
+ }
+
+ public List<String> readLinks(final EdmEntitySet entitySet, final Object content) throws EntityProviderException {
+ JsonReader reader = null;
+ EntityProviderException cachedException = null;
+
+ try {
+ reader = createJsonReader(content);
+ return new JsonLinkConsumer().readLinks(reader, entitySet);
+ } catch (final UnsupportedEncodingException e) {
+ cachedException = new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ throw cachedException;
+ } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (final IOException e) {
+ if (cachedException != null) {
+ throw cachedException;
+ } else {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ }
+ }
+ }
+ }
+ }
+
+ private JsonReader createJsonReader(final Object content) throws EntityProviderException, UnsupportedEncodingException {
+
+ if (content == null) {
+ throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT
+ .addContent("Got not supported NULL object as content to de-serialize."));
+ }
+
+ if (content instanceof InputStream) {
+ return new JsonReader(new InputStreamReader((InputStream) content, DEFAULT_CHARSET));
+ }
+ throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT
+ .addContent("Found not supported content of class '" + content.getClass() + "' to de-serialize."));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntryConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntryConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntryConsumer.java
new file mode 100644
index 0000000..6d54f5c
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntryConsumer.java
@@ -0,0 +1,311 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.ep.consumer;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
+import org.apache.olingo.odata2.api.ep.callback.OnReadInlineContent;
+import org.apache.olingo.odata2.api.ep.callback.ReadEntryResult;
+import org.apache.olingo.odata2.api.ep.callback.ReadFeedResult;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.aggregator.NavigationPropertyInfo;
+import org.apache.olingo.odata2.core.ep.entry.EntryMetadataImpl;
+import org.apache.olingo.odata2.core.ep.entry.MediaMetadataImpl;
+import org.apache.olingo.odata2.core.ep.entry.ODataEntryImpl;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+import org.apache.olingo.odata2.core.uri.ExpandSelectTreeNodeImpl;
+
+/**
+ * @author SAP AG
+ */
+public class JsonEntryConsumer {
+
+ private final Map<String, Object> properties = new HashMap<String, Object>();
+ private final MediaMetadataImpl mediaMetadata = new MediaMetadataImpl();
+ private final EntryMetadataImpl entryMetadata = new EntryMetadataImpl();
+ private final ExpandSelectTreeNodeImpl expandSelectTree = new ExpandSelectTreeNodeImpl();
+ private final Map<String, Object> typeMappings;
+ private final EntityInfoAggregator eia;
+ private final JsonReader reader;
+ private final EntityProviderReadProperties readProperties;
+ private final ODataEntryImpl entryResult;
+
+ public JsonEntryConsumer(final JsonReader reader, final EntityInfoAggregator eia, final EntityProviderReadProperties readProperties) {
+ typeMappings = readProperties.getTypeMappings();
+ this.eia = eia;
+ this.readProperties = readProperties;
+ this.reader = reader;
+ entryResult = new ODataEntryImpl(properties, mediaMetadata, entryMetadata, expandSelectTree);
+ }
+
+ public ODataEntry readSingleEntry() throws EntityProviderException {
+ try {
+ reader.beginObject();
+ String nextName = reader.nextName();
+ if (FormatJson.D.equals(nextName)) {
+ reader.beginObject();
+ readEntryContent();
+ reader.endObject();
+ } else {
+ handleName(nextName);
+ readEntryContent();
+ }
+ reader.endObject();
+
+ if (reader.peek() != JsonToken.END_DOCUMENT) {
+ throw new EntityProviderException(EntityProviderException.END_DOCUMENT_EXPECTED.addContent(reader.peek().toString()));
+ }
+ } catch (IOException e) {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ } catch (EdmException e) {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ } catch (IllegalStateException e) {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ }
+
+ return entryResult;
+ }
+
+ public ODataEntry readFeedEntry() throws EdmException, EntityProviderException, IOException {
+ reader.beginObject();
+ readEntryContent();
+ reader.endObject();
+ return entryResult;
+ }
+
+ private void readEntryContent() throws IOException, EdmException, EntityProviderException {
+ while (reader.hasNext()) {
+ String name = reader.nextName();
+ handleName(name);
+ }
+
+ //TODO: validate created entry
+ }
+
+ private void handleName(final String name) throws IOException, EdmException, EntityProviderException {
+ if (FormatJson.METADATA.equals(name)) {
+ readMetadata();
+ validateMetadata();
+ } else {
+ EntityPropertyInfo propertyInfo = eia.getPropertyInfo(name);
+ if (propertyInfo != null) {
+ JsonPropertyConsumer jpc = new JsonPropertyConsumer();
+ Object propertyValue = jpc.readPropertyValue(reader, propertyInfo, typeMappings.get(name));
+ if (properties.containsKey(name)) {
+ throw new EntityProviderException(EntityProviderException.DOUBLE_PROPERTY.addContent(name));
+ }
+ properties.put(name, propertyValue);
+ } else {
+ readNavigationProperty(name);
+ }
+ }
+ }
+
+ private void readMetadata() throws IOException, EdmException, EntityProviderException {
+ String name = null;
+ String value = null;
+ reader.beginObject();
+ while (reader.hasNext()) {
+ name = reader.nextName();
+
+ if (FormatJson.PROPERTIES.equals(name)) {
+ reader.skipValue();
+ continue;
+ }
+
+ value = reader.nextString();
+ if (FormatJson.ID.equals(name)) {
+ entryMetadata.setId(value);
+ } else if (FormatJson.URI.equals(name)) {
+ entryMetadata.setUri(value);
+ } else if (FormatJson.TYPE.equals(name)) {
+ String fullQualifiedName = eia.getEntityType().getNamespace() + Edm.DELIMITER + eia.getEntityType().getName();
+ if (!fullQualifiedName.equals(value)) {
+ throw new EntityProviderException(EntityProviderException.INVALID_ENTITYTYPE.addContent(fullQualifiedName).addContent(value));
+ }
+ } else if (FormatJson.ETAG.equals(name)) {
+ entryMetadata.setEtag(value);
+ } else if (FormatJson.EDIT_MEDIA.equals(name)) {
+ mediaMetadata.setEditLink(value);
+ } else if (FormatJson.MEDIA_SRC.equals(name)) {
+ mediaMetadata.setSourceLink(value);
+ } else if (FormatJson.MEDIA_ETAG.equals(name)) {
+ mediaMetadata.setEtag(value);
+ } else if (FormatJson.CONTENT_TYPE.equals(name)) {
+ mediaMetadata.setContentType(value);
+ } else {
+ throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(name).addContent(FormatJson.METADATA));
+ }
+ }
+
+ reader.endObject();
+ }
+
+ private void validateMetadata() throws EdmException, EntityProviderException {
+ if (eia.getEntityType().hasStream()) {
+ if (mediaMetadata.getSourceLink() == null) {
+ throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent(FormatJson.MEDIA_SRC).addContent(FormatJson.METADATA));
+ }
+ if (mediaMetadata.getContentType() == null) {
+ throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent(FormatJson.CONTENT_TYPE).addContent(FormatJson.METADATA));
+ }
+ //TODO Mime Type Mapping
+ } else {
+ if (mediaMetadata.getContentType() != null || mediaMetadata.getEditLink() != null
+ || mediaMetadata.getEtag() != null || mediaMetadata.getSourceLink() != null) {
+ throw new EntityProviderException(EntityProviderException.MEDIA_DATA_NOT_INITIAL);
+ }
+ }
+ }
+
+ private void readNavigationProperty(final String navigationPropertyName) throws IOException, EntityProviderException, EdmException {
+ NavigationPropertyInfo navigationPropertyInfo = eia.getNavigationPropertyInfo(navigationPropertyName);
+ if (navigationPropertyInfo == null) {
+ throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent(navigationPropertyName));
+ }
+
+ if (reader.peek() == JsonToken.BEGIN_OBJECT) {
+ reader.beginObject();
+ String name = reader.nextName();
+ if (FormatJson.DEFERRED.equals(name)) {
+ reader.beginObject();
+ String uri = reader.nextName();
+ if (FormatJson.URI.equals(uri)) {
+ String value = reader.nextString();
+ entryMetadata.putAssociationUri(navigationPropertyInfo.getName(), value);
+ } else {
+ throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent(uri));
+ }
+ reader.endObject();
+ } else {
+ EdmNavigationProperty navigationProperty = (EdmNavigationProperty) eia.getEntityType().getProperty(navigationPropertyName);
+ EdmEntitySet inlineEntitySet = eia.getEntitySet().getRelatedEntitySet(navigationProperty);
+ EntityInfoAggregator inlineEia = EntityInfoAggregator.create(inlineEntitySet);
+ EntityProviderReadProperties inlineReadProperties;
+ OnReadInlineContent callback = readProperties.getCallback();
+ try {
+ if (callback == null) {
+ inlineReadProperties = EntityProviderReadProperties.init().mergeSemantic(readProperties.getMergeSemantic()).build();
+
+ } else {
+ inlineReadProperties = callback.receiveReadProperties(readProperties, navigationProperty);
+ }
+
+ if (navigationProperty.getMultiplicity() == EdmMultiplicity.MANY) {
+ JsonFeedConsumer inlineConsumer = new JsonFeedConsumer(reader, inlineEia, inlineReadProperties);
+ ODataFeed feed = inlineConsumer.readStartedInlineFeed(name);
+ updateExpandSelectTree(navigationPropertyName, feed);
+ if (callback == null) {
+ properties.put(navigationPropertyName, feed);
+ entryResult.setContainsInlineEntry(true);
+ } else {
+ ReadFeedResult result = new ReadFeedResult(inlineReadProperties, navigationProperty, feed);
+ callback.handleReadFeed(result);
+ }
+ } else {
+ JsonEntryConsumer inlineConsumer = new JsonEntryConsumer(reader, inlineEia, inlineReadProperties);
+ ODataEntry entry = inlineConsumer.readInlineEntry(name);
+ updateExpandSelectTree(navigationPropertyName, entry);
+ if (callback == null) {
+ properties.put(navigationPropertyName, entry);
+ entryResult.setContainsInlineEntry(true);
+ } else {
+ ReadEntryResult result = new ReadEntryResult(inlineReadProperties, navigationProperty, entry);
+ callback.handleReadEntry(result);
+ }
+ }
+
+ } catch (ODataApplicationException e) {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ }
+ }
+ reader.endObject();
+ } else {
+ final EdmNavigationProperty navigationProperty = (EdmNavigationProperty) eia.getEntityType().getProperty(navigationPropertyName);
+ final EdmEntitySet inlineEntitySet = eia.getEntitySet().getRelatedEntitySet(navigationProperty);
+ final EntityInfoAggregator inlineInfo = EntityInfoAggregator.create(inlineEntitySet);
+ OnReadInlineContent callback = readProperties.getCallback();
+ EntityProviderReadProperties inlineReadProperties;
+ if (callback == null) {
+ inlineReadProperties = EntityProviderReadProperties.init().mergeSemantic(readProperties.getMergeSemantic()).build();
+ } else {
+ try {
+ inlineReadProperties = callback.receiveReadProperties(readProperties, navigationProperty);
+ } catch (final ODataApplicationException e) {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ }
+ }
+ ODataFeed feed = new JsonFeedConsumer(reader, inlineInfo, inlineReadProperties).readInlineFeedStandalone();
+ updateExpandSelectTree(navigationPropertyName, feed);
+ if (callback == null) {
+ properties.put(navigationPropertyName, feed);
+ entryResult.setContainsInlineEntry(true);
+ } else {
+ ReadFeedResult result = new ReadFeedResult(inlineReadProperties, navigationProperty, feed);
+ try {
+ callback.handleReadFeed(result);
+ } catch (final ODataApplicationException e) {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ }
+ }
+ }
+ }
+
+ private void updateExpandSelectTree(final String navigationPropertyName, final ODataFeed feed) {
+ List<ODataEntry> entries = feed.getEntries();
+ if (entries.size() > 0) {
+ updateExpandSelectTree(navigationPropertyName, entries.get(0));
+ } else {
+ expandSelectTree.setExpanded();
+ expandSelectTree.setExplicitlySelected();
+ expandSelectTree.putLink(navigationPropertyName, new ExpandSelectTreeNodeImpl());
+ }
+ }
+
+ private void updateExpandSelectTree(final String navigationPropertyName, final ODataEntry entry) {
+ expandSelectTree.setExpanded();
+ expandSelectTree.setExplicitlySelected();
+ expandSelectTree.putLink(navigationPropertyName, (ExpandSelectTreeNodeImpl) entry.getExpandSelectTree());
+ }
+
+ private ODataEntry readInlineEntry(final String name) throws EdmException, EntityProviderException, IOException {
+ //consume the already started content
+ handleName(name);
+ //consume the rest of the entry content
+ readEntryContent();
+ return entryResult;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonFeedConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonFeedConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonFeedConsumer.java
new file mode 100644
index 0000000..4da0420
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonFeedConsumer.java
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.ep.consumer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.feed.FeedMetadataImpl;
+import org.apache.olingo.odata2.core.ep.feed.ODataFeedImpl;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+
+/**
+ * @author SAP AG
+ */
+public class JsonFeedConsumer {
+
+ private JsonReader reader;
+ private EntityInfoAggregator eia;
+ private EntityProviderReadProperties readProperties;
+ private List<ODataEntry> entries = new ArrayList<ODataEntry>();
+ private FeedMetadataImpl feedMetadata = new FeedMetadataImpl();
+ private boolean resultsArrayPresent = false;
+
+ public JsonFeedConsumer(final JsonReader reader, final EntityInfoAggregator eia, final EntityProviderReadProperties readProperties) {
+ this.reader = reader;
+ this.eia = eia;
+ this.readProperties = readProperties;
+ }
+
+ public ODataFeed readFeedStandalone() throws EntityProviderException {
+ try {
+ readFeed();
+
+ if (reader.peek() != JsonToken.END_DOCUMENT) {
+
+ throw new EntityProviderException(EntityProviderException.END_DOCUMENT_EXPECTED.addContent(reader.peek().toString()));
+ }
+
+ } catch (IOException e) {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ } catch (EdmException e) {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ } catch (IllegalStateException e) {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ }
+ return new ODataFeedImpl(entries, feedMetadata);
+ }
+
+ private void readFeed() throws IOException, EdmException, EntityProviderException {
+ if (reader.peek() == JsonToken.BEGIN_ARRAY) {
+ readArrayContent();
+ } else {
+ reader.beginObject();
+ final String nextName = reader.nextName();
+ if (FormatJson.D.equals(nextName)) {
+ if (reader.peek() == JsonToken.BEGIN_ARRAY) {
+ readArrayContent();
+ } else {
+ reader.beginObject();
+ readFeedContent();
+ reader.endObject();
+ }
+ } else {
+ handleName(nextName);
+ readFeedContent();
+ }
+
+ reader.endObject();
+ }
+ }
+
+ private void readFeedContent() throws IOException, EdmException, EntityProviderException {
+ while (reader.hasNext()) {
+ final String nextName = reader.nextName();
+ handleName(nextName);
+ }
+
+ if (!resultsArrayPresent) {
+ throw new EntityProviderException(EntityProviderException.MISSING_RESULTS_ARRAY);
+ }
+ }
+
+ private void handleName(final String nextName) throws IOException, EdmException, EntityProviderException {
+ if (FormatJson.RESULTS.equals(nextName)) {
+ resultsArrayPresent = true;
+ readArrayContent();
+
+ } else if (FormatJson.COUNT.equals(nextName)) {
+ readInlineCount(reader, feedMetadata);
+
+ } else if (FormatJson.NEXT.equals(nextName)) {
+ if (reader.peek() == JsonToken.STRING && feedMetadata.getNextLink() == null) {
+ String nextLink = reader.nextString();
+ feedMetadata.setNextLink(nextLink);
+ } else {
+ throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(nextName).addContent("JsonFeed"));
+ }
+
+ } else if (FormatJson.DELTA.equals(nextName)) {
+ if (reader.peek() == JsonToken.STRING && feedMetadata.getDeltaLink() == null) {
+ String deltaLink = reader.nextString();
+ feedMetadata.setDeltaLink(deltaLink);
+ } else {
+ throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(nextName).addContent("JsonFeed"));
+ }
+ } else {
+ throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(nextName).addContent("JsonFeed"));
+ }
+ }
+
+ private void readArrayContent() throws IOException, EdmException, EntityProviderException {
+ reader.beginArray();
+ while (reader.hasNext()) {
+ final ODataEntry entry = new JsonEntryConsumer(reader, eia, readProperties).readFeedEntry();
+ entries.add(entry);
+ }
+ reader.endArray();
+ }
+
+ protected static void readInlineCount(final JsonReader reader, final FeedMetadataImpl feedMetadata) throws IOException, EntityProviderException {
+ if (reader.peek() == JsonToken.STRING && feedMetadata.getInlineCount() == null) {
+ int inlineCount;
+ try {
+ inlineCount = reader.nextInt();
+ } catch (final NumberFormatException e) {
+ throw new EntityProviderException(EntityProviderException.INLINECOUNT_INVALID.addContent(""), e);
+ }
+ if (inlineCount >= 0) {
+ feedMetadata.setInlineCount(inlineCount);
+ } else {
+ throw new EntityProviderException(EntityProviderException.INLINECOUNT_INVALID.addContent(inlineCount));
+ }
+ } else {
+ throw new EntityProviderException(EntityProviderException.INLINECOUNT_INVALID.addContent(reader.peek()));
+ }
+ }
+
+ protected ODataFeed readStartedInlineFeed(final String name) throws EdmException, EntityProviderException, IOException {
+ //consume the already started content
+ handleName(name);
+ //consume the rest of the entry content
+ readFeedContent();
+ return new ODataFeedImpl(entries, feedMetadata);
+ }
+
+ protected ODataFeed readInlineFeedStandalone() throws EdmException, EntityProviderException, IOException {
+ readFeed();
+ return new ODataFeedImpl(entries, feedMetadata);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonLinkConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonLinkConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonLinkConsumer.java
new file mode 100644
index 0000000..f82328c
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonLinkConsumer.java
@@ -0,0 +1,155 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.ep.consumer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.core.ep.feed.FeedMetadataImpl;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+
+/**
+ * @author SAP AG
+ */
+public class JsonLinkConsumer {
+
+ /**
+ * Reads single link with format <code>{"d":{"uri":"http://somelink"}}</code>
+ * or <code>{"uri":"http://somelink"}</code>.
+ * @param reader
+ * @param entitySet
+ * @return link as string object
+ * @throws EntityProviderException
+ */
+ public String readLink(final JsonReader reader, final EdmEntitySet entitySet) throws EntityProviderException {
+ try {
+ String result;
+ reader.beginObject();
+ String nextName = reader.nextName();
+ final boolean wrapped = FormatJson.D.equals(nextName);
+ if (wrapped) {
+ reader.beginObject();
+ nextName = reader.nextName();
+ }
+ if (FormatJson.URI.equals(nextName) && reader.peek() == JsonToken.STRING) {
+ result = reader.nextString();
+ } else {
+ throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(FormatJson.D + " or " + FormatJson.URI).addContent(nextName));
+ }
+ reader.endObject();
+ if (wrapped) {
+ reader.endObject();
+ }
+
+ reader.peek(); // to assert end of structure or document
+
+ return result;
+ } catch (final IOException e) {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ } catch (final IllegalStateException e) {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ }
+ }
+
+ /**
+ * Reads a collection of links, optionally wrapped in a "d" object,
+ * and optionally wrapped in an "results" object, where an additional "__count"
+ * object could appear on the same level as the "results".
+ * @param reader
+ * @param entitySet
+ * @return links as List of Strings
+ * @throws EntityProviderException
+ */
+ public List<String> readLinks(final JsonReader reader, final EdmEntitySet entitySet) throws EntityProviderException {
+ List<String> links = null;
+ int openedObjects = 0;
+
+ try {
+ String nextName;
+ if (reader.peek() == JsonToken.BEGIN_ARRAY) {
+ nextName = FormatJson.RESULTS;
+ } else {
+ reader.beginObject();
+ openedObjects++;
+ nextName = reader.nextName();
+ }
+ if (FormatJson.D.equals(nextName)) {
+ if (reader.peek() == JsonToken.BEGIN_ARRAY) {
+ nextName = FormatJson.RESULTS;
+ } else {
+ reader.beginObject();
+ openedObjects++;
+ nextName = reader.nextName();
+ }
+ }
+ FeedMetadataImpl feedMetadata = new FeedMetadataImpl();
+ if (FormatJson.COUNT.equals(nextName)) {
+ JsonFeedConsumer.readInlineCount(reader, feedMetadata);
+ nextName = reader.nextName();
+ }
+ if (FormatJson.RESULTS.equals(nextName)) {
+ links = readLinksArray(reader);
+ } else {
+ throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(FormatJson.RESULTS).addContent(nextName));
+ }
+ if (reader.hasNext() && reader.peek() == JsonToken.NAME) {
+ if (FormatJson.COUNT.equals(reader.nextName())) {
+ JsonFeedConsumer.readInlineCount(reader, feedMetadata);
+ } else {
+ throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(FormatJson.COUNT).addContent(nextName));
+ }
+ }
+ for (; openedObjects > 0; openedObjects--) {
+ reader.endObject();
+ }
+
+ reader.peek(); // to assert end of document
+ } catch (final IOException e) {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ } catch (final IllegalStateException e) {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ }
+
+ return links;
+ }
+
+ private List<String> readLinksArray(final JsonReader reader) throws IOException, EntityProviderException {
+ List<String> links = new ArrayList<String>();
+
+ reader.beginArray();
+ while (reader.hasNext()) {
+ reader.beginObject();
+ String nextName = reader.nextName();
+ if (FormatJson.URI.equals(nextName) && reader.peek() == JsonToken.STRING) {
+ links.add(reader.nextString());
+ } else {
+ throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(FormatJson.URI).addContent(nextName));
+ }
+ reader.endObject();
+ }
+ reader.endArray();
+
+ return links;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonPropertyConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonPropertyConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonPropertyConsumer.java
new file mode 100644
index 0000000..2a3327c
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonPropertyConsumer.java
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.ep.consumer;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityComplexPropertyInfo;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+
+/**
+ * @author SAP AG
+ */
+public class JsonPropertyConsumer {
+
+ public Map<String, Object> readPropertyStandalone(final JsonReader reader, final EdmProperty property, final EntityProviderReadProperties readProperties) throws EntityProviderException {
+ try {
+ EntityPropertyInfo entityPropertyInfo = EntityInfoAggregator.create(property);
+ Map<String, Object> typeMappings = readProperties == null ? null : readProperties.getTypeMappings();
+ Map<String, Object> result = new HashMap<String, Object>();
+
+ reader.beginObject();
+ String nextName = reader.nextName();
+ if (FormatJson.D.equals(nextName)) {
+ reader.beginObject();
+ nextName = reader.nextName();
+ handleName(reader, typeMappings, entityPropertyInfo, result, nextName);
+ reader.endObject();
+ } else {
+ handleName(reader, typeMappings, entityPropertyInfo, result, nextName);
+ }
+ reader.endObject();
+
+ if (reader.peek() != JsonToken.END_DOCUMENT) {
+ throw new EntityProviderException(EntityProviderException.END_DOCUMENT_EXPECTED.addContent(reader.peek().toString()));
+ }
+
+ return result;
+ } catch (final IOException e) {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ } catch (final IllegalStateException e) {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ }
+ }
+
+ private void handleName(final JsonReader reader, final Map<String, Object> typeMappings, final EntityPropertyInfo entityPropertyInfo, final Map<String, Object> result, final String nextName) throws EntityProviderException {
+ if (!entityPropertyInfo.getName().equals(nextName)) {
+ throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent(nextName));
+ }
+ Object mapping = null;
+ if (typeMappings != null) {
+ mapping = typeMappings.get(nextName);
+ }
+ Object propertyValue = readPropertyValue(reader, entityPropertyInfo, mapping);
+ result.put(nextName, propertyValue);
+ }
+
+ protected Object readPropertyValue(final JsonReader reader, final EntityPropertyInfo entityPropertyInfo, final Object typeMapping) throws EntityProviderException {
+ try {
+ return entityPropertyInfo.isComplex() ?
+ readComplexProperty(reader, (EntityComplexPropertyInfo) entityPropertyInfo, typeMapping) :
+ readSimpleProperty(reader, entityPropertyInfo, typeMapping);
+ } catch (final EdmException e) {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ } catch (final IOException e) {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ }
+ }
+
+ private Object readSimpleProperty(final JsonReader reader, final EntityPropertyInfo entityPropertyInfo, final Object typeMapping) throws EdmException, EntityProviderException, IOException {
+ final EdmSimpleType type = (EdmSimpleType) entityPropertyInfo.getType();
+ Object value = null;
+ final JsonToken tokenType = reader.peek();
+ if (tokenType == JsonToken.NULL) {
+ reader.nextNull();
+ } else {
+ switch (EdmSimpleTypeKind.valueOf(type.getName())) {
+ case Boolean:
+ if (tokenType == JsonToken.BOOLEAN) {
+ value = reader.nextBoolean();
+ value = value.toString();
+ } else {
+ throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY_VALUE.addContent(entityPropertyInfo.getName()));
+ }
+ break;
+ case Byte:
+ case SByte:
+ case Int16:
+ case Int32:
+ if (tokenType == JsonToken.NUMBER) {
+ value = reader.nextInt();
+ value = value.toString();
+ } else {
+ throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY_VALUE.addContent(entityPropertyInfo.getName()));
+ }
+ break;
+ default:
+ if (tokenType == JsonToken.STRING) {
+ value = reader.nextString();
+ } else {
+ throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY_VALUE.addContent(entityPropertyInfo.getName()));
+ }
+ break;
+ }
+ }
+
+ final Class<?> typeMappingClass = typeMapping == null ? type.getDefaultType() : (Class<?>) typeMapping;
+ return type.valueOfString((String) value, EdmLiteralKind.JSON, entityPropertyInfo.getFacets(), typeMappingClass);
+ }
+
+ @SuppressWarnings("unchecked")
+ private Object readComplexProperty(final JsonReader reader, final EntityComplexPropertyInfo complexPropertyInfo, final Object typeMapping) throws EdmException, EntityProviderException, IOException {
+ if (reader.peek().equals(JsonToken.NULL)) {
+ reader.nextNull();
+ return null;
+ }
+
+ reader.beginObject();
+ Map<String, Object> data = new HashMap<String, Object>();
+
+ Map<String, Object> mapping;
+ if (typeMapping != null) {
+ if (typeMapping instanceof Map) {
+ mapping = (Map<String, Object>) typeMapping;
+ } else {
+ throw new EntityProviderException(EntityProviderException.INVALID_MAPPING.addContent(complexPropertyInfo.getName()));
+ }
+ } else {
+ mapping = new HashMap<String, Object>();
+ }
+
+ while (reader.hasNext()) {
+ String childName = reader.nextName();
+ if (FormatJson.METADATA.equals(childName)) {
+ reader.beginObject();
+ childName = reader.nextName();
+ if (!FormatJson.TYPE.equals(childName)) {
+ throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent(FormatJson.TYPE).addContent(FormatJson.METADATA));
+ }
+ String actualTypeName = reader.nextString();
+ String expectedTypeName = complexPropertyInfo.getType().getNamespace() + Edm.DELIMITER + complexPropertyInfo.getType().getName();
+ if (!expectedTypeName.equals(actualTypeName)) {
+ throw new EntityProviderException(EntityProviderException.INVALID_ENTITYTYPE.addContent(expectedTypeName).addContent(actualTypeName));
+ }
+ reader.endObject();
+ } else {
+ EntityPropertyInfo childPropertyInfo = complexPropertyInfo.getPropertyInfo(childName);
+ if (childPropertyInfo == null) {
+ throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY.addContent(childName));
+ }
+ Object childData = readPropertyValue(reader, childPropertyInfo, mapping.get(childName));
+ if (data.containsKey(childName)) {
+ throw new EntityProviderException(EntityProviderException.DOUBLE_PROPERTY.addContent(childName));
+ }
+ data.put(childName, childData);
+ }
+ }
+ reader.endObject();
+ return data;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonServiceDocumentConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonServiceDocumentConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonServiceDocumentConsumer.java
new file mode 100644
index 0000000..b0fbb25
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonServiceDocumentConsumer.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.ep.consumer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.gson.stream.JsonReader;
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySetInfo;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.provider.EntityContainerInfo;
+import org.apache.olingo.odata2.api.edm.provider.EntitySet;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.core.edm.provider.EdmEntitySetInfoImplProv;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+import org.apache.olingo.odata2.core.servicedocument.ServiceDocumentImpl;
+
+/**
+ * Reads the OData service document (JSON).
+ * @author SAP AG
+ */
+public class JsonServiceDocumentConsumer {
+ private static final String DEFAULT_CHARSET = "UTF-8";
+ List<EdmEntitySetInfo> entitySets = new ArrayList<EdmEntitySetInfo>();
+ private String currentHandledObjectName;
+
+ public ServiceDocumentImpl parseJson(final InputStream in) throws EntityProviderException {
+ return readServiceDocument(createJsonReader(in));
+ }
+
+ private ServiceDocumentImpl readServiceDocument(final JsonReader reader) throws EntityProviderException {
+ try {
+ reader.beginObject();
+ currentHandledObjectName = reader.nextName();
+ if (FormatJson.D.equals(currentHandledObjectName)) {
+ reader.beginObject();
+ readContent(reader);
+ reader.endObject();
+ }
+ reader.endObject();
+ reader.peek();
+ reader.close();
+ } catch (final IOException e) {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ } catch (final IllegalStateException e) {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ } catch (final EdmException e) {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ }
+ return new ServiceDocumentImpl().setEntitySetsInfo(entitySets);
+ }
+
+ private void readContent(final JsonReader reader) throws IOException, EdmException, EntityProviderException {
+ currentHandledObjectName = reader.nextName();
+ if (FormatJson.ENTITY_SETS.equals(currentHandledObjectName)) {
+ reader.beginArray();
+ readEntitySets(reader);
+ reader.endArray();
+ }
+ }
+
+ private void readEntitySets(final JsonReader reader) throws IOException, EntityProviderException, EdmException {
+ while (reader.hasNext()) {
+ currentHandledObjectName = reader.nextString();
+ if (currentHandledObjectName != null) {
+ // Looking for the last dot: "\\.(?=[^.]+$)"
+ String[] names = currentHandledObjectName.split("\\" + Edm.DELIMITER + "(?=[^" + Edm.DELIMITER + "]+$)");
+ if (names.length == 1) {
+ EntitySet entitySet = new EntitySet().setName(names[0]);
+ EntityContainerInfo container = new EntityContainerInfo().setDefaultEntityContainer(true);
+ EdmEntitySetInfo entitySetInfo = new EdmEntitySetInfoImplProv(entitySet, container);
+ entitySets.add(entitySetInfo);
+ } else {
+ EntitySet entitySet = new EntitySet().setName(names[1]);
+ EntityContainerInfo container = new EntityContainerInfo().setName(names[0]).setDefaultEntityContainer(false);
+ EdmEntitySetInfo entitySetInfo = new EdmEntitySetInfoImplProv(entitySet, container);
+ entitySets.add(entitySetInfo);
+ }
+ }
+ }
+ }
+
+ private JsonReader createJsonReader(final InputStream in) throws EntityProviderException {
+ if (in == null) {
+ throw new EntityProviderException(EntityProviderException.INVALID_STATE.addContent(("Got not supported NULL object as content to de-serialize.")));
+ }
+ InputStreamReader isReader;
+ try {
+ isReader = new InputStreamReader(in, DEFAULT_CHARSET);
+ } catch (final UnsupportedEncodingException e) {
+ throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+ }
+ return new JsonReader(isReader);
+ }
+}