Backend
Die Hauptlast bei für die Administrierung der Dienste liegt im Backend. Welche in diesem Kapitel anhand ihrer Klassen und Schichten dokumentiert werden soll.
Services
Die Services übernehmen die Instanziierung der Objekte und erstellen die vom Clienten über das Dashboard gewünschten Dienste über die REST-Schnittstelle (routes.py). Für die OGC-Dienste wurde das Factory-Pattern eingesetzt, welches je nach Parametrisierung, den entsprechenden OGC-Layer instanziiert.
OGC-Factory
Die OGC-Factory wird von der routes.py aufgerufen um die gewünschten Dienste zu erstellen. Die Factory-Pattern-Methode definiert dabei ein Interface für die Erstellung von Objekten und delegiert die Objekterstellung an die Sub-Klassen. Ziel ist, dass der Client nichts von der Objekt-Instantiierung mitbekommt und über eine gemeinsame Schnittstelle auf die Objekte zugreift. Factory-Patterns kapseln dadurch den Creation Code vom Client [Quelle].
Um dies zu verdeutlichen ist nachfolgend der Code abgebildet:
class OgcFactory:
def __init__(self,_service):
self.service = _service.lower()
#localhost for testing
if("localhost" in request.url or "127.0.0.1:5000" in request.url):
app.logger.debug("OGC Service for localhost")
#dummy path
self.path ='G:\\test\\'.format(self.service)
# server path
else:
app.logger.debug("OGC Service for monitor.ioer.de")
#dummy path
self.path = '/server/'.format(self.service)
def create_service(self):
if self.service =='wms':
return WmsService(self.path)
elif self.service =='wcs':
return WcsService(self.path)
elif self.service=='wfs':
return WfsService(self.path)
Der Konstruktor definiert dabei auf welchen Pfaden die Services erstellt werden sollen.
WCS-Services
WFS-Service
WMS-Service
Die Klassen WCS-Services, WFS-Service und WMS-Service implementieren die vom OgcService-Interface definierten Methoden. Hierbei werden in der Methode createAllServices alle für die OGC-Rasterdienste bzw. Vektordienste freigegebenen Indikatoren vom Backend abgefragt. Diese Aufgabe wird von der Klasse Indicator-Values übernommen. Anhand einer Schleife wird für jeden verfügbaren Indikator ein neuer IoerIndicator instanziiert und an die writeFile Methode übergeben. Diese erstellt anhand der Getter-Methoden des übergebenen Indikators das entsprechende Mapfile in dem angegebenen Pfad. Der Pfad wird hierbei im Konstruktor übergegeben, diese Aufgabe übernimmt die Factory.
Folgend sind die Parameter und Methoden dokumentiert.
Methode | Parameter | Beschreibung |
---|---|---|
public: init | optional-String:Path | Konstruktor ![]() |
public: createAllServices | Object: Indikator, optional-String:Path | Methode um einzelne Dienste für einen übergebenen Indikator zu erstellen |
private: writeFile | optional-String:Path) | Diese Methode erstellt anhand des übergebenen Indikators das gewünschte Mapfile, primär wird der Pfad aus dem im Konstruktor definierten Pfad übergeben. Als Rückgabe wird ein Objekt mit dem Indikator und dessen Status (erstellt/Fehler) übergeben. |
Indicator-Values
Diese Klasse hat die Aufgabe für die Übergebene Raumgliederung alle verfügbaren Indikatoren vom Monitor-Backend abzurufen. Über die Methode getAllAvaliableServiceValues werden anhand des Paramters Raumgliederung (raster,gebiete) alle verfügbaren Indikatoren abgerufen und ein JSON-Objekt zurückgegeben. Der Code der Klasse ist nachfolgend abgebildet.
class IndicatorValues:
def __init__(self,format):
self.url = Config.URL_BACKEND_MONITOR
self.json = '{"format":{"id":"%s"},"query":"getAllIndicators"}' % format
self.format=format
req = requests.post(self.url, data={'values':self.json})
self.values = json.loads(req.text)
print (self.values)
#methon to return all possible indicator values which are possible for an indicator
def getAllAvaliableServiceValues(self,service):
res =[]
for x in self.values:
cat_name = self.values[x]['cat_name']
cat_name_en = self.values[x]['cat_name_en']
values = self.values[x]['indicators']
ind_values = []
for i in values:
# if 1: the service is avaliable else not
if int(values[i]["ogc"][service]) == 1:
ind_val=dict(values[i])
ind_id = dict({"id":i})
merge = dict()
merge.update(ind_id)
merge.update(ind_val)
del merge['atkis']
del merge['ogc']
ind_values.append(merge)
res.append({'cat_id':x,'cat_name':cat_name,'cat_name_en':cat_name_en,"values":ind_values})
return res
GeoSN
Diese Klasse implementiert das Interface GeoSN-Service und hat die Aufgabe, die Dienste des IÖR-Monitors mit dem GeoMIS zu verknüpfen. Der Service wurde notwendig, da zum aktuellen Zeitpunkt keine API auf der Seite des GeoMIS vorhanden ist, welche diese Aufgabe übernimmt.
Anhand der vom GeoMIS bereitgestellten XML-Dateien, werde diese mit den aktuellen Informationen der Datenbank synchronisiert. Hierfür parst die Methode updateFile alle XML-Dateien in dem vorgegebenen Verzeichnis. Passt die Parametrisierung mit der gesetzten Klassenvariable Indikator überein, wird dieses aktualisiert. Hierfür fällt der händische Update-Vorgang in der GUI des GeoMIS weg. Durch die Freigabe des Verzeichnisses nach außen, kann das GeoMIS die in den XML-Dateien definierten Dienste harvesten.
Die Methode update ruft von Dienst Indicator-Values alle Raster und Vektor Indikatoren auf, welche das IÖR nach außen freigibt und ruft auf deren Basis die private Methode updateFile auf. Iterativ wird dabei die Klassenvariable Indikator gesetzt, welche jeweils das Model IÖR-Indikator ist.
Interfaces
Eine Schnittstelle (englisch interface) gibt in der objektorientierten Programmierung an, welche Methoden in den unterschiedlichen Klassen vorhanden sind oder vorhanden sein müssen. Quelle
OgcService
Dieses Interface definiert die notwendigen Methoden für die Erstellung eines IÖR-OGC Dienstes.
GeoSN-Service
Dieses Interface definiert die notwendigen Methoden für die Erstellung eines GeoSN Dienstes.
Indikator
Dieses Interface definiert einen Indikator für das IÖR-Indikatorensystem.
Models
Repräsentiert den internen Zustand eines Objekts und speichert alle interessanten Geschäftsdaten. Ein Model bietet Methoden an, mit denen sich der aktuelle Zustand erfragen und ändern lässt. Quelle
IÖR-Indikator
Diese Klasse wird verwendet um innerhalb der Sevices einen Indikator zu instanziieren und damit auf die getter zuzugreifen. Das Verhalten der Klasse wird dabei durch das Interaface Indikator definiert. Die Klasse besitzt auch eine Methode toJSON, welche verwendet wird um in den Service-Klassen den Status der Indikatorerstellung festzuhalten. Hierfür wird ein sogenannter state übergeben. Nachfolgend ist der Code abgebildet:
def toJSON(self,state="create"):
return {self.id:{
"state": state,
"name": self.name,
"description": self.description,
"times": self.time_string,
"spatial_extends": self.spatial_extends,
"unit": self.units,
"methodik": self.methodology
}}
Toolbox
Die Toolbox übernimmt Aufgaben die in vielen Klassen benötigt werden. Nachfolgend ist ihr Code abgebildet.
class Toolbox:
def clean_string(self, string):
d = {"\\": "", "\n": "",'"':"","Kurzbeschreibung":""," ":""}
for i, j in d.items():
string = string.replace(i, j)
return string.strip()
def json_validator(self,data):
try:
json.loads(data)
return True
except ValueError as error:
return False
Methode | Definition |
---|---|
clean_string | Anhand eines übergebenen Strings wewrden nicht benötigte Charaktere aus diesem entfernt, dies kommt vor allem bei den langen Definitionen vor, welche von den Mapfiles nicht gelesen werden können |
json_validator | Prüft ob der übergebene String im JSON-Format ist, sonst wird False zurückgebenen. |
Color
Die Klasse Color wird für den WMS-Service verwendet, um die Farbliche Klasseneinteilung der Mapfiles zu bewerkstelligen und um notwendige Umrechnungen durchzuführen.
Methode | Paramter | Rückgabe | Definition |
---|---|---|---|
__init__ | String:min_color,String:max_color,int:classes | Konstruktor ![]() |
Bei der instanziierung der Color-Klasse muss der Minimale- und MAximale Farbwert als HEX-Code angegeben werden. Desweiteren ist es wichtig die Anzahl der Klassen zu definieren, um den Aufbauenden Berechnungen mitzuteilen, welche Breite des farbliche Spektrum besitzen soll. |
private:Berechnung | String:Min-Color, String:Max-Color | Array | Diese Methode erstellt ausgehend von der Anzhal der Klassen ein Array, welches für die übergebenen Minimal- und Maximalwerte die dazwischenliegenden Farbcodes generiert. |
private:HexToRGB | String:Hex-Code | String:RGB-Code | Diese Methode berechnet für den übergebenen Hex-Code den RGB-Wert aus |
private:RGBToHex | String:RGB-Code | String:Hex-Code | Diese Methode berechnet für den übergebenen RGB-Code den HEX-Wert aus |
public:buildColorPalette | Array | Diese Methode nutzt die privaten Methoden um die Finale Farbpallete zu erstellen. In dem Array wird dann für jede Klasse der entsprechende Farbwert als HEX-Code gespeichert | |
public: toString | String | Gibt die Klassen-Paramter als String zurück |
Routing
Das Route Mapping wurde für die administrativen Aufgaben implementiert. Um die Übersicht zu bewahren wurde wie auch schon für die anderen Aufgabend er API ein Blueprint angelegt, mit dem Kürzel admin, welches die URL erweitert. Nachfolgend ist der Code abgebildet, welcher demonstriert welche Klassen bei der jeweiligen URL aufgerufen werden. Die Schnittstelle ist nur für angemeldete User zu erreichen, was über die Expession @login_required realisiert wurde.
@admin.route('/')
@login_required
def admin_page():
return render_template("admin/index.html")
@admin.route('/wfs',methods=['GET', 'POST'])
@login_required
def wfs_service():
wfs = OgcFactory('wfs')
return jsonify(wfs.create_service().createAllServices())
@admin.route('/wcs',methods=['POST'])
@login_required
def wcs_service():
wcs = OgcFactory("wcs")
return jsonify(wcs.create_service().createAllServices())
@admin.route('/wms',methods=['POST'])
@login_required
def wms_service():
wms = OgcFactory("wms")
return jsonify(wms.create_service().createAllServices())
@admin.route('/geosn',methods=['POST'])
@login_required
def geosn_service():
geosn = GeoSN('/srv/www/htdocs/monitor_ogc_xml/')
return jsonify(geosn.update())
In der nachfolgenden Tabelle sind die URL-Endpoints und deren Aufgaben kurz zusammengefasst.
Endpoint | Beschreibung |
---|---|
/admin/ | beim Aufruf dieser URL wird das zugrundeliegende Template aus dem Static gerendert (admin/index.html). |
/admin/wfs | Hier wird der OGC-Factory als Service wfs mitgegeben, wodruch alle Web Feature Services des IÖR aktualisiert werden. |
/admin/wcs | Hier wird der OGC-Factory als Service wcs mitgegeben, wodruch alle Web Coverage Services des IÖR aktualisiert werden. |
/admin/wms | Hier wird der OGC-Factory als Service wms mitgegeben, wodruch alle Web Map Services des IÖR aktualisiert werden. |
/admin/geosn | Hier wird die Klasse GeoSN aufgerufen, womit alle Dienste des IÖR im GeoMIS aktualisiert werden. |