-- @atlcompiler emftvm -- @nsURI UML2=http://www.eclipse.org/uml2/3.0.0/UML -- $Id$ -- Implements the Observer profile. module UML2JavaObserver; create OUT : UML2 from IN : UML2, IMPLTYPES : UML2, UML2TYPES : UML2; uses "lib::Strings"; uses "lib::UML2"; uses "lib::Mappings"; uses UML2Copy; -- ====================================================================== -- model-specific helpers begin -- ====================================================================== helper def : language : String = 'language'.value(); helper def : separator : String = 'separator'.value(); helper def : Observer : UML2!"uml::Interface" = 'java::util::Observer'.interface().debug('Observer'); helper def : Observable : UML2!"uml::Class" = 'java::util::Observable'.class().debug('Observable'); helper def : ObserverName : String = thisModule.Observer.qualifiedName('separator'.value()).debug('ObserverName'); helper def : oclString : UML2!"uml::PrimitiveType" = 'String'.primitiveType(); helper def : oclAny : UML2!"uml::PrimitiveType" = 'OclAny'.primitiveType(); helper context UML2!"uml::Classifier" def : isObservable : Boolean = not self.getAppliedStereotype('Observer::Observable').oclIsUndefined(); helper context UML2!"uml::Classifier" def : isObserver : Boolean = not self.getAppliedStereotype('Observer::Observer').oclIsUndefined(); helper context UML2!"uml::Association" def : isSubscribe : Boolean = not self.getAppliedStereotype('Observer::subscribe').oclIsUndefined(); helper context UML2!"uml::Dependency" def : isAccessor : Boolean = not self.getAppliedStereotype('Accessors::accessor').oclIsUndefined(); helper context UML2!"uml::Dependency" def : accessor : UML2!"uml::Stereotype" = self.getAppliedStereotype('Accessors::accessor'); helper context UML2!"uml::Behavior" def : isNotifyMethod : Boolean = self.specification.isAccessor and self.owner.isObservableKind; helper context UML2!"uml::Behavior" def : isSubscribeMethod : Boolean = self.specification.isAccessor and self.owner.isObserverKind and self.specification.isSubscriber; helper context UML2!"uml::Operation" def : accessorFor : UML2!"uml::Property" = self.accessorDependency.supplier->any(p| p.oclIsKindOf(UML2!"uml::Property")); helper context UML2!"uml::Operation" def : accessorDependency : UML2!"uml::Dependency" = self.clientDependency->any(d|d.isAccessor); helper context UML2!"uml::Operation" def : isAccessor : Boolean = self.clientDependency->exists(d|d.isAccessor); helper context UML2!"uml::Classifier" def : isObservableKind : Boolean = self.isObservable or self.generalization->exists(g|g.general.isObservableKind); helper context UML2!"uml::Classifier" def : isObserverKind : Boolean = self.isObserver or self.generalization->exists(g|g.general.isObserverKind); helper context UML2!"uml::Operation" def : isSubscriber : Boolean = self.isAccessor and self.accessorFor.hasSubscribesAssociation; helper context UML2!"uml::Property" def : hasSubscribesAssociation : Boolean = not self.association.oclIsUndefined() and self.association.isSubscribe; helper context UML2!"uml::Operation" def : notify(body : String) : String = let d : UML2!"uml::Dependency" = self.accessorDependency in -- UML has its own enumeration literal implementations, which are NamedElements let kind : String = d.getValue(d.accessor, 'kind').name in if kind = 'remove' then self.accessorFor.removerNotify(body) else if kind = 'add' or kind = 'insert' then self.accessorFor.adderNotify(body) else if kind = 'set' then self.accessorFor.setterNotify(body) else body endif endif endif; helper context UML2!"uml::Property" def : setterNotify(body : String) : String = self.name.setterNotifyBody( self.type.qualifiedName(thisModule.separator), body, true); helper context UML2!"uml::Property" def : adderNotify(body : String) : String = self.name.adderNotifyBody( self.type.qualifiedName(thisModule.separator), body, self.isUnique, true); helper context UML2!"uml::Property" def : removerNotify(body : String) : String = self.name.removerNotifyBody( self.type.qualifiedName(thisModule.separator), body, true); helper context UML2!"uml::Operation" def : subscribe(body : String) : String = let d : UML2!"uml::Dependency" = self.accessorDependency in -- UML has its own enumeration literal implementations, which are NamedElements let kind : String = d.getValue(d.accessor, 'kind').name in if kind = 'remove' then self.accessorFor.name.removerSubscribeBody(body, true) else if kind = 'add' or kind = 'insert' then self.accessorFor.name.adderSubscribeBody(body) else if kind = 'set' then self.accessorFor.name.setterSubscribeBody(body, true) else body endif endif endif; -- ====================================================================== -- model-specific helpers end -- ====================================================================== -- ====================================================================== -- transformation rules begin -- ====================================================================== rule Class { from s : UML2!"uml::Class" in IN ( s.oclIsTypeOf(UML2!"uml::Class")) to t : UML2!"uml::Class" ( __xmiID__ <- s.__xmiID__, name <- s.name, visibility <- s.visibility, isLeaf <- s.isLeaf, isAbstract <- s.isAbstract, isActive <- s.isActive, eAnnotations <- s.eAnnotations, ownedComment <- s.ownedComment, clientDependency <- s.clientDependency, nameExpression <- s.nameExpression, elementImport <- s.elementImport, packageImport <- s.packageImport, ownedRule <- s.ownedRule, templateParameter <- s.templateParameter, templateBinding <- s.templateBinding, ownedTemplateSignature <- s.ownedTemplateSignature, generalization <- s.generalization, powertypeExtent <- s.powertypeExtent, redefinedClassifier <- s.redefinedClassifier, substitution <- s.substitution, representation <- s.representation, collaborationUse <- s.collaborationUse, ownedUseCase <- s.ownedUseCase, useCase <- s.useCase, ownedAttribute <- s.ownedAttribute, ownedConnector <- s.ownedConnector, interfaceRealization <- s.interfaceRealization, ownedOperation <- s.ownedOperation, ownedBehavior <- s.ownedBehavior ->union(if s.isObserver then Sequence{thisModule.ObserverClass(s)} else Sequence{} endif), classifierBehavior <- s.classifierBehavior, ownedTrigger <- s.ownedTrigger, nestedClassifier <- s.nestedClassifier, ownedReception <- s.ownedReception) } rule ObservableClass extends Class { from s : UML2!"uml::Class" in IN ( s.isObservable) to t : UML2!"uml::Class" ( name <- s.name.debug('ObservableClass'), ownedBehavior <- s.ownedBehavior ->union(if s.isObserver then Sequence{thisModule.ObserverClass(s)} else Sequence{} endif)), -- Observable functionality -- gen : UML2!"uml::Generalization" ( general <- thisModule.Observable, specific <- s) } lazy rule ObserverClass { from s : UML2!"uml::Class" to real : UML2!"uml::InterfaceRealization" ( contract <- thisModule.Observer, implementingClassifier <- s), -- Update -- updateOp : UML2!"uml::Operation" ( name <- 'update'.debug('ObserverClass : ' + s.name), class <- s, visibility <- #public, ownedParameter <- Sequence{updatePar1, updatePar2}, concurrency <- #sequential), updatePar1 : UML2!"uml::Parameter" ( name <- 'o', type <- thisModule.Observable, effect <- #read, direction <- #"in"), updatePar2 : UML2!"uml::Parameter" ( name <- 'arg', type <- thisModule.oclAny, effect <- #update, direction <- #"in"), updateBehavior : UML2!"uml::OpaqueBehavior" ( specification <- updateOp, name <- 'updateBehavior', ownedParameter <- Sequence{updateBPar1, updateBPar2}, language <- Sequence{thisModule.language}, body <- Sequence{'arg'.reflectiveUpdateBody()}), updateBPar1 : UML2!"uml::Parameter" ( name <- 'o', type <- thisModule.Observable, effect <- #read, direction <- #"in"), updateBPar2 : UML2!"uml::Parameter" ( name <- 'arg', type <- thisModule.oclAny, effect <- #update, direction <- #"in") do { updateBehavior; } } rule OpaqueBehavior { from s : UML2!"uml::OpaqueBehavior" in IN ( s.oclIsTypeOf(UML2!"uml::OpaqueBehavior")) to t : UML2!"uml::OpaqueBehavior" ( __xmiID__ <- s.__xmiID__, name <- s.name, visibility <- s.visibility, isLeaf <- s.isLeaf, isAbstract <- s.isAbstract, isActive <- s.isActive, isReentrant <- s.isReentrant, body <- if s.isNotifyMethod then if s.isSubscribeMethod then s.body->collect(b|s.specification.notify(s.specification.subscribe(b))) else s.body->collect(b|s.specification.notify(b)) endif else if s.isSubscribeMethod then s.body->collect(b|s.specification.subscribe(b)) else s.body endif endif, language <- s.language, eAnnotations <- s.eAnnotations, ownedComment <- s.ownedComment, clientDependency <- s.clientDependency, nameExpression <- s.nameExpression, elementImport <- s.elementImport, packageImport <- s.packageImport, ownedRule <- s.ownedRule, templateParameter <- s.templateParameter, templateBinding <- s.templateBinding, ownedTemplateSignature <- s.ownedTemplateSignature, generalization <- s.generalization, powertypeExtent <- s.powertypeExtent, redefinedClassifier <- s.redefinedClassifier, substitution <- s.substitution, representation <- s.representation, collaborationUse <- s.collaborationUse, ownedUseCase <- s.ownedUseCase, useCase <- s.useCase, ownedAttribute <- s.ownedAttribute, ownedConnector <- s.ownedConnector, ownedBehavior <- s.ownedBehavior, classifierBehavior <- s.classifierBehavior, interfaceRealization <- s.interfaceRealization, ownedTrigger <- s.ownedTrigger, nestedClassifier <- s.nestedClassifier, ownedOperation <- s.ownedOperation, ownedReception <- s.ownedReception, redefinedBehavior <- s.redefinedBehavior, ownedParameter <- s.ownedParameter, precondition <- s.precondition, postcondition <- s.postcondition, ownedParameterSet <- s.ownedParameterSet, specification <- s.specification) } -- ====================================================================== -- transformation rules end -- ======================================================================