Unversionierte Modellanpassung
Mit Hilfe der automatischen Datenmigration werden Fach-Daten beim Booten des System automatisch an eine neue Anwendungsversion angepasst, wenn dies nötig ist. Z.B. werden automatisch neue Attribute für Fachobjekt-Typen angelegt. In manchen Fällen ist es jedoch wünschenswert, dass das Modell so migriert wird, das es für die Anwendung so aussieht, als wäre der Zustand schon immer so gewesen. Z.B. wenn ein Attribut auch im historischen Kontext vorhanden sein soll, kann es nicht automatisch durch "Hochfahren" des Systems angelegt werden, da das Attribut vor diesem Zeitpunkt natürlich nicht existiert.
Für diesen Zweck gibt es MigrationProcessor
mit denen häufige Fälle abgedeckt sind. Diese können wie in Automatische Datenmigration beschrieben Datenbank-unabhängig in der SQL-Migration eingesetzt werden.
Anlegen eines neuen Moduls
Soll ein neues Modul angelegt werden, kann dies mit <create-module .../>
geschehen, z.B.
<create-module name="test.module">
<annotations>
...
</annotations>
</create-module>
Löschen eines Moduls
Soll ein Modul inklusive seinen Singletons, Typen und deren Attributen gelöscht werden, kann dies mit <delete-module .../>
geschehen, z.B:
<delete-module name="test.module" />
Achtung: Instanzen der einzelnen Typen werden nicht entfernt. Es wird empfohlen vor dem Löschen des Moduls die Fachobjekt-Typen einzeln zu löschen (<delete-class ...\>) um sicherzustellen, dass Instanzen des Types gelöscht werden.
Erstellen eines Fachobjekt-Typs
Soll ein neuer Fachobjekt-Typ angelegt werden, kann dies mit <create-class ... />
geschehen, z.B:
<create-class name="test.module:TestType"
abstract="false"
final="true"
primary-generalization="test.module:TypeGeneralization"
>
<annotations>
...
</annotations>
</create-class>
Der Name des Types muß voll qualifiziert angegeben werden. In den Annotationen kann die selbe Syntax verwendet werden wie in den Modell-Dateien. Es ist nicht möglich Attribute inline anzugeben. Für jedes Attribut muss ein separater Migrationseintrag erstellt werden.
Achtung: Jeder Fachobjekt-Typ benötigt als (geerbte) Generalisierung den Typ tl.model:TLObject
. Wird ein neuer Fachobjekt-Typ über die Anwendung angelegt, so wird dies programmatisch sichergestellt. Während der Migration muss dies der Entwickler tun, indem er im Attribut primary-generalization
eine Generalisierung angibt. Gibt keine fachliche Generalisierung, muss tl.model:TLObject
benutzt werden.
Löschen eines Fachobjekt-Typs
Soll ein Fachobjekt-Typ inklusive seinen Attributen gelöscht werden, kann dies mit <delete-class .../>
geschehen, z.B:
<delete-class name="test.module:TestType"
type-table="MyTable"
/>
Der Name des Types muß voll qualifiziert angegeben werden.
type-table
ist der Name der Tabellen in der Instanzen des Fachobjekt-Typs gespeichert werden. Alle Instanzen des Typs werden aus der Tabelle gelöscht. Ist kein Typ angegegben (z.B. weil der Typ abstrakt ist) wird nichts gelöscht.
Achtung: Die Referenzen zu anderen Objekten und die Flex-Daten werden nicht mitgelöscht. Es wird empfohlen zuerst die Referenz-Attribute und primitiven Eigenschaften des Fachobjekt-Typ's zu löschen (<delete-reference .../>
bzw. <delete-property .../>
).
Erstellen eines Datentyps
Soll ein neuer Datentyp angelegt werden, kann dies mit <create-datatype .../>
geschehen, z.B:
<create-datatype name="test.module:TestType"
db_type="clob"
kind="Custom"
>
<storage-mapping ... />
<annotations>
...
</annotations>
</create-datatype>
Der Name der Datentyps muß voll qualifiziert angegeben werden. In den Annotationen kann die selbe Syntax verwendet werden wie in den Modell-Dateien.
Erstellen einer Aufzählung
Soll eine neue Aufzählung angelege werden, kann dies mit <create-enumeration .../>
geschehen, z.B.:
<create-enumeration name="test.module:MyEnum">
<annotations>
...
</annotations>
</create-enumeration>
Der Name der Aufzählung muss qualifiziert angegeben werden. In den Annotationen kann die selbe Syntax verwendet werden wie in den Modell-Dateien. Es ist nicht möglich Classifier inline anzugeben. Für jeden Classifier muss ein separater Migrationseintrag erstellt werden.
Hinzufügen eines Classifiers
Soll ein neuer Classifier hinzugefügt werden, kann dies <create-classifier .../>
geschehen, z.B.:
<create-classifier name="test.module:MyEnum#classifier1"/>
Der Name des Classifiers muß qualifiziert angegeben werden.
Hinzufügen einer primitiven Eigenschaft
Soll eine TLProperty
, also der Verweis auf einen Datentyp erstellt werden, kann dies mit <create-property .../>
geschehen, z.B:
<create-property name="test.module:TestType#property1"
bag="false"
mandatory="false"
multiple="true"
ordered="true"
type="target.module:TargetType"
>
<annotations>
...
</annotations>
</create-property>
Der Name der Eigenschaft muß voll qualifiziert angegeben werden. In den Annotationen kann die selbe Syntax verwendet werden wie in den Modell-Dateien.
Löschen einer Eigenschaft
Soll eine TLProperty
gelöscht werden, kann dies mit <delete-property .../>
geschehen, z.B.:
<delete-property name="test.module:TestType#prop1"
type-tables="MyTable1, MyTable2,..."
/>
Der Name der Eigenschaft muß voll qualifiziert angegeben werden.
type-tables
sind die Tabellen in die der Type test.module:TestType
und seine Spezialisierungen ihre Daten ablegen. Sind diese Tabellen angegeben, werden die Flex-Daten die zu diesem Tabellen und dem Attribut prop1
gehören mitgelöscht. Achtung: Es muß sichergestellt sein, dass es keinen anderen Typ mit einem gleichnamigen Attribut gibt der in eine der angegeben Tabellen speichert.
Hinzufügen einer Referenz auf einen Fachobjekt-Typ
Soll eine TLReference
, also der Verweis auf einen Fachobjekt-Typ erstellt werden, kann dies <create-reference ... />
geschehen, z.B.:
<create-reference name="test.module:TestType#ref1"
aggregate="false"
composite="false"
mandatory="false"
multiple="true"
ordered="true"
type="target.module:TargetType"
>
<annotations>
...
</annotations>
</create-reference>
Der Name der Referenz muß voll qualifiziert angegeben werden. In den Annotationen kann die selbe Syntax verwendet werden wie in den Modell-Dateien.
Löschen einer Referenz
Soll eine TLReference
gelöscht werden, kann dies mit <delete-reference .../>
geschehen, z.B.:
<delete-reference name="test.module:MyType#ref1"/>
Der Name der Referenz muß voll qualifiziert angegeben werden. Es werden die Referenz und die zugehörigen Daten aus der Tabelle hasWrapperAttValue
gelöscht. Werden die Daten in einer speziellen hasWrapperAttValueBaseAssociation-
Tabelle gespeichert (z.B. hasMilestones
), so kann diese als Attribut angegeben werden: association-table="hasMIlestones"
.
Hinzufügen einer Rückwärts-Referenz zu einer bestehenden Referenz
Soll zu einer Vorwärts-Referenz eine zugehörige Rückwärts-Referenz angelegt werden, kann dies mit <create-inverse-reference .../>
, z.B.
<create-inverse-reference name="test.module:TestType#backRef"
aggregate="false"
composite="false"
mandatory="false"
multiple="true"
ordered="true"
inverse-reference="test.module:TestType#ref1"
>
<annotations>
...
</annotations>
</create-inverse-reference>
Die Syntax ist im wedentlichen dieselbe wie bei einer TLReference
, nur dass anstelle des qualifizierten Namen des Ziel-Typ's der qualifizierte Name der Referenz angegeben werden muß.
Löschen einer Rückwärts-Referenz
Soll eine Rückwärts-Referenz gelöscht werden, kann dies mit <delete-inverse-reference .../>
geschehen, z.B.:
<delete-inverse-reference name="test.module:MyType#invRef"/>
Der Name der Referenz muß voll qualifiziert angegeben werden.
Markieren eines Attributes als Überschreibung
Soll eine Überschreibung eines Attributes oder einer Referenz angelegt werden, so kann dies nicht mit dem Schlüsselwort override="true"
geschehen. Das neue Attribut oder die neue Referenz muß normal angelegt werden und daraufhin das neue Attribut als Überschreibung definiert werden.
Dies kann mit <mark-override .../>
geschehen, z.B.:
<mark-override name="test.module:TestType2#part"
definition="test.module:TestType1#part"
/>
Hier wird das Attribut test.module:TestType2#part
als override von test.module:TestType1#part
definiert (hier wird angenommen, dass test.module:TestType2
eine Subklasse von test.module:TestType1
ist). Achtung: Soll eine weitere Überschreibung von test.module:TestType2#part
erstellt werden, z.B. test.module:TestType3#part
, so muss wieder erst test.module:TestType3#part
angelegt werden und in dem Prozessor <mark-override .../>
für test.module:TestType3#part
, als definition
ebenfalls test.module:TestType1#part
angegeben werden.
Hinzufügen einer Generalisierung eines Fachobjekt-Typ
Soll ein Fachobjekt-Typ als Generalisierung eines anderen Fachobjekt-Typs hinzugefügt werden, so kann das mit <add-class-generalizations ... />
geschehen, z.B.:
<add-class-generalizations name="test.module:TestType">
<generalizations>
<generalization type="module1:Generalization1"/>
<generalization type="module2:Generalization2"/>
...
</generalizations>
</add-class-generalizations>
Hier werden dem Typ test.module:TestType
die Generalisierungen module1:Generalization1
und module2:Generalization2
hinzugefügt. Alle Typ-Namen sind qualifiziert anzugeben.
Entfernen einen Generalisierung eines Fachobjekt-Typ
Soll ein Fachobjekt-Typ einen anderen Typ nicht mehr erweitern, sol kann dies mit <remove-class-generalization .../> geschehen, z.B.:
<remove-class-generalizations name="test.module:TestType">
<generalizations>
<generalization type="module1:Generalization1"/>
<generalization type="module2:Generalization2"/>
...
</generalizations>
</remove-class-generalizations>
Hier werden dem Typ test.module:TestType
die Generalisierungen module1:Generalization1
und module2:Generalization2
entfernt. Alle Typ-Namen sind qualifiziert anzugeben.
Achtung: Es muss sichergestellt sein, dass der Typ mindestens (geerbt) tl.model:TLObject
als Generalisierung besitzt. Im Notfall muss dies mittels <add-class-generalizations ... />
sichergestellt werden.
Aktualisierung der Annotationen eines Modellelementes
Soll bei einem Modell-Element, also einem TLModule
, einem TLType
oder einem TLTypePart
, die Annotationen geändert werden, kann dies mit <update-tl-annotations ... />
geschehen, z.B.:
<update-annotations name="test.module:TestType#part1">
<annotations>
...
</annotations>
</update-annotations>
Hier muss der Name des Modellelementes qualifiziert angegeben werden.
Ändern des Zieltyps von Attributen
Soll in einem speziellen Attribute der Zieltyp geändert werden, oder in allen Attributen, so kann dies mit <change-part-type ... />
geschehen, z.B. wird mit
<change-part-type
source="module1:TestType1"
target="module2:TestType2"
/>
in allen Attributen die den Typ module1:TestType1
haben, der Typ module2:TestType2
gesetzt. Soll dies nur in einem speziellen Attribut geschehen wird
<change-part-type
part="test.module:TestType#part"
target="module2:TestType2"
/>
benutzt. Hier wird dem Attribut test.module:TestType#part
der Typ module2:TestType2
gesetzt.
Achtung: Soll bei einer TLReference
der Typ geändert werden, muss dies entweder an dem zugehörigen TLAssociationEnd
gemacht werden bzw.
<change-reference-type
reference="test.module:TestType#ref"
target="module2:TestType2"
/>
benutzt werden.
Anlegen von Fachobjekten
Soll ein neues Fachobjekt angelegt werden kann dies mit <create-object .../>
geschehen, z.B.:
<create-object
table="StructuredElement"
type="test.module:MyType"
>
<values>
<value
column="NAME"
column-type="string"
value="ROOT"
/>
</values>
</create-object>
Achtung: In den values werden die Werte für die Spalten angegeben, in column
steht der Name der Spalte wie sie in der Datenbank heißt, also meistens in Großbuchstaben und mit Unterstrichen getrennt. table
hingegen enthält den Namen des zu der Tabelle gehörenden MetaObject
.
Anlegen von Singletons
Soll ein neues Singleton zu einem Modul angelegt werden, kann dies mit <create-singleton .../>
geschehen, z.B.:
<create-singleton name="ROOT"
module="test.module"
>
<singleton
table="DemoTypes"
type="test.module:RootType"
>
<values>
<value
column="NAME"
column-type="string"
value="ROOT"
/>
</singleton>
</create-singleton>
Hier wird dem Modul test.module
, ein Singleton namens ROOT hinzugefügt. Die Syntax im Tag singleton
entspricht der des Prozessors <create-object .../>
.
Einen Classifier als "default" setzen
Soll in einer Aufzählung ein Classifier als "default" gesetzt werden, so kann dies mit <set-default-classifier .../>
geschehen, z.B.:
<set-default-classifier
enumeration="test.module:enum1"
default-classifier="classifier2"
/>
Hier wird in der Aufzählung test.module:enum1
der Classifier classifier2
als "default" gesetzt. Soll kein Classifier "default" sein kann default-classifier=""
gesetzt werden.
Aktualisieren einer primitiven Eigenschaft
Soll eine TLProperty
aktualisiert werden, kann dies mit <update-property .../>
geschehen, z.B.:
<update-property name="test.module:TestType#prop1"
mandatory="true"
new-name="test.module:OtherTestType#newProp1"
new-type="tl.core:Long"
/>
Hier ist new-name
der qualifizierte neue Name. Hier wird also nicht nur ein Umbenennen, sondern auch ein Umhängen an einen anderen Typ kodiert. Im Beispiel würde das TLProperty
umbenannt werden von prop1
nach newProp1
und verschoben werden von test.module:TestType
nach test.module:OtherTestType
.
Aktualisieren einer Referenz
Soll eine TLReference
aktualisiert werden, kann dies mit <update-reference .../>
geschehen, z.B.:
<update-reference name="test.module:TestType#ref1"
aggregate="false"
composite="false"
mandatory="false"
multiple="true"
ordered="true"
new-name="test.module:OtherTestType#ref2"
new-type="test.module2:TargetType"
/>
Hier ist new-name
der qualifizierte neue Name. Hier wird also nicht nur ein Umbenennen, sondern auch ein Umhängen an einen anderen Typ kodiert. Im Beispiel würde die TLReference
umbenannt werden von ref1
nach ref2
und verschoben werden von test.module:TestType
nach test.module:OtherTestType
.
Achtung: Rückwärts-Referenzen müssen mit <update-inverse-reference .../>
aktualisiert werden.
Aktualisieren einer Rückwärts-Referenz
Soll eine Rückreferenz aktualisiert werden, kann dies mit <update-inverse-reference .../>
geschehen, z.B.:
<update-reference name="test.module:TestType#ref1"
aggregate="false"
composite="false"
mandatory="false"
multiple="true"
ordered="true"
new-name="test.module:TestType#ref2"
/>
Hier ist new-name
der qualifizierte neue Name. Hier darf sich der Owner der Referenz nicht ändern. Sollte dies doch der Fall sein wird der neue Owner ignoriert. Ebenso kann hier kein neuer Zieltyp gesetzt werden.
Prinzipiell sind der Zieltyp einer Rückreferenz und der Owner der zugehörigen Hin-Referenz identisch, ebenso sind der Owner der Rückreferenz und der Zieltyp der entsprechenden Hin-Referenz identisch. Somit kann der Zieltyp, bzw. der Owner einer Rückreferenz angepasst werden, indem der Owner, bzw. der Zieltyp der zugehörigen Hinreferenz angepasst wird.