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

com.sap.cloud.sdk.service.prov.model.internal.CSNParser Maven / Gradle / Ivy

There is a newer version: 1.40.11
Show newest version
/*******************************************************************************
 * (c) 201X SAP SE or an SAP affiliate company. All rights reserved.
 ******************************************************************************/
package com.sap.cloud.sdk.service.prov.model.internal;

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 java.util.Map.Entry;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.ObjectMapper;

public class CSNParser {

	Map csnServiceMap = new HashMap();
	Map csnIndpendentEntityMap = new HashMap();
	CSNMetaModel csnMetaModel = new CSNMetaModel();
	private static Logger log = LoggerFactory.getLogger(CSNParser.class);
	private InputStream csn = null;
	Map svcMap = new HashMap();
	private static final ObjectMapper objectMapper = new ObjectMapper();
	
	public CSNMetaModel readAndParse(InputStream csnInputStream) {
		this.csn = csnInputStream;
		return readAndParse();
	}
	
	public CSNMetaModel readAndParse(byte[] csnByteArray) {
		CsnParserUtil.logDebug(log, "readAndParse started");
		try {
			Map csnMap = new HashMap<>();
			csnMap = objectMapper.readValue(csnByteArray, HashMap.class);

			// First Iterate through all services
			CSNServiceModel serviceModel = null;
			Map definitionMap = (Map) csnMap.get(CSNConstants.DEFINITIONS);
			for (Entry entry : definitionMap.entrySet()) {

				Map entryValue = (Map) entry.getValue();

				String csnObjKind = (String) entryValue.get(CSNConstants.KIND);
				String entryKey = (String) entry.getKey();

				if (CSNConstants.SERVICE.equals(csnObjKind)) {
					serviceModel = new CSNServiceModel();
					serviceModel.setServiceName(entryKey);
					svcMap.put(entryKey, entryKey);
					List entities = new ArrayList();
					serviceModel.setEntities(entities);
														
					if(entryValue.containsKey(CSNConstants.ACTIONS)){
						Map actionsMap = (Map) entryValue.get(CSNConstants.ACTIONS);
						addOperationsToService(actionsMap,serviceModel);
					
					}
					csnServiceMap.put(entryKey, serviceModel);
				}
			}
			addEntitiesToService(definitionMap,svcMap);
		} catch (IOException e) {
			log.error(e.getMessage(),e);
		}
		CsnParserUtil.logDebug(log, "readAndParse ended");
		csnMetaModel.setService(csnServiceMap);
		csnMetaModel.setEntities(csnIndpendentEntityMap);
		return csnMetaModel;
	}
	/**
	 * 
	 * @param uri
	 * @return CSNMetaModel
	 */
	public CSNMetaModel readAndParse() {
		CsnParserUtil.logDebug(log, "readAndParse started");
		InputStream csnInputStream = null;
		try {
			if(csn == null)
				csnInputStream = CSNParser.class.getClassLoader().getResourceAsStream("edmx/csn.json");
			else {
				csnInputStream = csn;
			}
			byte[] mapData = IOUtils.toByteArray(csnInputStream);

			return readAndParse(mapData);
		} catch (IOException e) {
			log.error(e.getMessage(),e);
		} finally{
			 try {if(csnInputStream!=null){
				 csnInputStream.close();
			 }else{
				 log.debug("csnInputStream was null");
			 }
			} catch (IOException e) {
				log.error("Error in closing inputstream for csn parsing",e);
			}
		}
		CsnParserUtil.logDebug(log, "readAndParse ended");
		return csnMetaModel;
	}
	
