
/**
 * Copyright (c) Jon Oldevik
 * MofScript to text transformation.
 * Reads mofscript model input and generates mofscript text output
 * author:	Jon Oldevik
 * version:	v1.2
 * date:	28.11.2005 
 * updated 13.12.2005 for new version of model and parser
 * updated Sept 12 2006 for new output notation + namespace
 */

texttransformation MofScript2Text2 (in mf:"http://org.sintef.mofscript.model") 
  var metaModelRefName: String
  property version: String = "1.2"

/////////////////////////////////////////////
/*
 * Main
 */
 
mf.MOFScriptSpecification::main() {
  property firstTr = self._getFeature("transformation").first().name
  property outputNameFromEnv = getenv ("MOFSCRIPT2TEXT_FILE")
  // property trName:String = firstTr.name
  // property trName:String = "generated.m2t"
  var fileString = firstTr + "-generated.m2t";
  if (outputNameFromEnv != "")
  	fileString = outputNameFromEnv + ".m2t"
  file (fileString)
  log ("Generating file: " + fileString)
  
'/**
 *
 * Transformation Generated by MOFScript2Text transformation
 * Date: ' date() + ", " + time() '
 * Version: ' version '
 *
 */
'
   
   self.commentTransformation()  
  
  self.imports->forEach(theImport:mf.MOFScriptImport) {
    theImport.transformationImport ()
  }
  self._getFeature("transformation")->forEach(trans:mf.MOFScriptTransformation) {
    trans.mofscriptTransformationMapping()       
  }
  
  
  
}

/**
 * the transformation
 */
mf.MOFScriptTransformation::mofscriptTransformationMapping () {
  
  property metaModel = self.parameters.first()  
  metaModelRefName = metaModel.parameterName()
  
  self.commentTransformation()  
'texttransformation ' self.name ' (' self.genTransformationParameters() ')' self.getExtendsRelation() '{
'

  self.declareVariablesAndConstants ()
    	  	
  self.transformationrules->forEach(rule:mf.TransformationRule)
  	rule.transformationRuleMapping()  	
  	
  print ("\n}")
}

/**
 *
 * the parameters
 *
 */
mf.MOFScriptTransformation::genTransformationParameters () {
  	self.parameters->forEach(p:mf.MOFScriptParameter) between (","){
  	  'in ' p.parameterName() ':"' p.parameterType() '"'
  	}
} 

/**
 * the extends
 */
mf.MOFScriptTransformation::getExtendsRelation ():String {
  result = ""
  if (self._getFeature("extends") != null) {
    result = "extends " + self._getFeature("extends")
  }  
}

mf.MOFScriptStatementOwner::declareVariablesAndConstants () {
  self.variables->forEach(theVar:mf.VariableDeclaration)
  	theVar.variableOrConstantDeclaration()  
}

/////////////////////////////////////////////
/**
  * Gets the parameter name from a MOFScriptParameter
  */
mf.MOFScriptParameter::parameterName (): String {
  result = self.name
}

/////////////////////////////////////////////
/**
  * Gets the parameterType from a MOFScriptParameter
  */
mf.MOFScriptParameter::parameterType (): String {
  result = self.type
}

/////////////////////////////////////////////
/*
 * Declares variables and constants   
 */
mf.VariableDeclaration::variableOrConstantDeclaration () {
  if (self.constant)
  	self.constantDeclaration()
  else
    self.variableDeclaration()
  newline
}

/////////////////////////////////////////////
/**
 * Declaras a variable
 */
mf.VariableDeclaration::variableDeclaration () {
'    var ' self.name ': ' self.type  
}

/////////////////////////////////////////////
/**
 * Declares a constant
 */
mf.VariableDeclaration::constantDeclaration () {  
'    property ' self.name ': ' self.type ' = ' self.value.expressionTransformation()
}

/////////////////////////////////////////////
/**
 * transformationImport
 */
mf.MOFScriptImport::transformationImport () {
}

/////////////////////////////////////////////
/**
 * TransformationRuleMapping
 */
mf.TransformationRule::transformationRuleMapping () {
   self.commentTransformation()
   writeComment ("TransformationRule: " + self.name)
''self.context.type '::' self.name ' ('  self.transformationRuleParameters() ') ' self.transformationRuleReturnType() '{ 
'  self.transformationRuleBody()'
} '  

}

////////////////////////////////////////////

mf.TransformationRule::transformationRuleReturnType():String {
  if (self.return = null)
  	result = ""
  else if (self.return.equalsIgnoreCase("void"))
  	result = ""
  else
    result = ": " + self.return
}


////////////////////////////////////////////

mf.TransformationRule::transformationRuleParameters() {
  self.parameters->forEach(param:mf.MOFScriptParameter) between (", "){
    param.name ':' param.type
  }
}


/////////////////////////////////////////////
/**
 * Transforms the body of a MOFScript statement
 */
mf.TransformationRule::transformationRuleBody () {  
  self.declareVariablesAndConstants()  	  
  self.statements->forEach(statement:mf.MOFScriptStatement) {
  	statement.statementTransformation()
//  	if (statement <> self.statements.last())
//	 	newline  	
  }
}

/////////////////////////////////////////////
/**
 *  Transforms a statement
 */
abstract mf.MOFScriptStatement::statementTransformation () 

/////////////////////////////////////////////
/**
 * IfStatement transformation
 */
mf.IfStatement::statementTransformation () {
  newline
  print ("  if (")
  self.ifExpression.expressionTransformation() 
  println (") {")
     self.statementIteratorMapping ()
  newline
  println ("  }")

  self.elseBranch->forEach(theElse:mf.IfStatement) {
    if (not(theElse.ifExpression = null)){
      print ("  else if (")
      theElse.ifExpression.expressionTransformation()
      println (") {")
      theElse.statementIteratorMapping()      
      newline
      println ("  }")
    } else {
      println ("  else {")
      theElse.statementIteratorMapping()
      newline
      println ("  }")      
    }
  }
  newline;
}

/////////////////////////////////////////////
/**
 * MOFScriptStatementOwner - mapping of statements
 */
mf.MOFScriptStatementOwner::statementIteratorMapping () {
  self.statements->forEach(statement:mf.MOFScriptStatement) /* between ("\n    ") */{
  	statement.statementTransformation()
  	newline
  }
}

/////////////////////////////////////////////
/**
 * forEach
 * IteratorStatement transformation
 */
mf.IteratorStatement::statementTransformation () { 
  newline
'  ' self.source.expressionTransformation() '->forEach ('self.variable 
  if (self.type != null) {
    ': ' self.type 
  }
  ' ) {
  ' 
     self.declareVariablesAndConstants()
     self.statementIteratorMapping()
  '
  }
  '
}

/////////////////////////////////////////////
/**
 * PrintStatement
 */
mf.PrintStatement::statementTransformation () {
//  log ("\n PRINT: self.context: " + self.context + " printCommand: " +   self.printCommand)  
  if (self.printCommand = "log") {
    'log (' + self.printBody.expressionTransformation() + ')'
  } else if (self.context != "") {
    print (self.context + "." + self.printCommand)
    '(' 
    self.printBody.expressionTransformation()
    ')'   
  } else {
    self.printBody.expressionPrintTransformation()
  }

}


/////////////////////////////////////////////
/*
 * FunctionCall Statement
 */ 
mf.FunctionCallStatement::statementTransformation () {
  self.function.expressionTransformation()
}
 

/////////////////////////////////////////////
/*
 * Result assignment
 */
mf.ResultAssignment::statementTransformation () {
  '    result '
  if (self.operator = "EQ"){
     '= '
  }
  else {
     '+= '
  }
  self.expression.expressionTransformation()
}

/**
 *
 */ 
mf.GeneralAssignment::statementTransformation () {
  newline
  '    ' self.name
  if (self.operator = "EQ"){
     '= '
  }
  else {
     '+= '
  }
  self.expression.expressionTransformation()    
}

///////////////////////////////////////////
mf.FileStatement::statementTransformation () {
  '    file ' self.getFileReference() '(' self.fileURI.expressionTransformation() ')'
  newline 
}

mf.FileStatement::getFileReference () : String {
  if (self.fileReference = null)
  	result = ""
  else 
  	result = self.fileReference
}

//////////////////////////////////////////
mf.BreakStatement::statementTransformation () {
  println ("\n    break")
}

///////////////////////////////////////////
/*
 * abstract expressionTransformation
 */
abstract mf.Expression::expressionTransformation ()


/////////////////////////////////////////////
/*
 * LogicalExpression mapping
 */
mf.LogicalExpression::expressionTransformation () {
  if (self.operator = "AND") {
    '(' self.part1.expressionTransformation() ') and (' self.part2.expressionTransformation() ')'
  } else if (self.operator = "OR") {
    '(' self.part1.expressionTransformation() ') or (' self.part2.expressionTransformation() ')'
  } else if (self.operator = "NOT"){    
    ' not ( ' self.part1.expressionTransformation() ')'
  } else{
    self.part1.expressionTransformation()
  }
}



/////////////////////////////////////////////
/*
 * ComparisonExpression mapping
 */
mf.ComparisonExpression::expressionTransformation () {
    self.part1.expressionTransformation ();
	if (self.operator = "EQ")
	   print (" = ")
	else if (self.operator = "NE")
	   print (" != ")	
	else if (self.operator = "LT")
	   print (" < ")
	else if (self.operator = "GT")
	   print (" > ")
	else if (self.operator = "LE")
	   print (" <= ")
	else if (self.operator = "GE")
	   print (" >= ")
    self.part2.expressionTransformation ();
}


/////////////////////////////////////////////
/*
 *
 */
mf.ArithmeticExpression::expressionTransformation () {
  self.part1.expressionTransformation();
  print("")
  if (self.operator = "PLUS")
  	print (" + ")
  else if (self.operator = "MINUS")
  	print (" - ")
  else if (self.operator = "STAR")
    print (" * ")
  else if (self.operator = "DIV")
    print (" / ")
  print ("")
  self.part2.expressionTransformation();
}


/////////////////////////////////////////////
mf.Reference::expressionTransformation () {
  print (self.name)
}


/////////////////////////////////////////////
/*
 * Function Call
 */
mf.FunctionCall::expressionTransformation () {
  print (self.name + "(") /* must print parameters */
  self.parameters->forEach(param:mf.ValueExpression) between (","){
    param.expressionTransformation()
  }
  print (")")
}

/////////////////////////////////////////////
/*
 * Abstract value expression transformation
 */
/* abstract */ mf.ValueExpression::expressionTransformation() {
  <% /* value expression */ %>
}


/////////////////////////////////////////////
/*
 * Literal mapping
 */
mf.Literal::expressionTransformation () {

  var escapedString:String = ""
  var literalChar:String = "\""
  if (self.type = "STRING") {
    escapedString = self.value
    if (escapedString.indexOf('"') > -1)
      literalChar = "'"
    else
      literalChar = '"'
    if (escapedString.indexOf("\n") > -1) {
    	escapedString = escapedString.replace("\n", "\\\\n")
    }
  	print (literalChar + escapedString + literalChar)
  } 
  else  
    print (self.value)
}


/////////////////////////////////////////////
/*
 * Mapping of comments for all mofscript objects
 */ 
mf.MOFScriptObject::commentTransformation () {
  self.comment->forEach(comment: mf.MOFScriptComment) {
    if (comment.singleLine) {
      println (comment.commentText)
    } else {
      println (comment.commentText)
    }
  }
}


/////////////////////////////////////////////
/*
 * Writes a comment string
 */
module::writeComment (commentText: String) {
'
/** 
 * ' commentText '
 */
'
}

////////////////////////////////////////////
/*
 * Returns true if 'theType' is a base type
 */
module::isBaseType (theType:String):Boolean {
  if (theType.equalsIgnoreCase("Object") or 
  	theType.equalsIgnoreCase("String") or
  	theType.equalsIgnoreCase("Real") or
	theType.equalsIgnoreCase("Integer") or
  	theType.equalsIgnoreCase("Boolean") or	
  	theType.equalsIgnoreCase("List") or  	
  	theType.equalsIgnoreCase("Hashtable") or  	
  	theType.equalsIgnoreCase("Dictionary"))
  	  result = true  	
  else
    result = false
}

/////////////////////////////////////////////
/*
 *
 */
mf.Expression::expressionPrintTransformation () {
}

mf.ArithmeticExpression::expressionPrintTransformation () {
  if (self.part1 != null)
	  self.part1.expressionPrintTransformation()
  if (self.part2 != null) {
    print (" + ");
    self.part2.expressionPrintTransformation();
  }
  	
}
mf.FunctionCall::expressionPrintTransformation () {
  if (self.isSuperCall) {
    'super.'
  }
  print (self.name + "(")
  self.parameters->forEach(param:mf.ValueExpression) between (",") {
    param.expressionTransformation()
  }
  print (")")
}

mf.Reference::expressionPrintTransformation () {
  print (self.name)
}

mf.Literal::expressionPrintTransformation () {
  self.expressionTransformation()
}

