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

com.reprezen.genflow.rapidml.xsd.XMLSchemaHelper.xtend Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright © 2013, 2016 Modelsolv, Inc.
 * All Rights Reserved.
 * 
 * NOTICE: All information contained herein is, and remains the property
 * of ModelSolv, Inc. See the file license.html in the root directory of
 * this project for further information.
 *******************************************************************************/
package com.reprezen.genflow.rapidml.xsd

import com.google.common.base.Splitter
import com.google.common.base.Strings
import com.google.common.collect.Lists
import com.reprezen.genflow.api.zenmodel.util.CommonServices
import com.reprezen.genflow.common.xtend.ZenModelHelper
import com.reprezen.rapidml.Constraint
import com.reprezen.rapidml.DataModel
import com.reprezen.rapidml.Documentable
import com.reprezen.rapidml.Element
import com.reprezen.rapidml.Enumeration
import com.reprezen.rapidml.Feature
import com.reprezen.rapidml.LengthConstraint
import com.reprezen.rapidml.Method
import com.reprezen.rapidml.PrimitiveType
import com.reprezen.rapidml.PropertyRealization
import com.reprezen.rapidml.ReferenceElement
import com.reprezen.rapidml.RegExConstraint
import com.reprezen.rapidml.ResourceAPI
import com.reprezen.rapidml.ResourceDefinition
import com.reprezen.rapidml.ServiceDataResource
import com.reprezen.rapidml.SingleValueType
import com.reprezen.rapidml.Structure
import com.reprezen.rapidml.TypedMessage
import com.reprezen.rapidml.UserDefinedType
import com.reprezen.rapidml.ValueRangeConstraint
import com.reprezen.rapidml.ZenModel
import java.util.Collection
import java.util.LinkedList
import java.util.List
import java.util.Set
import org.eclipse.emf.ecore.EObject

class XMLSchemaHelper {
	extension ZenModelHelper zenModelHelper
	extension ParamsHelper paramsHelper
	extension TraceHelper traceHelper

	new(Helpers helpers) {
		this.zenModelHelper = helpers.zenModelHelper
		this.paramsHelper = helpers.paramsHelper
		this.traceHelper = helpers.traceHelper
	}

