You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by js...@apache.org on 2002/06/08 18:43:59 UTC
cvs commit: jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/util XMLDoclet.java
jstrachan 2002/06/08 09:43:59
Added: jelly/src/java/org/apache/commons/jelly/util XMLDoclet.java
Log:
Added a patched version of Alexandria's XMLDoclet which we'll use to autogenerate the taglib documentation, using Jelly.
Revision Changes Path
1.1 jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/util/XMLDoclet.java
Index: XMLDoclet.java
===================================================================
/*
* $Header: /home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/Tag.java,v 1.6 2002/05/17 15:18:12 jstrachan Exp $
* $Revision: 1.6 $
* $Date: 2002/05/17 15:18:12 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-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
* <http://www.apache.org/>.
*
* $Id: Tag.java,v 1.6 2002/05/17 15:18:12 jstrachan Exp $
*/
package org.apache.commons.jelly.util;
import java.io.*;
import java.util.*;
import com.sun.javadoc.*;
import org.apache.xml.serialize.*;
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 <a href="mailto:gopi@aztecsoft.com">Gopinath M.R.</a>
* @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
*/
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 {
FileWriter writer = new FileWriter(targetFileName);
try {
OutputFormat format = new OutputFormat();
format.setEncoding(encodingFormat);
format.setIndenting(true);
format.setIndent(4);
format.setLineWidth(4);
/*
format.setDoctype("-//APACHE//DTD JavaDoc V0.4//EN", "javadoc-v04draft.dtd");
*/
XMLSerializer serializer = new XMLSerializer(writer, format);
cm = serializer.asContentHandler();
javadocXML(root);
writer.close();
} catch (IOException e) {
writer.close();
throw e;
}
}
/**
* Generates the xml data for the top element.
* <xmp><!ELEMENT javadoc (package*, class*, interface*)></xmp>
*/
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".
* <xmp><!ELEMENT package (doc?, package*, class*, interface*)>
*<!ATTLIST package
* name CDATA #REQUIRED></xmp>
*/
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".
* <xmp> <!ELEMENT class (doc?,
* extends_class?,
* implements?,
* constructor*,
* method*,
* innerclass*)>
* <!ATTLIST class
* %name;
* %extensibility;
* %class.access;></xmp>
*/
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, "extensiblity", "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"
* <xmp><!ELEMENT extends_class (classref+)></xmp>
*/
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"
* <xmp> <!ELEMENT innerclass (doc?,
* extends?,
* implements?,
* field*,
* constructor*,
* method*)>
* <!ATTLIST innerclass
* %name;
* %access;
* %abstract;
* %anonymous;
* %final;
* %static;></xmp>
*/
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"
* <xmp><!ELEMENT interface (doc?,
* extends_interface?,
* field*,
* method*)>
* <!ATTLIST interface
* %name;
* %access;></xmp>
*/
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"
* <xmp><!ELEMENT extends_interface (interfaceref+)></xmp>
*/
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"
* <xmp><!ELEMENT implements (interfaceref+)></xmp>
*/
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"
* <xmp><!ELEMENT throws (classref)+></xmp>
*/
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
* <xmp> <!ELEMENT classref EMPTY>
* <!ATTLIST classref %name;>
* <!ELEMENT interfaceref EMPTY>
* <!ATTLIST interfaceref %name;>
* <!ELEMENT methodref EMPTY>
* <!ATTLIST methodref %name;>
* <!ELEMENT packageref EMPTY>
* <!ATTLIST packageref %name;></xmp>
*/
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"
* <xmp> <!ELEMENT field (doc?, (classref | interfaceref | primitive))>
* <!ATTLIST field
* %name;
* %access;
* %dimension;
* %synthetic;
* %static;
* %final;
* %transient;
* %volatile;></xmp>
*/
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"
* <xmp><!ELEMENT constructor (doc?, parameter*, throws*)>
* <!ATTLIST constructor
* %name;
* %access;
* %synthetic;></xmp>
*/
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"
* <xmp> <!ELEMENT method (doc?, returns, parameter*, throws*)>
* <!ATTLIST method
* %name;
* %access;
* %extensibility;
* %native;
* %synthetic;
* %static;
* %synchronized;></xmp>
*/
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, "field");
}
/**
* Generates doc for element "returns"
* <xmp> <!ELEMENT returns (classref | interfaceref | primitive)>
* <!ATTLIST returns %dimension;></xmp>
*/
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"
* <xmp> <!ELEMENT parameter (classref | interfaceref | primitive)>
* <!ATTLIST parameter
* %name;
* %final;
* %dimension;></xmp>
*/
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"
* <xmp><!ELEMENT doc (#PCDATA |
* linktag |
* authortag |
* versiontag |
* paramtag |
* returntag |
* exceptiontag |
* throwstag |
* seetag |
* sincetag |
* deprecatedtag |
* serialtag |
* serialfieldtag |
* serialdatatag)*></xmp>
*/
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;
}
}
}
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>