blob: 098e1ee018513d6bd0733985697c1a72f27d64d8 [file] [log] [blame]
[module mt2mtl('http://www.eclipse.org/acceleo/mt/2.6.0')/]
[import ServiceUtils/]
[comment]
This will be used to convert a given Acceleo.org "template"
(an aggregate of scripts) to an Acceleo MTL "module" (aggregate of queries,
templates and macros). The name of the "template"'s containing file
will be used as the name of the converted module.
templ : Acceleo.org template that needs be converted.
[/comment]
[template public convertToModule(templ : Template)]
[comment @main /]
[file (fullpathName(), false)]
['['/]module [templ.shortName().replaceAll('-', '')/]([for (templ.imports->select(oclIsKindOf(Metamodel))) separator (', ')]'[name/]'[/for])/]
[for (imported : Resource | templ.imports->reject(oclIsKindOf(Metamodel))
->reject(oclIsKindOf(Service)))]
['['/]import [imported.qualifiedImportName()/]/]
[/for]
[comment We'll assume that a template beginning with "is*" or "has*" is a query returning a boolean/]
[for (script : Script | templ.scripts) separator('\n')]
[if (script.isBooleanQuery())][script.convertToBooleanQuery()/][elseif (script.isCollectionQuery())][script.convertToCollectionQuery()/][else][script.convertToTemplate()/][/if]
[/for]
[for (adaptCall : Call | selectUniqueCallAdapt())]
['['/]query private ['adaptTo'.concat(adaptCall.getAdaptType())/](o : OclAny) : [adaptCall.inferAdaptReturnType()/] = invoke('org.eclipse.acceleo.compatibility.services.MigrationServices', '['adaptTo'.concat(adaptCall.arguments->first().convertExpressionToOCL().replaceAll('\'', ''))/](java.lang.Object)', Sequence{o})/]
[/for]
[for (service : Method | templ.allCalls()->select(c | c.isServiceCall()).getTargetService()->asSet())]
[service.convertToQuery()/]
[/for]
[/file]
[/template]
[query private selectUniqueCallAdapt(templ : Template) : OrderedSet(Call) =
templ.ancestors()->last().allCalls()->select(name = 'adapt')
->iterate(call : Call; resSeq : Sequence(Call) = Sequence{} |
if resSeq->isNotTypeAdaptInCallsList(call.getAdaptType()) then
resSeq->append(call)
else
resSeq
endif)->asOrderedSet()
/]
[query private isNotTypeAdaptInCallsList(callList : Sequence(Call)
,str : String) : Boolean =
callList->collect(c:Call | getAdaptType(c))->select(s | s = str)
->isEmpty()
/]
[query private getAdaptType(adaptCall : Call) : String =
adaptCall.arguments->first().convertExpressionToOCL()
.replaceAll('\'', '') /]
[comment]
Generate the full path name of file module
template : Acceleo Template will be converted to an Acceleo MTL Module.
[/comment]
[query private fullpathName(templ : Template) : String =
templ.name.replaceAll('\\.', '/')
.replaceAll('-', '')
.concat('.mtl')/]
[comment Test if mt Script probably return a list/]
[query private isCollectionQuery(script : Script) : Boolean =
script.descriptor.file.statements->size() = 0 and
script.statements->size() = 1 and
if script.statements->first().oclIsKindOf(mt::statements::Feature) then
let subFeature : mt::statements::Feature =
script.statements->first().oclAsType(mt::statements::Feature)
in
if subFeature.expression.oclIsKindOf(mt::expressions::CallSet) then
let cSet : mt::expressions::CallSet =
subFeature.expression.oclAsType(mt::expressions::CallSet)
in
cSet.calls->size() = 1
and not cSet.calls->first().filter.oclIsUndefined()
else
false
endif
else
false
endif/]
[comment Test if mt Script probably return a boolean /]
[query private isBooleanQuery(script : Script) : Boolean =
script.descriptor.name.matches('(is|has)[A-Z_-].*')
and script.descriptor.file.statements->size() = 0/]
[query private matches(string : String, regex : String) :
Boolean = string.replace(regex, '') <> string/]
[comment]
This will be used to convert a given Acceleo.org "script"
to an Acceleo MTL "template".
script : Acceleo script that will be converted to an Acceleo MTL template.
[/comment]
[template public convertToTemplate(script : Script)]
['['/]template public [genTemplateHeader()/][']'/]
[if (script.descriptor.file.statements->size() > 0)]
['['/]comment This template is called by the main module file /]
['['/]file ([genFileName()/], false))]
[/if]
[script.statements.convertStatement()/]
[if (script.descriptor.file.statements->size() > 0)]
['[/'/]file]
[/if]
['[/'/]template[']'/]
[/template]
[comment]
Convert the header from mt to mtl
script : Acceleo script that will be converted to an Acceleo MTL query.
[/comment]
[query public genTemplateHeader(script : Script) : String =
script.descriptor.name.replaceAll('-', '')
.concat('(')
.concat(script.descriptor.type.getVariableNameForType())
.concat(' : ')
.concat(script.descriptor.type.convertType())
.concat(script.getAdditionalArguments())
.concat(')')
.concat(script.genPostTrim())
/]
[comment]
Convert post trim in the header
script : Acceleo script that will be converted to an Acceleo MTL query.
[/comment]
[query public genPostTrim(script : Script) : String =
if script.descriptor._post.oclIsUndefined() then
''
else
let setcall : CallSet =
script.descriptor._post.oclAsType(CallSet)
in
if setcall.calls->select(call : Call | call.name = 'trim')->isEmpty() then
''
else
' post(trim())'
endif
endif
/]
[comment]
Generate the content of file tag
script : Acceleo script that will be converted to an Acceleo MTL query.
[/comment]
[query public genFileName(script : Script) : Sequence(String) =
let
stmts : OrderedSet(mt::statements::Statement) =
script.descriptor.file.statements,
size : Integer =
script.descriptor.file.statements->size()
in
stmts->collect(stmt : mt::statements::Statement |
let convertedStmt : String =
stmt.convertStatementToOCL()
in
if size = 1 and stmt.oclIsKindOf(mt::statements::Text) then
'\''.concat(convertedStmt).concat('\'')
else if stmt.oclIsKindOf(mt::statements::Text) then
convertedStmt
else if stmts->indexOf(stmt) = 1 then
convertedStmt
else
'.concat('.concat(convertedStmt).concat(')')
endif endif endif)
/]
[comment]
This will be used to convert a given Acceleo.org "script"
to an Acceleo MTL "query" returning a boolean.
script : Acceleo script that will be converted to an Acceleo MTL query.
[/comment]
[template public convertToBooleanQuery(script : Script)]
['['/]query public [genTemplateHeader()/] : Boolean =
[script.statements.convertStatementToOCL()/]
['/]'/]
[/template]
[template public convertToCollectionQuery(script : Script)]
['['/]query public [genTemplateHeader()/] : Collection(OclAny) =
[script.statements.convertStatementToOCL()/]
['/]'/]
[/template]
[template public convertToQuery(method : Method)]
['['/]query private [method.name/]([for (param : Parameter | method.parameters) separator (', ')]arg[method.parameters->indexOf(param) - 1/] : [param.type.convertJavaTypeToOCL()/][/for]) : [method.return.convertJavaTypeToOCL()/] = invoke('[method.ancestors(Service)->first().name/]', '[method.signature()/]', Sequence{[for (param : Parameter | method.parameters) separator (', ')]arg[method.parameters->indexOf(param) - 1/][/for]})/]
[/template]
[query private getAdditionalArguments(script : Script) : String =
let additionalArguments : OrderedSet(String) =
script.eAllContents(mt::expressions::Call)
->select(name = 'args')->collect(name.concat(arguments->first()
.convertExpressionToOCL()))->asOrderedSet()
->sortedBy(s|s)
in
additionalArguments->iterate(arg; res : String = '' | (
if additionalArguments->first() = arg then
', '
else
res
endif).concat(arg).concat(' : OclAny')
.concat(
if additionalArguments->last() <> arg then
', '
else
''
endif))
/]
[comment]
This is as placeholder for the compiler to be able to compile calls on "Statement", yet this
getting called means we're missing a specialized implementation of "convertStatement" for the
runtime class of the given statement.
statement : Statement that is to be converted.
[/comment]
[template public convertStatement(statement : Statement)]
<<<FIXME : couldn't convert statement [statement/].>>>
[/template]
[comment]
This is as placeholder for the compiler to be able to compile calls on "Statement", yet this
getting called means we're missing a specialized implementation of "convertStatementToOCL" for the
runtime class of the given statement.
statement : Statement that is to be converted.
[/comment]
[template public convertStatementToOCL(statement : Statement)]
<<<FIXME : couldn't convert statement [statement/] to OCL.>>>
[/template]
[template public convertStatement(cmtStmt : Comment)]
['['/]comment [cmtStmt.value/]/]
[/template]
[template public convertStatementToOCL(cmtStmt : Comment)]
[cmtStmt.convertStatement()/]
[/template]
[template public convertStatement(ifStmt : If)
{isMultiLine : Boolean =
ifStmt.eAllContents(Text)->collect(value.index('\n') > 0)
->includes(true);}]
['['/]if [ifStmt.condition.convertExpressionToOCL()/]][if (isMultiLine)]['\n'/][/if][ifStmt.thenStatements.convertStatement()/][for (elseIf : If | ifStmt.elseIf)]['['/]elseif [elseIf.condition.convertExpressionToOCL()/]][if (isMultiLine)]['\n'/][/if][elseIf.thenStatements.convertStatement()/][/for][if (ifStmt.elseStatements->size() > 0)]['['/]else][if (isMultiLine)]['\n'/][/if][ifStmt.elseStatements.convertStatement()/][/if]['['/]/if][if (isMultiLine)]['\n'/][/if]
[/template]
[template public convertStatementToOCL(ifStmt : If)
{isMultiLine : Boolean =
ifStmt.eAllContents(Text)->collect(value.index('\n') > 0)
->includes(true);}]
if [ifStmt.condition.convertExpressionToOCL()/] then [if (isMultiLine)]['\n'/][/if][ifStmt.thenStatements.convertStatement()/][for (elseIf : If | ifStmt.elseIf)] else if [elseIf.condition.convertExpressionToOCL()/] then [if (isMultiLine)]['\n'/][/if][elseIf.thenStatements.convertStatement()/][/for][if (ifStmt.elseStatements->size() > 0)] else [if (isMultiLine)]['\n'/][/if][ifStmt.elseStatements.convertStatement()/][/if] endif[if (isMultiLine)]['\n'/][/if][for (elseIf : If | ifStmt.elseIf)] endif[/for]
[/template]
[comment]
Converts a for loop of Acceleo.org to Acceleo MTL. There is no difference between this and its
converStatementToOCL counterpart.
forLoop : The for loop that will be converted.
[/comment]
[template public convertStatement(forLoop : For) {isMultiLine : Boolean = forLoop.eAllContents(Text)->collect(value.index('\n') > 0)->includes(true);}]
['['/]for [if (forLoop.iterator.oclIsKindOf(mt::expressions::Parenthesis))][forLoop.iterator.convertExpressionToOCL()/][else]([forLoop.iterator.convertExpressionToOCL()/])[/if]][if (isMultiLine)]['\n'/][/if][forLoop.statements.convertStatement()/]['['/]/for][if (isMultiLine)]['\n'/][/if]
[/template]
[comment]
Converts a for loop of Acceleo.org to Acceleo MTL. There is no difference between this and its
converStatement counterpart.
forLoop : The for loop that will be converted.
[/comment]
[template public convertStatementToOCL(forLoop : For)]
[forLoop.convertStatement()/]
[/template]
[comment]
Converts a composite statement (property call, operation call, ...) to an
Acceleo MTL equivalent.
The returned expression will be nested within brackets.
This mustn't be used for Acceleo.org "script"s' 'file' attribute :
file="<%name%>.txt" must be converted to name.concat('.txt')
and not [name/].txt.
feature : Statement that is to be converted.
[/comment]
[template public convertStatement(feature : Feature)]
[if (not(isInUserCodeMarkerArea()))][expression.convertExpression()/][/if]
[/template]
[comment]
Test if feature is in a User Code Marler Area.
feature : Statement that is to be tested.
[/comment]
[query public isInUserCodeMarkerArea(obj : ecore::EObject) : Boolean =
if strInUserCodeMarkerArea(obj).endsWith('in') then
true
else
false
endif
/]
[comment]
Retun string out if Fearture is out of UserCode Marker Area
and in if in the UserCode Marker Area
in : have preceding usercode and not a text statment with NewLine
beteewn feature and usercode
feature : Statement that is to be tested.
[/comment]
[query public strInUserCodeMarkerArea(obj : ecore::EObject) : String =
obj.precedingSiblings()
->iterate( e ; acc : String = '' |
if e.oclIsTypeOf(mt::statements::Feature)
and e.oclAsType(mt::statements::Feature).isStartOfUserCode() then
acc.concat('in')
else if e.oclIsTypeOf(mt::statements::Text)
and e.oclAsType(mt::statements::Text).isTextEndOfAreaMarker() then
acc.concat('out')
else
acc
endif endif
)
/]
[comment]
Converts a composite statement (property call, operation call, ...)
to an Acceleo MTL equivalent.
The returned expression will not be nested within brackets.
This must be used for Acceleo.org "script"s' 'file' attribute :
file="<%name%>.txt" must be converted to name.concat('.txt')
and not [name/].txt.
feature : Statement that is to be converted.
[/comment]
[template public convertStatementToOCL(feature : Feature)]
[feature.expression.convertExpressionToOCL()/]
[/template]
[comment]
Converts a static text part region from Acceleo.org to Acceleo MTL. With this,
the text will be returned as is; as opposed to convertStatementToOCL.
text : Text that needs be converted.
[/comment]
[template public convertStatement(text : Text)]
[(let textValue : String =
if isInUserCodeMarkerArea() then
text.value.trimToFirstCarriageReturnOrEmplyString()
.convertStaticTextToAcceleo()
else
text.value
endif
in textValue.convertStaticTextToAcceleo())/]
[/template]
[comment]
Converts a static text part region from Acceleo.org to Acceleo MTL. With this,
the text will be nested within simple quotes, and possibly preceded
by ".concat(" if we're in the middle of a composite expression.
text : Text that needs be converted.
[/comment]
[template public convertStatementToOCL(text : Text)]
[(let textValue : String =
if isInUserCodeMarkerArea() then
text.value.trimToFirstCarriageReturn()
.convertStaticTextToAcceleo()
else
text.value.convertStaticTextToAcceleo()
endif
in
if oclAsType(ecore::EObject).eContainer()
.eContents()->indexOf(text) > 1 then
'.concat(\''.concat(textValue).concat('\')')
else
textValue endif)
/]
[/template]
[query private convertStaticTextToAcceleo(value : String) : String =
value.replaceAll('(\\[|\\])', '\\[\'$0\'/\\]')/]
[query private trimToFirstCarriageReturnOrEmplyString(value : String) : String =
if value.contains('\r\n') then
value.substring(value.index('\r\n') + 2, value.size())
else if value.contains('\r') then
value.substring(value.index('\r') + 1, value.size())
else if value.contains('\n') then
value.substring(value.index('\n') + 1, value.size())
else
''
endif endif endif/]
[query private trimToFirstCarriageReturn(value : String) : String =
let textValue : String = trimToFirstCarriageReturnOrEmplyString(value)
in
if textValue = '' then
value
else
textValue
endif/]
[comment]
Test if the currrent feature is an user code feature
feature : Statement that is to be tested.
[/comment]
[query private isStartOfUserCode(feature : Feature) : Boolean =
if feature.expression
.oclIsKindOf(mt::expressions::CallSet) then
let cSet : mt::expressions::CallSet =
feature.expression
.oclAsType(mt::expressions::CallSet)
in
cSet.calls->size() = 1
and cSet.calls->first().name = 'startUserCode'
else
false
endif
/]
[comment]
This is as placeholder for the compiler to be able to compile calls on
"Expression", yet this getting called means we're missing a specialized
implementation of "convertExpression" for the runtime class
of the given expression.
expression : The expression we should convert to an Acceleo equivalent.
[/comment]
[template public convertExpression(expression : Expression)]
<<<FIXME : couldn't convert expression [expression/].>>>
[/template]
[comment]
This is as placeholder for the compiler to be able to compile calls on
"Expression", yet this getting called means we're missing a specialized
implementation of "convertExpressionToOCL" for the
runtime class of the given expression.
expression : The expression we should convert to an Acceleo equivalent.
[/comment]
[template public convertExpressionToOCL(expression : Expression)]
<<<FIXME : couldn't convert expression [expression/].>>>
[/template]
[comment]
This will recursively call for the conversion of all calls contained
within the given callSet. The returned expression will
be nests within brackets.
For example, <%name%>.txt would be converted to [name.concat('.txt')/]
as opposed to convertExpressionToOCL which would return name.concat('.txt').
callSet : CallSet which contents are to be converted to Acceleo MTL equivalents.
[/comment]
[template public convertExpression(callSet : CallSet)]
[if (callSet.calls->size() = 1 and (callSet.calls->first().name = 'startUserCode' or callSet.calls->first().name = 'endUserCode'))][callSet.calls->first().convertUserCodeCall()/][else]['['/][convertExpressionToOCL()/]/][/if]
[/template]
[comment]
This will recursively call for the conversion of all calls contained within the given callSet. The
returned expression will not be nested within brackets.
For example, <%name%>.txt would be converted to name.concat('.txt') as opposed to convertExpression
which would return [name.concat('.txt')/].
callSet : CallSet which contents are to be converted to Acceleo MTL equivalents.
[/comment]
[template public convertExpressionToOCL(callSet : CallSet)]
[callSet.calls.convertExpressionToOCL()/]
[/template]
[comment]
Converts a single Acceleo.org call to an Acceleo MTL equivalent.
The returned expression will be nested within brackets.
call : The particular call that is to be converted to an equivalent.
[/comment]
[template public convertExpression(call : Call)]
['['/][call.getSeparator()/][if (call.isOperationCall())][convertServiceCall()/][else][convertPropertyCall()/][/if][if (not call.filter.oclIsUndefined())]->select([call.filter.convertExpressionToOCL()/])[/if]/]
[/template]
[comment]
Converts a single Acceleo.org call to an Acceleo MTL equivalent. The returned expression will not
be nested within brackets.
call : The particular call that is to be converted to an equivalent.
[/comment]
[template public convertExpressionToOCL(call : Call)]
[call.getSeparator()/][if (call.isOperationCall())][convertServiceCall()/][else][convertPropertyCall()/][/if][if (not call.filter.oclIsUndefined())]->select([call.filter.convertExpressionToOCL()/])[/if]
[/template]
[template public convertExpression(notExpr : Not)]
['['/][convertExpressionToOCL()/]/]
[/template]
[template public convertExpressionToOCL(notExpr : Not)]
not ([notExpr.expression.convertExpressionToOCL()/])
[/template]
[template public convertExpression(operator : Operator)]
['['/][convertExpressionToOCL()/]/]
[/template]
[template public convertExpressionToOCL(operator : Operator)]
[for (operand : Expression | operator.operands)][operand.convertExpressionToOCL()/][if (operator.operands->last() <> operand)][' '/][operator.operator.convertOperator()/][' '/][/if][/for]
[/template]
[comment]
Converts Acceleo.org parenthesis expression to an Acceleo MTL equivalent.
The expression nested within these parenthesis will be converted
nested within brackets.
parenthesis : Parenthesis expression that is to be converted to an equivalent.
[/comment]
[template public convertExpression(parenthesis : Parenthesis)]
([parenthesis.expression.convertExpression()/])
[/template]
[comment]
Converts Acceleo.org parenthesis expression to an Acceleo MTL equivalent.
The expression nested within these parenthesis will not be converted
nested within brackets.
parenthesis : Parenthesis expression that is to be converted to an equivalent.
[/comment]
[template public convertExpressionToOCL(parenthesis : Parenthesis)]
([parenthesis.expression.convertExpressionToOCL()/])
[/template]
[template public convertExpression(stringLiteral : StringLiteral)]
'[value/]'
[/template]
[template public convertExpressionToOCL(stringLiteral : StringLiteral)]
[convertExpression()/]
[/template]
[template public convertExpression(intLiteral : IntegerLiteral)]
[value/]
[/template]
[template public convertExpressionToOCL(intLiteral : IntegerLiteral)]
[convertExpression()/]
[/template]
[template public convertExpression(doubleLiteral : DoubleLiteral)]
[value/]
[/template]
[template public convertExpressionToOCL(doubleLiteral : DoubleLiteral)]
[convertExpression()/]
[/template]
[template public convertExpression(booleanLiteral : BooleanLiteral)]
[value/]
[/template]
[template public convertExpressionToOCL(booleanLiteral : BooleanLiteral)]
[convertExpression()/]
[/template]
[template public convertExpression(nullLiteral : NullLiteral)]
null
[/template]
[template public convertExpressionToOCL(nullLiteral : NullLiteral)]
[convertExpression()/]
[/template]
[comment]
Returns the short name (without path information) of the given template.
templ : Template which path is to be considered.
[/comment]
[query private shortName(templ : Template) : String =
templ.name.replaceAll('.*\\.(.*)', '$1')/]
[comment]
Returns the qualified name (without path information) of the given template.
templ : Template which path is to be considered.
[/comment]
[query private qualifiedImportName(templ : Resource) : String =
templ.name.replaceAll('\\.', '::')
.replaceAll('-', '')
.replaceAll('.*\\.(.*)', '$1')/]
[comment]
Converts qualified type names to uml notation.
For example, "ecore.EClass" would be converted to "ecore::EClass".
type : name of the type that is to be converted.
[/comment]
[query private convertType(type : String) : String =
let converted : String =
type.replace('\\.', '::')
in
if converted = 'EObject' then
'ecore::EObject'
else
converted
endif/]
[comment]
This will return a suitable variable name from a given type.
For example, this would return "eClass" for type "ecore.EClass" or
"_package" for type "uml.Package".
type : name of the type we need a variable for.
[/comment]
[query private getVariableNameForType(type : String) : String =
let protectedNames : Sequence(String) =
Sequence{'template', 'query', 'macro', 'import',
'module', 'private', 'protected', 'public',
'for', 'if', 'let', 'else', 'then'},
name : String =
if type.contains('.') then
type.substring(type.index('.') + 1, type.size())
else
type
endif
in
if protectedNames->includes(name) then
'_'.concat(name).toLowerFirst()
else
name.toLowerFirst()
endif/]
[query private convertSource(call : Call) : String =
let precedingCalls : Sequence(Call) =
call.oclAsType(ecore::EObject).eContainer().eContents()
.oclAsType(Call)->subSequence(1, call.oclAsType(ecore::EObject)
.eContainer().eContents()->indexOf(call))->excluding(call)
in
precedingCalls->iterate(element; res : String = ''
| res.concat(element.convertExpressionToOCL()))/]
[query private getSeparator(call : Call) : String =
if call.isFirstCall()
or call.isIgnoredCall() then
''
else
if isListOperation() then
'->'
else
'.'
endif
endif/]
[query private isFirstCall(call : Call) : Boolean =
call.oclAsType(ecore::EObject).eContainer()
.eContents()->indexOf(call) = 1/]
[query private isIgnoredCall(call : Call) : Boolean =
not call.isFirstCall()
and call.name = 'current'
and call.arguments->size() = 0/]
[query private isListOperation(call : Call) : Boolean =
call.name = 'select' or
call.name = 'delete' or
call.name = 'cast' or
call.name = 'filter' or
call.name = 'nMinimize' or
call.name = 'minmize' or
call.name = 'nContains' or
call.name = 'nFirst' or
call.name = 'nLast' or
call.name = 'nGet' or
call.name = 'nReverse' or
call.name = 'reverse' or
call.name = 'nSize' or
call.name = 'nSort' or
call.name = 'sort' or
call.name = 'sep' or
call.name = 'sepStr'/]
[query private convertOperator(operator : String) : String =
if operator = '&&' then
'and'
else if operator = '||' then
'or'
else if operator = '!=' then
'<>'
else if operator = '==' then
'='
else
operator
endif endif endif endif/]
[query private convertOperators(expression : String) :
String = expression.substituteAll('&&', 'and')
.substituteAll('||', 'or')
.substituteAll('!=', '<>')
.substituteAll('==', '=')
.substituteAll('!', ' not ')/]
[query private convertPropertyCall(call : Call) : String =
let reservedKeywords : Sequence(String) =
Sequence{'and', 'body', 'context', 'def', 'derive', 'else',
'endif', 'endPackage', 'if', 'implies', 'in', 'init',
'inv', 'let', 'not', 'oper', 'or', 'package', 'post',
'pre', 'static', 'then', 'xor'}
in
if reservedKeywords->includes(call.name) then
'_'.concat(call.name)
else
call.name
endif/]
[query private convertServiceCall(call : Call) : String =
if call.name.isStringService() then
convertStringService()
else if call.name.isEObjectService() then
convertEObjectService()
else if call.name.isRequestService() then
convertRequestService()
else if call.name.isResourceService() then
convertResourceService()
else if call.name.isSystemService() then
convertSystemService()
else if call.name.isXPathService() then
convertXPathService()
else if call.isENodeService() then
convertENodeService()
else if call.name.isContextService() then
convertContextService()
else if call.name.isPropertiesService() then
convertPropertiesService()
else
call.name.concat(call.convertArguments())
endif endif endif endif endif endif endif endif endif/]
[query private convertUserCodeCall(call : Call) : String =
if call.name = 'startUserCode' then
'[protected('.concat(call.protectedAreaMarker())
.concat(')]').concat(call.getProtectedNewLine())
else
'[/protected]'
endif/]
[query private protectedAreaMarker(call : Call) : String =
getSequenceAreaMarker()->iterate(e;r : String ='' |
r.concat(e)
)
/]
[query private protectedAreaMarkerText(statTxt : Text) : String =
let textValue : String =
statTxt.value
in
if textValue.contains('\r\n')
and textValue.index('\r\n') = textValue.index('\r')
and textValue.index('\r\n') < textValue.index('\n') then
'\''+textValue.substring(1, textValue.index('\r\n'))
.replaceAll('\n', '').replaceAll('\r', '') + '\''
else if textValue.contains('\r')
and (not(textValue.contains('\n'))
or textValue.index('\r') < textValue.index('\n')) then
'\''+textValue.substring(1, textValue.index('\r'))
.replaceAll('\n', '').replaceAll('\r', '')+ '\''
else if textValue.contains('\n') then
'\''+textValue.substring(1, textValue.index('\n'))
.replaceAll('\n', '').replaceAll('\r', '')+ '\''
else
'\''+textValue+ '\''
endif endif endif/]
[query private getSequenceAreaMarker(call : Call) : Sequence(String) =
call.ancestors(mt::statements::Feature)->first()
.oclAsType(ecore::EObject).followingSiblings()
->iterate(e;r : Sequence(String) = Sequence{}|
if r->last()<> '%end%'
and e.oclIsTypeOf(mt::statements::Feature) then
r->including(
e.oclAsType(mt::statements::Feature)
.convertStatementToOCL().trim()
)->including(' + ')
else if r->last() <> '%end%'
and e.oclIsTypeOf(mt::statements::Text)
and e.oclAsType(mt::statements::Text)
.isTextEndOfAreaMarker() then
r->including(e.oclAsType(mt::statements::Text)
.protectedAreaMarkerText())
->including('%end%')
else if r->last()<> '%end%'
and e.oclIsTypeOf(mt::statements::Text) then
r->including(e.oclAsType(mt::statements::Text)
.protectedAreaMarkerText())
->including(' + ')
else
r
endif endif endif
)->reject(s | s = '%end%')
/]
[query private isTextEndOfAreaMarker(txt : Text) : Boolean =
let textValue : String =
txt.value
in
if textValue.contains('\r') then
true
else if textValue.contains('\n') then
true
else
false
endif endif
/]
[comment]
Extract the newLine after Area Marker
call : The particular call that is to be converted to an equivalent.
[/comment]
[query private getProtectedNewLine(call : Call) : String =
let nextFeatureOrText : Sequence(OclAny) =
call.ancestors(mt::statements::Feature)->first()
.oclAsType(ecore::EObject).followingSiblings()
in
nextFeatureOrText->iterate(e;r : String = ''|
r.concat(
if e.oclIsTypeOf(mt::statements::Text) then
let textValue : String =
e.oclAsType(mt::statements::Text).value
in
if textValue.contains('\r\n') then
if r = '' then
'\r\n'
else
''
endif
else if textValue.contains('\r') then
if r = '' then
'\r'
else
''
endif
else if textValue.contains('\n') then
if r = '' then
'\n'
else
''
endif
else
''
endif endif endif
else
''
endif
)
)
/]
[query private followingSibling(object : ecore::EObject) : OclAny =
let siblings : Sequence(OclAny) =
object.eContainer().eContents()
in
if siblings->indexOf(object) = siblings->size() then
object
else
siblings->at(siblings->indexOf(object) + 1)
endif/]
[query private precedingSibling(object : ecore::EObject) : OclAny =
let siblings : Sequence(OclAny) =
object.eContainer().eContents()
in
if siblings->indexOf(object) = 1 then
object
else
siblings->at(siblings->indexOf(object) - 1)
endif/]
[query private convertArguments(call : Call) : String =
if call.arguments->size() = 0 then
'()'
else
call.arguments->iterate(arg;
aggregate : String = '(' |
aggregate.concat(arg.convertExpressionToOCL())
.concat(
if call.arguments->last() = arg then
''
else
', '
endif)).concat(')')
endif/]
[query private inferAdaptReturnType(adaptCall : Call) : String =
let typeName : String =
adaptCall.arguments->first().convertExpressionToOCL().toLower()
in
if typeName = 'double' then
'Real'
else if typeName = 'eobject'
or typeName = 'enode' then
'ecore::EObject'
else if typeName = 'list'
or typeName = 'enodelist' then
'Sequence(T)'
else if typeName = 'integer' then
'Integer'
else if typeName = 'boolean' then
'Boolean'
else
'String'
endif endif endif endif endif/]
[query private convertJavaTypeToOCL(typeName : String) : String =
if typeName = 'java.math.BigDecimal' then
'Real'
else if typeName = 'java.lang.Double'
or typeName = 'double' then
'Real'
else if typeName = 'java.math.BigInteger' then
'Integer'
else if typeName = 'java.lang.Integer'
or typeName = 'int' then
'Integer'
else if typeName = 'java.lang.Short'
or typeName = 'short' then
'Integer'
else if typeName = 'boolean' then
'Boolean'
else if typeName = 'java.lang.String' then
'String'
else if typeName = 'java.util.List'
or typeName = 'java.util.ArrayList'
or typeName = 'java.util.LinkedList' then
'Sequence(OclAny)'
else if typeName = 'java.util.Set'
or typeName = 'java.util.HashSet' then
'Set(OclAny)'
else if typeName = 'java.util.LinkedHashSet' then
'OrderedSet(OclAny)'
else if typeName = 'java.util.Collection' then
'Collection(OclAny)'
else if typeName = 'fr.obeo.acceleo.gen.template.eval.ENodeList' then
'Sequence(OclAny)'
else if typeName = 'fr.obeo.acceleo.gen.template.eval.ENode' then
'OclAny'
else
typeName.replace('.*\\.', '')
endif endif endif endif endif endif endif endif endif
endif endif endif endif/]
[query private convertStringService(call : Call) : String =
if call.name = 'length' then
'size()'
else if call.name = 'toUpperCase' then
'toUpper()'
else if call.name = 'toLowerCase' then
'toLower()'
else if call.name = 'toU1Case' then
'toUpperFirst()'
else if call.name = 'toL1Case' then
'toLowerFirst()'
else if call.name = 'substring'
and call.arguments->size() = 1 then
'substring('.concat(call.arguments->first().convertExpressionToOCL())
.concat(' + 1, ').concat(call.convertSource()).concat('.size())')
else if call.name = 'substring'
and call.arguments->size() = 2 then
'substring('.concat(call.arguments->first().convertExpressionToOCL())
.concat(' + 1, ').concat(call.arguments->last()
.convertExpressionToOCL()).concat(')')
else if call.name = 'replaceAll' then
'replaceAll('.concat(call.arguments->first().convertExpressionToOCL()
.escapeChars()).concat(', ').concat(call.arguments->last()
.convertExpressionToOCL().escapeChars()).concat(')')
else if call.name = 'trim' then
'trim()'
else if call.name = 'startsWith' then
'startsWith('.concat(call.arguments->first()
.convertExpressionToOCL()).concat(')')
else if call.name = 'endsWith' then
'endsWith('.concat(call.arguments->first().convertExpressionToOCL())
.concat(')')
else if call.name = 'equalsIgnoreCase' then
'toLower() = '.concat(call.arguments->first().convertExpressionToOCL())
.concat('.toLower()')
else if call.name = 'matches' then
'replace('.concat(call.arguments->first().convertExpressionToOCL())
.concat(', \'\') <> ').concat(call.convertSource())
else if call.name = 'charAt' then
'substring('.concat(call.arguments->first().convertExpressionToOCL())
.concat(' + 1, ').concat(call.arguments->first()
.convertExpressionToOCL()).concat(' + 1)')
else if call.name = 'indexOf'
and call.arguments->size() = 1 then
'index('.concat(call.arguments->first().convertExpressionToOCL())
.concat(')')
else if call.name = 'indexOf'
and call.arguments->size() = 2 then
'substring('.concat(call.arguments->last().convertExpressionToOCL())
.concat(' + 1, ').concat(call.convertSource())
.concat('.size()).index(').concat(call.arguments->first()
.convertExpressionToOCL()).concat(') + ')
.concat(call.arguments->last().convertExpressionToOCL())
else if call.name = 'lastIndexOf'
and call.arguments->size() = 1 then
'<<<FIXME "lastIndexOf" has no equivalent in Acceleo OCL. lastIndexOf('
.concat(call.arguments->first().convertExpressionToOCL())
.concat(')>>>')
else if call.name = 'lastIndexOf'
and call.arguments->size() = 2 then
'<<<FIXME "lastIndexOf" has no equivalent in Acceleo OCL. lastIndexOf('
.concat(call.arguments->first().convertExpressionToOCL())
.concat(', ').concat(call.arguments->last()
.convertExpressionToOCL()).concat(')>>>')
else if call.name = 'split' then
'<<<FIXME "split" has no equivalent in Acceleo OCL. split('
.concat(call.arguments->first().convertExpressionToOCL())
.concat(')>>>')
else if call.name = 'indentSpace' then
'replaceAll(\'(?!<\\r)\\n|\\r\\n|\\r(?!\\n)\', \'$0 \')'
else if call.name = 'indentTab'then
'replaceAll(\'(?!<\\r)\\n|\\r\\n|\\r(?!\\n)\', \'$0\\t\')'
else
'<<<FIXME couldn\'t convert call '.concat(call.name)
.concat(' to Acceleo OCL>>>')
endif endif endif endif endif endif endif endif endif endif endif endif
endif endif endif endif endif endif endif endif endif/]
[query private convertEObjectService(call : Call) : String =
if call.name = 'eAllContents'
and call.arguments->size() = 0 then
'eAllContents()'
else if call.name = 'eAllContents'
and call.arguments->size() = 1 then
'eAllContents('.concat(call.arguments->first().convertExpressionToOCL()
.replaceAll('\'', '')).concat(')')
else if call.name = 'eClass' then
'eClass()'
else if call.name = 'eContainer'
and call.arguments->size() = 0 then
'eContainer()'
else if call.name = 'eContainer'
and call.arguments->size() = 1 then
'ancestors('.concat(call.arguments->first().convertExpressionToOCL()
.replaceAll('\'', '')).concat(')->first()')
else if call.name = 'eContainingFeature' then
'eContainingFeature()'
else if call.name = 'eContainmentFeature' then
'eContainmentFeature()'
else if call.name = 'eContents' then
'eContents()'
else if call.name = 'eCrossReferences' then
'eCrossReferences()'
else if call.name = 'eResource' then
'eResource()'
else if call.name = 'eResourceName' then
'<<<FIXME "eResourceName" has no equivalent in Acceleo OCL. eResourceName()>>>'
else if call.name = 'getRootContainer' then
'ancestors()->last()'
else if call.name = 'load' then
'<<<FIXME "load" has no equivalent in Acceleo OCL. load('
.concat(call.arguments->first().convertExpressionToOCL())
.concat(')>>>')
else
'<<<FIXME couldn\'t convert call '.concat(call.name)
.concat(' to Acceleo OCL>>>')
endif endif endif endif endif endif endif endif endif endif
endif endif endif/]
[query private convertRequestService(call : Call) : String =
if call.name = 'select'
and call.arguments->size() = 1 then
'select('.concat(call.arguments->first().convertExpressionToOCL()
.replace('^\'', '').replace('\'$', '')
.convertOperators()).concat(')')
else if call.name = 'select'
and call.arguments->size() = 2 then
'select('.concat(call.arguments->first().convertExpressionToOCL()
.convertOperators()).concat(' = ')
.concat(call.arguments->last().convertExpressionToOCL())
.concat(')')
else if call.name = 'delete'
and call.arguments->size() = 1 then
'reject('.concat(call.arguments->first().convertExpressionToOCL()
.replaceAll('\'', '')).concat(')')
else if call.name = 'delete'
and call.arguments->size() = 2 then
'reject('.concat(call.arguments->first().convertExpressionToOCL()
.replaceAll('\'', '')).concat(' = ')
.concat(call.arguments->last().convertExpressionToOCL())
.concat(')')
else if call.name = 'evaluate' then
'<<<FIXME "evaluate" has no equivalent in Acceleo OCL. evaluate('
.concat(call.arguments->first().convertExpressionToOCL())
.concat(')>>>')
else
'<<<FIXME couldn\'t convert call '.concat(call.name)
.concat(' to Acceleo OCL>>>')
endif endif endif endif endif/]
[query private convertResourceService(call : Call) : String =
if call.name = 'getFileContent' then
'<<<FIXME "getFileContent" has no equivalent in Acceleo OCL. getFileContent('
.concat(call.arguments->first().convertExpressionToOCL())
.concat(')>>>')
else if call.name = 'getChainPath' then
'<<<FIXME "getChainPath" has no equivalent in Acceleo OCL. getChainPath()>>>'
else
'<<<FIXME couldn\'t convert call '
.concat(call.name).concat(' to Acceleo OCL>>>')
endif endif/]
[query private convertSystemService(call : Call) : String =
if call.name = 'i' then
'i - 1'
else if call.name = 'args' then
'args'.concat(arguments->first().convertExpressionToOCL())
else
'<<<FIXME couldn\'t convert call '
.concat(call.name).concat(' to Acceleo OCL>>>')
endif endif/]
[query private convertXPathService(call : Call) : String =
if call.name = 'ancestor' then
'ancestors()'
else if call.name = 'parent' then
'eContainer()'
else if call.name = 'self' then
'self'
else if call.name = 'child' then
'eContents()'
else if call.name = 'descendant' then
'eAllContents()'
else if call.name = 'precedingSibling' then
'precedingSiblings()'
else if call.name = 'preceding' then
'<<<FIXME "preceding()" has no equivalent in Acceleo OCL. preceding()>>>'
else if call.name = 'followingSibling' then
'followingSiblings()'
else if call.name = 'following' then
'<<<FIXME "following()" has no equivalent in Acceleo OCL. following()>>>'
else
'<<<FIXME couldn\'t convert call '
.concat(call.name).concat(' to Acceleo OCL>>>')
endif endif endif endif endif endif endif endif endif/]
[query private convertENodeService(call : Call) : String =
if call.name = 'adapt' then
'adaptTo'.concat(call.arguments->first()
.convertExpressionToOCL().replaceAll('\'', '')).concat('()')
else if call.name = 'cast' then
'filter('.concat(call.arguments->first()
.convertExpressionToOCL().replaceAll('\'', '')).concat(')')
else if call.name = 'filter' then
'filter('.concat(call.arguments->first()
.convertExpressionToOCL().replaceAll('\'', '')).concat(')')
else if call.name = 'current'
and call.arguments->size() = 0 then
if call.isFirstCall() then
'self'
else
''
endif
else if call.name = 'current'
and call.arguments->size() = 1
and call.arguments->first().oclIsKindOf(IntegerLiteral) then
let contextIndex : String =
call.arguments->first().convertExpressionToOCL()
in
if contextIndex = '0' then
'self'
else
'current('.concat(contextIndex).concat(')')
endif
else if call.name = 'current'
and call.arguments->size() = 1 then
'current('.concat(call.arguments->first().convertExpressionToOCL()
.replaceAll('\'', '')).concat(')')
else if call.name = 'debug' then
'<<<FIXME "debug()" has no equivalent in Acceleo OCL. debug()>>>'
else if call.name = 'trace' then
'<<<FIXME "trace()" has no equivalent in Acceleo OCL. trace()>>>'
else if call.name = 'nPut' then
'<<<FIXME "nPut(String)" has no equivalent in Acceleo OCL. nPut('
.concat(call.arguments->first().convertExpressionToOCL())
.concat(')>>>')
else if call.name = 'nPeek' then
'<<<FIXME "nPeek()" has no equivalent in Acceleo OCL. nPeek()>>>'
else if call.name = 'nPop' then
'<<<FIXME "nPop()" has no equivalent in Acceleo OCL. nPop()>>>'
else if call.name = 'nPush' then
'<<<FIXME "nPush()" has no equivalent in Acceleo OCL. nPush()>>>'
else if call.name = 'nMinimize' then
'asOrderedSet()->asSequence()'
else if call.name = 'minimize' then
'asOrderedSet()->asSequence()'
else if call.name = 'nContains' then
'includes('.concat(call.arguments->first().convertExpressionToOCL())
.concat(')')
else if call.name = 'nFirst' then
'first()'
else if call.name = 'nLast' then
'last()'
else if call.name = 'nGet'
and call.arguments->size() = 1 then
'at('.concat(call.arguments->first().convertExpressionToOCL())
.concat(')')
else if call.name = 'nGet'
and call.arguments->size() = 2 then
'subSequence('.concat(call.arguments->first().convertExpressionToOCL())
.concat(' + 1, ').concat(call.arguments->last()
.convertExpressionToOCL()).concat(' + 1)')
else if call.name = 'nReverse' then
'reverse()'
else if call.name = 'reverse' then
'reverse()'
else if call.name = 'nSize' then
'size()'
else if call.name = 'nSort'
and call.arguments->size() = 0 then
'sortedBy(toString())'
else if call.name = 'nSort'
and call.arguments->size() = 1 then
'sortedBy('.concat(call.arguments->first().convertExpressionToOCL())
.concat(')')
else if call.name = 'sort'
and call.arguments->size() = 0 then
'sortedBy(toString())->asOrderedSet()->asSequence()'
else if call.name = 'sort'
and call.arguments->size() = 1 then
'sortedBy('.concat(call.arguments->first().convertExpressionToOCL())
.concat(')->asOrderedSet()->asSequence()')
else if call.name = 'sep' then
'sep('.concat(arguments->first().convertExpressionToOCL()
.formatStringForOCL()).concat(')')
else if call.name = 'sepStr' then
'sep(\''.concat(call.arguments->first().convertExpressionToOCL())
.concat('\')')
else if call.name = 'toString' then
'toString()'
else if call.name = 'until' then
'<<<FIXME "until(String, String)" has no equivalent in Acceleo OCL. until('
.concat(call.arguments->first().convertExpressionToOCL())
.concat(', ').concat(call.arguments->last()
.convertExpressionToOCL()).concat(')>>>')
else
'<<<FIXME couldn\'t convert call '
.concat(call.name).concat(' to Acceleo OCL>>>')
endif endif endif endif endif endif endif endif endif endif endif endif
endif endif endif endif endif endif endif endif endif endif endif endif
endif endif endif endif endif endif/]
[query private formatStringForOCL(aString : String) : String =
let trimmed : String =
if aString.startsWith('\'')
and aString.endsWith('\'') then
aString.substring(2, aString.size() - 1)
else if aString.startsWith('\'') then
aString.substring(2, aString.size())
else if aString.endsWith('\'') then
aString.substring(1, aString.size() - 1)
else
aString
endif endif endif
in
trimmed.escapeChars()
/]
[query private escapeChars(toEscape : String) : String =
toEscape.replaceAll('\\r', '\\\\r').replaceAll('\\n', '\\\\n')
.replaceAll('\\t', '\\\\t').replaceAll('\\f', '\\\\f')
.replaceAll('\\r', '\\\\r').replaceAll('\\"', '\\\\"')/]
[query private convertContextService(call : Call) : String =
if call.name = 'get' then
'<<<FIXME "get()" has no equivalent in Acceleo OCL. get('
.concat(call.arguments->first().convertExpressionToOCL())
.concat(')>>>')
else if call.name = 'peek' then
'<<<FIXME "peek" has no equivalent in Acceleo OCL. peek()>>>'
else if call.name = 'pop' then
'<<<FIXME "pop" has no equivalent in Acceleo OCL. pop()>>>'
else if call.name = 'push' then
'<<<FIXME "push" has no equivalent in Acceleo OCL. push()>>>'
else if call.name = 'put' then
'<<<FIXME "put(String, Object)" has no equivalent in Acceleo OCL. put('
.concat(call.arguments->first().convertExpressionToOCL())
.concat(', ').concat(call.arguments->last()
.convertExpressionToOCL()).concat(')>>>')
else
'<<<FIXME couldn\'t convert call '.concat(call.name)
.concat(' to Acceleo OCL>>>')
endif endif endif endif endif/]
[query private convertPropertiesService(call : Call) : String =
if call.name = 'getBestProperty' then
'<<<FIXME "getBestProperty(String)" has no equivalent in Acceleo OCL. getBestProperty('
.concat(call.arguments->first().convertExpressionToOCL())
.concat(')>>>')
else if call.name = 'getProperty'
and call.arguments->size() = 1 then
'getProperty('.concat(call.arguments->first()
.convertExpressionToOCL()).concat(')')
else if call.name = 'getProperty'
and call.arguments->size() = 2 then
'getProperty('.concat(call.arguments->first()
.convertExpressionToOCL()).concat(', ')
.concat(call.arguments->last().convertExpressionToOCL())
.concat(')')
else
'<<<FIXME couldn\'t convert call '.concat(call.name)
.concat(' to Acceleo OCL>>>')
endif endif endif/]
[comment this has been externalized here to make use of the query's caching/]
[query private allCalls(root : OclAny) : Sequence(Call) =
root.eAllContents(mt::expressions::Call)/]