/*******************************************************************************
* Copyright 2013 SAP AG
*
* Licensed 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 com.sap.core.odata.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 com.sap.core.odata.api.edm.Edm;
import com.sap.core.odata.api.ep.EntityProviderException;
import com.sap.core.odata.api.servicedocument.Accept;
import com.sap.core.odata.api.servicedocument.Categories;
import com.sap.core.odata.api.servicedocument.Category;
import com.sap.core.odata.api.servicedocument.Collection;
import com.sap.core.odata.api.servicedocument.ExtensionAttribute;
import com.sap.core.odata.api.servicedocument.ExtensionElement;
import com.sap.core.odata.api.servicedocument.Fixed;
import com.sap.core.odata.api.servicedocument.Workspace;
import com.sap.core.odata.core.ep.util.FormatXml;
import com.sap.core.odata.core.servicedocument.AcceptImpl;
import com.sap.core.odata.core.servicedocument.AtomInfoImpl;
import com.sap.core.odata.core.servicedocument.CategoriesImpl;
import com.sap.core.odata.core.servicedocument.CategoryImpl;
import com.sap.core.odata.core.servicedocument.CollectionImpl;
import com.sap.core.odata.core.servicedocument.CommonAttributesImpl;
import com.sap.core.odata.core.servicedocument.ExtensionAttributeImpl;
import com.sap.core.odata.core.servicedocument.ExtensionElementImpl;
import com.sap.core.odata.core.servicedocument.ServiceDocumentImpl;
import com.sap.core.odata.core.servicedocument.TitleImpl;
import com.sap.core.odata.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"));
}
}
}