= definition()
:description: Lädt und parst die Objektdefinition des ECM-Servers (dms.GetObjDef, UTF-16-XML). Gibt ein ECMDefinition-Objekt mit Cabinets, Objekttypen und Felddefinitionen zurück.
:keywords: definition, dms.GetObjDef, ECMDefinition, asobjdef, Cabinets, Objekttypen, Felddefinitionen, UTF-16
:page-tags: api, system

Gibt die vollständige Objektdefinition des verbundenen ECM-Servers als typisiertes
`ECMDefinition`-Objekt zurück. Die Definition wird einmalig über `dms.GetObjDef` abgerufen
und dann auf dem `ecm.system`-Namespace gecacht. Folgeaufrufe liefern dieselbe Instanz zurück.

== Signatur

[tabs]
====
Sync::
+
[source,python]
----
ecm.system.definition(*, force_reload: bool = False) -> ECMDefinition
----

Async::
+
[source,python]
----
await ecm.system.definition(*, force_reload: bool = False) -> ECMDefinition
----
====

== Parameter

[cols="1,1,1,3"]
|===
|Parameter |Typ |Standard |Beschreibung

|`force_reload`
|`bool`
|`False`
|Wenn `True`, wird die gecachte Instanz verworfen und die Definition erneut vom Server abgerufen.
|===

== Rückgabewert

Eine `ECMDefinition`-Instanz. Das gesamte Parsen findet direkt beim Konstruieren statt.

=== ECMDefinition

[cols="1,1,3"]
|===
|Eigenschaft |Typ |Beschreibung

|`primary_language`
|`ECMLanguageDefinition`
|Die primäre Systemsprache.

|`available_languages`
|`dict[str, ECMLanguageDefinition]`
|Alle aktiven Sprachen, nach ISO-Locale-Code indexiert (z. B. `"de_DE"`).

|`all_languages`
|`dict[str, ECMLanguageDefinition]`
|Alle Sprachen, nach ISO-Locale-Code indexiert, inkl. inaktiver.

|`cabinets`
|`dict[str, ECMCabinetDefinition]`
|Alle Cabinet-Definitionen, nach internem Namen indexiert.

|`created`
|`datetime`
|Zeitstempel, wann die Definition auf dem Server erzeugt wurde.

|`version`
|`str`
|Server-Versionsstring (z. B. `"5.20"`).

|`limited_objects`
|`bool`
|`True`, wenn die Definition nur eine begrenzte Teilmenge von Objekttypen enthält.

|`definition["InternalName"]`
|`ECMObjectDefinition`
|Suche über alle Cabinets nach internem Namen. Wirft `KeyError`, wenn nicht gefunden.

|`definition[type_id]`
|`ECMObjectDefinition`
|Suche nach zusammengesetzter Typ-ID (`(maintype << 16) \| cotype`). Wirft `KeyError`.
|===

=== ECMLanguageDefinition

[cols="1,1,3"]
|===
|Feld |Typ |Beschreibung

|`lang_id`
|`int`
|Numerische Sprach-ID, die durchgehend im Definition-XML verwendet wird.

|`name`
|`str`
|Lesbarer Sprachname (z. B. `"German"`).

|`iso_code`
|`str`
|ISO-Locale-Code (z. B. `"de_DE"`).

|`is_active`
|`bool`
|`True`, wenn die Sprache auf dem Server aktiv ist.

|`is_primary`
|`bool`
|`True`, wenn dies die Primärsprache ist.
|===

=== ECMCabinetDefinition

[cols="1,1,3"]
|===
|Eigenschaft / Methode |Typ |Beschreibung

|`internal_name`
|`str`
|Interner Name des Cabinets.

|`name`
|`str`
|Anzeigename des Cabinets.

|`cotype`
|`int`
|Numerische Cabinet-Typ-ID.

|`objects`
|`dict[str, ECMObjectDefinition]`
|Alle Objekttypen in diesem Cabinet, nach internem Namen indexiert.

|`folders`
|`dict[str, ECMFolderDefinition]`
|Gefilterte Ansicht — nur Ordnertypen.

