java2kdm.atl
2581 lines (2435 with data), 71.9 kB
-- @atlcompiler atl2006
--Copyright (c) 2009 Mia-Software.
--All rights reserved. This program and the accompanying materials
--are made available under the terms of the Eclipse Public License v1.0
--which accompanies this distribution, and is available at
--http://www.eclipse.org/legal/epl-v10.html
---
--Contributors:
-- Gabriel BARBIER (Mia-Software) - initial API and implementation
-- Fabien GIQUEL (Mia-Software) - initial API and implementation
--
-- @nsURI kdm=http://www.eclipse.org/MoDisco/kdm/action
-- @nsURI java=http://www.eclipse.org/MoDisco/Java/0.2.incubation/java
--
--Transform Java Models to KDM models
module javaToKdm;-- Module Template
create OUT: kdm from IN: java;
rule InitializerToControlElement extends BodyDeclarationToAbstractCodeElement {
from
src: java!Initializer
to
tgt: kdm!ControlElement (
codeElement <- src.body
)
}
-- helpers --
-- specific case to attach all single elements to root model
endpoint rule manageDetachedElements() {
do {
for (alone in kdm!AbstractCodeElement.allInstances()) {
if (alone.refImmediateComposite().oclIsUndefined()) {
thisModule.externalModel.codeElement <- alone;
}
}
}
}
helper def: externalModel: kdm!CodeModel =
OclUndefined;
-- computes name of a generic type
helper context java!TypeDeclaration def: getGenericName(): String =
self.name + '<' + self.typeParameters -> collect(T | if (self.typeParameters ->
indexOf(T) < self.typeParameters -> size()) then
T.name + ', '
else
T.name
endif) -> sum() + '>';
--returns referenced type, or one created on the fly in case of UnresolvedItem
--this is used when creating variables or parameters which are containers for this kind
-- of type in kdm
helper context java!TypeAccess def: getType(): kdm!Datatype =
self.type -> getExtendsType();
helper context java!NamedElement def: getExtendsType(): kdm!Datatype =
if self.oclIsKindOf(java!UnresolvedItem) then
if self.refImmediateComposite().oclIsTypeOf(java!ClassDeclaration) then
thisModule -> CreateClassUnit(self) -- TODO why ?
else
thisModule -> CreateInterfaceUnit(self)
endif
else
-- java!Type or java!Package
self
endif;
-- to be able to filter expressions that are not useful, or need to be managed manually
helper def: filterExpression(expression: java!Expression): java!Expression =
if (expression.oclIsUndefined()) then
Sequence{}
else
if (expression.oclIsKindOf(java!SingleVariableAccess) or expression.
oclIsKindOf(java!TypeAccess) or expression.
oclIsKindOf(java!UnresolvedItemAccess)) then
Sequence{}
else
Sequence{expression}
endif
endif;
-- rules --
-- ===================================================== ---
-- Rules for the structure of a program
-- This part gives all the transformations for the structure of a Java program
-- ===================================================== ---
-- Transforms a Model into a code model
rule ModelToModel {
from
src: java!Model
to
kdmModel: kdm!CodeModel (
name <- src.name,
codeElement <- src.ownedElements -> select(e | e.proxy = false),
codeElement <- kdmLanguageUnit
),
kdmLanguageUnit: kdm!LanguageUnit (
name <- 'Common Java datatypes',
codeElement <- src.orphanTypes -> select(e | e.
oclIsKindOf(java!PrimitiveType)),
codeElement <- stringType
),
externalModel: kdm!CodeModel (
name <- 'externals',
codeElement <- src.ownedElements -> select(e | e.proxy = true),
codeElement <- src.orphanTypes -> select(e | not e.
oclIsKindOf(java!PrimitiveType))
),
sourcesModel: kdm!InventoryModel (
name <- 'source references',
inventoryElement <- src.compilationUnits,
inventoryElement <- src.archives
),
kdmSegment: kdm!Segment mapsTo src (
model <- kdmModel,
model <- externalModel,
model <- sourcesModel
),
stringType: kdm!StringType (
name <- 'string'
)
do {
thisModule.externalModel <- externalModel;
}
}
-- Transforms a package declaration into a package
rule PackageToPackage {
from
src: java!Package
to
tgt: kdm!Package (
name <- src.name --get the subpackages owned by the matched package
,
codeElement <- src.ownedPackages --adds classes and interfaces
,
codeElement <- src.ownedElements
)
}
-- ===================================================== ---
--
-- abstract rule to manage source reference in kdm model
-- in java, corresponding metaclass is ASTNode
-- in kdm, it is AbstractCodeElement (no better choice)
--
-- ===================================================== ---
abstract rule ASTNodeToAbstractCodeElement {
from
src: java!ASTNode
to
tgt: kdm!AbstractCodeElement (
-- comments
comment <- src.comments,
-- source file management
source <- sourceRef
),
sourceRef: kdm!SourceRef (
language <- 'java',
region <- sourceRegion
),
sourceRegion: kdm!SourceRegion (
language <- 'java' -- size expensive and redundant with SourceFile
-- information
-- ,path <- if (src.originalCompilationUnit.oclIsUndefined()) then
-- 'internal'
-- else
-- src.originalCompilationUnit.originalFilePath
-- endif
,
file <- if (src.originalCompilationUnit.oclIsUndefined()) then
src.originalClassFile
else
src.originalCompilationUnit
endif
)
}
abstract rule NamedElementToAbstractCodeElement extends ASTNodeToAbstractCodeElement {
from
src: java!NamedElement
to
tgt: kdm!AbstractCodeElement (
name <- src.name
)
}
abstract rule BodyDeclarationToAbstractCodeElement extends
NamedElementToAbstractCodeElement {
from
src: java!BodyDeclaration
to
tgt: kdm!AbstractCodeElement (
-- attributes to store additional information (visibility stays redundant)
attribute <- if (src.modifier.oclIsUndefined()) then
Sequence{}
else
src.modifier
endif -- annotations
,
codeRelation <- src.annotations
)
}
abstract rule AbstractTypeDeclarationToDatatype extends
BodyDeclarationToAbstractCodeElement {
from
src: java!AbstractTypeDeclaration
to
tgt: kdm!Datatype (
-- imports
codeRelation <- if (src.originalCompilationUnit.oclIsUndefined()) then
Sequence{}
else
src.originalCompilationUnit.imports
endif -- inheritance
,
codeRelation <- src.superInterfaces -> collect(e | if (src.
oclIsTypeOf(java!ClassDeclaration)) then
thisModule.CreateImplements(e)
else
thisModule.CreateExtends(e)
endif) -- end collect
-- annotations
,
codeRelation <- src.annotations -- TODO use superClass
-- comments
,
comment <- src.commentsBeforeBody,
comment <- src.commentsAfterBody,
comment <- src.comments,
comment <- if (src.originalCompilationUnit.oclIsUndefined() or not src.
refImmediateComposite().oclIsTypeOf(java!Package)) then
Sequence{}
else
-- top level type declaration -> retrieving CU heading comments
src.originalCompilationUnit.comments
endif
)
}
rule ModifierToAttribute {
from
src: java!Modifier
to
tgt: kdm!Attribute (
tag <- 'export',
value <- src.visibility.toString() + (if (src.inheritance = #none) then
''
else
' ' + src.inheritance.toString()
endif)
)
}
-- ===================================================== ---
-- Rules for the classes
-- This part gives all the transformations for the classes of a Java program
-- the transformations being quite different when the considered class is generic (Java
-- meaning)
-- ===================================================== ---
-- Transfoms a class declaration into a class unit
rule ClassDeclarationToClassUnit extends AbstractTypeDeclarationToDatatype {
from
src: java!ClassDeclaration (
src.typeParameters.isEmpty()
)
using{
-- For attributes, we have to separate FieldDeclaration and
-- VariableDeclarationFragment usage
javaAttributes: java!NamedElement = src.bodyDeclarations -> select(e | e.
oclIsTypeOf(java!FieldDeclaration)) -> collect(f | if (f.
fragments->isEmpty()) then f else f.fragments endif);
}
to
tgt: kdm!ClassUnit (
isAbstract <- if src.modifier.oclIsUndefined() then
OclUndefined
else
src.modifier.inheritance = 'abstract'
endif -- attributes
,
codeElement <- javaAttributes -- other elements
,
codeElement <- src.bodyDeclarations -> select(e | not e.
oclIsTypeOf(java!FieldDeclaration))
)
do {
-- inheritance
tgt.codeRelation <- if src.superClass.oclIsUndefined() then
Sequence{}
else
thisModule.CreateExtends(src.superClass)
endif;
}
}
-- Transfoms a class declaration into a class unit
rule AnonymousClassDeclarationToClassUnit extends ASTNodeToAbstractCodeElement {
from
src: java!AnonymousClassDeclaration
using{
-- For attributes, we have to separate FieldDeclaration and
-- VariableDeclarationFragment usage
javaAttributes: java!NamedElement = src.bodyDeclarations -> select(e | e.
oclIsTypeOf(java!FieldDeclaration)) -> collect(f | if (f.
fragments->isEmpty()) then f else f.fragments endif);
originalTypeAccess: java!TypeAccess = if ( src.refImmediateComposite().oclIsKindOf(java! EnumConstantDeclaration)) then
OclUndefined
else
src.refImmediateComposite().type
endif ;
}
to
tgt: kdm!ClassUnit (
name <- 'Anonymous type' -- attributes
,
codeElement <- javaAttributes -- other elements
,
codeElement <- src.bodyDeclarations -> select(e | not
e.oclIsTypeOf(java!FieldDeclaration)) -- imports
,
codeRelation <- if (src.originalCompilationUnit.oclIsUndefined()) then
Sequence{}
else
src.originalCompilationUnit.imports
endif -- inheritance
,
codeRelation <- if (originalTypeAccess.oclIsUndefined()) then
Sequence{}
else
thisModule.CreateImplementsForTemplated(tgt, originalTypeAccess)
endif -- TODO use superClass
-- comments
,
comment <- src.comments,
comment <- if (src.originalCompilationUnit.oclIsUndefined() or not src.
refImmediateComposite().oclIsTypeOf(java!Package)) then
Sequence{}
else
-- top level type declaration -> retrieving CU heading comments
src.originalCompilationUnit.comments
endif
)
}
-- ===================================================== ---
-- Rules for the interfaces
-- This part gives all the transformations for the interfaces of a java program
-- the transformations being quite different when the considered interface is generic
-- (java meaning)
-- ===================================================== ---
-- Transfoms an interface
rule InterfaceDeclarationToInterfaceUnit extends AbstractTypeDeclarationToDatatype {
from
src: java!InterfaceDeclaration (
src.typeParameters.isEmpty()
)
using{
-- For attributes, we have to separate FieldDeclaration and
-- VariableDeclarationFragment usage
javaAttributes: java!NamedElement = src.bodyDeclarations -> select(e | e.
oclIsTypeOf(java!FieldDeclaration)) -> collect(f | if (f.
fragments->isEmpty()) then f else f.fragments endif);
}
to
tgt: kdm!InterfaceUnit (
-- attributes
codeElement <- javaAttributes -- other elements
,
codeElement <- src.bodyDeclarations -> select(e | not e.
oclIsTypeOf(java!FieldDeclaration))
)
}
-- ===================================================== ---
-- Rules for the Enums
-- This part gives the transformation for the enums of a java programm
-- ===================================================== ---
-- Transforms a enumerated type
rule EnumDeclarationToEnumeratedType extends AbstractTypeDeclarationToDatatype {
from
src: java!EnumDeclaration
using{
-- For attributes, we have to separate FieldDeclaration and
-- VariableDeclarationFragment usage
javaAttributes: java!NamedElement = src.bodyDeclarations -> select(e | e.
oclIsTypeOf(java!FieldDeclaration)) -> collect(f | if (f.
fragments->isEmpty()) then f else f.fragments endif);
}
to
tgt: kdm!EnumeratedType (
-- enumerated values
value <- src.enumConstants -- TODO not allowed by kdm implementation !
-- attributes
,
codeElement <- javaAttributes -- other elements
,
codeElement <- src.bodyDeclarations -> select(e | not e.
oclIsTypeOf(java!FieldDeclaration))
)
}
-- transforms an array type into an array type
rule ArrayTypeToArrayType {
from
src: java!ArrayType
to
tgt: kdm!ArrayType (
name <- src.name -- size attribute will contains dimension information
-- instead of size
,
size <- src.dimensions,
itemUnit <- realType,
indexUnit <- indexUnit
),
realType: kdm!ItemUnit (
type <- src.elementType -> getType()
),
indexUnit: kdm!IndexUnit (
type <- java!PrimitiveTypeInt.allInstances() -> first()
)
}
-- transforms a wild card into a TypeUnit (DefinedType)
rule WildCardTypeToTypeUnit {
from
src: java!WildCardType
to
tgt: kdm!TypeUnit (
type <- if (src.bound.oclIsUndefined()) then
OclUndefined
else
src.bound -> getType()
endif
)
}
-- transforms an Annotation type into an InterfaceUnit (with an annotation)
rule AnnotationTypeDeclarationToInterfaceUnit extends AbstractTypeDeclarationToDatatype {
from
src: java!AnnotationTypeDeclaration
using{
-- For attributes, we have to separate FieldDeclaration and
-- VariableDeclarationFragment usage
javaAttributes: java!NamedElement = src.bodyDeclarations -> select(e | e.
oclIsTypeOf(java!FieldDeclaration)) -> collect(f | if (f.
fragments->isEmpty()) then f else f.fragments endif);
}
to
tgt: kdm!InterfaceUnit (
annotation <- annotation -- specific for annotation types, we have to
-- redefine these initializations ???
-- ATL mechanism of extends does not work very well ...
,
codeRelation <- src.annotations,
codeRelation <- if (src.originalCompilationUnit.oclIsUndefined()) then
Sequence{}
else
src.originalCompilationUnit.imports
endif -- attributes
,
codeElement <- javaAttributes -- other elements, it should be
-- AnnotationTypeMemberDeclaration
,
codeElement <- src.bodyDeclarations -> select(e | not e.
oclIsTypeOf(java!FieldDeclaration))
),
annotation: kdm!Annotation (
text <- 'annotation'
)
}
-- transforms an AnnotationTypeMemberDeclaration into a MemberUnit
-- it is here because ATL superimposition does not allow rules extensions.
rule AnnotationTypeMemberDeclarationToMemberUnit extends
BodyDeclarationToAbstractCodeElement {
from
src: java!AnnotationTypeMemberDeclaration
to
tgt: kdm!MemberUnit (
type <- if (src.type.oclIsUndefined()) then
OclUndefined
else
src.type -> getType()
endif
)
}
-- ========================================================
-- Rules for generic types (class, interface)
-- ========================================================
-- Transfoms a type with generic declarations into a TemplateUnit containing a type unit
abstract rule TypeDeclarationToTemplateUnit {
from
src: java!TypeDeclaration (
not src.typeParameters.isEmpty()
)
to
tgt: kdm!TemplateUnit (
-- template parameter should be first
name <- src -> getGenericName(),
codeElement <- src.typeParameters,
codeElement <- type
),
type: kdm!Datatype (
name <- src.name -- imports
,
codeRelation <- if (src.originalCompilationUnit.oclIsUndefined()) then
Sequence{}
else
src.originalCompilationUnit.imports
endif -- inheritance
,
codeRelation <- src.superInterfaces -> collect(e | if (src.
oclIsTypeOf(java!ClassDeclaration)) then
thisModule.CreateImplementsForTemplated(type, e)
else
thisModule.CreateExtendsForTemplated(type, e)
endif) -- end collect
-- comments
,
comment <- src.comments,
comment <- if (src.originalCompilationUnit.oclIsUndefined() or not src.
refImmediateComposite().oclIsTypeOf(java!Package)) then
Sequence{}
else
-- top level type declaration -> retrieving CU heading comments
src.originalCompilationUnit.comments
endif -- source file management
,
source <- sourceRef -- attributes to store additional informations
-- (visibility stay redundant)
,
attribute <- if (src.modifier.oclIsUndefined()) then
Sequence{}
else
src.modifier
endif -- annotations
,
codeRelation <- src.annotations
),
sourceRef: kdm!SourceRef (
language <- 'java',
region <- sourceRegion
),
sourceRegion: kdm!SourceRegion (
language <- 'java' -- size expensive and redundant with SourceFile
-- information
-- ,path <- if (src.originalCompilationUnit.oclIsUndefined()) then
-- 'internal'
-- else
-- src.originalCompilationUnit.originalFilePath
-- endif
,
file <- if (src.originalCompilationUnit.oclIsUndefined()) then
src.originalClassFile
else
src.originalCompilationUnit
endif
)
}
-- Transfoms a class with generic declarations into a TemplateUnit containing a class unit
rule ClassDeclarationToTemplateUnit extends TypeDeclarationToTemplateUnit {
from
src: java!ClassDeclaration (
not src.typeParameters.isEmpty()
)
using{
-- For attributes, we have to separate FieldDeclaration and
-- VariableDeclarationFragment usage
javaAttributes: java!NamedElement = src.bodyDeclarations -> select(e | e.
oclIsTypeOf(java!FieldDeclaration)) -> collect(f | if (f.
fragments->isEmpty()) then f else f.fragments endif);
}
to
tgt: kdm!TemplateUnit (
),
type: kdm!ClassUnit (
isAbstract <- if src.modifier.oclIsUndefined() then
OclUndefined
else
src.modifier.inheritance = 'abstract'
endif -- attributes
,
codeElement <- javaAttributes -- other elements
,
codeElement <- src.bodyDeclarations -> select(e | not e.
oclIsTypeOf(java!FieldDeclaration))
)
do {
-- inheritance
type.codeRelation <- if src.superClass.oclIsUndefined() then
Sequence{}
else
thisModule.CreateExtendsForTemplated(type, src.superClass)
endif;
}
}
-- Transfoms a generic interface
rule InterfaceDeclarationToTemplateUnit extends TypeDeclarationToTemplateUnit {
from
src: java!InterfaceDeclaration (
not src.typeParameters.isEmpty()
)
using{
-- For attributes, we have to separate FieldDeclaration and
-- VaraiableDeclarationFragment usage
javaAttributes: java!NamedElement = src.bodyDeclarations -> select(e | e.
oclIsTypeOf(java!FieldDeclaration)) -> collect(f | if (f.
fragments->isEmpty()) then f else f.fragments endif);
}
to
tgt: kdm!TemplateUnit (
),
type: kdm!InterfaceUnit (
-- attributes
codeElement <- javaAttributes -- other elements
,
codeElement <- src.bodyDeclarations -> select(e | not e.
oclIsTypeOf(java!FieldDeclaration))
)
}
-- Transforms parameters declared by a generic type
rule TypeParameterToTemplateParameter {
from
src: java!TypeParameter
to
parameter: kdm!TemplateParameter (
name <- src.name
)
}
-- ========================================================
-- Rules for usage of generic types
-- ========================================================
-- Transforms ParameterizedType to TemplateType
-- relationships ParameterTo link generic usage with type arguments
-- relationship InstanceOf links generic usage with generic type
rule ParameterizedTypeToTemplateType {
from
src: java!ParameterizedType
to
tgt: kdm!TemplateType (
name <- src.name,
codeRelation <- src.typeArguments -> collect(t | thisModule ->
CreateParameterTo(t)),
codeRelation <- typeLink
),
typeLink: kdm!InstanceOf (
from <- tgt,
-- to <- if (src.type.type -> oclIsKindOf(java!UnresolvedTypeDeclaration)) then
to <- if (src.type -> oclIsKindOf(java!UnresolvedTypeDeclaration)) then
OclUndefined -- typeParameters does not exist on
-- UnresolvedTypeDeclaration
else if (src.oclIsUndefined()) then
OclUndefined
else if (src.type.oclIsUndefined()) then
OclUndefined --else if (src.type.type.typeParameters.isEmpty()) then
else if (src.type.type.typeParameters.isEmpty()) then
OclUndefined
else
src.type -> getType()
endif
endif
endif
endif
)
}
-- ===================================================
-- CodeRelation section --
-- here is managed 'use' relations
-- and inheritance links (extends and implements)
-- ===================================================
-- Transforms an import declaration to an import declaration
rule ImportDeclarationToImports {
from
src: java!ImportDeclaration (
not src.static
)
to
tgt: kdm!Imports (
from <- src.refImmediateComposite().types -> at(1),
to <- src.importedElement -> getExtendsType()
)
}
--create the Extends for class or interface extension
lazy rule CreateExtends {
from
javaExtends: java!TypeAccess
to
kdmExtends: kdm!Extends (
from <- javaExtends.refImmediateComposite(),
to <- javaExtends -> getType()
)
}
lazy rule CreateExtendsForTemplated {
from targetFrom: kdm!CodeItem, sourceTo: java!TypeAccess
to
tgt: kdm!Extends (
from <- targetFrom,
to <- sourceTo -> getType()
)
}
--create the Implements for interface implementation
lazy rule CreateImplements {
from
javaImplements: java!TypeAccess
to
kdmImplements: kdm!Implements (
from <- javaImplements.refImmediateComposite(),
to <- javaImplements -> getType()
)
}
lazy rule CreateImplementsForTemplated {
from targetFrom: kdm!CodeItem, sourceTo: java!TypeAccess
to
tgt: kdm!Implements (
from <- targetFrom,
to <- sourceTo -> getType()
)
}
-- create a class unit in case of extends relationships
unique lazy rule CreateClassUnit {
from
src: java!UnresovedItem
to
tgt: kdm!ClassUnit (
name <- src.name
)
}
-- create an interface unit in case of extends or implements relationships
unique lazy rule CreateInterfaceUnit {
from
src: java!UnresovedItem
to
tgt: kdm!InterfaceUnit (
name <- src.name
)
}
--create the ParameterTo for type arguments of generics usage
lazy rule CreateParameterTo {
from
src: java!TypeAccess
to
tgt: kdm!ParameterTo (
from <- src.refImmediateComposite(),
to <- src -> getType()
)
}
-- ===================================================== ---
-- Rules for the primitive types
-- A primitive type can be translated into different types according to the "name"
-- attribute
-- ===================================================== ---
--creates the Boolean primitive type
rule PrimitiveTypeBooleanToBooleanType {
from
javaBoolean: java!PrimitiveTypeBoolean
to
kdmBoolean: kdm!BooleanType (
name <- 'boolean'
)
}
--creates the Byte primitive type
rule PrimitiveTypeByteToByteType {
from
javaByte: java!PrimitiveTypeByte
to
kdmByte: kdm!OctetType (
name <- 'byte'
)
}
--creates the Char primitive type
rule PrimitiveTypeCharToCharType {
from
javaChar: java!PrimitiveTypeChar
to
kdmChar: kdm!CharType (
name <- 'char'
)
}
--creates the Double primitive type
rule PrimitiveTypeDoubleToDoubleType {
from
src: java!PrimitiveTypeDouble
to
kdmFLoat: kdm!FloatType (
name <- 'double'
)
}
--creates the Float primitive type
rule PrimitiveTypeFloatToFloatType {
from
javaFloat: java!PrimitiveTypeFloat
to
kdmFloat: kdm!FloatType (
name <- 'float'
)
}
--creates the int primitive type
rule PrimitiveTypeIntToIntType {
from
javaInt: java!PrimitiveTypeInt
to
kdmInteger: kdm!IntegerType (
name <- 'int'
)
}
--creates the long primitive type
rule PrimitiveTypeLongToLongType {
from
javaLong: java!PrimitiveTypeLong
to
kdmInteger: kdm!IntegerType (
name <- 'long'
)
}
--creates the short primitive type
rule PrimitiveTypeShortToShortType {
from
javaShort: java!PrimitiveTypeShort
to
kdmInteger: kdm!IntegerType (
name <- 'short'
)
}
--creates the Void primitive type
rule PrimitiveTypeVoidToVoidType {
from
javaVoid: java!PrimitiveTypeVoid
to
kdmVoid: kdm!VoidType (
name <- 'void'
)
}
-- ===================================================== ---
-- Rules for the artefacts of a program
--
-- ===================================================== ---
rule CompilationUnitToSourceFile {
from
src: java!CompilationUnit
to
tgt: kdm!SourceFile (
name <- src.name,
language <- 'java',
path <- src.originalFilePath
)
}
rule ArchiveToBinaryFile {
from
src: java!Archive
to
tgt: kdm!BinaryFile (
path <- src.originalFilePath -- version <- TODO retrieve version from
-- Manifest infos ?
)
}
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- StructureWithMembers
-- helpers --
--returns an element of the ExportKind enumeration to set the visibility of the field or
-- method
helper context java!BodyDeclaration def: getVisibility(): kdm!ExportKind =
if (self.modifier.oclIsUndefined()) then
#unknown
else
if self.modifier.visibility.oclIsUndefined() then
#unknown
else
if (self.modifier.visibility = #public) then
#public
else
if (self.modifier.visibility = #protected) then
#protected
else
if (self.modifier.visibility = #none) then
if (self.abstractTypeDeclaration.
oclIsTypeOf(java!InterfaceDeclaration)) then
#public
else
#protected
endif
else
#private
endif
endif
endif
endif
endif;
-- rules --
-- ===================================================
-- Transformation of attributes : Field, EnumConstant, AnnotationTypeMemberDeclaration
-- ===================================================
-- ===================================================== ---
-- Rules for the Fields
-- This part gives the transformation for the fields of a java type
-- ===================================================== ---
--create the classes and interface attributes
-- Hope : kdm does not allow interface attributes ! we have to change it
rule FieldDeclarationToMemberUnit extends BodyDeclarationToAbstractCodeElement {
from
src: java!FieldDeclaration (
src.fragments -> isEmpty()
)
to
tgt: kdm!MemberUnit (
export <- src -> getVisibility(),
type <- if (src.type.oclIsUndefined()) then
OclUndefined
else
src.type -> getType()
endif,
comment <- src.comments
)
}
-- Transfoms an enumeration constant into a value
rule EnumConstantDeclarationToValue extends BodyDeclarationToAbstractCodeElement {
from
src: java!EnumConstantDeclaration
to
tgt: kdm!Value (
name <- 'enum literal',
ext <- src.name
--type <- src.refImmediateComposite() -- TODO waiting for a strategy for
-- constant arguments
)
}
-- ===================================================== ---
-- Rules for the methods
-- This part gives all the transformations for the methods
-- the transformations being quite different when the considered method is generic
-- ===================================================== ---
-- Transforms a method into a method unit
rule MethodDeclarationToMethodUnit extends BodyDeclarationToAbstractCodeElement {
from
src: java!AbstractMethodDeclaration (
src.typeParameters.isEmpty() --and
-- Anonymous types are not translated in kdm
--src.anonymousClassDeclarationOwner.oclIsUndefined()
)
to
tgt: kdm!MethodUnit (
kind <- if (src.oclIsKindOf(java!ConstructorDeclaration)) then #constructor
else #method endif,
export <- src -> getVisibility() -- signature management
,
type <- signature,
codeElement <- signature -- body (block)
,
codeElement <- if (src.body.oclIsUndefined()) then
Sequence{}
else
src.body
endif
),
signature: kdm!Signature (
name <- src.name -- return parameter
,
parameterUnit <- if (src.oclIsKindOf(java!ConstructorDeclaration)) then
Sequence{}
else
if (src.returnType.oclIsUndefined()) then
Sequence{}
else
thisModule.CreateReturnParameterUnit(src.returnType)
endif
endif -- usual parameters
,
parameterUnit <- src.parameters -- exceptions thrown
,
parameterUnit <- src.thrownExceptions -> collect(e | thisModule.
CreateExceptionParameterUnit(e))
)
do {
-- redefinitions / redefined MethodDeclaration
tgt.codeRelation <- if (src.oclIsKindOf(java!ConstructorDeclaration)) then
Sequence{}
else
if (src.redefinedMethodDeclaration.oclIsUndefined()) then
Sequence{}
else
thisModule.CreateImplementationOf(src, src.redefinedMethodDeclaration)
endif
endif;
}
}
-- Transforms a method into a method unit
rule MethodDeclarationToTemplateUnit {
from
src: java!AbstractMethodDeclaration (
(not src.typeParameters.isEmpty() --and
-- Anonymous types are not translated in kdm
--src.anonymousClassDeclarationOwner.oclIsUndefined()
)
)
to
tgt: kdm!TemplateUnit (
-- template parameter should be first
name <- src.name,
codeElement <- src.typeParameters,
codeElement <- method
),
method: kdm!MethodUnit (
name <- src.name,
kind <- if (src.oclIsKindOf(java!ConstructorDeclaration)) then #constructor
else #method endif,
export <- src -> getVisibility() -- signature management
,
type <- signature,
codeElement <- signature -- attributes to store additional information
-- (visibility stay redundant)
,
attribute <- if (src.modifier.oclIsUndefined()) then
Sequence{}
else
src.modifier
endif -- annotations
,
codeRelation <- src.annotations -- comments
,
comment <- src.comments -- body (block)
,
codeElement <- if (src.body.oclIsUndefined()) then
Sequence{}
else
src.body
endif -- redefinitions / redefined MethodDeclaration
,
codeRelation <- if (src.oclIsKindOf(java!ConstructorDeclaration)) then
Sequence{}
else
if (src.redefinedMethodDeclaration.oclIsUndefined()) then
Sequence{}
else
thisModule.CreateImplementationOf(src, src.
redefinedMethodDeclaration)
endif
endif -- source file management
,
source <- sourceRef
),
sourceRef: kdm!SourceRef (
language <- 'java',
region <- sourceRegion
),
sourceRegion: kdm!SourceRegion (
language <- 'java' -- size expensive and redundant with SourceFile
-- information
-- ,path <- if (src.originalCompilationUnit.oclIsUndefined()) then
-- 'internal'
-- else
-- src.originalCompilationUnit.originalFilePath
-- endif
,
file <- if (src.originalCompilationUnit.oclIsUndefined()) then
src.originalClassFile
else
src.originalCompilationUnit
endif
),
signature: kdm!Signature (
name <- src.name -- return parameter
,
parameterUnit <- if (src.oclIsKindOf(java!ConstructorDeclaration)) then
Sequence{}
else
if (src.returnType.oclIsUndefined()) then
Sequence{}
else
thisModule.CreateReturnParameterUnit(src.returnType)
endif
endif -- usual parameters
,
parameterUnit <- src.parameters -- exceptions thrown
,
parameterUnit <- src.thrownExceptions -> collect(e | thisModule.
CreateExceptionParameterUnit(e))
)
}
-- transforms a Block into a BlockUnit, it is here just to do articulation
-- between members and statements/expressions.
rule BlockToBlockUnit extends ASTNodeToAbstractCodeElement {
from
src: java!Block
to
tgt: kdm!BlockUnit (
codeElement <- if (src.statements -> isEmpty()) then
Sequence{}
else
src.statements
endif
)
}
rule CommentToCommentUnit {
from
src: java!Comment (
-- Anonymous types are not translated in kdm
not src.refImmediateComposite().oclIsTypeOf(java!AnonymousClassDeclaration) and
-- kdm!Imports can not own comments
not src.refImmediateComposite().oclIsTypeOf(java!ImportDeclaration) and --
-- Some expressions are not managed
not (src.refImmediateComposite().oclIsKindOf(java!Expression) and thisModule
-> filterExpression(src.refImmediateComposite()) -> isEmpty()) --
-- not src.refImmediateComposite().oclIsTypeOf(java!TypeAccess)
-- and
-- not src.refImmediateComposite().oclIsTypeOf(java!SingleVariableAccess)
)
to
tgt: kdm!CommentUnit (
text <- src.content
)
}
-- to explicit relationship between methods
lazy rule CreateImplementationOf {
from src: java!MethodDeclaration
, redefined: java!MethodDeclaration
to
tgt: kdm!ImplementationOf (
from <- src,
to <- redefined
)
}
-- ===================================================== ---
-- Rules for the method Parameters
-- This part gives the transformation for the parameters of a Java method
-- ===================================================== ---
-- Transforms a method parameter (other cases should be handled in further
-- transformations)
rule SingleVariableDeclarationToParameterUnit extends NamedElementToAbstractCodeElement {
from
src: java!SingleVariableDeclaration (
-- only for MethodDeclaration !
if (src.methodDeclaration.oclIsUndefined()) then
false
else
-- Anonymous types are not translated in kdm
--src.methodDeclaration.anonymousClassDeclarationOwner.oclIsUndefined()
true
endif
)
to
tgt: kdm!ParameterUnit (
kind <- #unknown,
type <- src.type -> getType()
)
}
--create the return Parameter
lazy rule CreateReturnParameterUnit {
from
src: java!TypeAccess
to
kdmParameter: kdm!ParameterUnit (
kind <- #return,
type <- src -> getType() -- source file management
,
source <- sourceRef
),
sourceRef: kdm!SourceRef (
language <- 'java',
region <- sourceRegion
),
sourceRegion: kdm!SourceRegion (
language <- 'java' -- size expensive and redundant with SourceFile
-- information
-- ,path <- if (src.originalCompilationUnit.oclIsUndefined()) then
-- 'internal'
-- else
-- src.originalCompilationUnit.originalFilePath
-- endif
,
file <- if (src.originalCompilationUnit.oclIsUndefined()) then
src.originalClassFile
else
src.originalCompilationUnit
endif
)
}
--create the exception Parameter
lazy rule CreateExceptionParameterUnit {
from
src: java!TypeAccess
to
kdmParameter: kdm!ParameterUnit (
kind <- #throws,
type <- src -> getType() -- source file management
,
source <- sourceRef
),
sourceRef: kdm!SourceRef (
language <- 'java',
region <- sourceRegion
),
sourceRegion: kdm!SourceRegion (
language <- 'java' -- size expensive and redundant with SourceFile
-- information
-- ,path <- if (src.originalCompilationUnit.oclIsUndefined()) then
-- 'internal'
-- else
-- src.originalCompilationUnit.originalFilePath
-- endif
,
file <- if (src.originalCompilationUnit.oclIsUndefined()) then
src.originalClassFile
else
src.originalCompilationUnit
endif
)
}
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- Statements
-- helpers --
-- rules --
-- handling statements and expressions :
-- everything must go through an ActionElement : indeed, "action relationships" can only
-- be owned by an ActionElement ...
-- alternatively, they can be put in the codeElement collection? Is it correct?
-- because of this limitation, all expressions will be expressed as ActionElement's also
-- (like statements)
-- and action relationships will be explicitly created instead of using mapping.
-- so for each expression we will have one ActionElement and perhaps one or more
-- ActionRelation.
-- ===================================================
-- Transformation of code in blocks: if, while, for, etc.
-- There are 23 statements in all, but Block is already handled by the parent
-- transformation
-- ===================================================
-- AssertStatement
rule AssertStatementToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!AssertStatement
to
tgt: kdm!ActionElement (
kind <- 'assert',
name <- 'assert' -- referenced elements
,
codeElement <- thisModule -> filterExpression(src.expression),
codeElement <- if (src.message.oclIsUndefined()) then
Sequence{}
else
Sequence{src.message}
endif
)
}
-- BreakStatement
rule BreakStatementToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!BreakStatement
to
tgt: kdm!ActionElement (
kind <- 'break' -- referenced elements
,
actionRelation <- if (src.label.oclIsUndefined()) then
Sequence{}
else
thisModule -> CreateCallsForLabel(src)
endif
)
}
-- create a Calls from a Method invocation (target element is binding with a TemplateUnit
-- and we want a MethodUnit !)
lazy rule CreateCallsForGenericMethod {
from
src: java!AbstractMethodInvocation
to
tgt: kdm!Calls (
from <- src,
to <- thisModule.resolveTemp(src.method, 'method')
)
}
-- create a Calls from a Method invocation
lazy rule CreateCalls {
from
src: java!AbstractMethodInvocation (
-- Methods from anonymous types will not be translated
-- because they will not have owners in kdm
src.method.anonymousClassDeclarationOwner.oclIsUndefined()
)
to
tgt: kdm!Calls (
from <- src,
to <- src.method
)
}
-- create a Calls from a Label goto
lazy rule CreateCallsForLabel {
from
src: java!Statement
to
tgt: kdm!Calls (
from <- src,
to <- src.label
)
}
-- CatchClause
rule CatchClauseToCatchUnit extends ASTNodeToAbstractCodeElement {
from
src: java!CatchClause
to
tgt: kdm!CatchUnit (
kind <- 'catch',
name <- 'catch' -- referenced elements
,
codeElement <- if (src.body.oclIsUndefined()) then
Sequence{}
else
src.body
endif,
codeElement <- if (src.exception.oclIsUndefined()) then
Sequence{}
else
src.exception
endif,
actionRelation <- exceptionFlow
),
exceptionFlow: kdm!ExceptionFlow (
from <- src.refImmediateComposite(),
to <- src
)
}
-- Transforms a method parameter (other cases should be handled in further
-- transformations)
rule SingleVariableDeclarationToStorableUnit extends NamedElementToAbstractCodeElement {
from
src: java!SingleVariableDeclaration (
-- only for CatchClause and EnhancedForStatement !
src.methodDeclaration.oclIsUndefined()
)
to
tgt: kdm!StorableUnit (
kind <- #local -- attributes to store additional information (final, etc.)
,
attribute <- if (src.modifier.oclIsUndefined()) then
Sequence{}
else
src.modifier
endif,
type <- src.type -> getType(),
codeElement <- if (src.initializer.oclIsUndefined()) then
Sequence{}
else
Sequence{src.initializer}
endif
)
}
-- ConstructorInvocation
rule ConstructorInvocationToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!ConstructorInvocation
to
tgt: kdm!ActionElement (
kind <- 'constructor invocation' -- referenced elements
,
actionRelation <- if (src.method.oclIsUndefined()) then
Sequence{}
else
if (src.method.typeParameters.isEmpty()) then
thisModule -> CreateCalls(src)
else
thisModule -> CreateCallsForGenericMethod(src)
endif
endif,
codeElement <- src.arguments
)
}
-- ContinueStatement
rule ContinueStatementToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!ContinueStatement
to
tgt: kdm!ActionElement (
kind <- 'continue',
name <- 'continue' -- referenced elements
,
actionRelation <- if (src.label.oclIsUndefined()) then
Sequence{}
else
thisModule -> CreateCallsForLabel(src)
endif
)
}
-- DoStatement
rule DoStatementToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!DoStatement
to
tgt: kdm!ActionElement (
kind <- 'do',
name <- 'do' -- referenced elements
,
codeElement <- thisModule -> filterExpression(src.expression),
codeElement <- if (src.body.oclIsUndefined()) then
Sequence{}
else
src.body
endif
)
}
-- EmptyStatement
rule EmptyStatementToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!EmptyStatement
to
tgt: kdm!ActionElement (
kind <- 'empty',
name <- 'empty' -- referenced elements
)
}
-- EnhancedForStatement
rule EnhancedForStatementToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!EnhancedForStatement
to
tgt: kdm!ActionElement (
kind <- 'foreach',
name <- 'foreach' -- referenced elements
,
codeElement <- thisModule -> filterExpression(src.expression),
codeElement <- if (src.body.oclIsUndefined()) then
Sequence{}
else
src.body
endif,
codeElement <- if (src.parameter.oclIsUndefined()) then
Sequence{}
else
src.parameter
endif
)
}
-- ExpressionStatement
rule ExpressionStatementToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!ExpressionStatement
to
tgt: kdm!ActionElement (
kind <- 'expression statement',
name <- 'expression statement' -- referenced elements
,
codeElement <- thisModule -> filterExpression(src.expression)
)
}
-- ForStatement
rule ForStatementToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!ForStatement
to
tgt: kdm!ActionElement (
kind <- 'for',
name <- 'for' -- referenced elements
,
codeElement <- thisModule -> filterExpression(src.expression),
codeElement <- src.initializers,
codeElement <- src.updaters,
codeElement <- if (src.body.oclIsUndefined()) then
Sequence{}
else
src.body
endif
)
}
-- IfStatement
rule IfStatementToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!IfStatement
to
tgt: kdm!ActionElement (
kind <- 'if',
name <- 'if' -- referenced elements
,
codeElement <- thisModule -> filterExpression(src.expression),
codeElement <- if (src.thenStatement.oclIsUndefined()) then
Sequence{}
else
src.thenStatement
endif,
codeElement <- if (src.elseStatement.oclIsUndefined()) then
Sequence{}
else
src.elseStatement
endif
)
}
-- LabeledStatement
rule LabeledStatementToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!LabeledStatement
to
tgt: kdm!ActionElement (
kind <- 'label',
name <- 'label' -- referenced elements
,
codeElement <- if (src.body.oclIsUndefined()) then
Sequence{}
else
src.body
endif
)
}
-- ReturnStatement
rule ReturnStatementToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!ReturnStatement
to
tgt: kdm!ActionElement (
kind <- 'return',
name <- 'return' -- referenced elements
,
codeElement <- thisModule -> filterExpression(src.expression)
)
}
-- SuperConstructorInvocation
rule SuperConstructorInvocationToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!SuperConstructorInvocation
to
tgt: kdm!ActionElement (
kind <- 'super constructor invocation',
name <- 'super constructor invocation' -- referenced elements
,
actionRelation <- if (src.method.oclIsUndefined()) then
Sequence{}
else
if (src.method.typeParameters.isEmpty()) then
thisModule -> CreateCalls(src)
else
thisModule -> CreateCallsForGenericMethod(src)
endif
endif,
codeElement <- src.arguments -> collect(e | thisModule ->
filterExpression(e)) -> flatten(),
codeElement <- thisModule -> filterExpression(src.expression)
)
}
-- SwitchCase
rule SwitchCaseToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!SwitchCase
to
tgt: kdm!ActionElement (
kind <- 'case',
name <- 'case' -- referenced elements
,
codeElement <- thisModule -> filterExpression(src.expression)
)
}
-- SwitchStatement
rule SwitchStatementToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!SwitchStatement
to
tgt: kdm!ActionElement (
kind <- 'switch',
name <- 'switch' -- referenced elements
,
codeElement <- thisModule -> filterExpression(src.expression),
codeElement <- src.statements
)
}
-- SynchronizedStatement
rule SynchronizedStatementToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!SynchronizedStatement
to
tgt: kdm!ActionElement (
kind <- 'synchronized',
name <- 'synchronized' -- referenced elements
,
codeElement <- thisModule -> filterExpression(src.expression),
codeElement <- if (src.body.oclIsUndefined()) then
Sequence{}
else
src.body
endif
)
}
-- ThrowStatement
rule ThrowStatementToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!ThrowStatement
to
tgt: kdm!ActionElement (
kind <- 'throw',
name <- 'throw' -- referenced elements
,
codeElement <- thisModule -> filterExpression(src.expression)
)
}
-- TypeDeclarationStatement
rule TypeDeclarationStatementToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!TypeDeclarationStatement
to
tgt: kdm!ActionElement (
kind <- 'type declaration',
name <- 'type declaration' -- referenced elements
,
codeElement <- if (src.declaration.oclIsUndefined()) then
Sequence{}
else
src.declaration
endif
)
}
-- TryStatement
rule TryStatementToTryUnit extends ASTNodeToAbstractCodeElement {
from
src: java!TryStatement
to
tgt: kdm!TryUnit (
kind <- 'try',
name <- 'try' -- referenced elements
,
codeElement <- if (src.body.oclIsUndefined()) then
Sequence{}
else
src.body
endif,
codeElement <- if (src.finally.oclIsUndefined()) then
Sequence{}
else
src.finally
endif,
codeElement <- src.catchClauses
)
}
-- VariableDeclarationStatement
rule VariableDeclarationStatementToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!VariableDeclarationStatement
to
tgt: kdm!ActionElement (
kind <- 'variable declaration',
name <- 'variable declaration' -- referenced elements
,
codeElement <- src.fragments,
codeRelation <- src.annotations -- management of fragments initializers (when
-- it is a class instance creation)
,
codeElement <- src.fragments -> select(fragment | fragment.initializer.
oclIsTypeOf(java!ClassInstanceCreation)) -> collect(fragment |
fragment.initializer)
)
}
-- VariableDeclarationFragment
-- Transforms a local variable
-- we have to find a solution to store action element potentially
-- created from initializer.
-- However, in a storable unit, we cannot contain action elements directly ...
rule VariableDeclarationFragmentInLocalDeclarationToStorableUnit extends
NamedElementToAbstractCodeElement {
from
src: java!VariableDeclarationFragment (
-- not for FieldDeclaration !
not src.variablesContainer.oclIsKindOf(java!FieldDeclaration)
)
to
tgt: kdm!StorableUnit (
name <- src.name,
kind <- #local -- attributes to store additional information (final, etc.)
,
attribute <- if (src.refImmediateComposite().oclIsTypeOf(java!Model)) then
-- Unresolved items
Sequence{}
else
if (src.refImmediateComposite().modifier.oclIsUndefined()) then
Sequence{}
else
src.refImmediateComposite().modifier
endif
endif,
type <- if (src.variablesContainer.oclIsUndefined()) then
OclUndefined -- Unresolved items
else
if (src.variablesContainer.type.oclIsUndefined()) then
OclUndefined
else
src.variablesContainer.type -> getType()
endif
endif,
codeRelation <- if (src.initializer.oclIsUndefined()) then
Sequence{}
else
thisModule -> CreateHasValue(src, src.initializer)
endif -- in some cases, if initializer is a complex expression,
-- we don't know how to store created elements in the storable unit
)
}
lazy rule CreateHasValue {
from src: java!VariableDeclaration,
value: java!Expression
to
tgt: kdm!HasValue (
from <- src,
to <- if (value.oclIsTypeOf(java!SingleVariableAccess)) then
value.variable
else
if (value.oclIsTypeOf(java!UnresolvedItemAccess)) then
-- TODO add a better management of unresolved items ...
thisModule -> CreateDatatype(value) -- type of element is
-- java!UnresolvedItem
else
value
endif
endif
)
}
lazy rule CreateDatatype {
from
src: java!UnresolvedItemAccess
to
tgt: kdm!Datatype (
name <- src.element.name
)
}
-- VariableDeclarationFragment
-- Transforms a global variable (other cases should be handled in further transformations)
rule VariableDeclarationFragmentInFieldToStorableUnit extends
NamedElementToAbstractCodeElement {
from
src: java!VariableDeclarationFragment (
-- only for FieldDeclaration !
src.variablesContainer.oclIsKindOf(java!FieldDeclaration)
)
to
tgt: kdm!StorableUnit (
kind <- if (src.variablesContainer.modifier.oclIsUndefined()) then
#global
else
if (src.variablesContainer.modifier.static) then
#static
else
#global
endif
endif -- attributes to store additional information (final, etc.)
,
attribute <- if src.variablesContainer.modifier.oclIsUndefined() then
Sequence{}
else
src.variablesContainer.modifier
endif,
type <- if (src.variablesContainer.type.oclIsUndefined()) then
OclUndefined
else
src.variablesContainer.type -> getType()
endif -- ok, but how to store action element that will be potentially
-- created from initializer ?
,
codeRelation <- if (src.initializer.oclIsUndefined()) then
Sequence{}
else
thisModule -> CreateHasValue(src, src.initializer)
endif,
codeRelation <- src.variablesContainer.annotations,
comment <- src.variablesContainer.comments
)
}
-- WhileStatement
rule WhileStatementToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!WhileStatement
to
tgt: kdm!ActionElement (
kind <- 'while',
name <- 'while' -- referenced elements
,
codeElement <- thisModule -> filterExpression(src.expression),
codeElement <- if (src.body.oclIsUndefined()) then
Sequence{}
else
src.body
endif
)
}
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- ##########################################################################
-- Expressions
-- rules --
-- handling statements and expressions :
-- everything must go through an ActionElement : indeed, "action relationships" can only
-- be owned by an ActionElement ...
-- alternatively, they can be put in the codeElement collection? Is it correct?
-- because of this limitation, all expressions will be expressed as ActionElement's also
-- (like statements)
-- and action relationships will be explicitly created instead of using mapping.
-- so for each expression we will have one ActionElement and perhaps one or more
-- ActionRelation.
-- ===================================================
-- Transformation of code in blocks: if, while, for, etc.
--
-- There are 27 statements in all.
-- But some model elements will also be handled (AnnotationMemberValuePair for example)
-- ===================================================
-- As explained below, for each expression we will be mapping to an ActionElement
-- and this is this element that will be able to contain ActionRelation!
-- Annotation
-- specific case
-- an annotation is always applied on a body declaration element,
-- so it should be mapped to a subclass of AbstractCodeRelationship
--rule AnnotationToActionElement extends ASTNodeToAbstractCodeElement {
-- from src : java!Annotation
-- to tgt :kdm!ActionElement(
-- kind <- 'annotation'
-- ,name <- 'annotation'
-- referenced elements
-- ,actionRelation <- if(src.type.oclIsUndefined()) then Sequence{} else
-- thisModule->CreateCreates(src.type) endif
-- ,codeElement <- src.values -- collection
-- )
--}
rule AnnotationToHasValue {
from
src: java!Annotation (
-- specific filter for annotation as value of another annotation (single
-- value or array)
not src.refImmediateComposite().oclIsTypeOf(java!AnnotationMemberValuePair) --and
-- not src.refImmediateComposite().oclIsTypeOf(java!ArrayInitializer)
)
to
tgt: kdm!HasValue (
from <- src -> filterRefImmediateCompositeForAnnotation(),
to <- src.type -> getType() -- specify that it is an annotation
,
annotation <- annotation -- store parameters as attributes
,
attribute <- src.values
),
annotation: kdm!Annotation (
text <- 'annotation'
)
}
-- specific case for field declarations that have an annotation
-- if the field declaration has fragments, then the HasValue.form should use the fragment.
helper context java!Annotation def: filterRefImmediateCompositeForAnnotation(): OclAny =
if (self.refImmediateComposite().oclIsTypeOf(java!FieldDeclaration)) then
if (self.refImmediateComposite().fragments->isEmpty()) then
self.refImmediateComposite()
else
self.refImmediateComposite().fragments -> first()
endif
else
if (self.refImmediateComposite().oclIsTypeOf(java!VariableDeclarationStatement))
then
self.refImmediateComposite().fragments -> first()
else
if (self.refImmediateComposite().oclIsTypeOf(java!ArrayInitializer) or self.
refImmediateComposite().oclIsTypeOf(java!AnnotationMemberValuePair))
then
OclUndefined
else
self.refImmediateComposite()
endif
endif
endif;
lazy rule CreateCreates {
from
src: java!TypeAccess
to
tgt: kdm!Creates (
from <- src.refImmediateComposite(),
to <- src -> getType()
)
}
-- AnnotationMemberValuePair
--rule AnnotationMemberValuePairToActionElement extends NamedElementToAbstractCodeElement
-- {
-- from src : java!AnnotationMemberValuePair
-- to tgt :kdm!ActionElement(
-- kind <- 'annotation member value'
-- ,name <- 'annotation member value'
-- -- referenced elements
-- ,actionRelation <- if(src.member.oclIsUndefined()) then Sequence{} else
-- thisModule->CreateWritesForAnnotationMember(src) endif
-- ,codeElement <- if(src.value.oclIsUndefined()) then Sequence{} else
-- Sequence{src.value} endif
-- )
--}
-- TODO Works only for values which are literals, not values which are code expressions
-- (uncommon use case)
rule AnnotationMemberValuePairToAttribute {
from
src: java!AnnotationMemberValuePair
to
tgt: kdm!Attribute (
tag <- if (src.member.oclIsUndefined()) then
'no member'
else
src.member.name
endif,
value <- if (src.value.oclIsUndefined()) then
'no value'
else
if (src.value.oclIsKindOf(java!NumberLiteral)) then
src.value.tokenValue.toString()
else
if (src.value.oclIsKindOf(java!StringLiteral) or src.value.
oclIsKindOf(java!CharacterLiteral)) then
src.value.escapedValue
else
if (src.value.oclIsKindOf(java!BooleanLiteral)) then
src.value.value.toString()
else
if (src.value.oclIsKindOf(java!Annotation)) then
src.value.type.type.name
else
'value expression'
endif
endif
endif
endif
endif
)
}
lazy rule CreateWritesForAnnotationMember {
from
src: java!AnnotationMemberValuePair
to
tgt: kdm!Writes (
from <- src,
to <- src.member
)
}
lazy rule CreateWritesForVariableAccess {
from
src: java!SingleVariableAccess
to
tgt: kdm!Writes (
from <- src.refImmediateComposite(),
to <- src.variable
)
}
-- ArrayAccess
rule ArrayAccessToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!ArrayAccess
to
tgt: kdm!ActionElement (
kind <- 'array access',
name <- 'array access' -- referenced elements
-- if attribut "array" is a reference (access), we have to create corresponding
-- relationship
,
codeElement <- thisModule -> filterExpression(src.array),
actionRelation <- if (src.array.oclIsUndefined()) then
Sequence{}
else
if (src.array.oclIsTypeOf(java!SingleVariableAccess)) then
thisModule -> CreateAddresses(src.array)
else
Sequence{}
endif
endif,
codeElement <- thisModule -> filterExpression(src.index)
)
}
-- ArrayCreation
rule ArrayCreationToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!ArrayCreation
to
tgt: kdm!ActionElement (
kind <- 'array creation',
name <- 'array creation' -- referenced elements
,
actionRelation <- if (src.type.oclIsUndefined()) then
Sequence{}
else
thisModule -> CreateCreates(src.type)
endif,
codeElement <- src.dimensions -> collect(e | thisModule ->
filterExpression(e)) -> flatten(),
codeElement <- thisModule -> filterExpression(src.initializer)
)
}
-- ArrayInitializer
rule ArrayInitializerToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!ArrayInitializer (
-- filter initialier of AnnotationMemberValuePair
not src.refImmediateComposite().oclIsTypeOf(java!AnnotationMemberValuePair)
)
to
tgt: kdm!ActionElement (
kind <- 'array initializer',
name <- 'array initializer' -- referenced elements
,
codeElement <- src.expressions -> select(e | not
e.oclIsTypeOf(java!Annotation)) -> collect(e | thisModule ->
filterExpression(e)) -> flatten() -- referenced elements
,
codeRelation <- src.expressions -> select(e | e.oclIsTypeOf(java!Annotation))
)
}
-- ArrayLengthAccess
rule ArrayLengthAccessToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!ArrayLengthAccess
to
tgt: kdm!ActionElement (
kind <- 'array length access',
name <- 'array length access' -- referenced elements
-- TODO should we create a Reads object ? the length field doesn't exist, so ...
,
codeElement <- thisModule -> filterExpression(src.array)
)
}
-- Assignment
rule AssignmentToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!Assignment
to
tgt: kdm!ActionElement (
kind <- 'assignment' -- operator
,
name <- if (src.operator.oclIsUndefined()) then
'assignment'
else
src.operator.toString()
endif -- referenced elements
-- left hand side
,
actionRelation <- if (src.leftHandSide.oclIsUndefined()) then
Sequence{}
else
if (src.leftHandSide.oclIsTypeOf(java!SingleVariableAccess)) then
thisModule -> CreateWritesForVariableAccess(src.leftHandSide)
else
Sequence{}
endif
endif,
codeElement <- thisModule -> filterExpression(src.leftHandSide) -- right hand
-- side
,
actionRelation <- if (src.rightHandSide.oclIsUndefined()) then
Sequence{}
else
if (src.rightHandSide.oclIsTypeOf(java!SingleVariableAccess)) then
thisModule -> CreateReads(src.rightHandSide)
else
Sequence{}
endif
endif,
codeElement <- thisModule -> filterExpression(src.rightHandSide)
)
}
-- generally apply to fields
lazy rule CreateReads {
from
src: java!SingleVariableAccess
to
tgt: kdm!Reads (
from <- src.refImmediateComposite(),
to <- src.variable
)
}
-- BooleanLiteral
rule BooleanLiteralToValue extends ASTNodeToAbstractCodeElement {
from
src: java!BooleanLiteral
to
tgt: kdm!Value (
name <- 'boolean literal',
ext <- if (src.value) then
'true'
else
'false'
endif,
type <- kdm!BooleanType.allInstances() -> first()
)
}
-- CastExpression
rule CastExpressionToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!CastExpression
to
tgt: kdm!ActionElement (
kind <- 'cast',
name <- 'cast' -- referenced elements
,
codeElement <- thisModule -> filterExpression(src.expression),
actionRelation <- if (src.type.oclIsUndefined()) then
Sequence{}
else
thisModule -> CreateUsesType(src.type)
endif
)
}
-- generally apply to cast or type conversion
lazy rule CreateUsesType {
from
src: java!TypeAccess
to
tgt: kdm!UsesType (
from <- src.refImmediateComposite(),
to <- src.type
)
}
-- CharacterLiteral
rule CharacterLiteralToValue extends ASTNodeToAbstractCodeElement {
from
src: java!CharacterLiteral
to
tgt: kdm!Value (
name <- 'character literal',
ext <- src.escapedValue,
type <- kdm!CharType.allInstances() -> first()
)
}
-- ClassInstanceCreation
rule ClassInstanceCreationToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!ClassInstanceCreation
to
tgt: kdm!ActionElement (
kind <- 'class instance creation',
name <- 'class instance creation' -- referenced elements
,
codeElement <- thisModule -> filterExpression(src.expression),
codeElement <- src.arguments -> collect(e | thisModule ->
filterExpression(e)) -> flatten() -- anonymous type are contained by
-- class instance creation
,
codeElement <- if (src.anonymousClassDeclaration.oclIsUndefined()) then
Sequence{}
else
src.anonymousClassDeclaration
endif,
actionRelation <- if (src.method.oclIsUndefined()) then
Sequence{}
else
thisModule -> CreateCalls(src)
endif,
actionRelation <- if (src.type.oclIsUndefined()) then
Sequence{}
else
thisModule -> CreateCreates(src.type)
endif
)
}
-- ConditionalExpression
rule ConditionalExpressionToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!ConditionalExpression
to
tgt: kdm!ActionElement (
kind <- 'conditional',
name <- 'conditional' -- referenced elements
,
codeElement <- thisModule -> filterExpression(src.expression),
codeElement <- thisModule -> filterExpression(src.thenExpression),
codeElement <- thisModule -> filterExpression(src.elseExpression)
)
}
-- FieldAccess
rule FieldAccessToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!FieldAccess
to
tgt: kdm!ActionElement (
kind <- 'field access',
name <- 'field access' -- referenced elements
,
codeElement <- thisModule -> filterExpression(src.expression),
actionRelation <- if (src.field.oclIsUndefined()) then
Sequence{}
else
thisModule -> CreateAddresses(src.field)
endif
)
}
lazy rule CreateAddresses {
from
src: java!SingleVariableAccess
to
tgt: kdm!Addresses (
from <- src.refImmediateComposite(),
to <- src.variable
)
}
-- InfixExpression
rule InfixExpressionToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!InfixExpression
to
tgt: kdm!ActionElement (
kind <- 'infix expression',
name <- src.operator.toString() -- referenced elements
,
codeElement <- thisModule -> filterExpression(src.leftOperand),
codeElement <- thisModule -> filterExpression(src.rightOperand),
codeElement <- src.extendedOperands -> collect(e | thisModule ->
filterExpression(e)) -> flatten()
)
}
-- InstanceofExpression
rule InstanceofExpressionToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!InstanceofExpression
to
tgt: kdm!ActionElement (
kind <- 'instanceof',
name <- 'instanceof' -- referenced elements
,
codeElement <- thisModule -> filterExpression(src.leftOperand),
actionRelation <- if (src.rightOperand.oclIsUndefined()) then
Sequence{}
else
thisModule -> CreateUsesType(src.rightOperand)
endif
)
}
-- MethodInvocation
rule MethodInvocationToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!MethodInvocation
to
tgt: kdm!ActionElement (
kind <- 'method invocation',
name <- 'method invocation' -- referenced elements
,
codeElement <- thisModule -> filterExpression(src.expression),
codeElement <- src.arguments -> collect(e | thisModule ->
filterExpression(e)) -> flatten(),
actionRelation <- if (src.method.oclIsUndefined()) then
Sequence{}
else
if (src.method.typeParameters.isEmpty()) then
thisModule -> CreateCalls(src)
else
thisModule -> CreateCallsForGenericMethod(src)
endif
endif
)
}
-- NullLiteral
rule NullLiteralToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!NullLiteral
to
tgt: kdm!ActionElement (
kind <- 'null',
name <- 'null'
)
}
-- NumberLiteral
rule NumberLiteralToValue extends ASTNodeToAbstractCodeElement {
from
src: java!NumberLiteral
to
tgt: kdm!Value (
name <- 'number literal',
ext <- src.tokenValue -- TODO : find the real type (int, float, ...)
,
type <- kdm!IntegerType.allInstances() -> first()
)
}
-- ParenthesizedExpression
rule ParenthesizedExpressionToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!ParenthesizedExpression
to
tgt: kdm!ActionElement (
kind <- 'parenthesized',
name <- 'parenthesized' -- referenced elements
,
codeElement <- thisModule -> filterExpression(src.expression)
)
}
-- PostfixExpression
rule PostfixExpressionToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!PostfixExpression
to
tgt: kdm!ActionElement (
kind <- 'postfix expression',
name <- src.operator.toString() -- referenced elements
,
codeElement <- thisModule -> filterExpression(src.operand)
)
}
-- PrefixExpression
rule PrefixExpressionToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!PrefixExpression
to
tgt: kdm!ActionElement (
kind <- 'prefix expression',
name <- src.operator.toString() -- referenced elements
,
codeElement <- thisModule -> filterExpression(src.operand)
)
}
-- StringLiteral
rule StringLiteralToValue extends ASTNodeToAbstractCodeElement {
from
src: java!StringLiteral (
-- TODO waiting for a strategy for storing enum constant arguments
not src.refImmediateComposite().oclIsKindOf(java!EnumConstantDeclaration)
)
to
tgt: kdm!Value (
name <- 'string literal',
ext <- src.escapedValue,
type <- kdm!StringType.allInstances() -> first()
)
}
-- SuperFieldAccess
rule SuperFieldAccessToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!SuperFieldAccess
to
tgt: kdm!ActionElement (
kind <- 'super field access',
name <- 'super field access' -- referenced elements
,
actionRelation <- if (src.field.oclIsUndefined()) then
Sequence{}
else
thisModule -> CreateUsesType(src.field)
endif,
actionRelation <- if (src.qualifier.oclIsUndefined()) then
Sequence{}
else
if (src.qualifier.oclIsTypeOf(java!SingleVariableAccess)) then
thisModule -> CreateReads(src.qualifier)
else
-- because it might apply to a type sometimes
-- YourType.super.yourmethod();
Sequence{}
endif
endif
)
}
-- SuperMethodInvocation
rule SuperMethodInvocationToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!SuperMethodInvocation
to
tgt: kdm!ActionElement (
kind <- 'super method invocation',
name <- 'super method invocation' -- referenced elements
,
codeElement <- src.arguments -> collect(e | thisModule ->
filterExpression(e)) -> flatten(),
actionRelation <- if (src.method.oclIsUndefined()) then
Sequence{}
else
if (src.method.typeParameters.isEmpty()) then
thisModule -> CreateCalls(src)
else
thisModule -> CreateCallsForGenericMethod(src)
endif
endif,
actionRelation <- if (src.qualifier.oclIsUndefined()) then
Sequence{}
else
if (src.qualifier.oclIsTypeOf(java!SingleVariableAccess)) then
thisModule -> CreateReads(src.qualifier)
else
-- because it might apply to a type sometimes
-- YourType.super.yourmethod();
Sequence{}
endif
endif
)
}
-- ThisExpression
rule ThisExpressionToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!ThisExpression
to
tgt: kdm!ActionElement (
kind <- 'this',
name <- 'this' -- referenced elements
,
actionRelation <- if (src.qualifier.oclIsUndefined()) then
Sequence{}
else
thisModule -> CreateUsesType(src.qualifier)
endif
)
}
-- TypeLiteral
rule TypeLiteralToValue extends ASTNodeToAbstractCodeElement {
from
src: java!TypeLiteral
to
tgt: kdm!Value (
name <- 'type literal',
type <- src.type -> getType()
)
}
-- VariableDeclarationExpression
rule VariableDeclarationExpressionToActionElement extends ASTNodeToAbstractCodeElement {
from
src: java!VariableDeclarationExpression
to
tgt: kdm!ActionElement (
kind <- 'variable declaration',
name <- 'variable declaration' -- referenced elements
,
codeElement <- src.fragments -> collect(e | thisModule ->
filterExpression(e)) -> flatten(),
actionRelation <- if (src.type.oclIsUndefined()) then
Sequence{}
else
thisModule -> CreateUsesType(src.type)
endif
)
}