Download this file

KDMtoUML.atl    757 lines (687 with data), 25.3 kB

-- @atlcompiler atl2006 
-- @nsURI uml=http://www.eclipse.org/uml2/2.1.0/UML
-- @nsURI kdm=http://www.eclipse.org/MoDisco/kdm
--authors: Gabriel Barbier, Mia-Software, gbarbier@mia-software.com 
--Transform KDM Models to UML 2.1 models

module KDMtoUML; 
create OUT : uml from IN : kdm;

-- specific case to attach all single elements to root model
entrypoint rule initExternalElementsContainer() {
--	to externalPackage :uml!Package(
--		name <- 'detached elements'
--		,packagedElement <- externalClass
--	)
--	,externalClass :uml!Class(
--		name <- 'detached elements'
--	)
--	do {
--		thisModule.externalPackage <- externalPackage;
--		thisModule.externalClass <- externalClass;
--	}
}

helper def : findExternalPackage() : kdm!CodeModel =
	kdm!Segment.allInstances()->select(e | e.refImmediateComposite().oclIsUndefined())
		->collect(e | e.model)->flatten()
		->select(e | e.name = 'externals')
		-->collect(e | e.codeElement)->flatten()
		-->select(e | e.name = 'detached elements')
		->first();

endpoint rule manageDetachedElements() {

  do {
  		if (not thisModule->findExternalPackage().oclIsUndefined()) {
  			thisModule.externalPackage <- thisModule.resolveTemp(thisModule->findExternalPackage(), 'tgt');
			for (detachedClass in thisModule->findExternalPackage().codeElement) {
				if (detachedClass.name = 'detached elements') {
					thisModule.externalClass <- thisModule.resolveTemp(detachedClass, 'tgt');
				}
			}
			for (alone in uml!Element.allInstances()) {
  				if (not (alone.oclIsTypeOf(uml!Model))) {
  					if (alone.refImmediateComposite().oclIsUndefined()) {
  						if (alone.oclIsKindOf(uml!PackageableElement)) {
  							thisModule.externalPackage.packagedElement <- alone;
  						} else {
  							if (not thisModule.externalClass.oclIsUndefined()) {
  								if (alone.oclIsKindOf(uml!Generalization)) {
  									thisModule.externalClass.generalization <- alone;
  								}
  								if (alone.oclIsKindOf(uml!Operation)) {
  									thisModule.externalClass.ownedOperation <- alone;
  								}
  								if (alone.oclIsKindOf(uml!Property)) {
	  								thisModule.externalClass.ownedAttribute <- alone;
  								}
  							}
  						}
  					}
  				}
  			}
  		}  		
   }
}

helper def: externalPackage : uml!Package = OclUndefined;
helper def: externalClass : uml!Class = OclUndefined;

--------------------------Helpers--------------------------------------------------------------------------------------------------

helper context kdm!Element def : getVisibility() : uml!VisibilityKind = 
	if (self.oclIsTypeOf(kdm!MethodUnit)) then
		self->getMethodVisibility()
	else
		if (self.oclIsTypeOf(kdm!Datatype)) then
			self->getDatatypeVisibility()
		else
			#public
		endif
	endif;

