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>
In den Annotationen kann die selbe Syntax verwendet werden wie in den Modell-Dateien.
 

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.