|`registers`
|`dict[str, ECMRegisterDefinition]`
|Gefilterte Ansicht — nur Registertypen.

|`documents`
|`dict[str, ECMDocumentDefinition]`
|Gefilterte Ansicht — nur Dokumenttypen.

|`cabinet["InternalName"]`
|`ECMObjectDefinition`
|Direktzugriff über internen Namen. Wirft `KeyError`, wenn nicht gefunden.

|`"InternalName" in cabinet`
|`bool`
|Mitgliedschaftstest über internen Namen.
|===

=== ECMObjectDefinition

Gemeinsame Basis für `ECMFolderDefinition`, `ECMRegisterDefinition` und `ECMDocumentDefinition`.

[cols="1,1,3"]
|===
|Eigenschaft |Typ |Beschreibung

|`internal_name`
|`str`
|Interner (programmatischer) Name des Objekttyps.

|`maintype`
|`ECMMainType`
|Haupttyp-Enum-Member (z. B. `FOLDER`, `REGISTER`, `DOC_WINDOWS`).

|`cotype`
|`int`
|Numerische Objekttyp-ID.

|`type_id`
|`int`
|Zusammengesetzte Typ-ID: `(maintype.value << 16) \| cotype`.

|`os_guid`
|`str`
|Server-seitiger GUID für diesen Objekttyp.

|`tablename`
|`str`
|Primärer Datenbanktabellenname.

|`description`
|`ECMDescriptionEntry \| None`
|Beschriftung für die Primärsprache oder `None`, wenn nicht vorhanden.

|`descriptions`
|`dict[str, ECMDescriptionEntry]`
|Sprachspezifische Beschriftungen, nach ISO-Locale-Code indexiert.

|`fields`
|`dict[str, ECMFieldDefinition]`
|Nur Top-Level-Felder. Felder in PageControl-Seiten sind nicht enthalten.

|`all_fields`
|`dict[str, ECMFieldDefinition]`
|Alle Felder, rekursiv über alle PageControl-Seiten hinweg abgeflacht.

|`obj["InternalName"]`
|`ECMFieldDefinition`
|Kurzform für `obj.all_fields["InternalName"]`. Wirft `KeyError`, wenn nicht gefunden.

|`fulltext`
|`ECMFulltextMode`
|Volltext-Indexierungsmodus: `DISABLED`, `AUTOMATIC` oder `MANUAL`.

|`history_flags`
|`ECMHistoryFlags`
|Entschlüsselte History-Flags (Index-History, Dokument-History, Versionen).

|`compression_flags`
|`ECMCompressionMode`
|Dateikomprimierungsmodus: `DISABLED`, `MERGE_ONLY` oder `MERGE_AND_COMPRESS`.

|`limited_objects`
|`list[ECMLimitedObjectEntry]`
|Erlaubte untergeordnete Objekttypen und ihre maximale Anzahl.
|===

`ECMDocumentDefinition` ergänzt ein zusätzliches Feld:

[cols="1,1,3"]
|===
|Feld |Typ |Beschreibung

|`cross_module_document_type`
|`bool`
|`True`, wenn dieser Dokumenttyp modulübergreifend ist.
|===

==== Enum ECMMainType

[cols="1,1"]
|===
|Member |Beschreibung

|`FOLDER`
|Ordnertyp.

|`REGISTER`
|Registertyp.

|`DOC_GRAYSCALE`
|Graustufen-Bilddokument.

|`DOC_BW`
|Schwarz-Weiß-Bilddokument.

|`DOC_COLOR`
|Farbiges Bilddokument.

|`DOC_WINDOWS`
|Windows-Anwendungsdokument.

|`DOC_MULTIMEDIA`
|Multimedia-Dokument.

|`DOC_MAIL`
|E-Mail-Dokument.

|`DOC_XML`
|XML-Dokument.

|`DOC_CONTAINER`
|Container-Dokument.
|===

=== ECMDescriptionEntry

Enthält die sprachspezifische Beschriftung eines Objekttyps, Feldes oder Tabs.

[cols="1,1,3"]
|===
|Feld |Typ |Beschreibung