	private void addOperationsToService(Map actionsMap,CSNServiceModel serviceModel){
		if(serviceModel == null || actionsMap ==null || actionsMap.isEmpty()){
			//Invalid situation as nothing to set back
			return;
		}
		List actions = new ArrayList();
		List functions = new ArrayList();
		
		for (Entry operation : actionsMap.entrySet()) {
			Map opValue = (Map) operation.getValue();
			String opName = (String)operation.getKey(); 
			if(CSNConstants.ACTION.equals(opValue.get(CSNConstants.KIND))){
				actions.add(constructCsnOperation(serviceModel.getServiceName(),opName,opValue));
			}
			else if(CSNConstants.FUNCTION.equals(opValue.get(CSNConstants.KIND))){
				functions.add(constructCsnOperation(serviceModel.getServiceName(),opName,opValue));
			}	
		}
		serviceModel.setActions(actions);
		serviceModel.setFunctions(functions);
		
	}
	
	private void addOperationsToEntity(Map actionsMap, String serviceName, CSNEntityModel entityModel){
		if(entityModel == null || actionsMap ==null || actionsMap.isEmpty()){
			//Invalid situation as nothing to set back
			return;
		}
		List actions = new ArrayList<>();
		List functions = new ArrayList<>();
		
		for (Entry operation : actionsMap.entrySet()) {
			Map opValue = (Map) operation.getValue();
			String opName = (String)operation.getKey(); 
			if(CSNConstants.ACTION.equals(opValue.get(CSNConstants.KIND))){
				actions.add(constructCsnOperation(serviceName,opName,opValue));
			}
			else if(CSNConstants.FUNCTION.equals(opValue.get(CSNConstants.KIND))){
				functions.add(constructCsnOperation(serviceName,opName,opValue));
			}	
		}
		entityModel.setActions(actions);
		entityModel.setFunctions(functions);
		
	}
	
	private void addEntitiesToService(Map definitionMap, Map svcMap){
		for (Entry entry : definitionMap.entrySet()) {

			Map entryValue = (Map) entry.getValue();

			String csnObjKind = (String) entryValue.get(CSNConstants.KIND);
			String entryKey = (String) entry.getKey();

			if (!( CSNConstants.ENTITY.equals(csnObjKind)  || CSNConstants.VIEW.equals(csnObjKind) )) {
				continue;
			}

			CSNEntityModel csnEntity = new CSNEntityModel();
			
			Map elementMap = (Map) entryValue.get(CSNConstants.ELEMENTS);
			List queryList = null;

			Map names = getEntityAndServiceName(entryKey);
			if(svcMap.containsKey(names.get(CSNConstants.SERVICE))){
				csnEntity.setEntityName(names.get(CSNConstants.ENTITY));

				csnEntity.setParentService(names.get(CSNConstants.SERVICE));
				csnEntity.setElements(constructCsnElementList(elementMap));
				csnEntity.setAssociations(constructCsnAssociationList(elementMap));
				csnEntity.setAnnotations(constructCsnAnnotationList(entryValue));

				if (entryValue.get(CSNConstants.QUERY) instanceof List) {
					queryList = (List) entryValue.get(CSNConstants.QUERY);

				} else {
					Map query = (Map) entryValue.get(CSNConstants.QUERY);
					if (query != null) {
						queryList = new ArrayList();
						queryList.add(query);
					}

				}
				csnEntity.setQueries(constructCsnQueryList(queryList));

				if (entryValue.containsKey(CSNConstants.ACTIONS) && entryValue.containsKey(CSNConstants.ODATA_DRAFT_ENABLED) 
						&& entryValue.get(CSNConstants.ODATA_DRAFT_ENABLED) != null 
						&& ((Boolean)entryValue.get(CSNConstants.ODATA_DRAFT_ENABLED))) {
					csnEntity.setDraftEnabled((Boolean)entryValue.get(CSNConstants.ODATA_DRAFT_ENABLED));
					Map actionsMap = (Map) entryValue.get(CSNConstants.ACTIONS);
					this.addOperationsToEntity(actionsMap, names.get(CSNConstants.SERVICE), csnEntity);
				}
				
				if (entryValue.containsKey(CSNConstants.CDS_PERSISTENCE_SKIP)) {
					if(entryValue.get(CSNConstants.CDS_PERSISTENCE_SKIP) instanceof Boolean) {
						csnEntity.setCdsPersistenceSkipAnnotationEnabled((boolean) entryValue.get(CSNConstants.CDS_PERSISTENCE_SKIP));
					} else if (entryValue.get(CSNConstants.CDS_PERSISTENCE_SKIP) instanceof String && CSNConstants.IFUNUSED.equals(entryValue.get(CSNConstants.CDS_PERSISTENCE_SKIP))) {
						csnEntity.setCdsPersistenceSkipAnnotationEnabled(true);
					}
				}				
				if (!"".equals(csnEntity.getParentService())) {
					csnServiceMap.get(names.get(CSNConstants.SERVICE)).getEntities().add(csnEntity);
				} else {
					csnIndpendentEntityMap.put(csnEntity.getEntityName(), csnEntity);
				}
			}
		}
	}

