All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sap.cds.adapter.odata.v2.metadata.ODataV2EdmProvider Maven / Gradle / Ivy

There is a newer version: 3.6.0
Show newest version
/**************************************************************************
 * (C) 2019-2024 SAP SE or an SAP affiliate company. All rights reserved. *
 **************************************************************************/
package com.sap.cds.adapter.odata.v2.metadata;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.apache.commons.io.IOUtils;
import org.apache.olingo.odata2.api.edm.FullQualifiedName;
import org.apache.olingo.odata2.api.edm.provider.AnnotationAttribute;
import org.apache.olingo.odata2.api.edm.provider.AnnotationElement;
import org.apache.olingo.odata2.api.edm.provider.Association;
import org.apache.olingo.odata2.api.edm.provider.AssociationSet;
import org.apache.olingo.odata2.api.edm.provider.ComplexType;
import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
import org.apache.olingo.odata2.api.edm.provider.EntityContainer;
import org.apache.olingo.odata2.api.edm.provider.EntityContainerInfo;
import org.apache.olingo.odata2.api.edm.provider.EntitySet;
import org.apache.olingo.odata2.api.edm.provider.EntityType;
import org.apache.olingo.odata2.api.edm.provider.FunctionImport;
import org.apache.olingo.odata2.api.edm.provider.Schema;
import org.apache.olingo.odata2.api.exception.ODataException;
import org.apache.olingo.odata2.core.commons.XmlHelper;
import org.apache.olingo.odata2.core.edm.provider.EdmxProvider;

public class ODataV2EdmProvider extends EdmProvider {

	private static final String EDM_REFERENCE = "Reference";
	private static final String EDM_INCLUDE = "Include";
	private static final String EDM_NAMESPACE = "Namespace";
	private static final String EDM_ALIAS = "Alias";
	private static final String EDMX_INCLUDE = "edmx:Include";
	private static final String XMLNS_EDMX = "xmlns:edmx";
	private static final String EDMX_REFERENCE = "edmx:Reference";
	private static final String EDMX = "edmx";
	private static final String URI = "Uri";

	private final EdmProvider provider;
	private final Map edmxRefMap;

	public ODataV2EdmProvider(InputStream edmxFile) throws ODataException, XMLStreamException, IOException {
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		IOUtils.copy(edmxFile, byteArrayOutputStream);
		// copy the content of input stream to reuse it
		byte[] inputContent = byteArrayOutputStream.toByteArray();
		InputStream inputStream1 = new ByteArrayInputStream(inputContent);
		this.provider = new EdmxProvider().parse(inputStream1, true);

		InputStream inputStream2 = new ByteArrayInputStream(inputContent);
		this.edmxRefMap = populateEdmxReference(inputStream2);
	}

	// Fetch the edmx reference tags part of the generated metadata file
	private Map populateEdmxReference(InputStream is) throws ODataException, XMLStreamException {
		Map edmxRefMap = new HashMap<>();
		int index = 1;
		XMLStreamReader streamReader = XmlHelper.createStreamReader(is);
		while (streamReader.hasNext()) {
			streamReader.next();
			if (streamReader.getEventType() == XMLStreamConstants.START_ELEMENT) {
				if (EDM_REFERENCE.equals(streamReader.getLocalName())) {
					EdmxReference edmxRef = new EdmxReference();
					if (streamReader.getNamespaceCount() != 0) {
						edmxRef.setNamespacePrefix(streamReader.getNamespacePrefix(0));
						edmxRef.setNamespaceUri(streamReader.getNamespaceURI(0));
					}
					edmxRef.setUri(streamReader.getAttributeValue(0));
					streamReader.next();
					if (streamReader.getEventType() == XMLStreamConstants.START_ELEMENT && EDM_INCLUDE.equals(streamReader.getLocalName())) {
						for (int i = 0; i < streamReader.getAttributeCount(); i++) {
							if (EDM_NAMESPACE.equals(streamReader.getAttributeName(i).toString())) {
								edmxRef.setNamespace(streamReader.getAttributeValue(i));
							}
							else if (EDM_ALIAS.equals(streamReader.getAttributeName(i).toString())) {
								edmxRef.setAlias(streamReader.getAttributeValue(i));
							}
						}
					} else {
						streamReader.next();
						if (streamReader.getEventType() == XMLStreamConstants.START_ELEMENT && EDM_INCLUDE.equals(streamReader.getLocalName())) {
							for (int i = 0; i < streamReader.getAttributeCount(); i++) {
								if (EDM_NAMESPACE.equals(streamReader.getAttributeName(i).toString())) {
									edmxRef.setNamespace(streamReader.getAttributeValue(i));
								}
								else if (EDM_ALIAS.equals(streamReader.getAttributeName(i).toString())) {
									edmxRef.setAlias(streamReader.getAttributeValue(i));
								}
							}
						}
					}
					edmxRefMap.put(index++, edmxRef);
				}
			}
		}
		return edmxRefMap;
	}

	public Map getEdmxReferencesMap() {
		return edmxRefMap;
	}

