Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.reprezen.genflow.rapidml.xsd.ResourceApiSchemaGenerator.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.collect.Iterables
import com.google.common.collect.Lists
import com.reprezen.genflow.api.template.IGenTemplateContext
import com.reprezen.genflow.api.zenmodel.ZenModelExtractOutputItem
import com.reprezen.genflow.api.zenmodel.ZenModelLocator
import com.reprezen.rapidml.CollectionResource
import com.reprezen.rapidml.Feature
import com.reprezen.rapidml.Method
import com.reprezen.rapidml.ObjectRealization
import com.reprezen.rapidml.ObjectResource
import com.reprezen.rapidml.PrimitiveProperty
import com.reprezen.rapidml.PropertyRealization
import com.reprezen.rapidml.ReferenceElement
import com.reprezen.rapidml.ReferenceEmbed
import com.reprezen.rapidml.ReferenceLink
import com.reprezen.rapidml.ReferenceProperty
import com.reprezen.rapidml.ReferenceTreatment
import com.reprezen.rapidml.ResourceAPI
import com.reprezen.rapidml.ResourceDefinition
import com.reprezen.rapidml.ServiceDataResource
import com.reprezen.rapidml.Structure
import com.reprezen.rapidml.TypedMessage
import com.reprezen.rapidml.ZenModel
import com.reprezen.rapidml.util.ResourceFinder
import java.util.Collection
import java.util.List
import org.eclipse.emf.ecore.EObject
class ResourceApiSchemaGenerator extends ZenModelExtractOutputItem {
extension FeatureHelper featureHelper
extension ReferenceLinkHelper referenceLinkHelper
extension XMLSchemaHelper xmlSchemaHelper
extension ParamsHelper paramsHelper
extension TraceHelper traceHelper
var ZenModelLocator locator
var ResourceFinder resourceFinder
override void init(IGenTemplateContext context) {
super.init(context)
}
override String generate(ZenModel zenModel, ResourceAPI api) {
val helpers = new Helpers(context, zenModel)
this.featureHelper = helpers.featureHelper
this.referenceLinkHelper = helpers.referecneLinkHelper
this.xmlSchemaHelper = helpers.xmlSchemaHelper
this.paramsHelper = helpers.paramsHelper
this.traceHelper = helpers.traceHelper
this.locator = new ZenModelLocator(zenModel)
this.resourceFinder = new ResourceFinder(api)
api.traceForApi //
.withProperty('namespace', api.namespace) //
.withProperty('namespacePrefix', api.nsPrefix) //
.withPrimarySourceItem(locator.locate(api)) //
'''
«api.generateSchemaImports»
«FOR dm : api.usedDataModels SEPARATOR ""»
«ENDFOR»
«FOR resource : api.ownedResourceDefinitions SEPARATOR ""»
«generateForResource(resource as ServiceDataResource, api)»
«ENDFOR»
«FOR resource : api.ownedResourceDefinitions SEPARATOR ""»
«FOR method : resource.methods SEPARATOR ""»
««« Make sure each method has an id value in trace
«{method.setIdInTrace; null}»
«method.request?.generateForMessage»
«FOR response : method.responses SEPARATOR ""»
«response.generateForMessage»
«ENDFOR»
«ENDFOR»
«ENDFOR»
«FOR dataType : api.zenModel.dataModels.map[it.ownedDataTypes.filter(Structure)].flatten SEPARATOR ""»
«dataType.generateForStructure(api)»
«ENDFOR»
'''
}
def private generateNamespaceAdditions(ResourceAPI api) {
'xmlns:atom="http://www.w3.org/2005/Atom"'
}
def private String generateSchemaImports(ResourceAPI api) {
api.generateAtomImports
}
//
// Per-resource generation
//
def private generateForResource(ServiceDataResource resource, ResourceAPI api) {
resource.traceForComplexType //
.withProperty('complexType', resource.typeName) //
.withProperty('elementName', resource.rootElementName) //
.withProperty('namespace', api.namespace) //
.withProperty('namespacePrefix', api.nsPrefix) //
.withPrimarySourceItem(locator.locate(api)) //
.withPrimarySourceItem(locator.locate(resource))
'''
«resource.dataType.generateResourceComplexType(resource, api)»
«resource.generateResourceElement»
«resource.generateTransitionalContainersForReferenceLinks(api)»
«generateContainersForReferenceEmbeds(resource.name, resource, resource.referenceTreatments, api)»
'''
}
def private dispatch generateResourceComplexType(Structure complexType, CollectionResource resource,
ResourceAPI api) {
val elementProperties = Iterables.concat(
resource.referenceLinks,
resource.referenceEmbeds
)
'''
«complexType.generateXSDDoc»
«elementProperties.generateAllBlock(resource, api)»
'''
}
def private dispatch generateResourceComplexType(Structure complexType, ObjectResource resource, ResourceAPI api) {
val elementProperties = Iterables.concat(
resource.includedProperties.filterForElements,
resource.referenceLinks,
resource.referenceEmbeds
)
val attributeProperties = resource.includedProperties.filterForAttributes
'''
«complexType.generateXSDDoc»
«elementProperties.generateAllBlock(resource, api)»
«attributeProperties.generateAttributeDecls(api)»
'''
}
def private generateAllBlock(Iterable properties, EObject context, ResourceAPI api) {
generateAllBlock(properties, context, api, null)
}
def private generateAllBlock(Iterable properties, EObject context, ResourceAPI api,
(EObject)=>String special) {
if (!properties.empty) {
'''
«FOR prop : properties SEPARATOR ""»
«special?.apply(prop) ?: generatePropertyDecl(prop, context, api, true)»
«ENDFOR»
'''
}
}
def private generateResourceElement(ServiceDataResource resource) {
'''
'''
}
def private generateTransitionalContainersForReferenceLinks(ServiceDataResource resource, ResourceAPI api) {
val links = resource.referenceLinks.map[it as ReferenceTreatment]
'''
«FOR referenceProperty : getContainmentReferencesAtPosition(links, 1)»
«generateContainmentSegment(referenceProperty, resource, api)»
«ENDFOR»
'''
}
def private generateContainmentSegment(ReferenceProperty referenceProperty, ServiceDataResource resource,
ResourceAPI api) {
generateContainmentSegment(#[referenceProperty], resource, api)
}
def private String generateContainmentSegment(List path, ServiceDataResource resource,
ResourceAPI api) {
val currentType = path.findLast[].type
val levelOfContainment = path.length
val elementProperties = Iterables.concat(
currentType.ownedFeatures.filterForElements,
resource.referenceLinks.filter[startsWithPath(path)].filter[containmentDepth < levelOfContainment + 1]
)
val attributeProperties = currentType.ownedFeatures.filterForAttributes
val nextLevelReferences = resource.referenceLinks.map[it as ReferenceTreatment]
'''
«elementProperties.generateAllBlock(resource, api)[
switch it {
ReferenceProperty:
it.generateReferenceProperty(resource, api, path)
default:
null
}
]»
«attributeProperties.generateAttributeDecls(api)»
«FOR referenceProperty : getContainmentReferencesAtPosition(nextLevelReferences, levelOfContainment + 1)»
«generateContainmentSegment(path.concat(referenceProperty), resource, api)»
«ENDFOR»
'''
}
//
// Per-Message Generation
//
def private generateForMessage(TypedMessage message) {
if (message.actualType !== null) {
val api = message.resourceAPI
'''
«message.actualType.generateMessageComplexType(message, api)»
«message.generateMessageTypeElement»
«message.generateTransitionalContainersForReferenceLinks(api)»
«generateContainersForReferenceEmbeds(message.typeName, message, message.referenceTreatments, api)»
'''
}
}
def private generateMessageComplexType(Structure complexType, TypedMessage message, ResourceAPI api) {
val elementProperties = Iterables.concat(
message.includedProperties.filterForElements,
message.referenceLinks,
message.referenceEmbeds
)
val attributeProperties = message.includedProperties.filterForAttributes
'''
«complexType.generateXSDDoc»
«elementProperties.generateAllBlock(message, api)[
switch it {
ReferenceEmbed: {
val nextReference = it.referenceElement as ReferenceProperty
nextReference.generateNestedReference(extend(message.typeName, #[nextReference]))
}
default:
null
}
]»
«attributeProperties.generateAttributeDecls(api)»
'''
}
def private generateMessageTypeElement(TypedMessage message) {
'''
'''
}
def private generateTransitionalContainersForReferenceLinks(TypedMessage message,
ResourceAPI api) {
'''
«FOR referenceProperty : getContainmentReferencesAtPosition(message.referenceLinks.map[it as ReferenceTreatment], 1)»
«generateContainmentSegment(referenceProperty, message, api)»
«ENDFOR»
'''
}
def private generateContainmentSegment(ReferenceProperty referenceProperty, TypedMessage message, ResourceAPI api) {
generateContainmentSegment(#[referenceProperty], message, api)
}
def private String generateContainmentSegment(List path, TypedMessage message, ResourceAPI api) {
val currentType = path.findLast[].type;
val levelOfContainment = path.length
val elementProperties = Iterables.concat(
currentType.ownedFeatures.filterForElements,
message.referenceLinks.filter[startsWithPath(path)].filter[containmentDepth < levelOfContainment + 1]
)
val attributeProperties = currentType.ownedFeatures.
filterForAttributes
'''
«elementProperties.generateAllBlock(message, api)»
«attributeProperties.generateAttributeDecls(api)»
«FOR referenceProperty : getContainmentReferencesAtPosition(message.referenceLinks.map[it as ReferenceTreatment], levelOfContainment + 1)»
«generateContainmentSegment(path.concat(referenceProperty), message, api)»
«ENDFOR»
'''
}
//
// ReferenceEmbed generation - for both Resources and Messages
//
def private generateContainersForReferenceEmbeds(String name, EObject obj,
Iterable referenceTreatments, ResourceAPI api) {
'''
«FOR referenceEmbed : referenceTreatments.filter(ReferenceEmbed)»
«referenceEmbed.generateContainersForReferenceEmbed(name, obj, api)»
«ENDFOR»
'''
}
def private String generateContainersForReferenceEmbed(ReferenceEmbed referenceEmbed, String name, EObject obj,
ResourceAPI api) {
val path = getPathTo(referenceEmbed)
'''
«path.generateEmbedSegment(name, obj, referenceEmbed)»
«FOR childReferenceEmbed : referenceEmbed.nestedReferenceTreatments.filter(ReferenceEmbed)»
«childReferenceEmbed.generateContainersForReferenceEmbed(name, obj, api)»
«ENDFOR»
'''
}
def private List getPathTo(ReferenceEmbed referenceEmbed) {
val Collection containers = Lists.newArrayList
val Collection references = Lists.newArrayList
references.addAll(referenceEmbed.containmentReferences)
if (referenceEmbed.eContainer.eContainer instanceof ReferenceEmbed) {
containers.addAll(getPathTo(referenceEmbed.eContainer.eContainer as ReferenceEmbed))
}
references.add(referenceEmbed.referenceElement as ReferenceProperty)
Iterables.concat(containers, references).toList
}
def private generateEmbedSegment(List path, String baseName, EObject obj,
ReferenceEmbed referenceEmbed) {
val elementProperties = Iterables.concat(
referenceEmbed.linkDescriptor.allIncludedProperties.map[baseProperty].filterForElements,
referenceEmbed.nestedReferenceTreatments.filter(ReferenceLink),
referenceEmbed.nestedReferenceTreatments.filter(ReferenceEmbed)
)
val attributeProperties = referenceEmbed.linkDescriptor.allIncludedProperties.map[baseProperty].
filterForAttributes
'''
«IF referenceEmbed.linkDescriptor !== null»
«elementProperties.generateAllBlock(obj, obj.resourceAPI)[
switch it {
ReferenceEmbed: {
val nextSegment = it.referenceElement as ReferenceProperty
nextSegment.generateNestedReference(extend(baseName, path.concat(nextSegment)))
}
default:
null
}
]»
«attributeProperties.generateAttributeDecls(obj.resourceAPI)»
«ENDIF»
'''
}
//
// Generators for properties in within complex types
//
def private dispatch String generatePropertyDecl(EObject prop, EObject context, ResourceAPI api,
boolean asElement) {
throw new IllegalArgumentException('''Cannot gernerate property decl for «prop?.class» in context «context?.class»''')
}
def private dispatch String generatePropertyDecl(PrimitiveProperty prop, EObject context, ResourceAPI api,
boolean asElement) {
if (asElement) {
if (prop.
isMultiValued) {
'''
'''
} else {
''' '''
}
} else {
if (prop.isMultiValued) {
throw new IllegalArgumentException("Cannot declare multi-valued property as a schema attribute");
}
'''
'''
}
}
def private dispatch String generatePropertyDecl(PropertyRealization property, EObject context, ResourceAPI api,
boolean asElement) {
switch (property.baseProperty) {
PrimitiveProperty:
if (asElement) {
if (property.
isMultiValued) {
'''
'''
} else {
''' '''
}
} else {
if (property.isMultiValued) {
throw new IllegalArgumentException("Cannot declare multi-valued property as a schema attribute")
}
'''
«IF !property.allConstraints.nullOrEmpty»
«property.basePrimitiveProperty.getTypeName(api).generateRestriction(property.allConstraints)»
«ENDIF»
'''
}
ReferenceProperty:
property.generateReferenceProperty(context, api, #[])
}
}
def private dispatch String generatePropertyDecl(ReferenceLink link, EObject context, ResourceAPI api,
boolean asElement) {
val ReferenceElement referenceProperty = link.referenceProperty
val ObjectRealization linkDescriptor = link.linkDescriptor
val elementProperties = Iterables.concat(
#[link],
linkDescriptor?.allIncludedProperties?.map[baseProperty]?.primitiveProperties?.filterForElements ?: #[]
)
val attributeProperties = linkDescriptor?.allIncludedProperties?.map[baseProperty]?.primitiveProperties?.
filterForAttributes ?: #[]
if (referenceProperty.
isMultiValued) {
'''
«elementProperties.generateAllBlock(context, api) [
switch it {
ReferenceLink: it.generateAtomLink
default: null
}
]»
«attributeProperties.generateAttributeDecls(api)»
'''
} else {
'''
«elementProperties.generateAllBlock(context, api)[
switch it {
ReferenceLink: it.generateAtomLink
default: null
}
]»
«attributeProperties.generateAttributeDecls(api)»
'''
}
}
def private dispatch String generatePropertyDecl(ReferenceEmbed embed, EObject context, ResourceAPI api,
boolean asElement) {
val baseName = switch context {
TypedMessage: context.typeName
ServiceDataResource: context.name
}
val complexTypeName = baseName.extend(#[embed.referenceElement])
generateNestedReference(embed.referenceElement, complexTypeName)
}
def private dispatch String generatePropertyDecl(ReferenceProperty prop, EObject context, ResourceAPI api,
boolean asElement) {
prop.generateReferenceProperty(context, api, #[])
}
def private dispatch String generateReferenceProperty(PropertyRealization referenceProperty,
ServiceDataResource resource, ResourceAPI api, List path) {
if (referenceProperty.baseReferenceProperty.isPropertyOverridenByReferenceLink(resource, path)) {
referenceProperty.generateContainmentProperty(
resource.typeName.extend(path.concat(referenceProperty.baseReferenceProperty)))
}
}
def private dispatch String generateReferenceProperty(ReferenceProperty referenceProperty,
ServiceDataResource resource, ResourceAPI api, List path) {
if (isPropertyOverridenByReferenceLink(referenceProperty, resource, path)) {
referenceProperty.generateNestedReference(resource.typeName.extend(path.concat(referenceProperty)))
}
}
def private dispatch generateReferenceProperty(ReferenceProperty referenceProperty, TypedMessage message,
ResourceAPI api, List path) {
if (isPropertyOverridenByReferenceLink(referenceProperty, message, path)) {
referenceProperty.generateNestedReference(message.typeName.extend(path.concat(referenceProperty)))
}
}
//
// Nested references
//
def private String generateNestedReference(ReferenceElement referenceElement, String typeName) {
if (!referenceElement.isMultiValued)
referenceElement.generateSimpleNestedReference(typeName)
else
referenceElement.generateMultiNestedReference(typeName)
}
def private String generateSimpleNestedReference(ReferenceElement referenceElement,
String typeName) {
'''
'''
}
def private String generateMultiNestedReference(ReferenceElement referenceElement,
String typeName) {
'''
'''
}
//
// Containment
//
def private String generateContainmentProperty(PropertyRealization property, String typeName) {
if (!property.isMultiValued) {
property.generateSimpleContainmentProperty(typeName)
} else {
property.generateMultiContainmentProperty(typeName)
}
}
def private String generateSimpleContainmentProperty(PropertyRealization property,
String typeName) {
'''
'''
}
def private String generateMultiContainmentProperty(PropertyRealization property,
String typeName) {
'''
'''
}
//
// Miscellaneous
//
def private String generateAtomImports(ResourceAPI api) {
'''
'''
}
def private String generateAtomLink(ReferenceLink referenceLink) {
if (referenceLink.targetResource !== null) '''
'''
}
def private dispatch String generateReferenceProperty(PropertyRealization referenceProperty, TypedMessage message,
ResourceAPI api, List path) {
if (referenceProperty.baseReferenceProperty.isPropertyOverridenByReferenceLink(message, path)) {
generateContainmentProperty(referenceProperty,
message.typeName.extend(path.concat(referenceProperty.baseReferenceProperty)))
}
}
def private getPropertyUse(PropertyRealization property) {
if(property.isRequired) 'required' else 'optional'
}
def private generateForStructure(Structure structure, ResourceAPI api) {
if (resourceFinder.findResource(structure, true) === null) {
val elementProperties = structure.ownedFeatures.filter[isPrimitiveProperty].filterForElements
val attrProperties = structure.ownedFeatures.filterForAttributes
'''
«structure.generateXSDDoc»
«elementProperties.generateAllBlock(structure, api)»
«attrProperties.generateAttributeDecls(api)»
'''
}
}
def private dispatch String generateAttributeDecls(ReferenceEmbed embed, ResourceAPI api) {
embed.linkDescriptor.generateAttributeDecls(api);
}
def private dispatch String generateAttributeDecls(ObjectRealization objectRealization, ResourceAPI api) {
objectRealization.allIncludedProperties.primitiveSingleProperties.generateAttributeDecls(api)
}
def private dispatch String generateAttributeDecls(Iterable properties, ResourceAPI api) {
'''
«FOR property : properties SEPARATOR ""»
«property.generatePropertyDecl(api, api, false)»
«ENDFOR»
'''
}
def private ReferenceProperty getBaseReferenceProperty(PropertyRealization property) {
property.baseProperty as ReferenceProperty
}
def private PrimitiveProperty getBasePrimitiveProperty(PropertyRealization property) {
property.baseProperty as PrimitiveProperty
}
def private dispatch ResourceAPI getResourceAPI(TypedMessage message) {
message.getEContainer(Method).containingResourceDefinition.resourceAPI
}
def private dispatch ResourceAPI getResourceAPI(ResourceDefinition resource) {
resource.eContainer as ResourceAPI
}
def private List concat(List list, T value) {
val copy = Lists.newArrayList(list)
copy.add(value)
return copy
}
def private Iterable filterForElements(Iterable properties) {
properties.filter[eltStyle || !it.isAttributeEligible].map[it as EObject]
}
def private Iterable filterForAttributes(Iterable properties) {
properties.filter[attrStyle && it.isAttributeEligible].map[it as EObject]
}
def private boolean isAttributeEligible(EObject property) {
switch property {
Feature: property.isPrimitiveProperty && property.isSingleValued
PropertyRealization: property.baseProperty.isPrimitiveProperty && property.isSingleValued
default: throw new IllegalArgumentException
}
}
}