	private Map getEntityAndServiceName(String fullname) {
		Map names = new HashMap<>();
		String entityName;
		String serviceName;
		if (fullname.indexOf('.') > 0) {           
			int lastIndex = fullname.lastIndexOf('.');
 			entityName = fullname.substring(lastIndex+1, fullname.length());
			serviceName = fullname.substring(0,	lastIndex );
			names.put(CSNConstants.ENTITY, entityName);
			names.put(CSNConstants.SERVICE, serviceName);
		} else if (fullname.indexOf('.') == -1) {
			names.put(CSNConstants.ENTITY, fullname);
			names.put(CSNConstants.SERVICE, "");
		}

		return names;

	}

	private CSNElementModel constructCsnElement(String elementName, Map elementValueMap) {
		CsnParserUtil.logDebug(log, "constructCsnElement started");
		CSNElementModel element = new CSNElementModel();
		element.setName(elementName);
		for (Entry entry : elementValueMap.entrySet()) {

			String eleAttributeKey = (String) entry.getKey();

			switch (eleAttributeKey) {
			case CSNConstants.TYPE:
				element.setType((String) entry.getValue());
				break;
			case CSNConstants.KEY:
				element.setKey((boolean) entry.getValue());
				break;
			case CSNConstants.NOT_NULL:
				element.setNotnull((boolean) entry.getValue());
				break;
			case CSNConstants.LENGTH:
				element.setLength((Integer) entry.getValue());
				break;
			}

		}
		CsnParserUtil.logDebug(log, "constructCsnElement ended");
		return element;
	}

	private List constructCsnElementList(Map elementsMap) {
		List elements = new ArrayList();
		CsnParserUtil.logDebug(log, "constructCsnElementList started");
		for (Entry entry : elementsMap.entrySet()) {
			String elementName = (String) entry.getKey();
			Map ele = (Map) entry.getValue();
			// check for type
			if (!CSNConstants.ASSOCIATION.equals(ele.get(CSNConstants.TYPE))
					&& !CSNConstants.COMPOSITION.equals(ele.get(CSNConstants.TYPE))) {
				elements.add(constructCsnElement(elementName, ele));
			}
		}
		CsnParserUtil.logDebug(log, "constructCsnElementList ended");
		return elements;
	}

	private CSNAssociationModel constructCsnAssociation(String associationName, Map associationValueMap) {
		CsnParserUtil.logDebug(log, "constructCsnAssociation started");
		CSNAssociationModel association = new CSNAssociationModel();
		//Add association name for this entity level association
		association.setAssociationName(associationName);
		
		for (Entry entry : associationValueMap.entrySet()) {

			String eleAttributeKey = (String) entry.getKey();
			switch (eleAttributeKey) {
			case CSNConstants.TYPE:
				association.setType((String) entry.getValue());
				break;
			case CSNConstants.TARGET:

				String qualifiedEntityName = (String) entry.getValue();
				if (qualifiedEntityName.indexOf('.') == -1) {

					association.setTargetEntity(qualifiedEntityName);
				} else if (qualifiedEntityName.indexOf('.') > 0) {
					Map names = getEntityAndServiceName(qualifiedEntityName);
					association.setTargetEntity(names.get(CSNConstants.ENTITY));
					association.setTargetService(names.get(CSNConstants.SERVICE));
				}
				break;
			case CSNConstants.CARDINALITY:
				association.setCardinality((Map) entry.getValue());
				break;
			case CSNConstants.ON:
				if(entry.getValue() instanceof String) {
					association.setOn((String) entry.getValue());
				}
				else if(entry.getValue() instanceof ArrayList)
				{
					association.setOn((ArrayList) entry.getValue());
				}
				break;

			}
		}
		CsnParserUtil.logDebug(log, "constructCsnAssociation ended");
		return association;
	}

