blob: 8564e8cb50b0d70463ca81316116dd5d8f405bca [file] [log] [blame]
--@atlcompiler atl2006
--Copyright (c) 2009 Mia-Software, 2017 Inria.
--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
-- Hugo Bruneliere (Inria) - Bug 526229 - InfixExpression rule update
-- Bug 526234 - SwitchStatementToActionElement update
--
-- @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 = src.refImmediateComposite().type;
}
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
OclUndefined -- typeParameters does not exist on UnresolvedTypeDeclaration
else
if (src.type.type.typeParameters.isEmpty()) then
OclUndefined
else
src.type->getType()
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
,actionRelation <-
if(src.expression.oclIsUndefined()) then
Sequence{}
else
if (src.expression.oclIsTypeOf(java!SingleVariableAccess)) then
thisModule->CreateReads(src.expression)
else
Sequence{}
endif
endif
,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
,actionRelation <-
if (src.leftOperand.oclIsUndefined()) then
Sequence{}
else
if (src.leftOperand.oclIsTypeOf(java!SingleVariableAccess)) then
thisModule -> CreateReads(src.leftOperand)
else
Sequence{}
endif
endif
,actionRelation <-
if (src.rightOperand.oclIsUndefined()) then
Sequence{}
else
if (src.rightOperand.oclIsTypeOf(java!SingleVariableAccess)) then
thisModule -> CreateReads(src.rightOperand)
else
Sequence{}
endif
endif
,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
)
}