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
@type | Felder |
|---|---|
crm.privatkunde | name, geburtsdatum |
crm.firmenkunde | name, 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
Wann: auftrag.kunde mit { "field": "kunde", "response": ["+"] }
-
1CDMS→Datenbankliest den
auftragund hängtkundeper LEFT JOIN an, dabei nuridund gespeicherten TypDer Typ kommt aus der Spalte_MODELTYPEdes Obermodells. -
2CDMSwählt anhand des Typs den Untertyp, z. B.
privatkunde -
3CDMSprüft die Leserolle dieses Untertyps
-
4CDMS→Datenbankliest den Kunden über den Untertyp, mit dessen Zeilenfiltern
-
5CDMSsetzt ihn mit
@typein das Feldkundeein
Ergebnis: "kunde": { "@type": "crm.privatkunde", "name": …, "geburtsdatum": … }
Wann: berater.kunden mit { "field": "kunden", "response": ["+"], "parameter": { … } }
-
1CDMS→DatenbankPhase 1: sucht auf dem Obermodell
kundenuridund Typ, mit dem Filter auf den Berater, deinem Filter, deiner Sortierung und deinemlimit -
2CDMSteilt die Treffer nach Untertyp auf
-
3CDMS→DatenbankPhase 2: liest je Untertyp alle seine Treffer auf einmal, über dessen Rechte und Filter
-
4CDMSsetzt 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
POST /api/rest/crm/berater/read/b5…
{
"response": [
"name",
{
"field": "kunden",
"response": ["+"],
"parameter": { "order": [{ "field": "name", "order": "ASC" }] }
}
]
}{
"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
| gespeicherter Typ | Leserolle dieses Untertyps | Inhalt von kunde |
|---|---|---|
| crm.privatkunde | ja | name, geburtsdatum, @type |
| crm.firmenkunde | ja | name, @type; geburtsdatum entfällt |
| – | nein | 403 mit der Rolle des Untertyps |
| keine Referenz gesetzt | – | null |
Fallen
Wie es weitergeht
- Grundlagen zu Obermodell, Untertypen und Hub-API: Abstrakte Modelle und
@type - Allgemein zum Ausbauen: Referenzen und Listen ausbauen