Slots

Ein Slot hält neben dem Datum auch den Typ der Daten, damit er auf einem entfernten System auch wieder entpackt werden kann. Man kann eigene Slot-Klassen registrieren. Es wird jedoch ausdrücklich empfohlen, dieses nicht zu tun, da damit auf die Interoperabilität mit anderen Clients und Tools verzichtet wird. Wir behalten uns vor, in späteren Versionen von devel.one weitere Slot-Typen anzubieten.

Zusätzlich enthält ein Slot auch einen Key, der ihn Inhalt kennzeichnet.

Zur Zeit gibt es folgende Slot-Typen:

  • BYTE: Ein byte (byte).
  • BYTEARRAY: Ein byte Array (byte[]).
  • CHAR: Ein Character (char).
  • CHARARRAY: Ein Character Array (char[]).
  • BOOLEAN: Ein Boolean (boolean).
  • BOOLEANARRAY: Ein Boolean Array (boolean[]).
  • SHORT: Ein Short (short).
  • SHORTARRAY: Ein Short Array (short[]).
  • INT: Ein Integer (int).
  • INTARRAY: Ein Integer Array (int[]).
  • LONG: Ein Long Integer (long).
  • LONGARRAY: Ein Long Integer Array (long[]).
  • FLOAT: Ein Float (float).
  • FLOATARRAY: Ein Float Array (float[]).
  • DOUBLE: Ein Double (double).
  • DOUBLEARRAY: Ein Double Array (double[]).
  • STRING: Ein String (String, im Stream UTF-8).
  • STRINGARRAY: Ein String Array (String[], im Stream UTF-8).
  • ID: Eine ID (IId).
  • IDARRAY: Ein ID Array (IId[]).
  • HID: Eine Host-ID (IHid).
  • HIDARRAY: Ein Host-ID Array (IHid[]).
  • TARGETADDRESS: Eine Target Adresse (ITargetAddress).
  • TARGETADDRESSARRAY: Ein Target Address Array (ITargetAddress[]).
  • UUID: Ein UUID (UUID).
  • UUIDARRAY: Ein UUID Array (UUID[]).
  • RECORD: Ein Message Record (CRecord).
  • RECORDARRAY: Ein Message Record Array (CRecord[]).
  • MESSAGE: Eine Message (IMessage).
  • OBJECT: Ein Object (Object - nicht routebar, nur lokal verwendbar).

Die Slot-Klassen sorgen auch für das Speichern und Wiederauslesen der Slot-Daten in Streams, Strings, Listen etc.. Dieses geschieht möglichst effizient, um ein Parsen der Messages zu beschleunigen und den Platzbedarf einer Message zu minimieren. So werden die oben genannten Slot-Typen als binäre Typen transportiert, mit einem 2-Byte-Header für den Typ des Slots. Dazu kommt noch eine 4-Byte-Längenangabe, um unbekannte Slot-Typen überspringen zu können. Dieses ist im Hinblick auf spätere Erweiterungen leider notwendig.

Die Slot Typen sind als CSlotType-Objekte in der Klasse CCommonSlotType zusammengefasst.

Die meisten Slot-Klassen sind immutable, also unveränderlich. So wird bei Arrays eine Kopie des Arrays angelegt. Eine Ausnahme ist wieder der Typ OBJECT.

Slots implementieren das Interface ISlot. Folgende Methoden stehen zur Verfügung:

// Erstellt eine Kopie
ISlot getCopy();

CSlotType getType();

Object getValue();

// Eine Vergleichsmethode
boolean isContentEqualTo(Object aValue);

// die übliche I/O-Methode
void toStream(DataOutputStream aStream) throws IOException;

// Eine Hilfsmethode für das Schreiben in XML-Dateien
void valueToList(List<String> aList);

String valueToString();

Erstellt werden Slots durch die SlotFactory.

Bei der Verwendung von statischen Zugriffsklassen, wie sie der Record-Generator aus XML-Message-Beschreibungen erstellt, erübrigt sich das Handling mit Slots. Die Verwendung dieser Klassen ist typsicher und sehr einfach:

final CEnvelope env = new CEnvelope(CWellKnownNID.SYSTEM);

final CRecord rec = CRecordRegisterMessageLogger.create();
CRecordRegisterMessageLogger.setParamObserver(rec, getAddress());
CRecordRegisterMessageLogger.setParamReceiverFilter(rec, aFilter);

sendNotification(env, rec);

Die Zugriffsmethoden dann eindeutig benannt (setParam**Observer**()), die Methoden nehmen nur ihre Argument-Typen (und keine Objects), und das Handling mit Slots und SlotKeys bleibt verborgen.

Slot Keys

Die SlotKeys bestehen aus zwei IDs:

  • der KeyId
  • dem KeyTyp

Im Prinzip reicht ein Key zum Zugriff, jedoch mit zwei Keys kann man z.B. gleiche Slot-Typen mit unterschiedlichen IDs betiteln, oder ein Namesschema à la “PATH/Key=Value” umsetzen. Platzsparend ist der Key dennoch, weil ein einzelnes Byte im Stream eine leere oder besetzte ID im Key anzeigt.

Die SlotFactory

Da die verschiedenen Slot-Typen mit ihren Factories registriert werden müssen, gibt es eine SlotFactory. Die ist über das Target, dem Namespace oder dem Kernel erreichbar:

ISlotFactory getSlotFactory();

Die SlotFactory hat diverse Methoden zum Erstellen von Slots:

// Erstellt ein Slot vom angegebenen Typ mit Default-Daten.
ISlot create(CSlotType aType) throws CException;

// Erstellt ein Slot vom angegebenen Typ mittels der mitgegebenen Daten.
ISlot create(CSlotType aType,
             Object aValue) throws CException;

// Überlässt dem Framework, welcher SlotType zu den Daten passt.
ISlot create(Object aValue);

// Liest einen Slot aus einem Stream.
ISlot createFromStream(DataInputStream aStream) throws IOException;

Ebenso gibt es dort Methoden zum Erstellen von SlotKeys:

// Erstellt einen SlotKey aus zwei IDs
ISlotKey createSlotKeyById(IId aKeyType,
                           IId aKeyId);

// Erstellt einen SlotKey aus einem Datenobjekt (Integer, String, UUID)
ISlotKey createSlotKeyByObject(Object aKeyType);

// Erstellt einen SlotKey aus zwei Datenobjekten (Integer, String, UUID)
ISlotKey createSlotKeyByObject(Object aKeyType,
                               Object aKeyId);

// Liest einen SlotKey aus einem Stream
ISlotKey createSlotKeyByStream(DataInputStream aStream) throws IOException;

// Liest einen SlotKey aus einem String. Der String ist so aufgebaut:
// "TTTTT|IIIIII", wobei T der KeyType ist und I die KeyId
ISlotKey createSlotKeyByString(String aValue);

Beispiel:

ISlotKey key = getSlotFactory().create("path", "key");
ISlot slot = getSlotFactory().create(CCommonSlotType.INT, 175);
aRecord.addSlot(key, slot);