	// Generate the edmx reference tags in the V2 metadata
	public VocabAnnotationElement generateAnnotationElement(Map edmxRefMap) {
		VocabAnnotationElement vocabEle = new VocabAnnotationElement();
		List annoElements = new ArrayList();
		for (int i = 0; i < edmxRefMap.size(); i++) {
			EdmxReference edmxRef = edmxRefMap.get(i + 1);
			List childAttributes = new ArrayList();
			childAttributes.add(new AnnotationAttribute().setName(EDM_ALIAS).setText(edmxRef.getAlias()));
			childAttributes.add(new AnnotationAttribute().setName(EDM_NAMESPACE).setText(edmxRef.getNamespace()));
			List referenceAttributes = new ArrayList();
			List childElements = new ArrayList();
			childElements.add(new AnnotationElement().setName(EDMX_INCLUDE).setAttributes(childAttributes));
			if (edmxRef.getNamespaceUri() != null) {
				referenceAttributes.add(new AnnotationAttribute().setName(XMLNS_EDMX).setText(edmxRef.getNamespaceUri()));
			}
			referenceAttributes.add(new AnnotationAttribute().setName(URI).setText(edmxRef.getUri()));
			annoElements.add(new AnnotationElement().setName(EDMX_REFERENCE).setPrefix(EDMX).setAttributes(referenceAttributes).setChildElements(childElements));
		}
		vocabEle.setAnnotationElements(annoElements);
		return vocabEle;
	}

	@Override
	public EntityContainerInfo getEntityContainerInfo(final String name)
			throws ODataException {
		// since no schema is specified, we take the first match in any schema
		return getEntityContainer(getSchemas(), name);
	}

	private EntityContainer getEntityContainer(List schemas, String name) {

		if (schemas == null) {
			return null;
		}

		// since no schema is specified, we take the first match in any schema

		for (Schema schema : schemas) {
			List entityContainers = schema
					.getEntityContainers();
			if (entityContainers == null) {
				return null;
			}
			for (EntityContainer entityContainer : entityContainers) {
				if ((entityContainer.isDefaultEntityContainer() && name == null)
						|| entityContainer.getName().equals(name)) {
					return entityContainer;
				}
			}
		}
		return null;
	}

	@Override
	public List getSchemas() throws ODataException {
		return this.provider.getSchemas();
	}

	@Override
	public EntitySet getEntitySet(final String entityContainer,
			final String name) throws ODataException {

		// since no schema is specified, we take the first match in any schema

		EntityContainer container = getEntityContainer(getSchemas(),
				entityContainer);
		if (container == null) {
			return null;
		}
		List sets = container.getEntitySets();
		if (sets == null) {
			return null;
		}
		for (EntitySet set : sets) {
			if (set.getName().equals(name)) {
				return set;
			}
		}
		return null;
	}

	@Override
	public AssociationSet getAssociationSet(final String entityContainer,
			final FullQualifiedName association,
			final String sourceEntitySetName, final String sourceEntitySetRole)
					throws ODataException {

		// since no schema is specified, we take the first match in any schema

		EntityContainer container = getEntityContainer(getSchemas(),
				entityContainer);
		if (container == null) {
			return null;
		}
		List sets = container.getAssociationSets();
		if (sets == null) {
			return null;
		}
		for (AssociationSet set : sets) {
			if (set.getAssociation().getNamespace()
					.equals(association.getNamespace())
					&& set.getAssociation().getName()
					.equals(association.getName())
					&& ((set.getEnd1().getEntitySet().equals(sourceEntitySetName)
							&& set.getEnd1().getRole().equals(sourceEntitySetRole)) || (set.getEnd2().getEntitySet().equals(sourceEntitySetName)
									&& set.getEnd2().getRole().equals(sourceEntitySetRole)))) {
				return set;
			}
		}
		return null;
	}

	@Override
	public FunctionImport getFunctionImport(final String entityContainer,
			final String name) throws ODataException {

		// since no schema is specified, we take the first match in any schema

		EntityContainer container = getEntityContainer(getSchemas(),
				entityContainer);
		if (container == null) {
			return null;
		}
		List functionImports = container.getFunctionImports();
		if (functionImports == null) {
			return null;
		}
		for (FunctionImport functionImport : functionImports) {
			if (functionImport.getName().equals(name)) {
				return functionImport;
			}
		}
		return null;
	}

	@Override
	public EntityType getEntityType(final FullQualifiedName edmFQName)
			throws ODataException {

		List schemas = getSchemas();
		if (schemas == null) {
			return null;
		}
		for (Schema schema : schemas) {
			if (schema.getNamespace().equals(edmFQName.getNamespace())) {
				List types = schema.getEntityTypes();
				if (types == null) {
					return null;
				}
				for (EntityType type : types) {
					if (type.getName().equals(edmFQName.getName())) {
						return type;
					}
				}
			}
		}
		return null;
	}

	@Override
	public ComplexType getComplexType(final FullQualifiedName edmFQName)
			throws ODataException {

		List schemas = getSchemas();
		if (schemas == null) {
			return null;
		}
		for (Schema schema : schemas) {
			if (schema.getNamespace().equals(edmFQName.getNamespace())) {
				List types = schema.getComplexTypes();
				if (types == null) {
					return null;
				}
				for (ComplexType type : types) {
					if (type.getName().equals(edmFQName.getName())) {
						return type;
					}
				}
			}
		}
		return null;
	}

	@Override
	public Association getAssociation(final FullQualifiedName edmFQName)
			throws ODataException {

		List schemas = getSchemas();
		if (schemas == null) {
			return null;
		}
		for (Schema schema : schemas) {
			if (schema.getNamespace().equals(edmFQName.getNamespace())) {
				List associations = schemas.get(0)
						.getAssociations();
				if (associations == null) {
					return null;
				}
				for (Association association : associations) {
					if (association.getName().equals(edmFQName.getName())) {
						return association;
					}
				}
			}
		}
		return null;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy