From 46d3cf7bfd3284b4ec41f61fec982507e2417b56 Mon Sep 17 00:00:00 2001 From: jstrachan Date: Fri, 7 Feb 2003 12:10:44 +0000 Subject: [PATCH] An early implementation of a jellydoc plugin. The idea behind this plugin is to generate javadoc-like documentation for Jelly tags. Now there are various projects which define their own library (or libraries) of Jelly tags. So this code which used to reside inside the Jelly build has now been refactored into a Maven plugin. To add it to your build just add this to your maven.xml Its still fairly simple and basic right now. Its using a doclet (rather than xdoclet or qdox) and doesn't handle DynaTag implementations very well - so I'm sure we can improve this over time. However for now this might help other projects (like Maven itself as well as other projects like Latka, Drools, Werkflow etc) create auto-generated documentation for their tags. git-svn-id: https://svn.apache.org/repos/asf/maven/maven-1/plugins/trunk@112852 13f79535-47bb-0310-9956-ffa450edef68 --- jellydoc/.cvsignore | 3 + jellydoc/plugin.jelly | 78 ++ jellydoc/plugin.properties | 11 + jellydoc/project.xml | 95 +++ .../apache/maven/jellydoc/TagXMLDoclet.java | 396 ++++++++++ .../org/apache/maven/jellydoc/XMLDoclet.java | 707 ++++++++++++++++++ .../maven-jellydoc-plugin.jelly | 163 ++++ jellydoc/xdocs/.cvsignore | 1 + jellydoc/xdocs/goals.xml | 27 + jellydoc/xdocs/index.xml | 22 + jellydoc/xdocs/navigation.xml | 16 + jellydoc/xdocs/properties.xml | 26 + 12 files changed, 1545 insertions(+) create mode 100644 jellydoc/.cvsignore create mode 100644 jellydoc/plugin.jelly create mode 100644 jellydoc/plugin.properties create mode 100644 jellydoc/project.xml create mode 100644 jellydoc/src/main/org/apache/maven/jellydoc/TagXMLDoclet.java create mode 100644 jellydoc/src/main/org/apache/maven/jellydoc/XMLDoclet.java create mode 100644 jellydoc/src/plugin-resources/maven-jellydoc-plugin.jelly create mode 100644 jellydoc/xdocs/.cvsignore create mode 100644 jellydoc/xdocs/goals.xml create mode 100644 jellydoc/xdocs/index.xml create mode 100644 jellydoc/xdocs/navigation.xml create mode 100644 jellydoc/xdocs/properties.xml diff --git a/jellydoc/.cvsignore b/jellydoc/.cvsignore new file mode 100644 index 00000000..e5e33942 --- /dev/null +++ b/jellydoc/.cvsignore @@ -0,0 +1,3 @@ +target +velocity.log +maven.log diff --git a/jellydoc/plugin.jelly b/jellydoc/plugin.jelly new file mode 100644 index 00000000..2df968d3 --- /dev/null +++ b/jellydoc/plugin.jelly @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Generating jellydoc for packages ${maven.jellydoc.packages} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jellydoc/plugin.properties b/jellydoc/plugin.properties new file mode 100644 index 00000000..25b03fbe --- /dev/null +++ b/jellydoc/plugin.properties @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------- +# P L U G I N P R O P E R I E S +# ------------------------------------------------------------------- +# Activity log plugin. +# ------------------------------------------------------------------- + +maven.build.dir = ${basedir}/target + +maven.docs.outputencoding = ISO-8859-1 + +maven.activitylog.range = 30 diff --git a/jellydoc/project.xml b/jellydoc/project.xml new file mode 100644 index 00000000..abf12aff --- /dev/null +++ b/jellydoc/project.xml @@ -0,0 +1,95 @@ + + + + ${basedir}/../project.xml + 3 + maven-jellydoc-plugin + Maven JellyDoc Plug-in + 1.0-SNAPSHOT + + + jakarta + + + Creates a JavaDoc like report for any Jelly Tags used in a project. + + + + + http://jakarta.apache.org/turbine/maven/reference/plugins/jellydoc/ + http://jira.werken.com/BrowseProject.jspa?id=10030 + jakarta.apache.org + /www/jakarta.apache.org/turbine/maven/reference/plugins/jellydoc/ + /www/jakarta.apache.org/builds/jakarta-turbine-maven/ + + + + James Strachan + jstrachan + jstrachan@apache.org + SpiritSoft, Inc. + + Java Developer + + + + + + + + + commons-jelly + commons-jelly-tags-jsl + SNAPSHOT + http://jakarta.apache.org/commons/jelly/tags/jsl/ + + root.maven + + + + + commons-jelly + commons-jelly-tags-xml + SNAPSHOT + http://jakarta.apache.org/commons/jelly/tags/xml/ + + root.maven + + + + + javadoc + 1.3 + + root.maven + + + + + nekohtml + 0.7.1 + + root.maven + + + + + + dom4j + 1.4-dev-8 + http://www.dom4j.org/ + + + xml-apis + 1.0.b2 + http://xml.apache.org/xerces2-j/ + + + xerces + 2.2.1 + http://xml.apache.org/xerces2-j/ + + + + + diff --git a/jellydoc/src/main/org/apache/maven/jellydoc/TagXMLDoclet.java b/jellydoc/src/main/org/apache/maven/jellydoc/TagXMLDoclet.java new file mode 100644 index 00000000..7ed31d51 --- /dev/null +++ b/jellydoc/src/main/org/apache/maven/jellydoc/TagXMLDoclet.java @@ -0,0 +1,396 @@ +/* + * /home/cvs/maven-plugins/jellydoc/src/main/org/apache/maven/jellydoc/TagXMLDoclet.java,v 1.1 2003/02/07 12:10:44 jstrachan Exp + * 1.1 + * 2003/02/07 12:10:44 + * + * ==================================================================== + * + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Commons", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + * TagXMLDoclet.java,v 1.1 2003/02/07 12:10:44 jstrachan Exp + */ + +package org.apache.maven.jellydoc; + +import java.beans.Introspector; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.StringReader; + +import org.cyberneko.html.parsers.SAXParser; +import org.dom4j.io.OutputFormat; +import org.dom4j.io.XMLWriter; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; +import org.xml.sax.helpers.DefaultHandler; + +import com.sun.javadoc.ClassDoc; +import com.sun.javadoc.Doc; +import com.sun.javadoc.Doclet; +import com.sun.javadoc.MethodDoc; +import com.sun.javadoc.PackageDoc; +import com.sun.javadoc.Parameter; +import com.sun.javadoc.RootDoc; +import com.sun.javadoc.SeeTag; +import com.sun.javadoc.Tag; + +/** + * Main Doclet class to generate Tag Library ML. + * + * @author Gopinath M.R. + * @author James Strachan + * @author Rodney Waldhoff + */ + +// #### somehow we need to handle taglib inheritence... + +public class TagXMLDoclet extends Doclet { + + private String xmlns = "jvx"; + private String encodingFormat="UTF-8"; + private String localName = "javadoc"; + private ContentHandler cm = null; + private String targetFileName="target/taglib.xml"; + private Attributes emptyAtts = new AttributesImpl(); + + public TagXMLDoclet (RootDoc root) throws Exception { + FileOutputStream writer = new FileOutputStream(targetFileName); + OutputFormat format = OutputFormat.createPrettyPrint(); + XMLWriter xmlWriter = new XMLWriter(writer, format); + try { + cm = xmlWriter; + cm.startDocument(); + javadocXML(root); + cm.endDocument(); + xmlWriter.close(); + } + catch (IOException e) { + xmlWriter.close(); + throw e; + } + } + + /** + * Generates the xml for the tag libraries + */ + private void javadocXML(RootDoc root) throws SAXException { + cm.startElement(xmlns, localName, "tags", emptyAtts); + PackageDoc[] packageArray = root.specifiedPackages(); + + // Generate for packages. + for (int i = 0; i < packageArray.length; ++i) { + packageXML(packageArray[i]); + } + + cm.endElement(xmlns, localName, "tags"); + } + + /** + * Generates doc for a tag library + */ + private void packageXML(PackageDoc packageDoc) throws SAXException { + ClassDoc[] classArray = packageDoc.ordinaryClasses(); + + // lets see if we find a Tag + boolean foundTag = false; + for (int i = 0; i < classArray.length; ++i) { + ClassDoc classDoc = classArray[i]; + if ( isTag( classArray[i] ) ) { + foundTag = true; + break; + } + } + if ( ! foundTag ) { + return; + } + + AttributesImpl atts = new AttributesImpl(); + atts.addAttribute(xmlns, localName, "name", "String", packageDoc.name()); + + String name = packageDoc.name(); + int idx = name.lastIndexOf('.'); + if ( idx > 0 ) { + name = name.substring(idx+1); + } + atts.addAttribute(xmlns, localName, "prefix", "String", name); + + String uri = "jelly:" + name; + + atts.addAttribute(xmlns, localName, "uri", "String", uri ); + cm.startElement(xmlns, localName, "library", atts); + + // generate Doc element. + docXML(packageDoc); + + // generate tags + for (int i = 0; i < classArray.length; ++i) { + if ( isTag( classArray[i] ) ) { + tagXML(classArray[i]); + } + } + cm.endElement(xmlns, localName, "library"); + } + + /** + * @return true if this class is a Jelly Tag + */ + private boolean isTag(ClassDoc classDoc) { + ClassDoc[] interfaceArray = classDoc.interfaces(); + for (int i = 0; i < interfaceArray.length; ++i) { + String name = interfaceArray[i].qualifiedName(); + if ("org.apache.commons.jelly.Tag".equals(name)) { + return true; + } + } + ClassDoc base = classDoc.superclass(); + if ( base != null ) { + return isTag(base); + } + return false; + } + + /** + * Generates doc for a tag + */ + private void tagXML(ClassDoc classDoc) throws SAXException { + if (classDoc.isAbstract()) { + return; + } + + AttributesImpl atts = new AttributesImpl(); + atts.addAttribute(xmlns, localName, "className", "String", classDoc.name()); + String name = classDoc.name(); + if ( name.endsWith( "Tag" ) ) { + name = name.substring(0, name.length() - 3 ); + } + name = Introspector.decapitalize(name); + + atts.addAttribute(xmlns, localName, "name", "String", name); + cm.startElement(xmlns, localName, "tag", atts); + + // generate "doc" sub-element + docXML(classDoc); + + // generate the attributes + propertiesXML(classDoc); + + // generate "method" sub-elements + cm.endElement(xmlns, localName, "tag"); + } + + /** + * Generates doc for a tag property + */ + private void propertiesXML(ClassDoc classDoc) throws SAXException { + MethodDoc[] methodArray = classDoc.methods(); + for (int i = 0; i < methodArray.length; ++i) { + propertyXML(methodArray[i]); + } + ClassDoc base = classDoc.superclass(); + if ( base != null ) { + propertiesXML( base ); + } + } + + + /** + * Generates doc for a tag property + */ + private void propertyXML(MethodDoc methodDoc) throws SAXException { + if ( ! methodDoc.isPublic() || methodDoc.isStatic() ) { + return; + } + String name = methodDoc.name(); + if ( ! name.startsWith( "set" ) ) { + return; + } + Parameter[] parameterArray = methodDoc.parameters(); + if ( parameterArray == null || parameterArray.length != 1 ) { + return; + } + Parameter parameter = parameterArray[0]; + + name = name.substring(3); + name = Introspector.decapitalize(name); + + if ( name.equals( "body") || name.equals( "context" ) || name.equals( "parent" ) ) { + return; + } + AttributesImpl atts = new AttributesImpl(); + atts.addAttribute(xmlns, localName, "name", "String", name); + atts.addAttribute(xmlns, localName, "type", "String", parameter.typeName()); + + cm.startElement(xmlns, localName, "attribute", atts); + + // maybe do more semantics, like use custom tags to denote if its required, optional etc. + + // generate "doc" sub-element + docXML(methodDoc); + + cm.endElement(xmlns, localName, "attribute"); + } + + /** + * Generates doc for element "doc" + */ + private void docXML(Doc doc) throws SAXException { + cm.startElement(xmlns, localName, "doc", emptyAtts); + // handle the "comment" part, including {@link} tags + { + Tag[] tags = doc.inlineTags(); + for(int i=0;i. + * + * XMLDoclet.java,v 1.1 2003/02/07 12:10:44 jstrachan Exp + */ + +package org.apache.maven.jellydoc; + +import java.io.*; +import java.util.*; +import com.sun.javadoc.*; + +import org.dom4j.io.OutputFormat; +import org.dom4j.io.XMLWriter; + +import org.xml.sax.*; +import org.xml.sax.helpers.*; + +/** + * Main Doclet class to generate JavaDocXML. This doclet generates the + * document conforming to DTD specified in javadoc-v04draft.dtd. + * @author Gopinath M.R. + * @author James Strachan + */ + +public class XMLDoclet extends Doclet { + + private String xmlns = "jvx"; + private String encodingFormat="UTF-8"; + private String localName = "javadoc"; + private ContentHandler cm = null; + private String targetFileName="target/javadoc.xml"; + private Attributes emptyAtts = new AttributesImpl(); + + public XMLDoclet (RootDoc root) throws Exception { + FileOutputStream writer = new FileOutputStream(targetFileName); + OutputFormat format = OutputFormat.createPrettyPrint(); + XMLWriter xmlWriter = new XMLWriter(writer, format); + try { + cm = xmlWriter; + cm.startDocument(); + javadocXML(root); + cm.endDocument(); + xmlWriter.close(); + } + catch (IOException e) { + xmlWriter.close(); + throw e; + } + } + + /** + * Generates the xml data for the top element. + * <!ELEMENT javadoc (package*, class*, interface*)> + */ + private void javadocXML(RootDoc root) throws SAXException { + cm.startElement(xmlns, localName, "javadoc", emptyAtts); + PackageDoc[] packageArray = root.specifiedPackages(); + + // Generate for packages. + for (int i = 0; i < packageArray.length; ++i) { + packageXML(packageArray[i]); + } + + // Generate for classes. + ClassDoc[] classArray = root.specifiedClasses(); + Vector interfaceVector = new Vector(); + for (int i = 0; i < classArray.length; ++i) { + if (classArray[i].isInterface()) { + interfaceVector.addElement(classArray[i]); + } else { + classXML(classArray[i]); + } + } + + // Generate for interfaces. + Enumeration interfaceEnum = interfaceVector.elements(); + if (interfaceEnum.hasMoreElements()) { + ClassDoc interfaceDoc = (ClassDoc)interfaceEnum.nextElement(); + interfaceXML(interfaceDoc); + } + cm.endElement(xmlns, localName, "javadoc"); + } + + /** + * Generates doc for "package". + * <!ELEMENT package (doc?, package*, class*, interface*)> + *<!ATTLIST package + * name CDATA #REQUIRED> + */ + private void packageXML(PackageDoc packageDoc) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + atts.addAttribute(xmlns, localName, "name", "String", packageDoc.name()); + cm.startElement(xmlns, localName, "package", atts); + + // generate Doc element. + docXML(packageDoc); + + // TODO:generate Package elements. + // doubt: How package can exist inside a package? + + /* Generate for classes. */ + // for ordinary classes. + ClassDoc[] classArray = packageDoc.ordinaryClasses(); + for (int i = 0; i < classArray.length; ++i) { + classXML(classArray[i]); + } + // for Exception classes. + classArray = packageDoc.exceptions(); + for (int i = 0; i < classArray.length; ++i) { + classXML(classArray[i]); + } + // for Error classes + classArray = packageDoc.errors(); + for (int i = 0; i < classArray.length; ++i) { + classXML(classArray[i]); + } + + /* Generate for interfaces. */ + ClassDoc[] interfaceArray = packageDoc.interfaces(); + for (int i = 0; i < interfaceArray.length; ++i) { + interfaceXML(interfaceArray[i]); + } + + cm.endElement(xmlns, localName, "package"); + } + + /** + * Generates doc for element "class". + * <!ELEMENT class (doc?, + * extends_class?, + * implements?, + * constructor*, + * method*, + * innerclass*)> + * <!ATTLIST class + * %name; + * %extensibility; + * %class.access;> + */ + private void classXML(ClassDoc classDoc) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + atts.addAttribute(xmlns, localName, "name", "String", classDoc.name()); + + String extensibility = "default"; + if (classDoc.isAbstract()) { + extensibility = "abstract"; + } else if (classDoc.isFinal()) { + extensibility = "final"; + } + atts.addAttribute(xmlns, localName, "extensibility", "String", extensibility); + String access = "package"; + if (classDoc.isPublic()) { + access = "public"; + } + atts.addAttribute(xmlns, localName, "access", "String", access); + cm.startElement(xmlns, localName, "class", atts); + + // generate "doc" sub-element + docXML(classDoc); + + // generate "extends_class" sub-element + extendsXML(classDoc); + + // generate "implements" sub-element + implementsXML(classDoc); + + // generate "field" sub-elements + FieldDoc[] fieldArray = classDoc.fields(); + for (int i = 0; i < fieldArray.length; ++i) { + fieldXML(fieldArray[i]); + } + + // generate "constructor" sub-elements + ConstructorDoc[] constructorArray = classDoc.constructors(); + for (int i = 0; i < constructorArray.length; ++i) { + constructorXML(constructorArray[i]); + } + + // generate "method" sub-elements + MethodDoc[] methodArray = classDoc.methods(); + for (int i = 0; i < methodArray.length; ++i) { + methodXML(methodArray[i]); + } + + // generate "innerclass" sub-elements + ClassDoc[] innerClassArray = classDoc.innerClasses(); + for (int i = 0; i < innerClassArray.length; ++i) { + innerClassXML(innerClassArray[i]); + } + + cm.endElement(xmlns, localName, "class"); + } + + /** + * Generates doc for element "extends_class" + * <!ELEMENT extends_class (classref+)> + */ + private void extendsXML(ClassDoc classDoc) throws SAXException { + if (classDoc.superclass() != null) { + cm.startElement(xmlns, localName, "extends_class", emptyAtts); + createRefXML("classref", classDoc.superclass().qualifiedName()); + cm.endElement(xmlns, localName, "extends_class"); + } + } + + /** + * Generates doc for element "innerclass" + * <!ELEMENT innerclass (doc?, + * extends?, + * implements?, + * field*, + * constructor*, + * method*)> + * <!ATTLIST innerclass + * %name; + * %access; + * %abstract; + * %anonymous; + * %final; + * %static;> + */ + private void innerClassXML(ClassDoc classDoc) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + atts.addAttribute(xmlns, localName, "name", "String", classDoc.name()); + String access = "package"; + if (classDoc.isPublic()) { + access = "public"; + } + atts.addAttribute(xmlns, localName, "access", "String", access); + atts.addAttribute(xmlns, localName, "abstract", "String", ""+ classDoc.isAbstract()); + String anonymous = "false"; + if (classDoc.name().equals("")) { + anonymous = "true"; + } + atts.addAttribute(xmlns, localName, "anonymous", "String", ""+ anonymous); + atts.addAttribute(xmlns, localName, "final", "String", ""+ "" + classDoc.isFinal()); + atts.addAttribute(xmlns, localName, "static", "String", ""+ "" + classDoc.isStatic()); + cm.startElement(xmlns, localName, "innerclass", atts); + + // generate "doc" sub-element + docXML(classDoc); + + // generate "extends" sub-element + extendsXML(classDoc); + + // generate "implements" sub-element + implementsXML(classDoc); + + // generate "field" sub-elements + FieldDoc[] fieldArray = classDoc.fields(); + for (int i = 0; i < fieldArray.length; ++i) { + fieldXML(fieldArray[i]); + } + + // generate "constructor" sub-elements + ConstructorDoc[] constructorArray = classDoc.constructors(); + for (int i = 0; i < constructorArray.length; ++i) { + constructorXML(constructorArray[i]); + } + + // generate "method" sub-elements + MethodDoc[] methodArray = classDoc.methods(); + for (int i = 0; i < methodArray.length; ++i) { + methodXML(methodArray[i]); + } + + cm.endElement(xmlns, localName,"innerclass"); + } + + /** + * Generates doc for element "interface" + * <!ELEMENT interface (doc?, + * extends_interface?, + * field*, + * method*)> + * <!ATTLIST interface + * %name; + * %access;> + */ + private void interfaceXML(ClassDoc interfaceDoc) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + atts.addAttribute(xmlns, localName, "name", "String", interfaceDoc.name()); + String access = "package"; + if (interfaceDoc.isPublic()) { + access = "public"; + } + atts.addAttribute(xmlns, localName, "access", "String", access); + cm.startElement(xmlns, localName, "interface", atts); + + // generate "doc" sub-element + docXML(interfaceDoc); + + // generate "extends_interface" + extends_interfaceXML(interfaceDoc); + + // generate "field" sub-elements + FieldDoc[] fieldArray = interfaceDoc.fields(); + for (int i = 0; i < fieldArray.length; ++i) { + fieldXML(fieldArray[i]); + } + + // generate "method" sub-elements + MethodDoc[] methodArray = interfaceDoc.methods(); + for (int i = 0; i < methodArray.length; ++i) { + methodXML(methodArray[i]); + } + cm.endElement(xmlns, localName, "interface"); + } + + /** + * Generates doc for element "extends_interface" + * <!ELEMENT extends_interface (interfaceref+)> + */ + private void extends_interfaceXML(ClassDoc interfaceDoc) throws SAXException { + ClassDoc[] interfaceArray = interfaceDoc.interfaces(); + if (interfaceArray.length > 0) { + cm.startElement(xmlns, localName, "extends_interface", emptyAtts); + for (int i = 0; i < interfaceArray.length; ++i) { + createRefXML("interfaceref", interfaceArray[i].qualifiedName()); + } + cm.endElement(xmlns, localName, "extends_interface"); + } + } + + /** + * Generates doc for element "implements" + * <!ELEMENT implements (interfaceref+)> + */ + private void implementsXML(ClassDoc classDoc) throws SAXException { + ClassDoc[] interfaceArray = classDoc.interfaces(); + if (interfaceArray.length > 0) { + cm.startElement(xmlns, localName, "implements", emptyAtts); + for (int i = 0; i < interfaceArray.length; ++i) { + createRefXML("interfaceref", interfaceArray[i].qualifiedName()); + } + cm.endElement(xmlns, localName, "implements"); + } + if (classDoc.superclass() != null) { + implementsXML(classDoc.superclass()); + } + } + + /** + * Generates doc for element "throws" + * <!ELEMENT throws (classref)+> + */ + private void throwsXML(ExecutableMemberDoc member) throws SAXException { + ThrowsTag[] tagArray = member.throwsTags(); + if(tagArray.length > 0) { + cm.startElement(xmlns, localName, "throws", emptyAtts); + for (int i = 0; i < tagArray.length; ++i) { + ClassDoc exceptionClass = tagArray[i].exception(); + String name = null; + if (exceptionClass == null) { + name = tagArray[i].exceptionName(); + } else { + name = tagArray[i].exception().qualifiedName(); + } + createRefXML("classref", name); + } + cm.endElement(xmlns, localName, "throws"); + } + } + + /** + * Generates doc for following elements + * <!ELEMENT classref EMPTY> + * <!ATTLIST classref %name;> + * <!ELEMENT interfaceref EMPTY> + * <!ATTLIST interfaceref %name;> + * <!ELEMENT methodref EMPTY> + * <!ATTLIST methodref %name;> + * <!ELEMENT packageref EMPTY> + * <!ATTLIST packageref %name;> + */ + private void createRefXML(String elementName, String nameValue) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + atts.addAttribute(xmlns, localName, "name", "String", nameValue); + cm.startElement(xmlns, localName, elementName, atts); + cm.endElement(xmlns, localName, elementName); + } + + /** + * Generates doc for "(classref|interfaceref|primitive)" sub-element + */ + private void createTypeRef(Type type) throws SAXException { + String qualifiedName = type.qualifiedTypeName(); + ClassDoc fieldType = type.asClassDoc(); + if (fieldType == null) { + // primitive data type + AttributesImpl subElmAtts = new AttributesImpl(); + subElmAtts.addAttribute(xmlns, localName, "type", "String", qualifiedName); + cm.startElement(xmlns, localName, "primitive", subElmAtts); + cm.endElement(xmlns, localName, "primitive"); + } else if (fieldType.isInterface()) { + // interface + createRefXML("interfaceref", qualifiedName); + } else { + // class + createRefXML("classref", qualifiedName); + } + } + + /** + * Generates doc for element "field" + * <!ELEMENT field (doc?, (classref | interfaceref | primitive))> + * <!ATTLIST field + * %name; + * %access; + * %dimension; + * %synthetic; + * %static; + * %final; + * %transient; + * %volatile;> + */ + private void fieldXML(FieldDoc field) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + + atts.addAttribute(xmlns, localName, "name", "String", field.name()); + + String access = "package"; + if (field.isPrivate()) { + access = "private"; + } else if (field.isProtected()) { + access = "protected"; + } else if (field.isPublic()) { + access = "public"; + } + atts.addAttribute(xmlns, localName, "access", "String", access); + + atts.addAttribute(xmlns, localName, "dimension", "String", field.type().dimension()); + atts.addAttribute(xmlns, localName, "synthetic", "String", "" + field.isSynthetic()); + atts.addAttribute(xmlns, localName, "static", "String", "" + field.isStatic()); + atts.addAttribute(xmlns, localName, "final", "String", "" + field.isFinal()); + atts.addAttribute(xmlns, localName, "transient", "String", "" + field.isTransient()); + atts.addAttribute(xmlns, localName, "volatile", "String", "" + field.isVolatile()); + cm.startElement(xmlns, localName, "field", atts); + + // generate "doc" sub-element + docXML(field); + + // generate "(classref|interfaceref|primitive)" sub-element + createTypeRef(field.type()); // foo , field.qualifiedName()); + + cm.endElement(xmlns, localName, "field"); + } + + /** + * Generates doc for element "constructor" + * <!ELEMENT constructor (doc?, parameter*, throws*)> + * <!ATTLIST constructor + * %name; + * %access; + * %synthetic;> + */ + private void constructorXML(ConstructorDoc constrDoc) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + atts.addAttribute(xmlns, localName, "name", "String", constrDoc.qualifiedName()); + String access = "package"; + if (constrDoc.isPrivate()) { + access = "private"; + } else if (constrDoc.isProtected()) { + access = "protected"; + } else if (constrDoc.isPublic()) { + access = "public"; + } + atts.addAttribute(xmlns, localName, "access", "String", access); + atts.addAttribute(xmlns, localName, "synthetic", "String", "" + constrDoc.isSynthetic()); + cm.startElement(xmlns, localName, "constructor", atts); + + // generate "doc" sub-element + docXML(constrDoc); + + // generate "parameter" sub-elements + Parameter[] parameterArray = constrDoc.parameters(); + for (int i = 0; i < parameterArray.length; ++i) { + parameterXML(parameterArray[i]); + } + + // generate "throws" sub-element + throwsXML(constrDoc); + + cm.endElement(xmlns, localName, "constructor"); + } + + /** + * Generates doc for element "method" + * <!ELEMENT method (doc?, returns, parameter*, throws*)> + * <!ATTLIST method + * %name; + * %access; + * %extensibility; + * %native; + * %synthetic; + * %static; + * %synchronized;> + */ + private void methodXML(MethodDoc methodDoc) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + //atts.addAttribute(xmlns, localName, "", String, ); + atts.addAttribute(xmlns, localName, "name", "String", methodDoc.name()); + + String access = "package"; + if (methodDoc.isPrivate()) { + access = "private"; + } else if (methodDoc.isProtected()) { + access = "protected"; + } else if (methodDoc.isPublic()) { + access = "public"; + } + atts.addAttribute(xmlns, localName, "access", "String", access); + + String extensibility = "default"; + if (methodDoc.isAbstract()) { + extensibility = "abstract"; + } else if (methodDoc.isFinal()) { + extensibility = "final"; + } + atts.addAttribute(xmlns, localName, "extensiblity", "String", extensibility); + + atts.addAttribute(xmlns, localName, "native", "String", ""+ methodDoc.isNative()); + atts.addAttribute(xmlns, localName, "synthetic", "String", "" + methodDoc.isSynthetic()); + atts.addAttribute(xmlns, localName, "static", "String", "" + methodDoc.isStatic()); + atts.addAttribute(xmlns, localName, "synchronized", "String", ""+ methodDoc.isSynchronized()); + cm.startElement(xmlns, localName, "method", atts); + + // generate "doc" sub-element + docXML(methodDoc); + + // generate "returns" sub-element + returnsXML(methodDoc.returnType()); + + // generate "parameter" sub-elements + Parameter[] parameterArray = methodDoc.parameters(); + for (int i = 0; i < parameterArray.length; ++i) { + parameterXML(parameterArray[i]); + } + + // generate "throws" sub-element + throwsXML(methodDoc); + + cm.endElement(xmlns, localName, "method"); + } + + /** + * Generates doc for element "returns" + * <!ELEMENT returns (classref | interfaceref | primitive)> + * <!ATTLIST returns %dimension;> + */ + private void returnsXML(Type type) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + atts.addAttribute(xmlns, localName, "dimension", "String", type.dimension()); + cm.startElement(xmlns, localName, "returns", atts); + + // generate "(classref|interfaceref|primitive)" sub-element + createTypeRef(type); + + cm.endElement(xmlns, localName, "returns"); + } + + /** + * Generates doc for element "parameter" + * <!ELEMENT parameter (classref | interfaceref | primitive)> + * <!ATTLIST parameter + * %name; + * %final; + * %dimension;> + */ + private void parameterXML(Parameter parameter) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + atts.addAttribute(xmlns, localName, "name", "String", parameter.name()); + boolean isFinal = false; + Type type = parameter.type(); + if (type.asClassDoc() == null) { + isFinal = true; + } + atts.addAttribute(xmlns, localName, "final", "String", ""+ "" + isFinal); + atts.addAttribute(xmlns, localName, "dimension", "String", parameter.type().dimension()); + cm.startElement(xmlns, localName, "parameter", atts); + + // generate "(classref|interfaceref|primitive)" sub-element + createTypeRef(parameter.type()); + + cm.endElement(xmlns, localName,"parameter"); + } + + /** + * Generates doc for element "doc" + * <!ELEMENT doc (#PCDATA | + * linktag | + * authortag | + * versiontag | + * paramtag | + * returntag | + * exceptiontag | + * throwstag | + * seetag | + * sincetag | + * deprecatedtag | + * serialtag | + * serialfieldtag | + * serialdatatag)*> + */ + private void docXML(Doc doc) throws SAXException { + String commentText = ""; + boolean createDoc = false; + commentText = doc.commentText(); + if (! commentText.equals("")) { + createDoc = true; + } + Tag[] tags = doc.tags(); + if (tags.length > 0) { + createDoc = true; + } + if (createDoc) { + cm.startElement(xmlns, localName, "doc", emptyAtts); + if (! commentText.equals("")) { + cm.characters(commentText.toCharArray(), 0, commentText.length()); + } + for (int i = 0; i < tags.length; ++i) { + tagXML(tags[i]); + } + cm.endElement(xmlns, localName, "doc"); + } + } + + /** + * Generates doc for all tag elements. + */ + private void tagXML(Tag tag) throws SAXException { + String name = tag.name().substring(1) + "tag"; + if (! tag.text().equals("")) { + cm.startElement(xmlns, localName, name, emptyAtts); + cm.characters(tag.text().toCharArray(), 0, tag.text().length()); + cm.endElement(xmlns, localName, name); + } + } + + public static boolean start(RootDoc root) { + try { + new XMLDoclet(root); + return true; + } catch (Exception e) { + e.printStackTrace(); + System.exit(1); + return false; + } + } +} diff --git a/jellydoc/src/plugin-resources/maven-jellydoc-plugin.jelly b/jellydoc/src/plugin-resources/maven-jellydoc-plugin.jelly new file mode 100644 index 00000000..7cd209a0 --- /dev/null +++ b/jellydoc/src/plugin-resources/maven-jellydoc-plugin.jelly @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tag Documentation + + + +
+ +

+ [tag libraries] + [tags] +

+

+ The following document contains a summary of all the core + Jelly tag libraries. +

+ +
+ +
+

+ [tag libraries] + [tags] +

+ + + + + + + + + + + + + +
LibraryDescription
${uri} + +
+ + + + + + + +

+ +

+ + + + + + + + + + + + + + + +
Tag NameDescription
${tagName} + +
+
+ +
+ +
+ + + +
+

+ [tag libraries] + [tags] +

+ + + + + + + +

+ +

+ + + + + + + + + + + + + + + +
Attribute NameTypeDescription
+ +
+
+ + + +
+
+
+ + +
+ +
+ + diff --git a/jellydoc/xdocs/.cvsignore b/jellydoc/xdocs/.cvsignore new file mode 100644 index 00000000..cb6131bb --- /dev/null +++ b/jellydoc/xdocs/.cvsignore @@ -0,0 +1 @@ +stylesheets diff --git a/jellydoc/xdocs/goals.xml b/jellydoc/xdocs/goals.xml new file mode 100644 index 00000000..21f07cfb --- /dev/null +++ b/jellydoc/xdocs/goals.xml @@ -0,0 +1,27 @@ + + + + + JellyDoc Plugin Goals + James Strachan + + + +
+ + + + + + + + + +
GoalDescription
jellydoc + The default goal. This goal generates the JellyDoc documentation of + all Jelly tags defined within your code base which can then be styled + into HTML as part of the xdoc goal +
+
+ +
diff --git a/jellydoc/xdocs/index.xml b/jellydoc/xdocs/index.xml new file mode 100644 index 00000000..cee9619c --- /dev/null +++ b/jellydoc/xdocs/index.xml @@ -0,0 +1,22 @@ + + + + + Maven JellyDoc Plug-in + James Strachan + + + +
+

+ This plug-in provides JellyDoc reporting documenting all the Jelly + Tags defined in your code base using the + jellydoc goal as described here. +

+

+ The properties that allow you to customize the execution + are documented here. +

+
+ + diff --git a/jellydoc/xdocs/navigation.xml b/jellydoc/xdocs/navigation.xml new file mode 100644 index 00000000..dc3ded21 --- /dev/null +++ b/jellydoc/xdocs/navigation.xml @@ -0,0 +1,16 @@ + + + + Maven JellyDoc Plugin + + + + + + + + + + + + diff --git a/jellydoc/xdocs/properties.xml b/jellydoc/xdocs/properties.xml new file mode 100644 index 00000000..e6b178a9 --- /dev/null +++ b/jellydoc/xdocs/properties.xml @@ -0,0 +1,26 @@ + + + + + JellyDoc Properties + James Strachan + + + +
+ + + + + + + +
PropertyOptional?Description
maven.jellydoc.packagesYes + Specifies the packages which contain Jelly tags. + By restricting this to a subset of your packages will optimise the + goal and simplify the documentation. e.g. setting it to org.foo.jelly.* + The default value is ${pom.build.sourceDirectory}.* +
+
+ +