	private List constructCsnAssociationList(Map elementsMap) {
		CsnParserUtil.logDebug(log, "constructCsnAssociationList started");
		List associations = new ArrayList();
		for (Entry entry : elementsMap.entrySet()) {
			String associationName = (String) entry.getKey();
			Map ele = (Map) entry.getValue();

			// check for type
			if (CSNConstants.ASSOCIATION.equals(ele.get(CSNConstants.TYPE))
					|| CSNConstants.COMPOSITION.equals(ele.get(CSNConstants.TYPE))) {
				associations.add(constructCsnAssociation(associationName, ele));
			}
		}

		CsnParserUtil.logDebug(log, "constructCsnAssociationList ended");
		return associations;
	}

	private List constructCsnQueryList(List queryList) {
		CsnParserUtil.logDebug(log, "constructCsnQueryList started");
		List querys = new ArrayList();
		if (queryList != null) {
			for (Object queryObj : queryList) {

				CSNQueryModel csnQuery = new CSNQueryModel();
				csnQuery.setValue(queryObj);
				querys.add(csnQuery);
			}
		}
		CsnParserUtil.logDebug(log, "constructCsnQueryList ended");
		return querys;
	}

	private List constructCsnAnnotationList(Map entityMap) {
		CsnParserUtil.logDebug(log, "constructCsnAnnotationList started");
		List annotations = new ArrayList();

		for (Entry entry : entityMap.entrySet()) {

			String entryKey = (String) entry.getKey();
			// check if annotation
			if ('@' == entryKey.charAt(0)) {
				CSNAnnotationModel anno = new CSNAnnotationModel();
				anno.setName(entryKey);
				anno.setValue(entry.getValue());

				annotations.add(anno);
			}
		}
		CsnParserUtil.logDebug(log, "constructCsnAnnotationList ended");
		return annotations;
	}
	private List constructCsnParamList(Map paramMap){
		List params = new ArrayList<>();		
		if(paramMap == null || paramMap.isEmpty()){
			//Nothing to construct
			return params;
		}

		for (Entry entry : paramMap.entrySet()) {
			CSNParamModel param = new CSNParamModel();
			param.setName((String) entry.getKey());
			Map paramValue =  (Map) entry.getValue();
			param.setType((String) paramValue.get(CSNConstants.TYPE));
			params.add(param);
		}
		return params;
	}
	
	private CSNOperationModel constructCsnOperation(String parentService, String opName, Map operationMap) {
		CsnParserUtil.logDebug(log, "constructCsnOperation started");
		CSNOperationModel operation = null;
		if(CSNConstants.ACTION.equals(operationMap.get(CSNConstants.KIND)) || CSNConstants.FUNCTION.equals(operationMap.get(CSNConstants.KIND))){
			operation = new CSNOperationModel();
			operation.setName(opName);
			operation.setParentService(parentService);
			Map params = (Map) operationMap.get(CSNConstants.PARAMS);
			Map returns = (Map) operationMap.get(CSNConstants.RETURNS);
			operation.setParams(constructCsnParamList(params));
			operation.setReturns(returns);			
		}		
		CsnParserUtil.logDebug(log, "constructCsnOperation ended");
		return operation;
	}
}