184 lines
6.4 KiB
Python
184 lines
6.4 KiB
Python
# Copyright (c) 2023 Thomas Tuerk (kontakt@thomas-tuerk.de)
|
|
#
|
|
# This file is part of PyAPplus64 (see https://www.thomas-tuerk.de/de/pyapplus64).
|
|
#
|
|
# Use of this source code is governed by an MIT-style
|
|
# license that can be found in the LICENSE file or at
|
|
# https://opensource.org/licenses/MIT.
|
|
|
|
from .applus import APplusServer
|
|
from . import sql_utils
|
|
import lxml.etree as ET # type: ignore
|
|
from typing import Optional, Tuple, Set
|
|
import pathlib
|
|
|
|
|
|
class XMLDefinition:
|
|
"""Repräsentation eines XML-Dokuments"""
|
|
|
|
def __init__(self, root: ET.Element) -> None:
|
|
self.root: ET.Element = root
|
|
"""das Root-Element, repräsentiert "object" aus Datei."""
|
|
|
|
def __str__(self) -> str:
|
|
return ET.tostring(self.root, encoding="unicode")
|
|
|
|
def getDuplicate(self) -> Tuple[Set[str], bool]:
|
|
"""
|
|
Extrahiert alle Properties, die für Duplizieren konfiguriert sind.
|
|
Zudem wird ein Flag geliefert, ob diese Properties ein oder ausgeschlossen werden sollen.
|
|
:return: Tuple aus allen Properties und ob dies aus- (True) oder ein-(False) zuschließen sind.
|
|
:rtype: Tuple[Set[str], bool]
|
|
"""
|
|
res: Set[str] = set()
|
|
excl = True
|
|
dupl = self.root.find("duplicate")
|
|
if (dupl is None):
|
|
return (res, excl)
|
|
|
|
exclS = dupl.get("type", default="exclude")
|
|
excl = exclS.casefold() == "exclude"
|
|
|
|
for e in dupl.findall("{ref}property"):
|
|
v = e.get("ref")
|
|
if not (v is None):
|
|
res.add(sql_utils.normaliseDBfield(str(v)))
|
|
|
|
return (res, excl)
|
|
|
|
|
|
class APplusScriptTool:
|
|
"""
|
|
Zugriff auf AppServer ScriptTool
|
|
|
|
:param server: die Verbindung zum Server
|
|
:type server: APplusServerConnection
|
|
|
|
"""
|
|
|
|
def __init__(self, server: APplusServer) -> None:
|
|
self.client = server.getClient("p2script", "ScriptTool")
|
|
|
|
def getCurrentDate(self) -> str:
|
|
return self.client.service.getCurrentDate()
|
|
|
|
def getCurrentTime(self) -> str:
|
|
return self.client.service.getCurrentTime()
|
|
|
|
def getCurrentDateTime(self) -> str:
|
|
return self.client.service.getCurrentDateTime()
|
|
|
|
def getLoginName(self) -> str:
|
|
return self.client.service.getLoginName()
|
|
|
|
def getUserName(self) -> str:
|
|
return self.client.service.getUserName()
|
|
|
|
def getUserFullName(self) -> str:
|
|
return self.client.service.getUserFullName()
|
|
|
|
def getSystemName(self) -> str:
|
|
return self.client.service.getSystemName()
|
|
|
|
def getInstallPath(self) -> str:
|
|
"""
|
|
Liefert den Installionspfad des Appservers
|
|
"""
|
|
return self.client.service.getInstallPath()
|
|
|
|
def getInstallPathAppServer(self) -> pathlib.Path:
|
|
"""
|
|
Liefert den Installionspfad des Appservers als PathLib-Path
|
|
"""
|
|
return pathlib.Path(self.getInstallPath())
|
|
|
|
def getInstallPathWebServer(self) -> pathlib.Path:
|
|
"""
|
|
Liefert den Installionspfad des Webservers als PathLib-Path
|
|
"""
|
|
return self.getInstallPathAppServer().parents[0].joinpath("WebServer")
|
|
|
|
def getXMLDefinitionString(self, obj: str, mandant: str = "") -> str:
|
|
"""
|
|
Läd die XML-Defintion als String vom APPServer. Auch wenn kein XML-Dokument im Dateisystem gefunden wird,
|
|
wird ein String zurückgeliefert, der einen leeren Top-"Object" Knoten enthält. Für gefundene XML-Dokumente
|
|
gibt es zusätzlich einen Top-"MD5"-Knoten.
|
|
|
|
:param obj: das Objekt, dessen Definition zu laden ist, "Artikel" läd z.B. "ArtikelDefinition.xml"
|
|
:type obj: str
|
|
:param mandant: der Mandant, dessen XML-Doku geladen werden soll, wenn "" wird der Standard-Mandant verwendet
|
|
:type mandant: str optional
|
|
:return: das gefundene XML-Dokument als String
|
|
:rtype: str
|
|
"""
|
|
return self.client.service.getXMLDefinition2(obj, "")
|
|
|
|
def getXMLDefinition(self, obj: str, mandant: str = "", checkFileExists: bool = False) -> Optional[ET.Element]:
|
|
"""
|
|
Läd die XML-Definition als String vom APPServer. und parst das XML in ein minidom-Dokument.
|
|
|
|
:param obj: das Objekt, dessen Definition zu laden ist, "Artikel" läd z.B. "ArtikelDefinition.xml"
|
|
:type obj: str
|
|
:param mandant: der Mandant, dessen XML-Doku geladen werden soll, wenn "" wird der Standard-Mandant verwendet
|
|
:type mandant: str optional
|
|
:return: das gefundene und geparste XML-Dokument
|
|
:rtype: ET.Element
|
|
"""
|
|
return ET.fromstring(self.getXMLDefinitionString(obj, mandant=mandant))
|
|
|
|
def getXMLDefinitionObj(self, obj: str, mandant: str = "") -> Optional[XMLDefinition]:
|
|
"""
|
|
Benutzt getXMLDefinitionObj und liefert den Top-Level "Object" Knoten zurück, falls zusätzlich
|
|
ein MD5 Knoten existiert, also falls das Dokument wirklich vom Dateisystem geladen werden konnte.
|
|
Ansonten wird None geliefert.
|
|
|
|
:param obj: das Objekt, dess Definition zu laden ist, "Artikel" läd z.B. "ArtikelDefinition.xml"
|
|
:type obj: str
|
|
:param mandant: der Mandant, dessen XML-Doku geladen werden soll, wenn "" wird der Standard-Mandant verwendet
|
|
:type mandant: str optional
|
|
:return: das gefundene und geparste XML-Dokument
|
|
:rtype: Optional[XMLDefinition]
|
|
"""
|
|
e = self.getXMLDefinition(obj, mandant=mandant)
|
|
if e is None:
|
|
return None
|
|
|
|
if e.find("md5") is None:
|
|
return None
|
|
|
|
o = e.find("object")
|
|
if o is None:
|
|
return None
|
|
else:
|
|
return XMLDefinition(o)
|
|
|
|
def getMandant(self) -> str:
|
|
"""
|
|
Liefert den aktuellen Mandanten
|
|
"""
|
|
return self.client.service.getCurrentClientProperty("MANDANTID")
|
|
|
|
def getMandantName(self) -> str:
|
|
"""
|
|
Liefert den Namen des aktuellen Mandanten
|
|
"""
|
|
return self.client.service.getCurrentClientProperty("NAME")
|
|
|
|
def getServerInfoString(self) -> str:
|
|
"""
|
|
Liefert Informationen zum Server als String. Dieser String repräsentiert ein XML Dokument.
|
|
|
|
:return: das XML-Dokument als String
|
|
:rtype: str
|
|
"""
|
|
return self.client.service.getP2plusServerInfo()
|
|
|
|
def getServerInfo(self) -> Optional[ET.Element]:
|
|
"""
|
|
Liefert Informationen zum Server als ein XML Dokument.
|
|
|
|
:return: das gefundene und geparste XML-Dokument
|
|
:rtype: ET.Element
|
|
"""
|
|
return ET.fromstring(self.getServerInfoString())
|