Java tutorial
/* * Copyright 2001-2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jvnet.maven.jellydoc; import org.apache.maven.reporting.AbstractMavenReportRenderer; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import org.codehaus.doxia.sink.Sink; import java.net.URL; import java.util.List; import java.util.Set; import java.util.HashSet; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.ArrayList; import java.io.StringWriter; import net.java.textilej.parser.MarkupParser; import net.java.textilej.parser.builder.HtmlDocumentBuilder; import net.java.textilej.parser.markup.confluence.ConfluenceDialect; /** * Generates a Maven report from <tt>taglib.xml</tt>. * * @author Kohsuke Kawaguchi */ public class ReferenceRenderer extends AbstractMavenReportRenderer { private final Document taglibXml; private static final Comparator<Element> SORT_BY_NAME = new Comparator<Element>() { public int compare(Element o1, Element o2) { return o1.attributeValue("name").compareTo(o2.attributeValue("name")); } }; public ReferenceRenderer(Sink sink, URL taglibXml) throws DocumentException { super(sink); this.taglibXml = new SAXReader().read(taglibXml); } public String getTitle() { return "Jelly Taglib references"; } protected void renderBody() { List<Element> libraries = sortByName((List<Element>) taglibXml.getRootElement().elements("library")); paragraph("The following Jelly tag libraries are defined in this project."); if (libraries.size() > 1) { startTable(); tableHeader(new String[] { "Namespace URI", "Description" }); for (Element library : libraries) { sink.tableRow(); sink.tableCell(); sink.rawText(String.format("<a href='#%s'>%s</a>", library.attributeValue("prefix"), library.attributeValue("uri"))); sink.tableCell_(); docCell(library); sink.tableRow_(); } endTable(); } for (Element library : libraries) { String prefix = library.attributeValue("prefix"); anchor(prefix); startSection(library.attributeValue("uri")); doc(library); paragraphHtml( "This tag library is <a href='taglib-" + prefix + ".xsd'>also available as an XML Schema</a>"); renderSummaryTable(library, prefix); for (Element tag : sortByName((List<Element>) library.elements("tag"))) renderTagReference(prefix, tag); endSection(); } } private void paragraphHtml(String rawText) { sink.paragraph(); sink.rawText(rawText); sink.paragraph_(); } private void renderSummaryTable(Element library, String prefix) { startTable(); tableHeader(new String[] { "Tag Name", "Description" }); List<Element> tags = sortByName((List<Element>) library.elements("tag")); for (Element tag : tags) { sink.tableRow(); sink.tableCell(); String name = tag.attributeValue("name"); sink.rawText("<a href='#" + prefix + ':' + name + "'>" + name + "</a>"); sink.tableCell_(); docCell(tag); sink.tableRow_(); } endTable(); } private List<Element> sortByName(List<Element> list) { List<Element> tags = new ArrayList<Element>(list); Collections.sort(tags, SORT_BY_NAME); return tags; } /** * Generates a documentation for one tag. */ private void renderTagReference(String taglibPrefix, Element tag) { String name = tag.attributeValue("name"); anchor(taglibPrefix + ':' + name); startSection(name); doc(tag); if (hasVisibleAttributes(tag)) { startTable(); tableHeader(new String[] { "Attribute Name", "Type", "Description" }); for (Element att : sortByName((List<Element>) tag.elements("attribute"))) renderAttribute(att); endTable(); } // renders description of the body if (tag.attributeValue("no-content", "false").equals("true")) paragraph("This tag does not accept any child elements/text."); else { Element body = tag.element("body"); if (body != null) { startSection("body"); doc(body); endSection(); } } endSection(); } private boolean hasVisibleAttributes(Element tag) { for (Element att : (List<Element>) tag.elements("attribute")) { String name = att.attributeValue("name"); if (!HIDDEN_ATTRIBUTES.contains(name)) return true; } return false; } private void anchor(String name) { sink.anchor(name); sink.anchor_(); } /** * Generates a documentation for one attribute. */ private void renderAttribute(Element att) { String name = att.attributeValue("name"); if (HIDDEN_ATTRIBUTES.contains(name)) return; // defined in TagSupport. sink.tableRow(); String suffix = ""; if (att.attributeValue("use", "optional").equals("required")) suffix += " (required)"; if (att.attributeValue("deprecated", "false").equals("true")) suffix += " (deprecated)"; tableCell(name + suffix); tableCell(att.attributeValue("type")); docCell(att); sink.tableRow_(); } /** * Renders the <doc> tag as raw text. */ private void doc(Element tag) { sink.rawText(docXml(tag)); } /** * Renders the <doc> tag as table cell. */ private void docCell(Element tag) { sink.tableCell(); sink.rawText(docXml(tag)); sink.tableCell_(); } private String docXml(Element parent) { Element doc = parent.element("doc"); // remove all javadoc tags that don't belong. doc.content().removeAll(doc.elements("authortag")); String xml = doc.getText(); StringWriter w = new StringWriter(); MarkupParser parser = new MarkupParser(new ConfluenceDialect()); HtmlDocumentBuilder builder = new HtmlDocumentBuilder(w) { @Override public void lineBreak() { // no line break since IDEs usually don't wrap text. } }; builder.setEmitAsDocument(false); parser.setBuilder(builder); parser.parse(xml); return w.toString(); } private static final Set<String> HIDDEN_ATTRIBUTES = new HashSet<String>(Arrays.asList("escapeText", "trim")); }