|`name`
|`str`
|Anzeigename.

|`tooltip`
|`str`
|Tooltip-Text in der Oberfläche.

|`image_id`
|`str`
|Icon-Bezeichner.

|`default_url`
|`str`
|URL für die Standardansicht.

|`new_url`
|`str`
|URL beim Anlegen eines neuen Objekts.

|`update_url`
|`str`
|URL beim Aktualisieren eines Objekts.

|`request_url`
|`str`
|URL für Checkout / Anforderung.

|`readonly_url`
|`str`
|URL für die Nur-Lesen-Ansicht.
|===

=== ECMFieldDefinition

Repräsentiert ein einzelnes Feld eines Objekttyps.

[cols="1,1,3"]
|===
|Eigenschaft |Typ |Beschreibung

|`internal_name`
|`str`
|Interner (programmatischer) Name des Feldes.

|`field_name`
|`str`
|Datenbankspaltename (z. B. `"feld001"`). Leer bei statischen UI-Elementen.

|`data_type`
|`ECMFieldDataType \| None`
|Logischer Datentyp. `None` bei statischen UI-Elementen (Gruppen, Labels usw.).

|`control`
|`ECMControlType`
|UI-Steuerelementtyp (Textfeld, Checkbox, Tabelle, PageControl usw.).

|`catalog`
|`ECMCatalogType \| None`
|Katalogtyp oder `None`, wenn kein Katalog konfiguriert ist.

|`description`
|`ECMDescriptionEntry`
|Beschriftung für die Primärsprache.

|`descriptions`
|`dict[str, ECMDescriptionEntry]`
|Beschriftungen für alle Sprachen, nach ISO-Locale-Code indexiert.

|`required`
|`bool`
|`True`, wenn das Feld ein Pflichtfeld ist.

|`readonly`
|`bool`
|`True`, wenn das Feld immer schreibgeschützt ist.

|`readonly_after_archiving`
|`bool`
|`True`, wenn das Feld nach der Archivierung schreibgeschützt wird.

|`key_field`
|`bool`
|`True`, wenn dies ein Schlüsselfeld ist.

|`supervisor`
|`bool`
|`True`, wenn nur Supervisoren das Feld bearbeiten dürfen.

|`multiline`
|`bool`
|`True`, wenn das Feld mehrzeilige Texteingabe unterstützt.

|`input_length`
|`int \| None`
|Maximale Eingabelänge oder `None`, wenn nicht angegeben.

|`regular_expression`
|`str`
|Validierungs-Regex, leer wenn keiner konfiguriert.

|`init`
|`str`
|Standardwert-Ausdruck, leer wenn keiner konfiguriert.

|`is_static`
|`bool`
|`True` für reine UI-Elemente ohne Datenbankspalte (Gruppen, Labels, PageControls).

|`pages`
|`dict[str, ECMPageDefinition]`
|Tabs eines PageControl-Feldes (`control == PAGE_CONTROL`). Bei allen anderen Typen leer.

|`columns`
|`dict[str, ECMTableColumnDefinition]`
|Spaltendefinitionen eines TableFields (`control == TABLEFIELD`). Bei allen anderen Typen leer.

|`list_values`
|`ECMFieldList \| None`
|In der Definition eingebettete Katalogwerte oder `None` bei Datenbank-/Addon-Katalogen.
|===

==== Enum ECMFieldDataType

[cols="1,1"]
|===
|Member |Beschreibung

|`STRING`
|Textfeld (`field_name` beginnt mit `feld`).

|`INTEGER`
|Ganzzahliges Feld.

|`BOOLEAN`
|Boolean / Checkbox-Feld.

|`DOUBLE`
|Dezimalzahlenfeld.

|`DATE`
|Datumsfeld.

|`TIME`
|Zeitfeld.

|`DATE_TIME`
|Kombiniertes Datum-Uhrzeit-Feld.
|===

==== Enum ECMControlType

[cols="1,1"]
|===
|Member |Beschreibung

|`TEXTFIELD`
|Standard-Text-, Datum- oder Zahleneingabe.

