Skip to content

Commit

Permalink
feat: Enum support
Browse files Browse the repository at this point in the history
  • Loading branch information
manticore-projects committed May 14, 2023
1 parent 94b0327 commit 1569291
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 23 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
A doclet to output javadoc as XML
=================================

This library provides a doclet to output the javadoc comments from Java source code to a XML, Restructured Text (*.rst) document.
This library provides a doclet to output the javadoc comments from Java source code to a XML or a Restructured Text (*.rst) document.

All modern JDKs 11, 17 and 21 are supported (via `languageVersion.set(JavaLanguageVersion.of(11)` enforcing JavaDoc 11).

Planned support for Markdown (*.md), Docbook XML and ASCII Doctor (*.adoc). Sponsors or Contributors are most welcome.
Expand Down Expand Up @@ -35,17 +36,14 @@ dependencies {
tasks.register('xmldoc', Javadoc) {
source = sourceSets.main.allJava
// beware, that this folder will be overwittten by Gradle
// beware, that this folder will be overwritten hard by Gradle
destinationDir = reporting.file("xmlDoclet")
options.docletpath = configurations.xmlDoclet.files.asType(List)
options.doclet = "com.github.markusbernhardt.xmldoclet.XmlDoclet"
// @see https://github.com/gradle/gradle/issues/11898#issue-549900869
title = null
options.noTimestamp(false)
// transform to Restructured Text and copy to Sphinx Source folder
options.addBooleanOption("rst", true)
options.addStringOption("basePackage", "net.sf.jsqlparser")
doLast {
copy {
Expand Down Expand Up @@ -88,7 +86,7 @@ If you are using maven you can use this library by adding the following report t
<docletArtifact>
<groupId>com.manticore-projects.tools</groupId>
<artifactId>xml-doclet</artifactId>
<version>1.1.3</version>
<version>1.2.1</version>
</docletArtifact>
</configuration>
</execution>
Expand Down Expand Up @@ -122,3 +120,5 @@ Options

-adoc Not implemented yet: Write Ascii Doctor (*.adoc)
Default: false

-basePackage <name> Shortens the Qualified Names by the Base Package name
1 change: 0 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,6 @@ configurations.configureEach {
force 'org.dom4j:dom4j:+'

// avoid vulnerable optional artifacts
//exclude(group: 'org.dom4j')
exclude(group: 'org.jdom')
}
}
47 changes: 43 additions & 4 deletions src/main/java/com/github/markusbernhardt/xmldoclet/XmlDoclet.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;

Expand Down Expand Up @@ -37,6 +38,7 @@
import net.sf.saxon.s9api.*;

import java.io.OutputStream;
import java.util.Map;
import java.util.logging.Level;

/**
Expand Down Expand Up @@ -116,9 +118,33 @@ public class XmlDoclet {

OptionBuilder.withArgName("filename");
OptionBuilder.isRequired(false);
OptionBuilder.hasArg();
OptionBuilder.hasArgs(1);
OptionBuilder.withDescription("Name of the output file.\nDefault: javadoc.xml");
OPTIONS.addOption(OptionBuilder.create("filename"));

OptionBuilder.withArgName("basePackage");
OptionBuilder.isRequired(false);
OptionBuilder.hasArgs(1);
OptionBuilder.withDescription("Name of the base package.\n");
OPTIONS.addOption(OptionBuilder.create("basePackage"));

OptionBuilder.withArgName("doctitle");
OptionBuilder.isRequired(false);
OptionBuilder.hasArgs(1);
OptionBuilder.withDescription("Document Title\n");
OPTIONS.addOption(OptionBuilder.create("doctitle"));

OptionBuilder.withArgName("windowtitle");
OptionBuilder.isRequired(false);
OptionBuilder.hasArgs(1);
OptionBuilder.withDescription("Window Title\n");
OPTIONS.addOption(OptionBuilder.create("windowtitle"));

OptionBuilder.withArgName("noTimestamp");
OptionBuilder.isRequired(false);
OptionBuilder.hasArgs(0);
OptionBuilder.withDescription("No Timestamp.\n");
OPTIONS.addOption(OptionBuilder.create("notimestamp"));
}

/**
Expand Down Expand Up @@ -181,7 +207,8 @@ public static boolean start(RootDoc rootDoc) {
return true;
}

public static void transform(InputStream xsltInputStream, File xmlFile, File outFile)
public static void transform(InputStream xsltInputStream, File xmlFile, File outFile,
Map<String, String> parameters)
throws IOException, SaxonApiException {

try (InputStream xmlInputStream = new FileInputStream(xmlFile);
Expand Down Expand Up @@ -212,6 +239,11 @@ public static void transform(InputStream xsltInputStream, File xmlFile, File out
Serializer serializer = processor.newSerializer(output);
transformer.setDestination(serializer);

for (Map.Entry<String, String> parameter : parameters.entrySet()) {
transformer.setParameter(new QName(parameter.getKey()),
new XdmAtomicValue(parameter.getValue()));
}

// Transform the XML
transformer.transform();
}
Expand Down Expand Up @@ -271,11 +303,18 @@ public static void save(CommandLine commandLine, Root root) {

LOGGER.info("Wrote XML to: " + xmlFile.getAbsolutePath());

HashMap<String, String> parameters = new HashMap<>();
for (Option o : commandLine.getOptions()) {
if (o.getValue() != null) {
parameters.put(o.getArgName(), o.getValue());
}
}

if (commandLine.hasOption("rst")) {
File outFile = new File(xmlFile.getParent(), basename + ".rst");
try (InputStream inputStream =
XmlDoclet.class.getResourceAsStream(RESTRUCTURED_XSL);) {
transform(inputStream, xmlFile, outFile);
transform(inputStream, xmlFile, outFile, parameters);
} catch (Exception ex) {
LOGGER.log(Level.SEVERE, "Failed to write Restructured Text", ex);
}
Expand All @@ -286,7 +325,7 @@ public static void save(CommandLine commandLine, Root root) {
File outFile = new File(xmlFile.getParent(), basename + ".md");
try (InputStream inputStream =
XmlDoclet.class.getResourceAsStream(MARKDOWN_XSL);) {
transform(inputStream, xmlFile, outFile);
transform(inputStream, xmlFile, outFile, parameters);
} catch (Exception ex) {
LOGGER.log(Level.SEVERE, "Failed to write Markdown", ex);
}
Expand Down
89 changes: 78 additions & 11 deletions src/main/resources/com/manticore/xsl/restructured.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,30 @@
omit-xml-declaration="yes"
indent="no" />

<xsl:param name="basePackage" select="''" />
<xsl:param name="doctitle" select="'Java API'" />

<xsl:function name="my:replacePRE">
<xsl:param name="input"/>
<xsl:variable name="content" select='replace($input, "&lt;pre&gt;\s*([^&lt;]*)\s*&lt;/pre&gt;", "$1")' />
<xsl:text>``</xsl:text><xsl:value-of select="normalize-space($content)" disable-output-escaping="yes"/><xsl:text>``</xsl:text>
</xsl:function>

<xsl:function name="my:replaceTags">
<xsl:param name="input"/>
<xsl:variable name="linkTag" select='replace($input, "\{@link (.*)\}", "`$1`_")' />
<xsl:variable name="preTag" select='replace($linkTag, "&lt;pre&gt;(.*)&lt;/pre&gt;", "``$1``")' />
<xsl:variable name="codeTag" select='replace($preTag, "\{@code (.*)\}", "`$1`")' />
<xsl:variable name="codeTag1" select='replace($codeTag, "&lt;code&gt;(.*)&lt;/code&gt;", "``$1``")' />
<xsl:variable name="linkTag" select='replace($input, "\{@link [\s|\n]*([^\}]*[^\s])[\s|\n]*\}", "`$1`")' />
<xsl:variable name="preTag" select='replace($linkTag, "&lt;pre&gt;\s*([\s\S]*?)\s*&lt;/pre&gt;", "`$1`")' />
<xsl:variable name="codeTag" select='replace($preTag, "\{@code [\s|\n]*([^\}]*[^\s])[\s|\n]*\}", "`$1`")' />
<xsl:variable name="codeTag1" select='replace($codeTag, "&lt;code&gt;\s*([\s\S]*?)\s*&lt;/code&gt;", "``$1``")' />

<xsl:variable name="normalized" select='replace($codeTag1, "\n\s*", " ")' />
<xsl:variable name="normalized1" select='replace($normalized, "&lt;p&gt;\s*([\s\S]*?)\s*&lt;/p&gt;", "&#xa;| $1")' />
<xsl:variable name="normalized2" select='replace($normalized1, "&lt;blockquote&gt;\s*([\s\S]*?)\s*&lt;/blockquote&gt;", "&#xa;| $1 &#xa;|")' />
<xsl:variable name="normalized3" select='replace($normalized2, "&lt;p&gt;\s*", "&#xa;| ")' />
<xsl:variable name="normalized4" select='replace($normalized3, "&lt;br&gt;\s*", "&#xa;| ")' />

<xsl:value-of select="concat('| ', $normalized4)" disable-output-escaping="yes"/>

<xsl:value-of select="normalize-space($codeTag1)" disable-output-escaping="yes"/>
</xsl:function>

<xsl:function name="my:className">
Expand All @@ -32,16 +48,21 @@
</xsl:choose>
</xsl:function>

<xsl:variable name="basePackageName" select="concat('', 'net.sf.jsqlparser')"/>

<!-- Match the root element -->
<xsl:template match="/root">
<xsl:text disable-output-escaping="yes">
#######################################################################
JAVA API </xsl:text><xsl:value-of select="$basePackageName"/><xsl:text>
</xsl:text><xsl:value-of select="$doctitle"/><xsl:text>
#######################################################################

</xsl:text>
<xsl:choose>
<xsl:when test="string-length($basePackage)>0"><xsl:text>Base Package: </xsl:text><xsl:value-of select="$basePackage"/><xsl:text>

</xsl:text></xsl:when>
</xsl:choose>

<xsl:for-each select="package">
<xsl:sort select="@name"/>
<xsl:apply-templates select="."/>
Expand All @@ -55,12 +76,19 @@ JAVA API </xsl:text><xsl:value-of select="$basePackageName"/><xsl:text>
.. _</xsl:text><xsl:value-of select="@name"/><xsl:text disable-output-escaping="yes">:
***********************************************************************
</xsl:text><xsl:choose>
<xsl:when test="substring(@name, string-length(concat($basePackageName, '.')))=''">Base</xsl:when>
<xsl:otherwise><xsl:value-of select="substring(@name, string-length($basePackageName)+2)"/></xsl:otherwise>
<xsl:when test="$basePackage=''"><xsl:value-of select="@name"/></xsl:when>
<xsl:when test="substring(@name, string-length(concat($basePackage, '.')))=''">Base</xsl:when>
<xsl:otherwise><xsl:value-of select="substring(@name, string-length($basePackage)+2)"/></xsl:otherwise>
</xsl:choose><xsl:text disable-output-escaping="yes">
***********************************************************************
</xsl:text>

<!-- Process enums in the package -->
<xsl:for-each select="enum">
<xsl:sort select="@qualified"/>
<xsl:apply-templates select="."/>
</xsl:for-each>

<!-- Process classes in the package -->
<xsl:for-each select="class">
<xsl:sort select="@qualified"/>
Expand Down Expand Up @@ -196,6 +224,46 @@ JAVA API </xsl:text><xsl:value-of select="$basePackageName"/><xsl:text>
<xsl:apply-templates select="method"/>
</xsl:template>

<!-- Match enum elements -->
<xsl:template match="enum">
<xsl:variable name="enumName" select="@name"/>
<xsl:variable name="qualifiedEnumName" select="@qualified"/>

<!-- Generate reStructuredText heading for class -->
<xsl:text disable-output-escaping="yes">
.. _</xsl:text><xsl:value-of select="@qualified"/><xsl:text disable-output-escaping="yes">:

=======================================================================
</xsl:text>
<xsl:value-of select="$enumName"/>
<xsl:text>(</xsl:text>
<xsl:for-each select="constant">
<xsl:value-of select="@name"/>
<xsl:if test="/comment">
<xsl:text>:'</xsl:text>
<xsl:value-of select="/comment"/><xsl:text>'</xsl:text>
</xsl:if>
<xsl:if test="position() != last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:text>)</xsl:text>
<xsl:text disable-output-escaping="yes">
=======================================================================

</xsl:text>

<xsl:choose>
<xsl:when test="comment">
<xsl:value-of select='my:replaceTags(comment)' disable-output-escaping="yes"/>
<xsl:text>

</xsl:text>
</xsl:when>
</xsl:choose>

</xsl:template>

<!-- Match constructor elements -->
<xsl:template match="constructor[@scope='public']">
<xsl:variable name="constructorName" select="@name"/>
Expand Down Expand Up @@ -225,14 +293,13 @@ JAVA API </xsl:text><xsl:value-of select="$basePackageName"/><xsl:text>
<xsl:apply-templates select="parameter"/>
</xsl:template>

<!-- Match method elements -->
<xsl:template match="method[@scope='public']">
<xsl:variable name="methodName" select="@name"/>
<!-- Generate reStructuredText heading for method -->
<xsl:text disable-output-escaping="yes">
-----------------------------------------------------------------------
</xsl:text>
<xsl:value-of select="$methodName"/>
<xsl:value-of select="$methodName"/>
<xsl:text>(</xsl:text>
<xsl:choose>
<xsl:when test="parameter">
Expand Down

0 comments on commit 1569291

Please sign in to comment.