carstenSpraener / cgV19

A production proofed code generator framework
Apache License 2.0
3 stars 0 forks source link

IDEA: establish an section/snippet concept to use in GodeGenerators #44

Closed carstenSpraener closed 1 year ago

carstenSpraener commented 1 year ago

When writing templates for code generators a certain aspect, that needs to be handled results in many output targets. To make this more clear take a look at the following situation:

In The model is a Class A that has a reference to another Class B. Like this A <>------myB-> B A and B my not in the same package. To generate this in Java, TypeScript, PHP or most other language there are several areas in the target code related to this aspect:

With the current template technique this aspects will spread into several section/methods of the template. The implementation of this aggregation spreads out to more than one point.

To avoid this there should be some kind of structure that allows to apply sinppets to several sections of a target code and evaluate them, when the handling of all modled aspects is done.

So a implementation of such an aggregation aspect should look like:

ClassTarget.importSection.addSinppet(imports)
ClassTarget.attributeSection.addSnippet(attributeDeclaration)
ClassTarget.contructorSeciont.addSnippet(contructorCode)
ClassTarget.methodSection.addMethodSnippet(getteSetterCode)

So the CodeGenerator can now look like:

ClassTarget classTarget = new ClassTarget();
applyAllAspects(classTarget, myModelElement);
return classTarget.evauate();

Each section in a ClassTarget should have different requirements/behaviour.

carstenSpraener commented 1 year ago

When grouping this aspects into small pieces, a code generator could now look like:

def myClass = (MClass)getProperty("ModelElement");
ClassTarget classTarget = new JavaClassTarget(myClass.getName(), myClass.getPackage());

myClass.applyDeclarationAspects(myClass, classTarget);
myClass.attributes.forEach {
    applyAttributeAspects(it, myClass, classTarget);
}
myClass.associations.forEach {
    applyAssociationAspects(it, myClass, classTarget);
}
myClass.dependencies.forEach {
    applyDependencyAspects(it, myClass, classTarget);
}
return classTarget.evaluate();
carstenSpraener commented 1 year ago

To minimize the risk, this feature could be implemented in the PoJo or Rest cartridge and from there seep into the core. This way the implementation can not break the current implementation of the meta cartridge, which is a main component of cgV19.

The PoJo cartridge is very simple but limited to java. The REST cartridge is way more complicated but also has generators for TypeScript and PHP. That will help to identify common needs for different target languages.

So the feature should be implemented in an cgV19-oom package in the cgv19-restcartridge module. That will make it easy to migrate it later into the cgv19-oom module when it is out of incubator state.

This way it can be started to implement on a sub branch of Release-23 branch and merged into the release when it is finished.

carstenSpraener commented 1 year ago

With the concept of Target->Section->Snippet it should be possible to request a Section in a Target by an ModelElement. So a CodeGenerator for Entities working onMClass entityClass could use a PoJo-Generator and do the following:

MClass entityClass = getProperty("MClass");
// Use the PoJoGenerator from another Cartridge to build a base Java Class with all its
// imports, inheritance, implementations ... 
ClassTarget entityTarget = PoJoGenerator.buildTarget(entityClass);

Now add the Aspect of JPA-Mapping to the created ClassTarget:

entityTarget.getSection(JavaSection.IMPORTS)
   .getSnippet(PoJoGenerator.ASPECT_STANDARD_IMPORTS)
   .insertAfter(ASPECT_JPA, "import javax.persistence.*");
carstenSpraener commented 1 year ago

Release 23.1 contains this feature