001: /*
002: Copyright (c) 2007, Dennis M. Sosnoski
003: All rights reserved.
004:
005: Redistribution and use in source and binary forms, with or without modification,
006: are permitted provided that the following conditions are met:
007:
008: * Redistributions of source code must retain the above copyright notice, this
009: list of conditions and the following disclaimer.
010: * Redistributions in binary form must reproduce the above copyright notice,
011: this list of conditions and the following disclaimer in the documentation
012: and/or other materials provided with the distribution.
013: * Neither the name of JiBX nor the names of its contributors may be used
014: to endorse or promote products derived from this software without specific
015: prior written permission.
016:
017: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
018: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
019: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
020: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
021: ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
022: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
023: LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
024: ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
026: SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027: */
028:
029: package org.jibx.binding.model;
030:
031: import java.util.ArrayList;
032: import java.util.List;
033:
034: import javax.xml.parsers.DocumentBuilderFactory;
035:
036: import org.w3c.dom.Document;
037: import org.w3c.dom.Node;
038:
039: /**
040: * Formatter for JavaDoc conversion to XML documentation components.
041: */
042: public class DocumentFormatter {
043: /** Document used for constructing DOM components. */
044: private final Document m_document;
045:
046: /**
047: * Constructor.
048: */
049: public DocumentFormatter() {
050: try {
051: DocumentBuilderFactory fact = DocumentBuilderFactory
052: .newInstance();
053: m_document = fact.newDocumentBuilder().newDocument();
054: } catch (Exception e) {
055: throw new RuntimeException(
056: "Internal error: unable to create DOM builder", e);
057: }
058: }
059:
060: /**
061: * Reformat a segment of JavaDoc text as either a CDATA section (if it
062: * contains embedded HTML tags) or a simple text node. This also replaces
063: * line breaks with single spaces, so that the output format will not use
064: * indenting based on the original supplied text.
065: *
066: * @param jdoc raw JavaDoc text
067: * @return formatted text
068: */
069: public Node reformDocSegment(String jdoc) {
070: StringBuffer buff = new StringBuffer(jdoc);
071: int index = 0;
072: boolean dirty = false;
073: while (index < buff.length()) {
074: char chr = buff.charAt(index);
075: if (chr < 0x20) {
076: if (chr == '\n' || chr == '\r') {
077: if ((index > 0 && buff.charAt(index) == ' ')
078: || (index + 1 < buff.length() && buff
079: .charAt(index + 1) == ' ')) {
080: buff.deleteCharAt(index);
081: } else {
082: buff.setCharAt(index, ' ');
083: }
084: } else {
085: buff.deleteCharAt(index);
086: }
087: } else {
088: dirty = dirty || chr == '&' || chr == '<';
089: index++;
090: }
091: }
092: String text = buff.toString();
093: if (dirty) {
094: return m_document.createCDATASection(text);
095: } else {
096: return m_document.createTextNode(text);
097: }
098: }
099:
100: /**
101: * Convert JavaDoc text to a list of formatted nodes.
102: *
103: * @param jdoc JavaDoc text (may be <code>null</code>)
104: * @return formatted representation (may be <code>null</code>)
105: */
106: public List docToNodes(String jdoc) {
107: if (jdoc != null) {
108: jdoc = jdoc.trim();
109: if (jdoc.length() > 0) {
110: List nodes = new ArrayList();
111: boolean dirty = jdoc.indexOf('<') >= 0;
112: if (dirty) {
113: String ldoc = jdoc.toLowerCase();
114: int split;
115: int base = 0;
116: while ((split = ldoc.indexOf("<pre>", base)) > 0) {
117: if (split > base) {
118: nodes.add(reformDocSegment(jdoc.substring(
119: base, split)));
120: }
121: int end = ldoc.lastIndexOf("</pre>");
122: if (end < 0) {
123: end = ldoc.length();
124: }
125: nodes.add(reformDocSegment(jdoc.substring(
126: split, end)));
127: base = end + 1;
128: }
129: if (base < jdoc.length()) {
130: nodes
131: .add(reformDocSegment(jdoc
132: .substring(base)));
133: }
134: } else {
135: nodes.add(reformDocSegment(jdoc));
136: }
137: return nodes;
138: }
139: }
140: return null;
141: }
142: }
|