|`TABLEFIELD`
|Mehrzeiliges Tabellen-/Rastersteuerelement.

|`RADIOBUTTON`
|Optionsschaltfläche.

|`CHECKBOX`
|Kontrollkästchen.

|`PICTURE`
|Bildsteuerelement.

|`GROUP`
|Gruppenrahmen (nur visuelle Gruppierung, keine Datenbankspalte).

|`PAGE_CONTROL`
|Tab-/Seitensteuerung (enthält `pages`).

|`WEBCONTROL`
|Eingebettetes Websteuerelement.

|`BUTTON`
|Schaltfläche.

|`LABEL`
|Statisches Label (keine Datenbankspalte).
|===

==== Enum ECMCatalogType

[cols="1,1"]
|===
|Member |Beschreibung

|`DATABASE`
|Datenbankbasierter Katalog.

|`ADDON`
|Addon- (DLL-)Katalog.

|`LIST`
|Flache inline Liste.

|`TREE`
|Baumkatalog.

|`HIERARCHY_TREE`
|Hierarchischer Baumkatalog.

|`STRUCTURE_TREE`
|Strukturbaumkatalog.
|===

=== ECMPageDefinition

Repräsentiert einen einzelnen Tab innerhalb eines PageControl-Feldes.

[cols="1,1,3"]
|===
|Feld |Typ |Beschreibung

|`internal_name`
|`str`
|Interner Name des Tabs.

|`position`
|`int`
|Nullbasierte Anzeigeposition innerhalb des PageControls.

|`description`
|`ECMDescriptionEntry \| None`
|Beschriftung für die Primärsprache oder `None`, wenn nicht gesetzt.

|`descriptions`
|`dict[str, ECMDescriptionEntry]`
|Beschriftungen für alle Sprachen, nach ISO-Locale-Code indexiert.

|`fields`
|`dict[str, ECMFieldDefinition]`
|Felder auf diesem Tab, nach internem Namen indexiert.
|===

=== ECMTableColumnDefinition

Repräsentiert eine einzelne Spalte eines TableFields.

[cols="1,1,3"]
|===
|Feld |Typ |Beschreibung

|`internal_name`
|`str`
|Interner Name der Spalte.

|`field_name`
|`str`
|Datenbankspaltename.

|`data_type`
|`ECMFieldDataType \| None`
|Logischer Datentyp der Spalte.

|`readonly`
|`bool`
|`True`, wenn die Spalte schreibgeschützt ist.

|`col_pos`
|`int`
|Nullbasierte Anzeigeposition im Raster.

|`col_width`
|`int`
|Anzeigebreite in Rastereinheiten (`0` = automatisch).

|`description`
|`ECMDescriptionEntry \| None`
|Beschriftung für die Primärsprache.

|`descriptions`
|`dict[str, ECMDescriptionEntry]`
|Beschriftungen für alle Sprachen, nach ISO-Locale-Code indexiert.
|===

== Beispiele

=== Primärsprache und Server-Version lesen

[tabs]
====
Sync::
+
[source,python]
----
definition = ecm.system.definition()
print(definition.version)                       # z. B. "5.20"
print(definition.primary_language.iso_code)     # z. B. "de_DE"
print(definition.created)
----

Async::
+
[source,python]
----
definition = await ecm.system.definition()
print(definition.version)
print(definition.primary_language.iso_code)
print(definition.created)
----
====

=== Alle Objekttypen aller Cabinets auflisten

[tabs]
====
Sync::
+
[source,python]
----
definition = ecm.system.definition()
for cabinet in definition.cabinets.values():
    print(f"Cabinet: {cabinet.name}")
    for folder in cabinet.folders.values():
        label = folder.description.name if folder.description else folder.internal_name
        print(f"  Ordner: {folder.internal_name} ({label})")
    for doc in cabinet.documents.values():
        label = doc.description.name if doc.description else doc.internal_name
        print(f"  Dokument: {doc.internal_name} ({label})")
----

