If you got the latest doxygen which also supports subsubsection, do a
s/@subsection ss/@subsubsection s/ and there you have your
subsubsection.

/** @page designpage (German) Design-berblick


@note Sorry, this is only German



In dieser Datei finden sich einige Texte, die Neulingen helfen sollen
einen besseren Einstieg in OpenHBCI zu erhalten. Bei Unstimmigkeiten
ist immer die Kommentierung im source bzw. die durch doxygen
generierte HTML-Dokumentation der API massgeblich. Die Benutzung von
OpenHBCI wird auch in der Klassen-Dokumentation von HBCI::API erklaert
und ist dort evtl. aktueller.



@section sect0 Inhalt
<ol>
<li>@ref sect1</li>
<li>@ref sect2</li>
<li>@ref sect3</li>
<li>@ref sect4</li>
</ol>

@section sect1 Struktur von OpenHBCI


Im folgenden mal eine kleine "Einleitung" zur Struktur von OpenHBCI.

Die Bibliothek ist in \e zwei verschiedenen Ebenen organisiert: Zum
einen gibt es die <b>"core"-Klassen</b> im Verzeichnis
<code>src/openhbci/core/</code>, zum anderen die
<b>Applikations-Klassen</b> fr den Programmablauf der Applikation im
Verzeichnis <code>src/openhbci/</code>.

Die <b>"core"-Klassen</b> bestehen zum einen aus der Definition von
abstrakten Basisklassen (Interfaces) fr die grundlegenden
Datenstrukturen in %HBCI (z.B. HBCI::Bank, HBCI::Account etc.), zum
anderen enthalten die core-Klassen die Implementierungen dieser
Basisklassen und der notwendigen Segmente/Datenformate fr das
konkrete %HBCI-Protokoll. Fr den Anwendungsprogrammierer sind *nur*
die Kenntnis der Basisklassen wichtig! Der Anwendungsprogrammierer
sollte sich *nicht* um die Implementierungen jener Basisklassen oder
gar um die Segmentstrukturen des %HBCI-Protokolls kmmern mssen.

Die <b>Applikations-Klassen</b> bestehen aus der Definition der mglichen
Geschftsvorflle in jeweils einer OutboxJob-Klasse sowie der
zentralen Verwaltungsklasse HBCI::API, die alle anderen Objekte in
passenden Listen gespeichert hlt und Warteschlangen fr alle
auszufhrenden Geschftsvorflle verwaltet. Auerdem ldt und
speichert die Klasse HBCI::API die notwendigen Konfigurationsdaten.



@subsection subsect1 Grundlegende "core"-Klassen 


@subsection ss1s1s1 Klasse HBCI::Bank


Eine Bank in %HBCI. Die Bank wird identifiziert durch Bankleitzahl und
Lndercode. Die Bank hat eine Liste ihrer Benutzer (User) und eine
Liste der bei ihr existierenden Konten (Account).


@subsection ss1s1s2 Klasse HBCI::User

Ein Benutzer, d.h. eine reale Person, die bei genau einer Bank als
%HBCI Benutzer registriert ist. Ein Benutzer besitzt genau ein
Sicherheitsmedium (HBCI::Medium), wo seine geheimen Schlssel
gespeichert sind. Ein Benutzer besitzt mindestens eine Kundennummer
(Customer) bzw. eine Liste von Kundennummern, mit der er/sie auf
Konten (Account) zugreifen darf.


@subsection ss1s1s3 Klasse HBCI::Customer

Eine Kundennummer (Customer) beschreibt die Rolle eines Benutzers
(User), die festlegt, mit welchen Rechten der Benutzer auf Konten
zugreifen kann. Jedes Konto (Account) hat eine Liste von Kundennummern
(Customer), denen der Zugriff auf jenes Konto erlaubt ist. ber die
Kundennummer (Customer) ergibt sich dann der Benutzer (User), der
diesen Kontozugriff ausfhren darf.


@subsection ss1s1s4 Klasse HBCI::Account

Ein Konto gehrt zu genau einer Bank und wird dort eindeutig durch die
Kontonummer identifiziert. Ein Konto besitzt eine Liste von
Kundennummern (Customer), denen der Zugriff auf dieses Konto erlaubt
ist.


@subsection ss1s1s5 Klasse HBCI::Medium

Das Sicherheitsmedium speichert die geheimen Schlssel eines Benutzers
(User) und implementiert die notwendigen Methoden zum
Ver-/Entschlsseln und Signieren von Nachrichten. Manche
Sicherheitsmedien knnen mehrere Schlssel speichern (jeden Schlssel
in einem sogenannten Context) und damit fr mehrere Benutzer als
Sicherheitsmedium dienen. Ein Sicherheitsmedium kann mit symmetrischen
Schlsseln arbeiten (DES-DES-Verfahren, DDV) oder mit asymmetrischen
Schlsseln (RSA-DES-Hybridverfahren, RDH).



@subsection subsect2 Applikations-Klassen



@subsection ss1s2s1 Klasse HBCI::API

Die zentrale Verwaltungsklasse, die alle anderen Objekte in passenden
Listen gespeichert hlt und Warteschlangen fr alle auszufhrenden
Geschftsvorflle verwaltet. Auerdem ldt und speichert die Klasse
HBCI::API die notwendigen Konfigurationsdaten.


@subsection ss1s2s2 Abgeleitete Klassen von HBCI::OutboxJob 

Alle implementierten Geschftsvorflle sind als eine abgeleitete
Klasse von OutboxJob zu finden. Fr eine Applikation ist damit nur
noch mageblich, welche der von OutboxJob abgeleiteten Klassen fr den
Geschftsvorfall bentigt wird, und welche zustzlichen Objekte diese
Klassen erfordern knnte. Alle von OutboxJob abgeleiteten Klassen
knnen in die Warteschlange der HBCI::API eingereiht werden und dann
als HBCI-Geschftsvorfall durch HBCI::API::executeQueue ausgefhrt
werden.


@subsection s1s3 Beispiele

Als Beispiele zu Verwendung von OpenHBCI in C++ dient der Programmcode
von aqmoney, zu finden im separaten Projekt
aqmoney.sourceforge.net. Ein minimalistisches Beispiel in C ist das
kurze Programm cmoney im OpenHBCI-Verzeichnis src/cmoney.


@subsection s1s4 Ansonsten

Das openHBCI-Team ist ansonsten uebereingekommen, dass die Verwendung
von konventionellen Pointern eingeschraenkt bleiben soll.  Wenn ein
Objekt einen Pointer uebergeben bekommt, darf es seinen Inhalt NICHT
loeschen, allerdings ist inzwischen sowieso an den allermeisten
Stellen HBCI::Pointer in Benutzung. 



@section sect2 Hinzufuegen neuer Geschaeftsvorfaelle


Ich habe zwar noch mal versucht den Job und die Segmente betreffend 
Saldoabfrage (GetBalance) ausfuehrlicher zu dokumentieren, aber das allein 
ist noch nicht aussagekraeftig genug.
Deshalb hier mal eine Einfuehrung in die Arbeit mit Segmenten und Jobs.


@subsection sect2subsect1 Interne Implementierungs-Klassen


@subsection ss2s1s1 Jobs, Segmente

Zur Kommunikation mit dem Server dienen direkt die Segmente (in 
adminsegs/accountsegs). Die werden von Programmen aber nie direkt verwendet, 
stattdessen erzeugt das Programm einen Job, der seinerseits fuer die 
Erzeugung aller noetigen Segmente sorgt.
Jobs die Administrationszwecken dienen, sind in den Dateien 
"adminjobs.h"/"adminjobs.cpp" definiert.
Jobs zum Umgang mit Konten sind hingegen in den Dateien 
"accountjobs.h"/"accountjobs.cpp" zu finden.


@subsection ss2s1s2 Klasse HBCI::MessageQueue

Wenn die vom User gewuenschten Jobs erzeugt sind, will man sie ja auch an den 
Mann bringen (respektive den Server). Dazu dient die MessageQueue. Man erzeugt 
sich ein Objekt dieser Klasse und ruft dann fuer jeden Job "addJob" auf. Als 
naechstes braucht man dann "HBCI::Connection".

@subsection ss2s1s3 Klasse HBCI::Connection

Diese Klasse managed die Verbindung zum Server, ausserdem kann man mit ihr 
den Inhalt einer HBCI::MessageBox an den Server senden sowie dessen Antwort 
abholen.



@subsection sect2subsect2 Unterscheidung JOBS/Segmente


Das Interface zum HBCI-Server sind die Segmente, sie stellen die unterste 
Ebene von openHBCI dar.
Kein Programm erstellt diese Segmente selber !

Ein Programm erzeugt stattdessen einen HBCI::OutboxJob als
Applikations-Klasse von OpenHBCI. Die Applikations-Klasse erzeugt
ihrerseits einen HBCI::JOB, der zwar seinerseits wieder ein bis
mehrere Segmente erzeugen kann, aber das geht das Programm nix an.
Der Gedanke, der dahinter steckt, ist folgender: Selbst die JOBS
wissen nicht, wie die einzelnen Segmente aussehen, die an den Server
geschickt werden (und der OutboxJob schon gar nicht). Wenn sich also
spaeter an dem Format der Segmente etwas aendert, muss man nur die
Segment-Klassen aendern, die JOBS und OutboxJobs hingegen kaum, und
das Hauptprogramm im besten Fall sogar gar nicht. Damit ist dann das
Hauptprogramm weit genug von %HBCI abstrahiert.


@subsection subsect3 Einbinden eigener Geschaeftsvorfaelle


Wenn man einen Geschaeftsvorfall einbinden moechte, muss man als erstes 
in den HBCI-Specs nachsehen, welche Segmente dabei im Spiel sind.
Dabei gibt es meistens drei Segmente: 
- Eines, dass man an den Server schickt, 
- eines, dass der Server als Antwort schickt.
- eines, dass eine Beschreibung fuer dieses Segment enthaelt und vom
  Server im Rahmen der Dialoginitialisierung gesendet werden kann (Stichwort
  in den HBCI-Specs: Bank-Parameter-Daten)

Im Beispiel von GetBalance:

@subsection ss2s3s1 Zum Server: Segment "HKSAL" ->SEGGetBalance

Dieses Segment muessen wir nur erzeugen koennen, wir brauchen es aber nicht 
Parsen zu koennen, da nur ein Server jemals so ein Segment geschickt bekommt.
Daher brauchen wir hier auch nur die Methode "toString()" implementieren.

@subsection ss2s3s2 Vom Server: Segment "HISAL" ->SEGBalance

Dieses Segment werden wir niemals erzeugen muessen, aber da es die Antwort des 
Servers ist und wir an der Antwort interessiert sind, muessen wir es parsen 
koennen. Also ist hier die Methode "parse()" implementiert, dafuer aber nicht 
"toString()".

@subsection ss2s3s3 Beschreibung: Segment "HISALS"

Dieses Segment enthaelt zusaetzliche Parameter fuer den Geschaeftsvorfall
"Saldenabfrage".


@subsection s2s4 Jobs

Ok, jetzt, wo wir grundsaetzlich in der Lage sind, uns mit dem Server
ueber Salden zu unterhalten, muessen wir das ganze noch in eine
einfache Form fuer die Applikations-Klassen bringen. Denn der
Entwickler einer Applikation will sich ja nicht mit der untersten
Ebene - den Segmenten - herumschlagen.  Bei JOBS gibt es auch wieder 2
wichtige Methoden:


@subsection ss2s4s1 Erzeugen der Segmente fuer den Server

Die Methode "toString()" erzeugt die noetigen Segmente aus den Daten, die im 
Job gespeichert sind. In diesem Fall ist das beispielsweise die Kontonummer 
und Bankleitzahl des Kontos, dessen Saldo wir abfragen wollen.
Diese Methode ruft man uebrigends nicht selber auf, das tut spaeter die 
HBCI::MessageQueue automatisch.

@subsection ss2s4s2 Verarbeiten der Antwort des Server

Sobald die Antwort des Servers eintrifft, die von der Klasse HBCI::MessageQueue
entgegengenommen wird und aus einzelnen Segmenten besteht, wird sofort 
nachgesehen, welches Segment die Antwort auf welchen Job darstellt.
Jeder Job weiss, wass fuer Antwort-Segmente er zu erwarten hat, und wie er 
sie zu parsen hat (das macht dann die Methode "parseResponse()". Tatsaechlcih 
parsed der Job natuerlich die Segmente nicht selbst, sondern ruft die 
entsprechende Methode der Segmentklassen auf -> "parse()").
Die HBCI::MessageQueue ruft also zu jedem Segment die Methode "parseResponse()"
des passenden Jobs auf.
Der Job sieht sich nun jeweils die Segmente an und entnimmt ihnen die 
Informationen, auf die er gewartet hat (hier ist es zum Beispiel der 
Kontostand).

Wichtig ist, dass die Account-Segmente und Jobs die Daten nur in sich
selbst speichern duerfen !!  Sie duerfen also nicht einfach ihre Daten
in den in der HBCI-Klasse gespeicherten Listen ablegen, sonderm
muessen sie lokal als Member ihrer Klasse speichern. Wenn die
Applikations-Klasse interesse an den Daten hat, soll es sie
gefaelligst selbst aus den Jobs holen und ihrerseits Member-Methoden
fr die Applikation anbieten. Im Falle des JOBGetBalance kann man den
frischen Kontostand beispielsweise mit "getBalance()" abholen, und
dann, wenn man will, in der HBCI-Klasse oder wo auch immer speichern.





@section sect3 Verwendung vom HBCI::Pointer


Dieses Thema sieht in den Sourcen manchmal etwas verwirrend aus, deshalb hier 
eine kurze Einleitung zu dem HBCI::Pointer.

Ein HBCI::Pointer ist ein referenzzhlender Zeiger auf ein Objekt.
Das Problem mit Zeigern ist, dass man sich immer merken muss, WER das
Objekt, auf das er zeigt, loeschen darf oder MUSS. Ausserdem will man
auch vermeiden, dass eine Klasse dieses Objekt loescht, waehrende eine
andere Klasse noch damit arbeitet. Eine andere Geschichte ist, wenn
man in einer Prozedur/Methode viele Pointer benutzt, und dann wegen
eines Fehlers abbrechen muss. Welche Pointer hatte man schon gesetzt?
Welche muessen freigegeben werden und welche DUERFEN nicht? Mit dem
HBCI::Pointer reicht ein einfaches "return", und die Freigabe der
Ressourcen geht automatisch.

Diese Arbeit uebernimmt nun der HBCI::Pointer. Er speichert intern
einen Zeiger auf das zu verwaltende Objekt und zustzlich einen
Benutzerzaehler/Referenzzhler.  Solange noch irgendein HBCI::Pointer
auf das angegebene Objekt zeigt, wird es nicht geloescht. Sobald aber
KEIN HBCI::Pointer mehr darauf zeigt, wird es AUTOMATISCH freigegeben,
d.h. delete() wird aufgerufen.

Das bedeutet fuer den Programmierer aber:
Solange man mit dem Objekt arbeiten moechte, muss man dafuer sorgen, dass 
irgendein HBCI::Pointer noch auf dieses Objekt verweist. Folgendes waere 
beispielsweise ein Fehler:

@code
HBCI::Pointer<HBCI::Account> hptr_acc = new HBCI::Account(...);
HBCI::Account *ptr_acc;

// hole einen konventionellen Zeiger auf das Objekt
ptr_acc=hptr_acc.ptr();

/* HBCI::Pointer zeigt jetzt nicht mehr auf das Konto (zeigt nun
 * auf garnix mehr. Dadurch wird aber das Objekt, auf das er
 * zeigte geloescht, wenn er der letzte HBCI::Pointer war) */
