Unversioned model fitting
With the help of automatic data migration, compartment data is automatically adapted to a new application version when the system is booted, if this is necessary. For example, new attributes are automatically created for the tray object types. In some cases, however, it is desirable to migrate the model in such a way that it looks to the application as if it has always been that way. For example, if an attribute should also exist in the historical context, it cannot be created automatically by "booting up" the system, since the attribute obviously did not exist before that point in time.
For this purpose, there are MigrationProcessor
with which common cases are covered. These can be used database-independently in SQL migration as described in Automatic Data Migration.
Creating a new module
If a new module is to be created, this can be done with <create-module .../>
, e.g.
<create-module name="test.module">
<annotations>
...
</annotations>
</create-module>
Deleting a module
If you want to delete a module including its singletons, types and their attributes, you can do this with <delete-module .../>
, e.g:
<delete-module name="test.module" />
Attention: instances of the single types will not be removed. It is recommended to delete the subject object types individually (<delete-class ...\>) before deleting the module to ensure that instances of the type are deleted.
Creating a subject object type
If a new subject object type is to be created, this can be done using <create-class ... />
, for example:
<create-class name="test.module:TestType"
abstract="false"
final="true"
primary-generalization="test.module:TypeGeneralization"
>
<annotations>
...
</annotations>
</create-class>
The name of the type must be specified fully qualified. The same syntax can be used in the annotations as in the model files. It is not possible to specify attributes inline. A separate migration entry must be created for each attribute.
Attention: Each subject object type needs as (inherited) generalization the type tl.model:TLObject
. If a new subject object type is created via the application, this is ensured programmatically. During migration, the developer must do this by specifying a generalization in the primary-generalization
attribute. If there is no domain-oriented generalization, tl.model:TLObject
must be used.
Deleting a Specialized Object Type
If a special-purpose object type including its attributes is to be deleted, this can be done with <delete-class .../>
, e.g:
<delete-class name="test.module:TestType"
type-table="MyTable"
/>
The name of the type must be specified fully qualified.
type-table
is the name of the table in which instances of the subject object type are stored. All instances of the type are deleted from the table. If no type is specified (e.g. because the type is abstract) nothing is deleted.
Attention: The references to other objects and the flex data are not deleted. It is recommended to delete the reference attributes and primitive properties of the subject object type first (<delete-reference .../>
or <delete-property .../>
).
Creating a data type
If a new data type is to be created, this can be done with <create-datatype .../>
, e.g:
<create-datatype name="test.module:TestType"
db_type="clob"
kind="Custom"
>
<storage-mapping ... />
<annotations>
...
</annotations>
</create-datatype>
The name of the datatype must be specified fully qualified. The same syntax can be used in the annotations as in the model files.
Creating an enumeration
If a new enumeration is to be created, this can be done with <create-enumeration .../>
, e.g.:
<create-enumeration name="test.module:MyEnum">
<annotations>
...
</annotations>
</create-enumeration>
The name of the enumeration must be qualified. The same syntax can be used in the annotations as in the model files. It is not possible to specify classifiers inline. A separate migration entry must be created for each classifier.
Adding a Classifier
If a new Classifier is to be added, this can be done at <create-classifier .../>
, for example:
<create-classifier name="test.module:MyEnum#classifier1"/>
The name of the classifier must be specified in a qualified manner.
Adding a primitive property
If a TLProperty
, i.e. the reference to a data type is to be created, this can be done with <create-property .../>
, e.g.:
<create-property name="test.module:TestType#property1"
bag="false"
mandatory="false"
multiple="true"
ordered="true"
type="target.module:TargetType"
>
<annotations>
...
</annotations>
</create-property>
The name of the property must be specified fully qualified. The same syntax can be used in the annotations as in the model files.
Deleting a property
If a TLProperty
is to be deleted, this can be done with <delete-property .../>
, e.g.:
<delete-property name="test.module:TestType#prop1"
type-tables="MyTable1, MyTable2,..."
/>
The name of the property must be specified fully qualified.
type-tables
are the tables in which the type test.module:TestType
and its specializations store their data. If these tables are specified, the Flex data belonging to these tables and the attribute prop1
are also deleted. Attention: It must be ensured that there is no other type with an attribute of the same name that stores in one of the specified tables.
Adding a reference to a subject object type
If a TLReference
, i.e. the reference to a subject object type is to be created, this can be done <create-reference ... />
, e.g.:
<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>
The name of the reference must be specified fully qualified. The same syntax can be used in the annotations as in the model files.
Deleting a reference
If a TLReference
is to be deleted, this can be done with <delete-reference .../>
, e.g.:
<delete-reference name="test.module:MyType#ref1"/>
The name of the reference must be specified fully qualified. The reference and the associated data are deleted from the table hasWrapperAttValue
. If the data is stored in a specialhasWrapperAttValueBaseAssociation-
table (e.g. hasMilestones
), this can be specified as an attribute: association-table="hasMIlestones"
.
Adding a backward reference to an existing reference
If a backward reference is to be added to a forward reference, this can be done using <create-inverse-reference .../>
, e.g.
<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>
The syntax is basically the same as for a TLReference
, except that the qualified name of the reference must be specified instead of the qualified name of the target type.
Deleting a backward reference
If a backward reference is to be deleted, this can be done with <delete-inverse-reference .../>
, e.g.:
<delete-inverse-reference name="test.module:MyType#invRef"/>
The reference name must be specified fully qualified.
Marking an attribute as an override
If an override of an attribute or reference is to be created, this cannot be done with the keyword override="true"
. The new attribute or reference must be created normally and then the new attribute defined as an override.
This can be done with <mark-override .../>
, for example:
<mark-override name="test.module:TestType2#part"
definition="test.module:TestType1#part"
/>
Here the attribute test.module:TestType2#part
is defined as an override of test.module:TestType1#part
(here it is assumed that test.module:TestType2
is a subclass of test.module:TestType1
). Attention: If another override of test.module:TestType2#part
is to be created, e.g. test.module:TestType3#part
, then againtest.module:TestType3#part
must be created first and in the processor <mark-override .../>
for test.module:TestType3#part
, as definition
also test.module:TestType1#part
must be specified.
Adding a generalization of a subject object type
If a subject object type is to be added as a generalization of another subject object type, this can be done with <add-class-generalizations ... />
, e.g.:
<add-class-generalizations name="test.module:TestType">
<generalizations>
<generalization type="module1:Generalization1"/>
<generalization type="module2:Generalization2"/>
...
</generalizations>
</add-class-generalizations>
Here the generalizations module1:Generalization1
and module2:Generalization2
are added to the type test.module:TestType
. All type names must be specified in a qualified manner.
Removing a generalization of a subject object type
If a subject object type is no longer to extend another type, this can be done with <remove-class-generalization .../>, e.g.:
<remove-class-generalizations name="test.module:TestType">
<generalizations>
<generalization type="module1:Generalization1"/>
<generalization type="module2:Generalization2"/>
...
</generalizations>
</remove-class-generalizations>
Here, the generalizations module1:Generalization1
and module2:Generalization2
are removed from the type test.module:TestType
. All type names must be specified in a qualified manner.
Attention: It must be ensured that the type has at least (inherited) tl.model:TLObject
as generalization. In case of emergency, this must be ensured using <add-class-generalizations ... />
.
Updating the annotations of a model element
If the annotations of a model element, i.e. a TLModule
, a TLType
or a TLTypePart
, are to be changed, this can be done with <update-tl-annotations ... />
, e.g.:
<update-annotations name="test.module:TestType#part1">
<annotations>
...
</annotations>
</update-annotations>
Here the name of the model element must be specified in a qualified way.
Changing the target type of attributes
If the target type is to be changed in a special attribute, or in all attributes, this can be done with <change-part-type ... />
, e.g. with
<change-part-type
source="module1:TestType1"
target="module2:TestType2"
/>
sets the type module2:TestType2
in all attributes that have the type module1:TestType1
. If this is only to be done in a special attribute, use
<change-part-type
part="test.module:TestType#part"
target="module2:TestType2"
/>
is used. Here the attribute test.module:TestType#part
is set to the type module2:TestType2
.
Attention: If you want to change the type of an attribute TLReference
, you have to change the type of the attribute TLAssociationEnd
.
<change-reference-type
reference="test.module:TestType#ref"
target="module2:TestType2"
/>
must be used.
Creating subject objects
If a new subject object is to be created this can be done with <create-object .../>
, e.g.:
<create-object
table="StructuredElement"
type="test.module:MyType"
>
<values>
<value
column="NAME"
column-type="string"
value="ROOT"
/>
</values>
</create-object>
Attention: in the values the values for the columns are given, in column
the name of the column is given as it is called in the database, i.e. mostly in capital letters and separated by underscores. table
on the other hand contains the name of the MetaObject
belonging to the table.
Creating Singletons
If a new singleton is to be created for a module, this can be done with <create-singleton .../>
, e.g.:
<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>
Here, a singleton named ROOT is added to the module test.module
,. The syntax in the tag singleton
corresponds to that of the processor <create-object .../>
.
Setting a Classifier as "default
If a classifier is to be set as "default" in an enumeration, this can be done with <set-default-classifier .../>
, e.g.:
<set-default-classifier
enumeration="test.module:enum1"
default-classifier="classifier2"
/>
Here, the classifier classifier2
is set as "default" in the enumeration test.module:enum1
. If no classifier is to be "default", default-classifier=""
can be set.
Updating a primitive property
If a TLProperty
is to be updated, this can be done with <update-property .../>
, e.g.:
<update-property name="test.module:TestType#prop1"
mandatory="true"
new-name="test.module:OtherTestType#newProp1"
new-type="tl.core:Long"
/>
Here new-name
is the qualified new name. So here not only a rename is encoded, but also a reassign to a different type. In the example, the TLProperty
would be renamed from prop1
to newProp1
and moved from test.module:TestType
to test.module:OtherTestType
.
Updating a reference
If a TLReference
is to be updated, this can be done with <update-reference .../>
, for example:
<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"
/>
Here new-name
is the qualified new name. So not only a rename is coded here, but also a reassign to a different type. In the example, the TLReference
would be renamed from ref1
to ref2
and moved from test.module:TestType
to test.module:OtherTestType
.
Note: Backward references must be updated with <update-inverse-reference .../>
.
Updating a backward reference
If a back reference is to be updated, this can be done with <update-inverse-reference .../>
, e.g.:
<update-reference name="test.module:TestType#ref1"
aggregate="false"
composite="false"
mandatory="false"
multiple="true"
ordered="true"
new-name="test.module:TestType#ref2"
/>
Here new-name
is the qualified new name. Here the owner of the reference must not change. If it does, the new owner will be ignored. Likewise, no new target type can be set here.
In principle, the target type of a back reference and the owner of the corresponding forward reference are identical, as are the owner of the back reference and the target type of the corresponding forward reference. Thus, the target type or the owner of a back reference can be adjusted by adjusting the owner or the target type of the corresponding forward reference.