raimund@716: Lada-Server
raimund@716: ===========
raimund@716: Die Software bietet Funktionalität zur Erfassung und Bearbeitung
raimund@716: von Messdaten. Sowie der Planung der Messungen.
raimund@716: 
raimund@716: Weitere Informationen finden sich auf der Projektwebseite unter
raimund@716: der Adresse: https://wald.intevation.org/projects/lada/
raimund@716: 
raimund@716: Die Software entstand im Rahmen einer Software Entwicklung durch die
raimund@716: Intevation GmbH im Auftrag des Bundesamt für Strahlenschutz in den Jahren 2013
raimund@716: bis 2015.
raimund@716: 
raimund@716: Kontakt
raimund@716: -------
raimund@716: Bundesamt für Strahlenschutz
raimund@716: SW2 Notfallschutz, Zentralstelle des Bundes (ZdB)
raimund@716: Willy-Brandt-Strasse 5
raimund@716: 38226 Salzgitter
raimund@716: info@bfs.de
raimund@716: 
raimund@716: Lizenz
raimund@716: ------
raimund@716: Die Software ist unter der GNU GPL v>=3 Lizenz verfügbar.
raimund@716: Details siehe die Datei `COPYING`.
raimund@716: 
raimund@716: Quelltext
raimund@716: ---------
raimund@716: Die Quelldateien lassen sich wie folgt auschecken:
raimund@716: ```
raimund@716: hg clone https://scm.wald.intevation.org/hg/lada/lada-server
raimund@716: ```
raimund@716: 
raimund@716: Entwicklung
raimund@716: -----------
raimund@716: Für die Entwicklung wird ein JDK7 und maven3 oder höher benötigt. Sämtliche
raimund@716: Abhängigkeiten werden von dem maven build System aufgelöst.
raimund@716: 
raimund@716: Installation
raimund@716: ------------
tom@750: Die Installation des Lada-Servers erfolgt in einem Wildfly-Application-Server
tom@750: (http://wildfly.org). Dazu müssen folgende Schritte unternommen werden:
raimund@716: 
raimund@716:  $ mvn clean compile package
tom@750:  $ mv target/lada-server-$VERSION.war $JBOSS_HOME/standalone/deployments
tom@750:  $ touch $JBOSS_HOME/standalone/deployments/lada-server-$VERSION.war.dodeploy
raimund@716: 
tom@750: $JBOSS_HOME ist hierbei durch den Pfad zur Wildfly-Installation zu ersetzen,
tom@750: $VERSION durch die aktuelle Versionsbezeichnung (entsprechend der Angabe in
tom@750: pom.xml).
raimund@716: 
tom@750: Zum Aktualisieren der Anwendung genügt es, das WAR-Archiv zu aktualisieren.
tom@750: 
tom@750: Die Anwendung ist dann unter dem Pfad "/lada-server-$VERSION" erreichbar.
raimund@716: 
tom@782: Um zu garantieren, dass die von den REST-Schnittstellen ausgelieferten
tom@782: Zeitstempel sich korrekt auf UTC beziehen, muss die entsprechende System-
tom@782: Property `user.timezone=UTC` vor dem Start des Application-Servers gesetzt
tom@782: werden (siehe `wildfly/standalone.conf`).
tom@782: 
tom@784: Das PostgreSQL-Datenbank-Backend des Lada-Servers kann als Nutzer `postgres`
tom@784: (bzw. als PostgreSQL-Superuser) mit dem Skript `db_schema/setup-db.sh`
tom@784: eingerichtet werden.
tom@784: 
tom@784: Details zur Installation können den Dateien `Dockerfile` und
tom@784: `db_schema/Dockerfile` entnommen werden.
tom@784: 
tom@1210: Docker
tom@1210: ------
tom@1210: Um schnell und automatisiert ein Entwicklungs-Setup für LADA aufsetzen zu
tom@1210: können, werden Dockerfiles mitgeliefert. Voraussetzung für die Anwendung ist
tom@1210: eine Docker-Installation. Folgendes Vorgehen führt zu einem
tom@1210: Vollständigen Setup inklusive LADA-Client, in dem jeweils der auf dem Host
tom@1210: vorhandene Quellcode in die Container gemounted wird, so dass auf dem Host
tom@1210: durchgeführte Änderungen leicht innerhalb der Container getestet werden können.
tom@1210: 
tom@1210: Bauen der Images:
tom@1210:  $ cd ./db_schema
tom@1210:  $ docker build -t koala/lada_db .
tom@1210:  $ cd ..
tom@1210:  $ docker build -t koala/lada_wildfly .
tom@1210:  $ cd your/repo/of/lada-client
tom@1210:  $ docker build -t koala/lada_client .
tom@1210: 
tom@1210: Aufbau eines Netzwerks für die LADA-Komponenten:
tom@1210:  $ docker network create lada_network
tom@1210: 
tom@1210: Starten der Container:
tom@1210:  $ cd db_schema
tom@1210:  $ docker run --name your_lada_db --net=lada_network -v $PWD:/opt/lada_sql/ \
tom@1210:           -d koala/lada_db:latest
tom@1210:  $ cd ..
tom@1210:  $ docker run --name lada_wildfly --net=lada_network \
tom@1210:           --link your_lada_db:lada_db -v $PWD:/usr/src/lada-server \
tom@1210:           -d koala/lada_wildfly
tom@1210:  $ cd your/repo/of/lada-client
tom@1210:  $ docker run --name lada_client --net=lada_network \
tom@1210:               -v $PWD:/var/www/html/ \
tom@1210:               --link lada_wildfly:lada-server \
tom@1210:               -p 8180-8184:80-84 -d koala/lada_client
tom@1210: 
tom@1210: Die LADA-Anwendung kann dann unter den angegebenen Ports mit verschiedenen
tom@1210: Rollen im Browser ausgeführt werden.
tom@1210: 
raimund@716: Tests
raimund@716: -----
raimund@716: Die auf Arquillian basierenden Tests erfordern einen vollständig konfigurierten
raimund@716: und gestarteten Wildfly Application-Server, da für die Schnittstellentest eine
raimund@716: Clientanwendung simuliert wird und HTTP-Requests ausgeführt werden.
raimund@716: 
raimund@716: Das Ausführen der Tests erfolgt durch das Kommando
raimund@716: 
raimund@716:  $ mvn -Premote-test clean test
raimund@716: 
tom@977: und benötigt eine leere Datenbank, die z.B. mit
tom@977: 
tom@977:  $ ./setup-db.sh -cn
tom@977: 
tom@977: angelegt werden kann.
tom@977: 
raimund@716: Dokumenation
raimund@716: ------------
raimund@716: Die Entwicklerdokumentation (Javadoc) kann mit dem folgenden Befehl im
raimund@716: Verzeichnis der Serveranwendung erzeugt werden:
raimund@716: 
raimund@716:  $ mvn javadoc:javadoc
raimund@716: 
raimund@716: Der Ordner 'target' enthält dann die Dokumentation im HTML-Format in dem
raimund@716: Verzeichnis 'site/apidocs'.
raimund@985: 
tom@1093: Erstellen von Queries
raimund@985: ---------------------
tom@1093: Queries können als SQL-Statement in der Tabelle stammdaten.queries definiert
tom@1093: werden. Eine Filterung kann über Variablen erfolgen, die in stammdaten.filter
tom@1093: definiert werden müssen und mittels SQL-Interpolation im SQL-Statement
tom@1093: verwendet werden können.
tom@1093: Um neue Queries für die Suche von Proben, Messungen und Messprogrammen zu
raimund@985: erstellen sind die folgenden Schritte erforderlich:
raimund@985: 
raimund@985: 1. In der Tabelle 'stammdaten.query' einen neuen Eintrag erzeugen.
raimund@985:    * id: Primary-Key (wird generiert)
tom@1093:    * name: Der Name der Query
raimund@985:    * type: Der Datentyp der gefiltert werden soll.
tom@1093:      (mögliche Werte siehe Datenbank-Schema-Definition)
raimund@985:    * sql: Das auszuführende SQL-Statement (siehe #Regeln für die Syntax)
raimund@985:    * description: Ein beschreibender Text
raimund@985: 
raimund@985: 2. In der Tabelle 'stammdaten.result' für die anzuzeigenden Felder je einen
raimund@985:    Eintrag erzeugen:
raimund@985:    * id: Primary-Key (wird generiert)
raimund@985:    * query_id: ID der zugehörigen und in Schritt 1. erzeugten Query
raimund@985:    * data_index: Name des Feldes zur Übertragung an den Client (in CamelCase)
raimund@985:    * header: Der Titel der Spalte für diesen Eintrag
raimund@985:    * width: Die Spaltenbreite (in Pixel)
raimund@985:    * flex: Dynamische Spaltenbreite (true/false)
raimund@985:    * index: Der Datenindex
raimund@985: 
tom@1093: 3. In der Tabelle 'stammdaten.filter' für jeden Parameter in der 'WHERE'-Clause
tom@1093:    der Query einen Eintrag erzeugen:
raimund@985:    * id: Primary-Key (wird generiert)
raimund@985:    * query_id: ID der zugehörigen und in Schritt 1. erzeugten Query
raimund@985:    * data_index: Der Name der Variablen, die in dem 'WHERE'-Statement ersetzt
raimund@985:      werden soll
raimund@985:    * type: Datenbasis, die im Client als Eingabe genutzt werden soll
tom@1093:      (mögliche Werte siehe Datenbank-Schema-Definition)
raimund@985:    * label: Der angezeigte Name des Filters
raimund@985:    * multiselect: Mehrfachangabe von Werten für diesen Filter (true/false)
raimund@985: 
raimund@985: ### Regeln
raimund@985: 
raimund@985: * Bei Queries vom Typ `probe` muss das erste selektierte Feld `probe.id` sein.
raimund@985:   Dieses wird in der Oberfläche nicht angezeigt.
tom@1093: * Bei Queries vom Typ `messung` muss das erste selektierte Feld `messung.id`
tom@1093:   und das zweite `probe.id` sein. Diese werden in der Oberfläche nicht
tom@1093:   angezeigt. Für `probe.id` muss in stammdaten.result ein Eintrag mit
tom@1093:   `data_index = 'probeId'` angelegt werden (obwohl diese Spalte nicht angezeigt
tom@1093:   wird). Um im Client die Funktionalität zu erhalten, sollten Messungsfilter
tom@1093:   die beiden Felder `probe.hauptproben_nr` und `messung.nebenproben_nr`
tom@1093:   enthalten.
raimund@985: * Bei Queries vom Typ `messprogramm` muss das erste selektierte Feld
raimund@985:   `messprogramm.id` sein. Dieses wird in der Oberfläche nicht angezeigt.
tom@1093: * Werden bei einem JOIN Spalten gleichen Namens aus verschiedenen Tabellen
tom@1093:   in der SELECT-Clause verwendet, so müssen diese mit einem expliziten Alias
tom@1093:   versehen werden, um eine
tom@1093:   org.hibernate.loader.custom.NonUniqueDiscoveredSqlAliasException zu
tom@1093:   vermeiden.
raimund@985: * Im `WHERE`-Statement genutzte Variablen müssen in der Form `:variablenName`
raimund@985:   angegeben werden und dem Feld `data_index` im zugehörigen Filter entsprechen.
tom@1093: * Wenn ein Filter mit `multiselect = true` angegeben wird, so wird in der
tom@1093:   `WHERE`-Clause ein `SIMILAR TO` erwartet.
raimund@985: * Das Feld `index` in der Tabelle `stammdaten.result` dient zur Zuordnung des
raimund@985:   selektierten Datenfeldes zu dem Entsprechenden Eintrag in der Tabelle
raimund@985:   `stammdaten.result`. Beispiel:
raimund@985: ```
raimund@985:     'SELECT probe.id, probe.mst_id AS mstId, probe.hauptproben_nr AS hpNr, ...'
raimund@985:                       |----- index 1 -----|  |--------- index 2 --------|
raimund@985:     Wird in der Tabelle 'stammdaten.result' zu:
raimund@985:     Result 1:
raimund@985:     ...
raimund@985:         data_index: mstId
raimund@985:         header: Messstelle
raimund@985:         width: 100
raimund@985:         flex: false
raimund@985:         index: 1
raimund@985:     ...
raimund@985:     Result 2:
raimund@985:     ...
raimund@985:         data_index: hpNr
raimund@985:         header: Hauptproben Nr
raimund@985:         width: 150
raimund@985:         flex: false
raimund@985:         index: 2
raimund@985:     ....
raimund@985: ```
raimund@990: * Queries für Stammdaten werden gesondert behandelt und beinhalten keine
raimund@985:   SQL-Statements. Dementsprechend können auch keine Einträge für Ergebnisse in
raimund@985:   der Tabelle `stammdaten.result` gemacht werden. Filter können allerdings,
raimund@990:   unter der Bedingung, dass `data_index` auf einen in dem Datentyp vorhandenes
raimund@990:   und in CamelCase geschriebenes Datenfeld zeigt, angelegt werden.
raimund@990:   Momentan sind Queries für die folgenden Stammdaten möglich:
raimund@985:    * Orte
raimund@985:    * Probennehmer
raimund@985:    * Datensatzerzeuger
raimund@985:    * Messprogrammkategorien