Ich habe mich mit der Idee zu diesem Projekt Monate abgequält - hätte ich gewusst, was die eigentliche Implementierung für Qualen verursachen würde, hätte ich sie wahrscheinlich eingestampft.
Dieses Projekt war in meiner Erinnerung das schmerzhafteste, das ich bisher angegangen bin - aber von Anfang an...
Für (Java) Projekte, die eine Scripting-API anbieten ist es schön, automatisch Dokumentation aus den Javadoc-Kommentaren erzeugen zu können - für die sQLshell konnte ich das sofort benutzen, da das Default-Ergebnis des Javadoc-Processing HTML ist und das ist dieselbe Technologie, die auch hinter JavaHelp steht. Für meine Projekte deren Dokumentation auf DocBook beruht wäre es schön, wenn man eine entsprechende Technologie hätte, die die Javadoc-Kommentare nach DocBook umsetzen - damit könnte man dann die API in allen von DocBook unterstützten Zielformaten erzeugen.
Javadoc bietet die Möglichkeit, sogenannte Doclets für andere als das Default-Zielformat zu benutzen und sogar die Möglichkeit, neue Tags zu definieren und diese mit dem Default-Zielformat oder anderen Zielformaten zu benutzen. Mit einer solchen Flexibilität ist doch bestimmt bereits einmal jemand auf die Idee gekommen, ein DocBooc Doclet zu schreiben und es als OpenSource zu veröffentlichen? Sollte man denken...
In den commit-Messages war aber zu erkennen, dass das Projekt vor kurzem auf die neue Doclet-API umgestellt worden war - und es gab sogar eine neue Release. Das ließ mich wieder hoffen. Die Hoffnung wurde zerstört: Das Ausführen des Doclet führte zu einer Menge kryptischer Fehlermeldungen und als ich mir den Quelltext ansah stellte ich fest, dass die Migration auf die neue API nicht vollständig war.
Beim Versuch, das Projekt dann eben selbst zu bauen fiel ich dann total vom Glauben ab - nicht nur, dass der Originalautor die Migration auf die neue API nicht auf einem entsprechenden Branch erledigt hat - er hat einfach die betrofenen Klassen kopiert und in ein beinahe namensgleiches Package parallel zu dem ursprünglichen abgelegt, nur mit einer 8 angehängt. Das benutzte Buildsystem ist Apache Ant - nichts dagegen zu sagen, benutze ich auch immer noch. Aber: das toplevel build.xml includiert ein anderes aus einem darüberliegenden Verzeichnis. Damit kann man das Projekt nicht bauen.
Irgendwann war es aber dann so weit: Ich hatte über die API eine Datenstruktur erstellt, die alle von mir für den ersten Wurf definierten Tags und syntaktischen Konstrukte aus dem Javadoc extrahierte - nun konnte es an die Erstellung des DocBook gehen.
Caused by: java.lang.IllegalAccessException: class org.apache.velocity.util.DuckType cannot access \
class com.sun.tools.javac.util.List (in module jdk.compiler) because module jdk.compiler does not export \
com.sun.tools.javac.util to unnamed module @12dae582
Nun musste ich zunächst herausfinden, wie man JVM-Argumente korrekt an javadoc übergibt - Spoiler: -J. Das führte dazu, dass ich meine Kommandozeile/ANT-Datei mit schwarz-magischen Kommandozeilenparametern überfrachten musste - nur um das Doclet überhaupt benutzen zu können:
--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED \
--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED \
--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
Das Template (aktueller Stand) für die derzeit unterstützten Features sieht wie folgt aus:
<?xml version="1.0" encoding="UTF-8"?>
<refentry>
<refnamediv>
<refname>${stringifier.toString(${data.className})}</refname>
<refpurpose>${stringifier.toString(${data.firstSentence})}</refpurpose>
</refnamediv>
<refsynopsisdiv>
<classsynopsis language="java">
<ooclass>
<!--modifier>class</modifier-->
<package>${stringifier.toString(${data.namespace})}</package>
<classname>${stringifier.toString(${data.className})}</classname>
</ooclass>
#if(${data.methodDescriptions})
#foreach ($value in ${data.methodDescriptions.values()})
<methodsynopsis>
<type>${stringifier.toString(${value.returnType})}</type>
<methodname><xref endterm="refsect_${data.namespace}_${data.className}_${stringifier.toString(${value.simpleName})}_title" linkend="refsect_${data.namespace}_${data.className}_${stringifier.toString(${value.simpleName})}"/></methodname>
#if(${value.params})
#foreach ($param in ${value.methodParameters})
<methodparam>
<type>${stringifier.toString(${param.asType()})}</type>
<parameter>${stringifier.toString(${param.simpleName})}</parameter>
</methodparam>
#end
#else
<void/>
#end
</methodsynopsis>
#end
#end
</classsynopsis>
</refsynopsisdiv>
#if(${data.authors})
<refsect1><title>Authors</title>
<itemizedlist>
#foreach ($part in ${data.authors})
<listitem>
${stringifier.toString(${part.name})}
</listitem>
#end
</itemizedlist>
</refsect1>
#end
#if(${data.body})
<refsect1><title>Description</title>
<para>
#foreach ($part in ${data.body})
${stringifier.toString(${part})}
#end
</para>
</refsect1>
#end
#if(${data.methodDescriptions})
<refsect1><title>Methods</title>
#foreach ($part in ${data.methodDescriptions})
<refsect2 xml:id="refsect_${data.namespace}_${data.className}_${stringifier.toString(${part.simpleName})}"><title xml:id="refsect_${data.namespace}_${data.className}_${stringifier.toString(${part.simpleName})}_title">${stringifier.toString(${part.simpleName})}</title>
#if(${part.firstSentence})
<para>
#foreach ($sentencepart in ${part.firstSentence})
${stringifier.toString(${sentencepart})}
</para>
#end
#end
<para>
<methodsynopsis>
<type>${stringifier.toString(${part.executableElement.returnType})}</type>
<methodname>${stringifier.toString(${part.executableElement.simpleName})}</methodname>
#if(${part.executableElement.parameters})
#foreach ($param in ${part.executableElement.parameters})
<methodparam>
<type>${stringifier.toString(${param.asType()})}</type>
<parameter>${stringifier.toString(${param.simpleName})}</parameter>
</methodparam>
#end
#else
<void/>
#end
</methodsynopsis>
</para>
#if(${part.body})
<para>
#foreach ($bodypart in ${part.body})
${stringifier.toString(${bodypart})}
#end
</para>
#end
#if(${part.params})
<refsect3><title>Parameters</title>
<variablelist>
#foreach ($param in ${part.params})
<varlistentry>
<term>${stringifier.toString(${param.name})}</term>
<listitem>
<para>
#foreach ($descriptionpart in ${param.description})
${stringifier.toString(${descriptionpart})}
#end
</para>
</listitem>
</varlistentry>
#end
</variablelist>
</refsect3>
#end
#if(${part.throwables})
<refsect3><title>Exceptions</title>
<variablelist>
#foreach ($throwable in ${part.throwables})
<varlistentry>
<term>${stringifier.toString(${throwable.exceptionName})}</term>
<listitem>
<para>
#foreach ($descriptionpart in ${throwable.description})
${stringifier.toString(${descriptionpart})}
#end
</para>
</listitem>
</varlistentry>
#end
</variablelist>
</refsect3>
#end
#if($part.returns)
<refsect3><title>Return Value</title>
#foreach ($return in ${part.returns})
<para>
<returnvalue>
#foreach ($descriptionpart in ${return.description})
${stringifier.toString(${descriptionpart})}
#end
</returnvalue>
</para>
#end
</refsect3>
#end
</refsect2>
#end
</refsect1>
#end
</refentry>
<?xml version="1.0" encoding="UTF-8"?>
<refentry>
<refnamediv>
<refname>WorkspaceExporter</refname>
<refpurpose>Dieses Interface ist die Grundlage für die Möglichkeiten, Workspaces in beliebigen Formaten
direkt aus dWb+ heraus zu exportieren.</refpurpose>
</refnamediv>
<refsynopsisdiv>
<classsynopsis language="java">
<ooclass>
<!--modifier>class</modifier-->
<package>de.netsysit.dataflowframework.logic.services.workspace</package>
<classname>WorkspaceExporter</classname>
</ooclass>
<methodsynopsis>
<type>boolean</type>
<methodname><xref endterm="refsect_de.netsysit.dataflowframework.logic.services.workspace_WorkspaceExporter_save_title" linkend="refsect_de.netsysit.dataflowframework.logic.services.workspace_WorkspaceExporter_save"/></methodname>
<methodparam>
<type>de.netsysit.dataflowframework.logic.services.workspace.WorkspaceExporter.Support</type>
<parameter>support</parameter>
</methodparam>
<methodparam>
<type>de.netsysit.dataflowframework.ui.WorkspaceDescription[]</type>
<parameter>wda</parameter>
</methodparam>
<methodparam>
<type>java.io.OutputStream</type>
<parameter>os</parameter>
</methodparam>
</methodsynopsis>
<methodsynopsis>
<type>java.lang.String</type>
<methodname><xref endterm="refsect_de.netsysit.dataflowframework.logic.services.workspace_WorkspaceExporter_getSuffix_title" linkend="refsect_de.netsysit.dataflowframework.logic.services.workspace_WorkspaceExporter_getSuffix"/></methodname>
<void/>
</methodsynopsis>
</classsynopsis>
</refsynopsisdiv>
<refsect1><title>Authors</title>
<itemizedlist>
<listitem>
elbosso
</listitem>
</itemizedlist>
</refsect1>
<refsect1><title>Description</title>
<para>
Das Interface beschreibt zwei Methoden: eine davon
enthält den Code zur eigentlichen Serialisierung und die andere dient hauptsächlich der Verankerung in dWb+.
/para
para
Es können mehrere Implementierungen dieses Interface innerhalb der Anwendung registriert sein.
Der Anwender startet den Exportprozeß und gibt an, wie die resultierende Datei heißen soll.
dWb+ bestimmt dann anhand der Endung der gewählten Export-Datei,
welche Implementierung zur Serialisierung herangezogen wird.
</para>
</refsect1>
<refsect1><title>Methods</title>
<refsect2 xml:id="refsect_de.netsysit.dataflowframework.logic.services.workspace_WorkspaceExporter_save"><title xml:id="refsect_de.netsysit.dataflowframework.logic.services.workspace_WorkspaceExporter_save_title">save</title>
<para>
Methode zum Export der Struktur eines Workspace.
</para>
<para>
<methodsynopsis>
<type>boolean</type>
<methodname>save</methodname>
<methodparam>
<type>de.netsysit.dataflowframework.logic.services.workspace.WorkspaceExporter.Support</type>
<parameter>support</parameter>
</methodparam>
<methodparam>
<type>de.netsysit.dataflowframework.ui.WorkspaceDescription[]</type>
<parameter>wda</parameter>
</methodparam>
<methodparam>
<type>java.io.OutputStream</type>
<parameter>os</parameter>
</methodparam>
</methodsynopsis>
</para>
<para>
Diese Methode muß den Inhalt der Workspaces, wie er
übergeben wurde transformieren und die transformierte Darstellung in den Strem schreiben,
der von der Anwendung mit der vom Anwender gewählten Datei verbunden wurde.
</para>
<refsect3><title>Parameters</title>
<variablelist>
<varlistentry>
<term>support</term>
<listitem>
<para>
Referenz auf den Workspace, zu dem die zu serialisierenden Objekte gehören.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>wda</term>
<listitem>
<para>
Referenz auf ein Array von WorkspaceDescriptions, die die folgenden Angaben enthalten:
itemizedlist
listitem
Angaben zu den Modulen als Instanzen
/listitem
listitem
Angaben zu den Verbindungen zwischen den Modulen
/listitem
/itemizedlist
Der Parameter ist als Array gestaltet. In der aktuellen Implementierung ist dieses Array immer mit genau einem Element
bestückt. Implementierungen müssen aber dafür Sorge tragen, auch damit umgehen zu können, daß
der Parameter
itemizedlist
listitem
eine null-Referenz ist
/listitem
listitem
ein leeres Array ist
/listitem
listitem
ein Array mit mehr als einem Element ist
/listitem
/itemizedlist
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>os</term>
<listitem>
<para>
Stream, in den das Resultat geschrieben werden soll. Dieser Stream wird von der Implementierung nicht geschlossen.
Um das Freigeben der damit verknüpften Ressourcen kümmert sich dr Aufrufer.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect3>
<refsect3><title>Return Value</title>
<para>
<returnvalue>
Aussage, ob der Exportvorgang erfolgreich abgeschlossen werden konnte
</returnvalue>
</para>
</refsect3>
</refsect2>
<refsect2 xml:id="refsect_de.netsysit.dataflowframework.logic.services.workspace_WorkspaceExporter_getSuffix"><title xml:id="refsect_de.netsysit.dataflowframework.logic.services.workspace_WorkspaceExporter_getSuffix_title">getSuffix</title>
<para>
Diese Methode dient der Integration einer Klasse, die dieses Interface implementiert in die Anwendung dWb+:
Es besteht die Möglichkeit, daß mehrere Implementierungen in der Anwendung registriert sind.
</para>
<para>
<methodsynopsis>
<type>java.lang.String</type>
<methodname>getSuffix</methodname>
<void/>
</methodsynopsis>
</para>
<para>
dWb+ entscheidet dann anhand der Übereinstimmung der Endung des vom Anwender gewählten Namens der Export-Datei
mit dem Rückgabewert dieser Methode, welche der Implementierungen tatsächlich benutzt wird,
um die Ergebnisdatei zu erzeugen.
</para>
<refsect3><title>Return Value</title>
<para>
<returnvalue>
Dateinamens-Endung: klein geschrieben, ohne Punkt (".") am Anfang. Beispiel: "xml"
</returnvalue>
</para>
</refsect3>
</refsect2>
</refsect1>
</refentry>
Diese Fragmente kann man in einen Abschnitt des Appendix einhängen.
OAuth und OTP
16.02.2020
Wie bereits beschrieben will ich mich demnächst näher mit OAuth befassen...
Weiterlesen...Android Basteln C und C++ Chaos Datenbanken Docker dWb+ ESP Wifi Garten Geo Go GUI Gui Hardware Java Jupyter JupyterBinder Komponenten Links Linux Markdown Markup Music Numerik OpenSource PKI-X.509-CA Präsentationen Python QBrowser Rants Raspi Revisited Security Software-Test sQLshell TeleGrafana Verschiedenes Video Virtualisierung Windows Upcoming...
Ich musste neulich darüber nachdenken, eine Parallelisierung für einen meiner ANT-Tasks in meinem Static Site Generator einzubauen.
WeiterlesenDa ich mich in den letzten Wochen wieder einmal mit Javas Sicherheitsmechanismen und dem Erzeugen von Animationen beschäftigt habe, habe ich den Entschluss gefasst, die bisher mittels JMF AVIs in dWb+ zu erstetzen - nur wodurch?
WeiterlesenIch hatte neulich hier einen Link zu Multi-Scale Truchet Patterns und habe seitdem den Algorithmus mit java umgesetzt und ihn als Teil meines Projekts zur Testdatengenerierung veröffentlicht.
WeiterlesenManche nennen es Blog, manche Web-Seite - ich schreibe hier hin und wieder über meine Erlebnisse, Rückschläge und Erleuchtungen bei meinen Hobbies.
Wer daran teilhaben und eventuell sogar davon profitieren möchte, muss damit leben, daß ich hin und wieder kleine Ausflüge in Bereiche mache, die nichts mit IT, Administration oder Softwareentwicklung zu tun haben.
Ich wünsche allen Lesern viel Spaß und hin und wieder einen kleinen AHA!-Effekt...
PS: Meine öffentlichen Codeberg-Repositories findet man hier.