-- @atlcompiler emftvm -- @nsURI UML2 http://www.eclipse.org/uml2/3.0.0/UML -- @nsURI OWL http:///org/eclipse/owl.ecore -- $Id$ -- Base module for transforming a UML2 model to an API OWL ontology module UML2ToAPIOntology; --abstract create OUT : OWL from IN : UML2, PLATFORM : OWL, ISA : OWL, JAVA : OWL;--, PREVOUT : OWL, PREVIN : UML2; uses UML2Comparison; -- ====================================================================== -- helper attributes begin -- ====================================================================== helper def : UML2ToAPIOntologyVersionString : String = '$Id$'; helper def : inElements : Set(UML2!"ecore::EObject") = UML2!"ecore::EObject".allInstancesFrom('IN'); helper def : prevModels : Set(UML2!"uml::Model") = UML2!"uml::Model".allInstances()->select(m| thisModule.inElements->excludes(m)); helper def : includedPackages : Set(UML2!"uml::Package") = UML2!"uml::Package".allInstancesFrom('IN') ->reject(e|e.isInferred) ->select(p|p.oclIsTypeOf(UML2!"uml::Package")) ->select(p1|p1.packagedElement ->select(c|c.oclIsKindOf(UML2!"uml::Class") or c.oclIsKindOf(UML2!"uml::Interface"))->notEmpty()); helper def : platformPlatform : OWL!"owl::OWLClass" = OWL!"owl::OWLClass".allInstancesFrom('PLATFORM') ->any(o|o.localName = 'Platform'); helper def : javaAPI : OWL!"owl::OWLClass" = OWL!"owl::OWLClass".allInstancesFrom('JAVA') ->any(o|o.localName = 'JavaAPI'); helper def : javaAPIPart : OWL!"owl::OWLClass" = OWL!"owl::OWLClass".allInstancesFrom('JAVA') ->any(o|o.localName = 'JavaAPIPart'); helper def : javaLibrary : OWL!"owl::OWLClass" = OWL!"owl::OWLClass".allInstancesFrom('JAVA') ->any(o|o.localName = 'JavaClassLibrary'); helper def : javaVM : OWL!"owl::OWLClass" = OWL!"owl::OWLClass".allInstancesFrom('JAVA') ->any(o|o.localName = 'JavaVM'); helper def : javaBytecode : OWL!"owl::OWLClass" = OWL!"owl::OWLClass".allInstancesFrom('ISA') ->any(o|o.localName = 'JavaBytecode'); helper def : javaJRE : OWL!"owl::OWLClass" = OWL!"owl::OWLClass".allInstancesFrom('JAVA') ->any(o|o.localName = 'JRE'); helper def : providesFeature : OWL!"owl::OWLObjectProperty" = OWL!"owl::OWLObjectProperty".allInstancesFrom('PLATFORM') ->any(p|p.localName = 'providesFeature'); helper def : implementsInterface : OWL!"owl::OWLObjectProperty" = OWL!"owl::OWLObjectProperty".allInstancesFrom('PLATFORM') ->any(p|p.localName = 'implementsInterface'); helper def : comprisesInterfacePart : OWL!"owl::OWLObjectProperty" = OWL!"owl::OWLObjectProperty".allInstancesFrom('PLATFORM') ->any(p|p.localName = 'comprisesInterfacePart'); helper def : majorVersionNumber : OWL!"owl::OWLDatatypeProperty" = OWL!"owl::OWLDatatypeProperty".allInstancesFrom('JAVA') ->any(p|p.localName = 'majorVersionNumber'); helper def : minorVersionNumber : OWL!"owl::OWLDatatypeProperty" = OWL!"owl::OWLDatatypeProperty".allInstancesFrom('JAVA') ->any(p|p.localName = 'minorVersionNumber'); helper def : preverified : OWL!"owl::OWLDatatypeProperty" = OWL!"owl::OWLDatatypeProperty".allInstancesFrom('JAVA') ->any(p|p.localName = 'preverified'); helper def : platformOntology : Set(OWL!"owl::OWLOntology") = OWL!"owl::OWLOntology".allInstancesFrom('PLATFORM'); helper def : javaOntology : Set(OWL!"owl::OWLOntology") = OWL!"owl::OWLOntology".allInstancesFrom('JAVA'); helper def : importedOntologies : Set(OWL!"owl::OWLOntology") = OWL!"owl::OWLOntology".allInstances()->select(o| OWL!"owl::OWLOntology".allInstancesFrom('PLATFORM')->excludes(o) and OWL!"owl::OWLOntology".allInstancesFrom('JAVA')->excludes(o)); -- ====================================================================== -- general context helper attributes begin -- ====================================================================== helper context UML2!"uml::NamedElement" def : javaQualifiedName : String = if self.owner.oclIsTypeOf(UML2!"uml::Package") or self.owner.oclIsKindOf(UML2!"uml::Classifier") then self.owner.javaQualifiedName + '.' + self.name else self.name endif; helper context UML2!"uml::NamedElement" def : ontClassName : String = if self.owner.oclIsTypeOf(UML2!"uml::Package") then self.owner.ontClassName else '' endif + self.name.legalOntClassName; helper context String def : legalOntClassName : String = self .replaceAll('.', '_') .split(' ')->collect(s|s.firstToUpper())->iterate(e; acc : String = ''|acc + e); helper context String def : legalOntName : String = self .toLower() .replaceAll('.', '_') .replaceAll(' ', '-'); -- ====================================================================== -- helper attributes for finding references -- ====================================================================== helper context UML2!"uml::Package" def : references : Set(UML2!"uml::Package") = self.allOwnedClassifiers ->collect(c|c.references)->flatten()->asSet() ->collect(r|r.referencesOtherPackageThan(self))->flatten()->asSet() ->reject(e|e.isInferred) .debug(thisModule.modelName.prefix + self.qualifiedName + ' referenced packages'); -- Non-transitive references helper context UML2!"uml::Classifier" def : references : Set(UML2!"uml::Classifier") = self.general->union( self.suppliers->select(s|s.oclIsKindOf(UML2!"uml::Classifier")))->union( self.feature->collect(f|f.referencesOtherThan(self))) ->flatten()->asSet() ->reject(e|e.isInferred); -- ====================================================================== -- helper attributes for determining compatibility -- ====================================================================== helper context UML2!"uml::NamedElement" def : owlClassesInPrev : Sequence(OWL!"owl::OWLClass") = OWL!"owl::OWLClass".allInstances() ->select(c|c.localName = self.ontClassName) ->select(o|o.namespace.name = self.getModel().name.legalOntName); helper context UML2!"uml::NamedElement" def : owlApiClassesInPrev : Sequence(OWL!"owl::OWLClass") = OWL!"owl::OWLClass".allInstances() ->select(c|c.localName = self.ontClassName + 'API') ->select(o|o.namespace.name = self.getModel().name.legalOntName); helper context UML2!"uml::NamedElement" def : owlLibraryClassesInPrev : Sequence(OWL!"owl::OWLClass") = OWL!"owl::OWLClass".allInstances() ->select(c|c.localName = self.ontClassName + 'ClassLibrary') ->select(o|o.namespace.name = self.getModel().name.legalOntName); helper context UML2!"uml::NamedElement" def : owlBytecodeClassesInPrev : Sequence(OWL!"owl::OWLClass") = OWL!"owl::OWLClass".allInstances() ->select(c|c.localName = self.ontClassName + 'BytecodeFormat') ->select(o|o.namespace.name = self.getModel().name.legalOntName); helper context UML2!"uml::Package" def : compatibleClasses : Sequence(OWL!"owl::OWLClass") = self.compatibleInPrev->collect(p|p.owlClassesInPrev)->flatten(); helper context UML2!"uml::Package" def : equivalentClasses : Sequence(OWL!"owl::OWLClass") = self.equivalentInPrev->collect(p|p.owlClassesInPrev)->flatten(); helper context UML2!"uml::Package" def : compatibleApiClasses : Sequence(OWL!"owl::OWLClass") = self.compatibleInPrev->collect(p|p.owlApiClassesInPrev)->flatten(); helper context UML2!"uml::Package" def : equivalentApiClasses : Sequence(OWL!"owl::OWLClass") = self.equivalentInPrev->collect(p|p.owlApiClassesInPrev)->flatten(); helper context UML2!"uml::Package" def : compatibleLibraryClasses : Sequence(OWL!"owl::OWLClass") = self.compatibleInPrev->collect(p|p.owlLibraryClassesInPrev)->flatten(); helper context UML2!"uml::Package" def : equivalentLibraryClasses : Sequence(OWL!"owl::OWLClass") = self.equivalentInPrev->collect(p|p.owlLibraryClassesInPrev)->flatten(); helper context UML2!"uml::Model" def : compatibleBytecodeClasses : Sequence(OWL!"owl::OWLClass") = self.bytecodeCompatibleInPrev->collect(p|p.owlBytecodeClassesInPrev)->flatten(); helper context UML2!"uml::Package" def : equivalentBytecodeClasses : Sequence(OWL!"owl::OWLClass") = self.bytecodeEquivalentInPrev->collect(p|p.owlBytecodeClassesInPrev)->flatten(); -- ====================================================================== -- helper attributes end -- ====================================================================== -- ====================================================================== -- general helper methods -- ====================================================================== helper context String def: firstToUpper() : String = self.substring(1, 1).toUpper() + self.substring(2, self.size()); -- ====================================================================== -- helper methods for finding references -- ====================================================================== helper context UML2!"uml::PackageableElement" def : referencesOtherPackageThan(p : UML2!"uml::Package") : Set(UML2!"uml::Package") = let np : UML2!"uml::Package" = self.getNearestPackage() in if np <> p then Set{np} else Set{} endif; helper context UML2!"uml::BehavioralFeature" def : referencesOtherThan(c : UML2!"uml::Classifier") : Sequence(UML2!"uml::Classifier") = self.ownedParameter->collect(p|p.referencesOtherThan(c))->flatten(); helper context UML2!"uml::TypedElement" def : referencesOtherThan(c : UML2!"uml::Classifier") : Sequence(UML2!"uml::Classifier") = if self.type.oclIsKindOf(UML2!"uml::Class") or self.type.oclIsKindOf(UML2!"uml::Interface") then if self.type.getModel() = c.getModel() and self.type <> c then Sequence{self.type} else Sequence{} endif else Sequence{} endif; -- ====================================================================== -- helper methods end -- ====================================================================== -- ====================================================================== -- transformation rules begin -- ====================================================================== rule PrevNamespace(o : OWL!"owl::OWLOntology") { to n : OWL!"rdfs::Namespace" ( URI <- o.namespace.URI, name <- o.namespace.name) do { n; } } rule APIRestriction(p : UML2!"uml::Package") { to t : OWL!"owl::SomeValuesFromRestriction" ( OWLOnProperty <- thisModule.comprisesInterfacePart, OWLSomeValuesFrom <- p, namespace <- p.getModel()) do { t; } } rule APISlot(p : UML2!"uml::Package") { to t : OWL!"owl::ObjectSlot" ( property <- thisModule.comprisesInterfacePart, content <- thisModule.resolveTemp(p, 'apiPart')) do { t; } } rule APIClass(s : UML2!"uml::Model") { to apiClass : OWL!"owl::OWLClass" ( localName <- s.name.legalOntClassName + 'API', RDFSSubClassOf <- Sequence{thisModule.javaAPI}, OWLEquivalentClass <- Sequence{apiRestriction}, RDFSComment <- Sequence{apiComment}, namespace <- s), apiComment : OWL!"rdfs::PlainLiteral" ( language <- 'en', lexicalForm <- s.name + ' API'), apiRestriction : OWL!"owl::IntersectionClass" ( OWLIntersectionOf <- thisModule.includedPackages ->collect(p|thisModule.APIRestriction(p)), namespace <- s) do { apiClass; } } rule LibraryClass(s : UML2!"uml::Model", apiClass : OWL!"owl::OWLClass") { to libraryClass : OWL!"owl::OWLClass" ( localName <- s.name.legalOntClassName + 'ClassLibrary', RDFSSubClassOf <- Sequence{thisModule.javaLibrary}, OWLEquivalentClass <- Sequence{libraryRestriction}, RDFSComment <- Sequence{libraryComment}, namespace <- s), libraryComment : OWL!"rdfs::PlainLiteral" ( language <- 'en', lexicalForm <- 'Java class library implementing the ' + s.name + ' API'), libraryRestriction : OWL!"owl::SomeValuesFromRestriction" ( OWLOnProperty <- thisModule.implementsInterface, OWLSomeValuesFrom <- apiClass, namespace <- s) do { Sequence{apiClass, libraryClass}; } } rule BytecodeClass(s : UML2!"uml::Model", integer : OWL!"rdfs::RDFSDatatype", boolean : OWL!"rdfs::RDFSDatatype") { using { jar2uml : UML2!"ecore::EAnnotation" = s.getEAnnotation('Jar2UML'); majorVersion : Integer = s.bytecodeMajorVersion; minorVersion : Integer = s.bytecodeMinorVersion; preverified : Boolean = s.bytecodePreverified; superClasses : Sequence(OWL!"owl::OWLClass") = s.compatibleBytecodeClasses->select(c|s.equivalentBytecodeClasses->excludes(c)); } to bytecodeClass : OWL!"owl::OWLClass" ( localName <- s.name.legalOntClassName + 'BytecodeFormat', RDFSSubClassOf <- if superClasses->isEmpty() then Sequence{thisModule.javaBytecode} else superClasses endif, OWLEquivalentClass <- s.equivalentBytecodeClasses, RDFSComment <- Sequence{bytecodeComment, bytecodeRestriction}, namespace <- s), bytecodeComment : OWL!"rdfs::PlainLiteral" ( language <- 'en', lexicalForm <- s.name + ' bytecode format'), bytecodeInstance : OWL!"owl::Individual" ( localName <- 'the' + bytecodeClass.localName, RDFType <- bytecodeClass, datatypeSlot <- Sequence{ bytecodeMajorVersionSlot, bytecodeMinorVersionSlot, bytecodePreverifiedSlot}, namespace <- s), bytecodeMajorVersionSlot : OWL!"owl::DatatypeSlot" ( property <- thisModule.majorVersionNumber, content <- bytecodeMajorVersionValue), bytecodeMajorVersionValue : OWL!"rdfs::TypedLiteral" ( datatype <- integer, lexicalForm <- majorVersion.toString(), namespace <- s), bytecodeMinorVersionSlot : OWL!"owl::DatatypeSlot" ( property <- thisModule.minorVersionNumber, content <- bytecodeMinorVersionValue), bytecodeMinorVersionValue : OWL!"rdfs::TypedLiteral" ( datatype <- integer, lexicalForm <- minorVersion.toString()), bytecodePreverifiedSlot : OWL!"owl::DatatypeSlot" ( property <- thisModule.preverified, content <- bytecodePreverifiedValue), bytecodePreverifiedValue : OWL!"rdfs::TypedLiteral" ( datatype <- boolean, lexicalForm <- if preverified then 'true' else 'false' endif), --!!! EODM does not support restricted data types !!! bytecodeRestriction : OWL!"rdfs::PlainLiteral" ( language <- 'OWLManchester', lexicalForm <- 'java:majorVersionNumber some xsd:integer[>="' + majorVersion + '"^^xsd:integer]' + if preverified then '' else ' and java:preverified value false' endif) do { Sequence{bytecodeClass, bytecodeInstance}; } } -- ====================================================================== -- transformation rules end -- ======================================================================