Changes
Page history
[Dev] Add documentation for the ACR
authored
Oct 01, 2018
by
Rico Bergmann
Show whitespace changes
Inline
Side-by-side
asciidoc/Developer-documentation.asciidoc
View page @
5c54ae79
...
...
@@ -2,32 +2,103 @@
:sectanchors:
:sectlinks:
:imagesdir: ../assets/generated
:toc:
If you want to find out how to extend the
g
enerator and adapt it to fit your own needs, this page
If you want to find out how to extend the
G
enerator and adapt it to fit your own needs, this page
is for you.
== General architecture and workflow
When invoking the
g
enerator, it will (roughly) perform the following actions:
When invoking the
G
enerator, it will (roughly) perform the following actions:
.Basic invocation workflow
image::invocation_workflow.png[width=90%, align=center, link={imagesdir}/invocation_workflow.png]
Each of these steps has a corresponding Scala class (called _Services_ hereafter) to take care of
it. So, when extending the
g
enerator there are two basic approaches:
it. So, when extending the
G
enerator there are two basic approaches:
[loweralpha]
. modifying one of the _Services_ (either directly or by means of subclassing)
. intercepting the workflow by adding more _Services_
To give you a rough idea of what _Services_ are available and where they will be located, here is an
overview of the
g
enerator's architecture:
overview of the
G
enerator's architecture:
.The coarse-scale architecture of the
g
enerator
.The coarse-scale architecture of the
G
enerator
image::architecture.png[width=90%, align=center, link={imagesdir}/architecture.png]
== The Scala abstract class representation
== The Scala _Abstract class representation_
The _Abstract class representation_ (ACR) is the hearth of the Generator. It forms the meta-model
for the code to generate and provides facilities to adapt model instances for different purposes.
In short each element of a Scala class has a matching class in the _ACR_. E.g. a method will be
represented by an instance of `SMethod`, attributes become ``SAttribute``s and a class itself will
be mapped to a `SClass`. As the main purpose of the Generator is to provide executable software
models, an abstraction of a model, the `SModel` is provided as well. It is pretty straightforward
and simply provides all the classes in the model.
=== Types and Classes
Models seldom start from scratch. Instead, they will reuse certain data types, such as ``String``s,
``Integer``s, etc. as attributes in the classes that are specified by the model. Usually these data
types are provided by some library and may be mapped to a basic data types of the target programming
language (or a converter is provided along with them).
The Generator follows a similar approach: it provides an abstraction for user-supplied classes (i.e.
the classes specified within the model). This is the `SClass` class already mentioned above.
Additionally a `SType` class is provided to handle predefined data types. When generating source
code these types are expected to exist "as are" and will not be tackled further. I.e. no `.scala`
files will be created for `SType` instances.
As _types_ and _classes_ are concepts only found at a more abstract level and are irrelevant when it
comes to Scala source code, they share a common superclass - `STypedElement` - which will be used
whenever type information (no matter if it is user-supplied or generic) is needed.
=== Working with the _ACR_ on a more abstract level
The _ACR_ forms a trade-off between an abstract meta-model on one side, and a straightforward (hence
simplified) usage on the other side. Therefore low-level abstraction will oftentimes be wrapped by
some higher abstraction. E.g. a `SMethod` consists of abstract ``SMethodStatement``s and may thus
provide abstract functionality for modification. However a `SMethodStatement` simply wraps a
`String` (the actual statement). Dealing with the statements _themselves_ may therefore become
pretty cumbersome at a certain point. To circumvent this issue, the __ACR__'s elements should be
extended by means of subclassing to provide more tailored versions which handle the additional
complexity.
A good example for this approach is the extension of the `SMethod` class to easily generate
__Getter__s and __Setter__s for attributes:
.Example for modifying the _ACR_ on a more abstract level
[source, scala]
----
class SMethod(val name: String,
val result: STypedElement,
val params: Seq[SMethodParameter],
var implementation: Seq[SMethodStatement]) {
// implementation omitted
}
class SGetter(attr: SAttribute) extends SMethod(
name = s"get${attr.name.firstLetterToUpperCase}",
result = attr.attrType,
params = Seq.empty,
implementation = Seq(SMethodStatement(content = attr.name, usedTypes = Set(attr.attrType))) {
// implementation omitted
}
----
__Getter__s may now be generated by only specifying the attribute they are created for - the
cumbersome creation of the actual method statements is hidden within the class implementation.
== Working with models
=== Incremental construction of `SModel` instances
=== Building a model from EMF
== Writing to the File system