helper context kdm!MethodUnit def : getMethodVisibility() : uml!VisibilityKind =
	if (self.export = #private) then
		#private
	else
		if (self.export = #protected) then
			#protected
		else
			#public
		endif
	endif;

helper context kdm!Datatype def : getDatatypeVisibility() : uml!VisibilityKind = 
	let attribute : kdm!Attribute = self.attribute->select(e | e.tag = 'visibility')->first() in
		if (attribute.oclIsUndefined()) then
			#public
		else
			let value : String = attribute.value in
			if (value = 'private') then
				#private
			else
				if (value = 'protected') then
					#protected
				else
					#public
				endif
			endif
		endif;

helper context kdm!DataElement def : getLowerCardinality() : Integer =
	let attribute : kdm!Attribute = self.attribute->select(e | e.tag = 'inheritance')->first() in
		if (attribute.oclIsUndefined()) then
			0
		else
			if (attribute.value = 'final') then
				1
			else
				0
			endif
		endif;

-- depends on type of DataElement
helper context kdm!DataElement def : getUpperCardinality() : Integer =
	if (not self.size.oclIsUndefined()) then
		self.size
	else
		if (not self.type.oclIsUndefined()) then
			if (self.type.oclIsKindOf(kdm!ArrayType)) then
				-1
			else
				if (self.type.oclIsTypeOf(kdm!TemplateType)) then
					if (self.type->isCollection() or self.type->isMap()) then
						-1
					else
						1
					endif
				else
					1
				endif
		    endif
		else
			1
		endif
	endif;

helper context kdm!Datatype def : isCollection() : Boolean =
	if (self.name.oclIsUndefined()) then
	false
	else
	if (self.name->startsWith('Collection')) then
		true
	else
		if (self.oclIsTypeOf(kdm!TemplateType)) then
			self->getTemplateUnit()->isCollection()
		else
			if (self.oclIsTypeOf(kdm!TemplateUnit)) then
				self->getRealType()->isCollection()
			else
				if (self->getInheritanceLinks()->isEmpty()) then
					false
				else
					let parents : Sequence(kdm!AbstractCodeRelationship) = self->getInheritanceLinks() in
						parents->exists(parent | parent.to->isCollection())
				endif
			endif
		endif
	endif
	endif;

helper context kdm!Datatype def : isMap() : Boolean =
	if (self.name.oclIsUndefined()) then
	false
	else
	if (self.name->startsWith('Map')) then
		true
	else
		if (self.oclIsTypeOf(kdm!TemplateType)) then
			self->getTemplateUnit()->isMap()
		else
			if (self.oclIsTypeOf(kdm!TemplateUnit)) then
				self->getRealType()->isMap()
			else
				if (self->getInheritanceLinks()->isEmpty()) then
					false
				else
					let parents : Sequence(kdm!AbstractCodeRelationship) = self->getInheritanceLinks() in
						parents->exists(parent | parent.to->isMap())
				endif
			endif
		endif
	endif
	endif;


helper context kdm!Datatype def : getInheritanceLinks() : Sequence(kdm!AbstractCodeRelationship) = 
	if ((self.oclIsTypeOf(kdm!EnumeratedType)) or (self.oclIsTypeOf(kdm!ClassUnit))
			or (self.oclIsTypeOf(kdm!InterfaceUnit)) or (self.oclIsTypeOf(kdm!TemplateUnit))) then
		self.codeRelation->select(e | e.oclIsTypeOf(kdm!Extends) or e.oclIsTypeOf(kdm!Implements))
	else
		Sequence{}
	endif;
	
	
helper context kdm!TemplateType def : getTemplateUnit() : kdm!Datatype =
	let link : kdm!InstanceOf = self.codeRelation->select(e | e.oclIsTypeOf(kdm!InstanceOf))->first() in
	if (link.oclIsUndefined()) then
		OclUndefined
	else
		if (link.to.oclIsUndefined()) then
			let otherLink : kdm!HasType = self.codeRelation->select(e | e.oclIsTypeOf(kdm!HasType))->first() in
			if (otherLink.oclIsUndefined()) then
				OclUndefined
			else
				otherLink.to
			endif
		else
			link.to
		endif
	endif;

helper context kdm!TemplateUnit def : getRealType() : kdm!CodeItem =
	self.codeElement->select(e | not e.oclIsTypeOf(kdm!TemplateParameter))->first();

helper context kdm!InterfaceUnit def : getRealType() : kdm!Datatype =
	self;

helper context kdm!ClassUnit def : getRealType() : kdm!Datatype =
	self;

helper context kdm!CodeItem def : getPackageContainer() : kdm!Package =
	if (self.refImmediateComposite().oclIsTypeOf(kdm!Package)) then
		self.refImmediateComposite()
	else
		if (self.refImmediateComposite().oclIsKindOf(kdm!CodeItem)) then
			self.refImmediateComposite()->getPackageContainer()
		else
			thisModule->findExternalPackage()
		endif
	endif;

helper context kdm!DataElement def : getDataElementType() : kdm!Datatype =
	if (self.type.oclIsTypeOf(kdm!TemplateType)) then
		if (self.type->isCollection() or self.type->isMap()) then
			self.type->getTemplateTypeBinding()
		else
			self.type
		endif
	else
		if (self.type.oclIsTypeOf(kdm!ArrayType)) then
			self.type.itemUnit.type
		else
			self.type
		endif
	endif;
helper context kdm!DataElement def : getDataElementQualifierType() : kdm!Datatype =
	if (self.type.oclIsTypeOf(kdm!TemplateType)) then
		if (self.type->isMap()) then
			self.type.codeRelation->select(e | e.oclIsTypeOf(kdm!ParameterTo))->first().to
		else
			OclUndefined
		endif
	else
		OclUndefined
	endif;

helper context kdm!TemplateType def : getTemplateTypeBinding() : kdm!Datatype =
	let parameter : kdm!ParameterTo = self.codeRelation->select(e | e.oclIsTypeOf(kdm!ParameterTo))->last() in
		if (parameter.to.oclIsTypeOf(kdm!TemplateType)) then
			if (parameter.to->isCollection() or parameter.to->isMap()) then
				parameter.to->getTemplateTypeBinding()
			else
				parameter.to
			endif
		else
			parameter.to
		endif;

helper context kdm!Datatype def : isPrimitiveType() : Boolean =
	if (self.oclIsUndefined() or (self.oclIsKindOf(kdm!PrimitiveType))) then
		true
	else
		-- specific case for primitive objects
		if ((self.name = 'String') or (self.name = 'Integer') 
				or (self.name = 'Long') or (self.name = 'Short')
				or (self.name = 'Float') or (self.name = 'Double')
				or (self.name = 'Boolean') or (self.name = 'Number')) then
			true
		else
			false
		endif
	endif;
	
--------------------------End-Helpers-----------------------------------------------------------------------------------------------------------------------------------------



--------------------------Rules-----------------------------------------------------------------------------------------------------------------------------------------------

rule SegmentToRootModel {
	from src :kdm!Segment
	to tgt :uml!Model(
		name<- if (src.name.oclIsUndefined()) then 'root model' else src.name endif
		,packagedElement<-src.segment
		,packagedElement<-src.model
		,packagedElement<-src.extension
		-- contains external elements
--		,packagedElement<- if (src.refImmediateComposite().oclIsUndefined()) then
--								thisModule.externalPackage
--							else Sequence{} endif
	)
}

rule ExtensionFamilyToProfile {
	from src :kdm!ExtensionFamily
	to tgt :uml!Profile (
		name <- src.name
		,packagedElement <- src.annotation
		,packagedElement <- src.attribute
		,packagedElement <- src.stereotype
	)
}

rule KDMModelToModel {
	from src :kdm!KDMModel
	to tgt :uml!Model (
		name <- src.name
		,packagedElement <- src.extension
		,packagedElement <- src.ownedElement
	)
}

--------------------------------End-Rules------------------------------------

-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################

-- Specific rules for source package in KDM metamodel------------------------

rule InventoryModelToModel extends KDMModelToModel {
	from src :kdm!InventoryModel
	to tgt :uml!Model (
		packagedElement <- src.inventoryElement
	)
}

--rule SourceFileToArtifact extends KDMEntityToNamedElement {
--	from src :kdm!SourceFile
--	to tgt :uml!Artifact (
--		fileName <- src.path
--	)
--}

rule InventoryItemToArtifact extends KDMEntityToNamedElement {
	from src :kdm!InventoryItem
	to tgt :uml!Artifact (
		fileName <- src.path
	)
}
rule InventoryContainerToPackage extends KDMEntityToNamedElement {
	from src :kdm!InventoryContainer
	to tgt :uml!Package (
		packagedElement <- src.inventoryElement
	)
}
--------------------------------End-Rules------------------------------------

-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################

---Specific rules for code package in KDM metamodel--------------------------

rule CodeModelToModel extends KDMModelToModel {
	from src :kdm!CodeModel
	to tgt :uml!Model (
		packagedElement <- src.codeElement
	)
}

abstract rule KDMEntityToNamedElement {
	from src :kdm!KDMEntity
	to tgt :uml!NamedElement (
		name <- src.name
		,visibility <- src->getVisibility()
	)
}

-- to manage LanguageUnit and Package
rule ModuleToPackage extends KDMEntityToNamedElement {
	from src :kdm!Module
	to tgt :uml!Package (
		packagedElement <- src.codeElement
	)
}

-- to manage all primitive types (Boolean, Integer, Void, ...)
rule PrimitiveTypeToPrimitiveType extends KDMEntityToNamedElement {
	from src :kdm!PrimitiveType
	to tgt :uml!PrimitiveType ()
}

-- we have to filter dummy class only needed in kdm to manage behaviour element in StorableUnit
rule ClassUnitToClass extends KDMEntityToNamedElement {
	from src :kdm!ClassUnit (
		not src.refImmediateComposite().oclIsTypeOf(kdm!TemplateUnit)
		and not (src.refImmediateComposite().oclIsTypeOf(kdm!StorableUnit))
		
	)
	to tgt :uml!Class (
		isAbstract <- src.isAbstract
		-- specific case to manage templated methods (encapsulated in a TemplateUnit)
		,nestedClassifier <- src.codeElement->select(e | e.oclIsKindOf(kdm!Datatype))
				->select(e | if (e.oclIsTypeOf(kdm!TemplateUnit)) then not (e->getRealType().oclIsTypeOf(kdm!MethodUnit)) else true endif)
		,generalization <- src.codeRelation->select(e | e.oclIsTypeOf(kdm!Extends))
		,interfaceRealization <- src.codeRelation->select(e | e.oclIsTypeOf(kdm!Implements))
		,ownedOperation <- src.codeElement->select(e | e.oclIsTypeOf(kdm!MethodUnit))
		,ownedAttribute <- src.codeElement->select(e | e.oclIsKindOf(kdm!DataElement))
	)
}

rule InterfaceUnitToInterface extends KDMEntityToNamedElement {
	from src :kdm!InterfaceUnit (not src.refImmediateComposite().oclIsTypeOf(kdm!TemplateUnit))
	to tgt :uml!Interface (
		-- specific case to manage templated methods (encapsulated in a TemplateUnit)
		nestedClassifier <- src.codeElement->select(e | e.oclIsKindOf(kdm!Datatype))
				->select(e | if (e.oclIsTypeOf(kdm!TemplateUnit)) then not (e->getRealType().oclIsTypeOf(kdm!MethodUnit)) else true endif)
		,generalization <- src.codeRelation->select(e | e.oclIsTypeOf(kdm!Extends))
		,ownedOperation <- src.codeElement->select(e | e.oclIsTypeOf(kdm!MethodUnit))
		,ownedAttribute <- src.codeElement->select(e | e.oclIsKindOf(kdm!DataElement))
	)
}

rule EnumeratedTypeToEnumeration extends KDMEntityToNamedElement {
	from src :kdm!EnumeratedType
	to tgt :uml!Enumeration (
		ownedLiteral <- src.value
	)
}


abstract rule TemplateUnitToTemplateableElement {
	from src :kdm!TemplateUnit
--	to tgt :uml!TemplateableElement (
--		ownedTemplateSignature <- signature
--	)
	to signature :uml!RedefinableTemplateSignature (
		name <- src.name
		,ownedParameter <- src.codeElement->select(e | e.oclIsTypeOf(kdm!TemplateParameter))
								->collect(parameter | thisModule->TemplateParameterToClassifierTemplateParameter(parameter))
	)
}

lazy rule TemplateParameterToClassifierTemplateParameter {
	from src :kdm!TemplateParameter
	to tgt :uml!ClassifierTemplateParameter (
		-- name is not managed in UML
		ownedParameteredElement <- parameter
	)
	, parameter :uml!Class (
		name <- src.name
	)
}

rule TemplateUnitToClass extends TemplateUnitToTemplateableElement {
	from src :kdm!TemplateUnit (
		src->getRealType().oclIsTypeOf(kdm!ClassUnit)
		)
	using {
		realType :kdm!Datatype = src->getRealType();
	}
	to tgt :uml!Class (
		name <- realType.name
		,isAbstract <- realType.isAbstract
		-- specific case to manage templated methods (encapsulated in a TemplateUnit)
		,nestedClassifier <- realType.codeElement->select(e | e.oclIsKindOf(kdm!Datatype))
				->select(e | if (e.oclIsTypeOf(kdm!TemplateUnit)) then not (e->getRealType().oclIsTypeOf(kdm!MethodUnit)) else true endif)
		,generalization <- realType.codeRelation->select(e | e.oclIsTypeOf(kdm!Extends))
		,interfaceRealization <- realType.codeRelation->select(e | e.oclIsTypeOf(kdm!Implements))
		,ownedOperation <- realType.codeElement->select(e | e.oclIsTypeOf(kdm!MethodUnit))
		,ownedAttribute <- realType.codeElement->select(e | e.oclIsKindOf(kdm!DataElement))
	)
}

rule TemplateUnitToInterface extends TemplateUnitToTemplateableElement {
	from src :kdm!TemplateUnit (
		src->getRealType().oclIsTypeOf(kdm!InterfaceUnit)
		)
	using {
		realType :kdm!Datatype = src->getRealType();
	}
	to tgt :uml!Interface (
		name <- realType.name
		-- specific case to manage templated methods (encapsulated in a TemplateUnit)
		,nestedClassifier <- realType.codeElement->select(e | e.oclIsKindOf(kdm!Datatype))
				->select(e | if (e.oclIsTypeOf(kdm!TemplateUnit)) then not (e->getRealType().oclIsTypeOf(kdm!MethodUnit)) else true endif)
		,generalization <- realType.codeRelation->select(e | e.oclIsTypeOf(kdm!Extends))
		,ownedOperation <- realType.codeElement->select(e | e.oclIsTypeOf(kdm!MethodUnit))
		,ownedAttribute <- realType.codeElement->select(e | e.oclIsKindOf(kdm!DataElement))
	)
}

rule ExtendsToGeneralization {
	from src :kdm!Extends
	to tgt :uml!Generalization (
		general <- src.to
	)
}

rule ImplementsToInterfaceRealization {
	from src :kdm!Implements
	to tgt :uml!InterfaceRealization (
		contract <- if (src.to.oclIsTypeOf(kdm!ClassUnit)) then OclUndefined else src.to endif
	)
	do {
		if (src.to.oclIsTypeOf(kdm!ClassUnit)) {
			src.from->debug('Invalid implements, from ');
			src.to->debug('to ');
		}
	}
}

rule ImportsToDependency {
	from src :kdm!Imports
	to tgt :uml!Dependency (
		client <- src.from
		,supplier <- src.to
	)
	do {
		-- store the created dependency in first parent package of client element
		thisModule.resolveTemp(src.from->getPackageContainer(), 'tgt').packagedElement <- tgt;
	}
}

rule TemplateTypeToInterface {
	from src : kdm ! TemplateType (
		if (src->getTemplateUnit() = OclUndefined) then
			false
		else
			src->getTemplateUnit()->getRealType().oclIsTypeOf(kdm!InterfaceUnit)
		endif
	)
	to tgt :uml!Interface(
		name<-src.name
		,templateBinding <- src.codeRelation->select(e | e.oclIsTypeOf(kdm!ParameterTo))
	)
	do {
		thisModule.resolveTemp(src->getTemplateUnit()->getPackageContainer(), 'tgt').packagedElement <- tgt;
	}
}

rule TemplateTypeToClass {
	from src : kdm ! TemplateType (
		if (src->getTemplateUnit() = OclUndefined) then
			false
		else
			not src->getTemplateUnit()->getRealType().oclIsTypeOf(kdm!InterfaceUnit)
		endif		
	)
	to tgt :uml!Class(
		name<-src.name
		,templateBinding <- src.codeRelation->select(e | e.oclIsTypeOf(kdm!ParameterTo))
	)
	do {
		thisModule.resolveTemp(src->getTemplateUnit()->getPackageContainer(), 'tgt').packagedElement <- tgt;
	}
}

rule ParameterToToTemplateBinding {
	from src :kdm!ParameterTo (src.from->getTemplateUnit().oclIsTypeOf(kdm!TemplateUnit))
	to tgt :uml!TemplateBinding (
		signature <- thisModule.resolveTemp(src.from->getTemplateUnit(), 'signature')
		,parameterSubstitution <- substitution
	)
	, substitution :uml!TemplateParameterSubstitution (
--		actual <- src.to
		--,formal <- src.from->getTemplateUnit().codeElement->at(src.from.codeRelation->indexOf(src))
	)
	do {
		substitution.formal <- tgt.signature.ownedParameter->at(src.from.codeRelation->indexOf(src));
	}
}
--------------------------------End-Rules------------------------------------

-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################

---Specific rules for code package in KDM metamodel, dedicated to members----

rule ValueToEnumerationLiteral {
	from src :kdm!Value (src.refImmediateComposite().oclIsTypeOf(kdm!EnumeratedType))
	to tgt :uml!EnumerationLiteral (
		name <- src.name
	)
}

-- we have to filter dummy operations (needed in KDM to store behaviour)
rule MethodUnitToOperation extends KDMEntityToNamedElement {
	from src :kdm!MethodUnit (
		not src.refImmediateComposite().oclIsTypeOf(kdm!TemplateUnit)
		and not (src.type.oclIsUndefined())
		and not (src.refImmediateComposite().oclIsTypeOf(kdm!CodeModel)) -- Unresolved items
	)
	to tgt :uml!Operation (
		ownedParameter <- src.type.parameterUnit
	)
}

rule TemplateUnitToOperation extends TemplateUnitToTemplateableElement {
	from src :kdm!TemplateUnit (
		src->getRealType().oclIsTypeOf(kdm!MethodUnit)
	)
	using {
		realType :kdm!MethodUnit = src->getRealType();
	}
	to tgt :uml!Operation (
		name <- realType.name
		,visibility <- src->getVisibility()
		,ownedParameter <- realType.type.parameterUnit
	)
}

rule ParameterUnitToParameter extends KDMEntityToNamedElement {
	from src :kdm!ParameterUnit
	to tgt :uml!Parameter (
		direction <- if (src.kind = #return) then #return else OclUndefined endif
--		,type <- src->getDataElementType()
		,lowerValue <- lower
		,upperValue <- upper
	)
	, lower : uml!LiteralInteger (
		value <- src.getLowerCardinality()
	)
	, upper : uml! LiteralUnlimitedNatural (
		value <- src.getUpperCardinality()
	)
}

rule MemberUnitToProperty extends KDMEntityToNamedElement {
	from src :kdm!MemberUnit
	to tgt :uml!Property (
		type <- src->getDataElementType()
		,lowerValue <- lower
		,upperValue <- upper
	)
	, lower : uml!LiteralInteger (
		value <- src.getLowerCardinality()
	)
	, upper : uml! LiteralUnlimitedNatural (
		value <- src.getUpperCardinality()
	)
	do {
		if (not (src->getDataElementType().oclIsUndefined())) {
			if (not (src->getDataElementType()->isPrimitiveType())) {
				thisModule->DataElementToAssociation(src);
			}
			if (not (src->getDataElementQualifierType().oclIsUndefined())) {
				tgt.qualifier <- thisModule.DatatypeToProperty(src->getDataElementQualifierType());
			}
		}
	}
}

rule StorableUnitToProperty extends KDMEntityToNamedElement {
	from src :kdm!StorableUnit (not (src.kind = #local)
		and not (src.refImmediateComposite().oclIsTypeOf(kdm!CodeModel))) -- Unresolved items
	to tgt :uml!Property (
--		type <- src->getDataElementType(),
		isStatic <- if (src.kind = #static) then true else false endif
		,lowerValue <- lower
		,upperValue <- upper
	)
	, lower : uml!LiteralInteger (
		value <- src.getLowerCardinality()
	)
	, upper : uml! LiteralUnlimitedNatural (
		value <- src.getUpperCardinality()
	)
	do {
		if (not (src->getDataElementType().oclIsUndefined())) {
			if (not (src->getDataElementType()->isPrimitiveType())) {
				thisModule->DataElementToAssociation(src);
			}
			if (not (src->getDataElementQualifierType().oclIsUndefined())) {
				tgt.qualifier <- thisModule.DatatypeToProperty(src->getDataElementQualifierType());
			}
		}
	}
}

lazy rule DataElementToAssociation {
	from src :kdm!DataElement
	to tgt :uml!Association (
		memberEnd<- src
		,memberEnd <- targetProperty
		,ownedEnd <- targetProperty
	)
	, targetProperty :uml!Property (
--		type <- src.refImmediateComposite()
	)
	do {
		thisModule.resolveTemp(src->getPackageContainer(), 'tgt').packagedElement <- tgt;
	}
}

-- to create qualifier for a parent property
lazy rule DatatypeToProperty {
	from src :kdm!Datatype
	to tgt :uml!Property (
		name <- 'qualifier'
		,type <- src
	)
}
--------------------------------End-Rules------------------------------------