Async::
+
[source,python]
----
definition = await ecm.system.definition()
for cabinet in definition.cabinets.values():
    print(f"Cabinet: {cabinet.name}")
    for folder in cabinet.folders.values():
        label = folder.description.name if folder.description else folder.internal_name
        print(f"  Ordner: {folder.internal_name} ({label})")
    for doc in cabinet.documents.values():
        label = doc.description.name if doc.description else doc.internal_name
        print(f"  Dokument: {doc.internal_name} ({label})")
----
====

=== Felder eines Objekttyps untersuchen

[tabs]
====
Sync::
+
[source,python]
----
definition = ecm.system.definition()
obj = definition["RechnungsOrdner"]

for field in obj.all_fields.values():
    if field.is_static:
        continue
    print(
        field.internal_name,
        field.data_type,
        "Pflicht" if field.required else "",
        "Nur-Lesen" if field.readonly else "",
    )
----

Async::
+
[source,python]
----
definition = await ecm.system.definition()
obj = definition["RechnungsOrdner"]

for field in obj.all_fields.values():
    if field.is_static:
        continue
    print(
        field.internal_name,
        field.data_type,
        "Pflicht" if field.required else "",
        "Nur-Lesen" if field.readonly else "",
    )
----
====

=== Felder mit Katalogwerten auslesen

[tabs]
====
Sync::
+
[source,python]
----
definition = ecm.system.definition()
obj = definition["RechnungsOrdner"]

for field in obj.all_fields.values():
    if field.catalog is None:
        continue
    print(f"{field.internal_name}: Katalog={field.catalog}")
    if field.list_values:
        for row in field.list_values.rows:
            print(f"  [{row.index}] {row.value}")
----

Async::
+
[source,python]
----
definition = await ecm.system.definition()
obj = definition["RechnungsOrdner"]

for field in obj.all_fields.values():
    if field.catalog is None:
        continue
    print(f"{field.internal_name}: Katalog={field.catalog}")
    if field.list_values:
        for row in field.list_values.rows:
            print(f"  [{row.index}] {row.value}")
----
====

=== PageControl-Tabs und ihre Felder untersuchen

[tabs]
====
Sync::
+
[source,python]
----
definition = ecm.system.definition()
obj = definition["RechnungsOrdner"]

for field in obj.fields.values():
    if field.control.value != "page_control":
        continue
    for page in field.pages.values():
        label = page.description.name if page.description else page.internal_name
        print(f"Tab: {label}")
        for page_field in page.fields.values():
            if not page_field.is_static:
                print(f"  {page_field.internal_name} ({page_field.data_type})")
----

Async::
+
[source,python]
----
definition = await ecm.system.definition()
obj = definition["RechnungsOrdner"]

for field in obj.fields.values():
    if field.control.value != "page_control":
        continue
    for page in field.pages.values():
        label = page.description.name if page.description else page.internal_name
        print(f"Tab: {label}")
        for page_field in page.fields.values():
            if not page_field.is_static:
                print(f"  {page_field.internal_name} ({page_field.data_type})")
----
====

=== Tabellenspalten eines TableFields untersuchen

[tabs]
====
Sync::
+
[source,python]
----
definition = ecm.system.definition()
obj = definition["RechnungsOrdner"]

for field in obj.all_fields.values():
    if field.control.value != "tablefield":
        continue
    print(f"Tabelle: {field.internal_name}")
    for col in field.columns.values():
        print(f"  {col.internal_name} ({col.data_type})")
----

Async::
+
[source,python]
----
definition = await ecm.system.definition()
obj = definition["RechnungsOrdner"]

for field in obj.all_fields.values():
    if field.control.value != "tablefield":
        continue
    print(f"Tabelle: {field.internal_name}")
    for col in field.columns.values():
        print(f"  {col.internal_name} ({col.data_type})")
----
====

=== Definition nach einer Serveränderung neu laden

[tabs]
====
Sync::
+
[source,python]
----
definition = ecm.system.definition(force_reload=True)
----

Async::
+
[source,python]
----
definition = await ecm.system.definition(force_reload=True)
----
====

== Siehe auch

* xref:api/system/index.adoc[ecm.system] — Namespace-Übersicht