	// TODO: Use Guava's 15 Escaper after migration 
	def String escapeXml(String source) {
		source.replaceAll("&", "&").replaceAll("\"", """).replaceAll("<", "<").replaceAll(">", ">").
			replaceAll("\'", "'");
	}

	def  T getEContainer(EObject ele, Class type) {
		CommonServices::getContainerOfType(ele, type)
	}

	def  Collection putAll(Iterable iterable, Class _class) {
		val Collection result = new LinkedList
		iterable.forEach[result.add(it)]
		return result
	}

	def ZenModel zenModel(EObject obj) {
		obj.getEContainer(ZenModel)
	}

	def dispatch String namespace(DataModel dataModel) {
		schemaRoot(dataModel.zenModel) + dataModel.name.toLowerCase()
	}

	def dispatch String namespace(ResourceAPI resourceAPI) {
		schemaRoot(resourceAPI.zenModel) + resourceAPI.name.toLowerCase()
	}

	def String schemaRoot(ZenModel zenModel) {
		val uriFragment = if (zenModel.namespace.nullOrEmpty) {
				'http://modelsolv.com/reprezen/schemas'
			} else {
				'http://' + reverseNamespace(zenModel.namespace)
			}
		uriFragment + "/" + zenModel.name.toLowerCase + "/"
	}

	def String reverseNamespace(String namespace) {
		val int idx = namespace.indexOf('.')
		if(idx == -1) namespace else Lists.reverse(Splitter.on('.').split(namespace).toList).join('.')
	}

	def nsPrefix(DataModel dataModel, ResourceAPI resourceAPI) {
		if (dataModel !== null) {
			if (resourceAPI.zenModel == dataModel.zenModel)
				dataModel.name.toFirstLower
			else {
				val String alias = getAliasForDataModel(resourceAPI.zenModel, dataModel)
				if(Strings.isNullOrEmpty(alias)) dataModel.getShortestUniqueName(resourceAPI) else alias
			}
		}
	}

	def dispatch String nsPrefix(ResourceAPI resourceAPI) {
		if (resourceAPI !== null)
			resourceAPI.name.toLowerCase + ""
	}

	def dispatch String nsPrefix(ServiceDataResource dataResource) {
		nsPrefix(dataResource.getInterface)
	}

	def xsdFileName(DataModel dataModel, ZenModel zenModel) {
		if (zenModel == dataModel.zenModel)
			dataModel.name.toFirstLower + ".xsd"
		else {
			val ZenModel model = dataModel.zenModel
			val String woNsName = model.name.toFirstLower + "-" + dataModel.name.toFirstLower + ".xsd"
			if (model.namespace.nullOrEmpty)
				woNsName
			else
				model.namespace.toFirstLower.replaceAll("\\.", "-") + "-" + woNsName
		}
	}

	def xsdFileName(ResourceAPI resourceAPI) {
		resourceAPI.name.toFirstLower + ".xsd"
	}

	def dispatch String typeName(TypedMessage message) {
		val name = switch typeNamingMethod {
			case SIMPLE_NAME: CommonServices.getMessageTypeName(message)
			case FULLY_QUALIFIED_NAME: message.fqName.toFirstUpper
		}
		message.typeNameInTrace = name
		return name
	}

	def dispatch String typeName(Structure structure) {
		val name = switch typeNamingMethod {
			case SIMPLE_NAME: structure.name.toFirstUpper
			case FULLY_QUALIFIED_NAME: structure.fqName.toFirstUpper
		}
		structure.typeNameInTrace = name
		return name
	}

	def dispatch String typeName(Enumeration enumeration) {
		val name = switch typeNamingMethod {
			case SIMPLE_NAME: enumeration.name // backward compatibility - no firstUpper
			case FULLY_QUALIFIED_NAME: enumeration.fqName.toFirstUpper
		}
		enumeration.typeNameInTrace = name
		return name
	}

	def dispatch String typeName(UserDefinedType type) {
		val name = switch typeNamingMethod {
			case SIMPLE_NAME: type.name // backward compatibility - no firstUpper
			case FULLY_QUALIFIED_NAME: type.fqName.toFirstUpper
		}
		type.typeNameInTrace = name
		return name
	}

	def dispatch String typeName(PrimitiveType type) {
		type.name
	}

	def dispatch String typeName(ServiceDataResource dataResource) {
		val name = switch typeNamingMethod {
			case SIMPLE_NAME: dataResource.name.toFirstUpper
			case FULLY_QUALIFIED_NAME: dataResource.fqName.toFirstUpper
		}
		dataResource.typeNameInTrace = name
		return name
	}

	def String extend(String baseName, List path) {
		'''«baseName»_«path.map[name].join("_")»'''
	}

	def dispatch getRootElementName(Structure structure) {
		val name = structure.typeName.toFirstLower
		structure.rootElementInTrace = name
		return name
	}

	def dispatch getRootElementName(ServiceDataResource resource) {
		val name = resource.typeName.toFirstLower
		resource.rootElementInTrace = name
		return name
	}

	def dispatch getRootElementName(TypedMessage message) {
		val name = message.typeName.toFirstLower
		message.rootElementInTrace = name
		return name
	}

	def getElementName(Element element) {
		val name = switch element {
			Feature: element.name
			ReferenceElement: element.name
		}.toFirstLower
		element.elementNameInTrace = name
		return name
	}

	def getElementName(PropertyRealization property) {
		property.baseProperty.elementName
	}

	def getAttributeName(Element element) {
		val name = switch element {
			Feature: element.name
			ReferenceElement: element.name
		}.toFirstLower
		element.attributeNameInTrace = name
		return name
	}

	def getAttributeName(PropertyRealization property) {
		property.baseProperty.attributeName
	}

	def dispatch String typeQName(TypedMessage message) {
		val resourceType = message.resourceType
		typeQName(toServiceDataResource(resourceType))
	}

	def dispatch String typeQName(ServiceDataResource dataResource) {
		if(dataResource === null) null else nsPrefix(dataResource) + ":" + typeName(dataResource)
	}

	def private toServiceDataResource(ResourceDefinition resource) {
		if(resource instanceof ServiceDataResource) resource else null
	}

	// FIXME support nested data types
	def protected DataModel getInterfaceDataModel(Structure complexType) {
		complexType.eContainer as DataModel
	}

	def getInterface(ServiceDataResource dataResource) {
		if(dataResource === null) null else dataResource.getEContainer(ResourceAPI)
	}

	def Iterable getUsedTypes(ZenModel zenModel) {
		CommonServices.getUsedSimpleTypes(zenModel)
	}

	def Iterable getUsedTypes(ResourceAPI resourceAPI) {
		CommonServices.getUsedSimpleTypes(resourceAPI)
	}

	def getAliasForDataModel(ZenModel zenModel, DataModel dataModel) {
		zenModel.getImportDeclaration(dataModel).alias
	}

	def getImportDeclaration(ZenModel zenModel, DataModel dataModel) {
		if (zenModel == dataModel.zenModel)
			null
		else
			zenModel.imports.findFirst [
				it.importedNamespace == dataModel.getFQN
			]
	}

	def getFQN(DataModel dataModel) {
		val ZenModel zenModel = dataModel.zenModel
		val String woNsName = zenModel.name + "." + dataModel.name
		if(Strings.isNullOrEmpty(zenModel.namespace)) woNsName else zenModel.namespace + "." + woNsName
	}

	def getShortestUniqueName(DataModel dataModel, ResourceAPI resourceAPI) {
		var String result
		var Set dataModels = resourceAPI.getUsedDataModels.filter [
			(
                    (resourceAPI.zenModel == it.zenModel) || resourceAPI.zenModel.getImportDeclaration(it).alias === null
                ) && (it.name == dataModel.name)
		].filter[it != dataModel].toSet

		// dataModels.remove(dataModel)
		if (dataModels.empty)
			result = dataModel.name
		else {
			if (!dataModels.exists[it.zenModel.name == dataModel.zenModel.name])
				result = dataModel.zenModel.name + "." + dataModel.name
			else
				result = dataModel.getFQN
		}

		return result
	}

	def getBaseTypeName(UserDefinedType userDefinedType) {
		val prefix = if(userDefinedType.baseType instanceof PrimitiveType) "xs:" else ""
		return prefix + userDefinedType.baseType.name
	}

	def dispatch Iterable getUsedDataModels(ResourceAPI resourceAPI) {
		resourceAPI.getUsedTypes.map[it.getEContainer(DataModel)].filter[it !== null].toSet
	}

	def dispatch Iterable getUsedDataModels(ZenModel zenModel) {
		zenModel.resourceAPIs.map[it.usedDataModels].flatten.toSet
	}

	def getParentResourceDefinition(TypedMessage message) {
		message.getEContainer(Method).getEContainer(ResourceDefinition)
	}

	def String generateXSDDoc(Documentable doc) {
		val String docText = getDocumentation(doc)
		val String escapedDoc = docText.replaceAll("[\r\n]+", " ").replaceAll("[\n]+", " ").replaceAll("([\"\\\\])",
			"\\\\$1").trim()
		if (!escapedDoc.nullOrEmpty) {
			'''
				
					
						
					
				
			'''
		}
	}

	def generateRestriction(String baseTypeName, Iterable constraints) {
		'''
			
			«IF !constraints.nullOrEmpty»
				«FOR constraint : constraints SEPARATOR ""»
					«IF constraint instanceof LengthConstraint»
						«IF constraint.maxLength != 0 && constraint.maxLength == constraint.minLength»
							
						«ELSE»
							«IF (constraint.minLength != 0)»
								
							«ENDIF»
							«IF (constraint.maxLength != 0)»
								
							«ENDIF»
						«ENDIF»
					«ENDIF»
					«IF constraint instanceof RegExConstraint»
						
					«ENDIF»
					«IF constraint instanceof ValueRangeConstraint»
						«IF constraint.minValueExclusive»
							
						«ELSEIF constraint.minValue !== null» 
							
						«ENDIF»
						«IF constraint.maxValueExclusive»
							
						«ELSEIF constraint.maxValue !== null» 
							
						«ENDIF»
					«ENDIF»
				«ENDFOR»
			«ENDIF»
			
		'''
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy