CodamAIDocs
Themafertig

Lesen über abstrakte Typen

Zeigt eine Referenz auf ein abstraktes Modell, liefert CDMS die Felder aller möglichen Untertypen. Hier steht, wie das aufgelöst wird und wie der Client die Typen unterscheidet.

Ausprägungen
abstrakte Einzelreferenzabstrakte Liste@type in der Antwort+ heißt: Felder aller UntertypenFeld nur eines UntertypsRechte des Untertyps

Worum es geht

Ein abstraktes Modell ist ein Oberbegriff mit mehreren konkreten Untertypen, etwa kunde mit privatkunde und firmenkunde. Wie das grundsätzlich funktioniert, steht unter Abstrakte Modelle und @type.

Diese Seite behandelt den Fall, dass eine Referenz auf ein abstraktes Modell zeigt. Ein Auftrag gehört zu einem Kunden, und dieser Kunde kann ein Privatkunde oder ein Firmenkunde sein. Beim Ausbauen weiß CDMS vorher nicht, welcher Untertyp kommt.

Das Beispielmodell

classDiagram
    class auftrag {
        nummer
        kunde
    }
    class berater {
        name
        kunden
    }
    class kunde {
        <<abstrakt>>
        name
    }
    class privatkunde {
        geburtsdatum
    }
    class firmenkunde {
        handelsregisternummer
    }
    auftrag --> kunde : kunde (einzeln)
    berater --> kunde : kunden (Liste)
    kunde <|-- privatkunde
    kunde <|-- firmenkunde
@typeFelder
crm.privatkundename, geburtsdatum
crm.firmenkundename, handelsregisternummer

Wie CDMS die response auflöst

Beim Auflösen der response sieht CDMS, dass kunde abstrakt ist. Es wendet deine innere response auf jeden Untertyp an und vereinigt die Ergebnisse:

flowchart TB
    R["{ field: kunde, response: ['+'] }"] --> P["für privatkunde:<br/>name, geburtsdatum"]
    R --> F["für firmenkunde:<br/>name, handelsregisternummer"]
    P --> U["Vereinigung:<br/>name, geburtsdatum, handelsregisternummer"]
    F --> U
    U --> L["Lesen je Objekt über seinen Untertyp:<br/>Felder, die der Untertyp nicht hat, entfallen"]

Ein + in einer abstrakten Referenz heißt also „alle einfachen Felder aller möglichen Untertypen“. Beim Lesen eines Privatkunden bleibt davon name und geburtsdatum übrig, beim Firmenkunden name und handelsregisternummer.

Einzelreferenz und Liste

Abstrakte Referenzen ausbauen

Wann: auftrag.kunde mit { "field": "kunde", "response": ["+"] }

  1. 1
    CDMS→Datenbank
    liest den auftrag und hängt kunde per LEFT JOIN an, dabei nur id und gespeicherten Typ
    Der Typ kommt aus der Spalte _MODELTYPE des Obermodells.
  2. 2
    CDMS
    wählt anhand des Typs den Untertyp, z. B. privatkunde
  3. 3
    CDMS
    prüft die Leserolle dieses Untertyps
  4. 4
    CDMS→Datenbank
    liest den Kunden über den Untertyp, mit dessen Zeilenfiltern
  5. 5
    CDMS
    setzt ihn mit @type in das Feld kunde ein

Ergebnis: "kunde": { "@type": "crm.privatkunde", "name": …, "geburtsdatum": … }

Wann: berater.kunden mit { "field": "kunden", "response": ["+"], "parameter": { … } }

  1. 1
    CDMS→Datenbank
    Phase 1: sucht auf dem Obermodell kunde nur id und Typ, mit dem Filter auf den Berater, deinem Filter, deiner Sortierung und deinem limit
  2. 2
    CDMS
    teilt die Treffer nach Untertyp auf
  3. 3
    CDMS→Datenbank
    Phase 2: liest je Untertyp alle seine Treffer auf einmal, über dessen Rechte und Filter
  4. 4
    CDMS
    setzt die Liste in der Reihenfolge aus Phase 1 zusammen, jedes Objekt mit @type

Ergebnis: Eine gemischte Liste aus Privat- und Firmenkunden, richtig sortiert.

Wann: { "field": "kunde", "response": ["name", "geburtsdatum"] }, der Kunde ist aber ein Firmenkunde.

geburtsdatum gibt es beim Firmenkunden nicht. CDMS lässt es für dieses Objekt still weg, ohne Fehler.

Ergebnis: 200 mit name, geburtsdatum fehlt bei diesem Objekt.

Wann: Der Benutzer darf Privatkunden lesen, Firmenkunden aber nicht.

Rechte gelten pro Untertyp. Zeigt die Referenz auf einen Firmenkunden, scheitert die Anfrage mit 403 und der Rolle des Firmenkunden. Zeigt sie auf einen Privatkunden, klappt sie.

Ergebnis: Ob die Anfrage klappt, hängt davon ab, welcher Untertyp in den Daten steht.

Das Ergebnis im Beispiel

Ein Berater mit gemischter Kundenliste
Anfrage
POST /api/rest/crm/berater/read/b5…
{
  "response": [
    "name",
    {
      "field": "kunden",
      "response": ["+"],
      "parameter": { "order": [{ "field": "name", "order": "ASC" }] }
    }
  ]
}
Antwort
{
  "data": {
    "id": "b5…",
    "name": "Petra Berger",
    "kunden": [
      { "@type": "crm.privatkunde", "id": "5a2b…",
        "name": "Anna Muster", "geburtsdatum": "1990-04-01" },
      { "@type": "crm.firmenkunde", "id": "7c1d…",
        "name": "Muster GmbH", "handelsregisternummer": "HRB 12345" }
    ]
  },
  "meta": { "error": false }
}

@type im Client auswerten

@type ist der API-Pfad des Untertyps mit Punkten statt Schrägstrichen. Verzweige im Client darauf, nicht auf die Frage, welche Felder gefüllt sind:

for (const kunde of berater.kunden) {
  switch (kunde["@type"]) {
    case "crm.privatkunde":
      zeigePrivatkunde(kunde);
      break;
    case "crm.firmenkunde":
      zeigeFirmenkunde(kunde);
      break;
  }
}

Entscheidungstabelle

Referenz kunde mit response ["name", "geburtsdatum"]
gespeicherter TypLeserolle dieses UntertypsInhalt von kunde
crm.privatkundejaname, geburtsdatum, @type
crm.firmenkundejaname, @type; geburtsdatum entfällt
–nein403 mit der Rolle des Untertyps
keine Referenz gesetzt–null

Fallen

Wie es weitergeht

Quellen im Code und in der Wissensdatenbank
  • CDMS/cdms-rest-api – Expander.expandModelResponse (Vereinigung über alle Untertypen)
  • CDMS/cdms-system-layer – AbstractLayer.fetchAndSetModel, fetchAndSetList, queryAbstract
  • CDMS/cdms-persistence-database – SelectionBuilder.resolveJoinTypeExpression
  • CDMS/cdms-integrationtest – AbstractPolymorphicReferenceTest, AbstractResponseTest.simpleReadAbstractWithModelType
  • documentation/20-api/03-response-requests.md
Suchen