blob: 20f92d5b83391ae2db33355c6ce81713ab2c7c1f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 Draeger Medical GmbH (http://www.draeger.com).
* 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:
* Peter Karlitschek (initial contribution)
*
*******************************************************************************/
package org.eclipse.etrice.generator.cpp.gen
import com.google.inject.Inject
import com.google.inject.Singleton
import java.util.List
import org.eclipse.etrice.core.genmodel.etricegen.Root
import org.eclipse.etrice.core.genmodel.fsm.base.ILogger
import org.eclipse.etrice.core.room.Attribute
import org.eclipse.etrice.core.room.ComplexType
import org.eclipse.etrice.core.room.DataClass
import org.eclipse.etrice.generator.generic.ProcedureHelpers
import org.eclipse.etrice.generator.generic.RoomExtensions
import org.eclipse.xtext.generator.JavaIoFileSystemAccess
import org.eclipse.etrice.core.room.util.RoomHelpers
@Singleton
class DataClassGen {
@Inject extension JavaIoFileSystemAccess fileAccess
@Inject extension CppExtensions stdExt
@Inject extension RoomExtensions roomExt
@Inject extension ProcedureHelpers helpers
// @Inject extension TypeHelpers typeHelpers
@Inject Initialization initHelper
@Inject extension RoomHelpers
@Inject ILogger logger
def doGenerate(Root root) {
logger.logInfo("generating code")
for (dc: root.usedDataClasses) {
var path = dc.generationTargetPath + dc.getPath
// header file
logger.logInfo("generating DataClass header '"+dc.getCppHeaderFileName+"' in '"+path+"'")
fileAccess.setOutputPath(path)
fileAccess.generateFile(dc.getCppHeaderFileName, root.generateHeaderFile(dc))
// source file
logger.logInfo("generating DataClass source '"+dc.getCppSourceFileName+"' in '"+path+"'")
fileAccess.setOutputPath(path)
fileAccess.generateFile(dc.getCppSourceFileName, root.generateSourceFile(dc))
}
}
def generateHeaderFile(Root root, DataClass dc) {
//TODO: getReferencedDataClasses does not contain a base class of the own package
'''
«generateIncludeGuardBegin(dc, '')»
#include "common/etDatatypesCpp.hpp"
«IF dc.base!=null»#include "«dc.base.path»«dc.base.name».h"«ENDIF»
«FOR classes : root.getReferencedDataClasses(dc)»
#include "«classes.path»«classes.name».h"
«ENDFOR»
«FOR model : root.getReferencedModels(dc)»
«FOR classes : model.dataClasses»
#include "«classes.path»«classes.name».h"
«ENDFOR»
«ENDFOR»
«dc.userCode1.userCode»
using namespace etRuntime; // TODO JH remove
«dc.generateNamespaceBegin»
class «dc.name»«IF dc.base!=null» : public «dc.base.name»«ENDIF» {
public:
«helpers.userCode(dc.userCode2)»
«helpers.attributes(dc.attributes)»
«helpers.attributeSettersGettersImplementation(dc.attributes, dc.name)»
«helpers.operationsDeclaration(dc.operations, dc.name)»
// default constructor, copy constructor and assignment operator
«dc.name»();
«dc.name»(const «dc.name»& rhs);
«dc.name»& operator=(const «dc.name»& rhs);
// constructor using fields
«IF !dc.allAttributes.empty»«dc.name»(«dc.allAttributes.argList»);«ENDIF»
};
«dc.generateNamespaceEnd»
«generateIncludeGuardEnd(dc, '')»
'''
}
def generateSourceFile(Root root, DataClass dc) {
'''
/**
* @author generated by eTrice
*
* Source File of DataClass «dc.name»
*/
#include "«dc.getCppHeaderFileName»"
#include "etUnit/etUnit.h"
«dc.generateNamespaceBegin»
«helpers.userCode(dc.userCode3)»
// default constructor
«dc.name»::«dc.name»()
«dc.generateDefaultInitalizerList»
{
«initHelper.genExtraInitializers(dc.attributes)»
«dc.userStructorBody(true)»
}
// copy constructor
«dc.name»::«dc.name»(const «dc.name»& rhs)
«dc.generateCopyInitalizerList»
{
}
// constructor using fields
// TODO
«IF !dc.allAttributes.empty»
«dc.name»::«dc.name»(«dc.allAttributes.argList»)
«dc.generateFieldInitializerList»
{
}
«ENDIF»
// assignment operator
«dc.name»& «dc.name»::operator=(const «dc.name»& rhs)
{
if (this == &rhs) { return *this; };
«IF dc.base!=null»«dc.base.name»::operator=(rhs);«ENDIF»
«FOR attr : dc.attributes»
this->«attr.name» = rhs.«attr.name»;
«ENDFOR»
return *this;
}
«helpers.operationsImplementation(dc.operations, dc.name)»
«dc.generateNamespaceEnd»
'''}
def private generateDefaultInitalizerList(DataClass dataClass){
val extension initHelper = initHelper
var initList = <CharSequence>newArrayList
if(dataClass.base != null) initList += dataClass.base.name + '()'
initList += dataClass.attributes.map['''«name»(«initializerListValue»)''']
initList.generateCtorInitializerList
}
def private generateCopyInitalizerList(DataClass dataClass){
val extension initHelper = initHelper
var initList = <CharSequence>newArrayList
if(dataClass.base != null) initList += dataClass.base.name + '(rhs)'
initList += dataClass.attributes.map['''«name»(rhs.«name»)''']
initList.generateCtorInitializerList
}
def private generateFieldInitializerList(DataClass dataClass){
val extension initHelper = initHelper
var initList = <CharSequence>newArrayList
if(dataClass.base != null)
initList += '''«dataClass.base.name»(«dataClass.base.allAttributes.map[name].join(', ')»)'''
initList += dataClass.attributes.map['''«name»(«name»)''']
initList.generateCtorInitializerList
}
// def paramList(DataClass _dc) {
// var result = ""
// var dc = _dc
// while (dc!=null) {
// result = dc.attributes.paramList.toString + result
// dc = dc.base
// if (dc!=null)
// result = ", "+result
// }
// return result
// }
// def paramList(List<Attribute> attributes) {
// '''«FOR a: attributes SEPARATOR ", "»«a.name»_«ENDFOR»'''
// }
//
// def argList(DataClass _dc) {
// var result = ""
// var dc = _dc
// while (dc!=null) {
// result = dc.attributes.argListConstructor.toString + result
// dc = dc.base
// if (dc!=null)
// result = ", "+result
// }
// return result
// }
//
// def argListConstructor(List<Attribute> attributes) {
// '''«FOR a : attributes SEPARATOR ", "»«a.type.type.typeName»«IF a.size>1»[]«ENDIF» «a.name»_«ENDFOR»'''
// }
def deepCopy(DataClass _dc) {
var result = ""
var dc = _dc
while (dc!=null) {
result = deepCopy(dc.attributes).toString + result
dc = dc.base
}
return result
}
def deepCopy(List<Attribute> attributes) {
'''
«FOR a : attributes»
«IF a.type.type instanceof ComplexType»
if («a.name»!=null) {
«IF a.size==0»
copy.«a.name» = «a.name».deepCopy();
«ELSE»
for (int i=0;i<«a.name».length;i++){
copy.«a.name»[i] = «a.name»[i].deepCopy();
}
«ENDIF»
}
«ELSE»
«IF a.size==0»
copy.«a.name» = «a.name»;
«ELSE»
for (int i=0;i<«a.name».length;i++){
copy.«a.name»[i] = «a.name»[i];
}
«ENDIF»
«ENDIF»
«ENDFOR»
'''
}
}