hptr_acc=0;

/* der konventionelle Pointer zeigt nun auf ein Objekt, das gerade 
 * geloescht wurde. Deshalb gibt es gleich einen Segfault ! */
printf("AccountId==%s\n",ptr_acc->accountId());
@endcode

Manche Klassen sind aber nicht vorbereitet auf die Verwendung von
HBCI::Pointer, sie erwarten konventionelle Pointer. Fuer diesen Fall
gibt es die eben gezeigte Methode HBCI::Pointer::ptr(), die genau DAS
liefert. (Der Operator "*" tut das uebrigends auch, macht die Sourcen
aber schwerer lesbar.) Man muss dann aber sicherstellen, dass diese
Klassen den konventionellen Pointer nicht loeschen, denn sonst wrden
zum einen noch existierende HBCI::Pointer pltzlich ungltig und zum
anderen wrde das Objekt durch den letzten HBCI::Pointer ein zweites
Mal gelscht.

Will man eine Referenz auf das Objekt haben, verwendet man
HBCI::Pointer::ref().

Wenn das automatische Loeschen nicht durchgefhrt werden soll, gibt es
die Methode HBCI::Pointer::setAutoDelete(). Mit setAutoDelete(false)
wird der letzte HBCI::Pointer *nicht* das Objekt lschen, sondern der
Programmierer mu sich (wahrscheinlich) selber darum kmmern. Manchmal
braucht man das halt. Es wre wohl besser, diese Methode nicht so oft
zu benutzen.

Werden HBCI::Pointer kopiert, so erhoeht sich automatisch der
Benutzerzaehler/Referenzzhler des Objektes, auf das der Pointer
zeigt.



@section sect4 Verwendung von libchipcard fuer ChipKarten-Support


Seit Version 0.3.1 ist die Unterstuetzung von Chipkarten deutlich verbessert.
Der Grund dafuer sind tiefgreifende Aenderungen an libchipcard (zu finden bei
http://libchipcard.sf.net). Seit dessen Version 0.3 benoetigt es beim Linken
und kompilieren keine CTAPI Bibliothek mehr (das ist die Treiber-Bibliothek
der Chipkarten-Terminals). Diese wird nunmehr dynamisch und erst bei Bedarf
nachgeladen. 

Sobald die Chipkarten-Medien nur noch ber plugins zur Laufzeit in
OpenHBCI geladen werden, ist libchipcard berhaupt nicht mehr in
OpenHBCI notwendig. Dies wird wohl ab Version 0.9.10 so sein.


@section sect5 Autoren

Martin Preuss<openhbci@aquamaniac.de>,
Hamburg, 11. Maerz 2002

Christian Stimming <stimming@tuhh.de, 23. April 2003

*/