001: /*
002: * Project: BeautyJ - Customizable Java Source Code Transformer
003: * Class: de.gulden.util.javasource.DocumentationDeclared
004: * Version: 1.1
005: *
006: * Date: 2004-09-29
007: *
008: * Note: Contains auto-generated Javadoc comments created by BeautyJ.
009: *
010: * This is licensed under the GNU General Public License (GPL)
011: * and comes with NO WARRANTY. See file license.txt for details.
012: *
013: * Author: Jens Gulden
014: * Email: beautyj@jensgulden.de
015: */
016:
017: package de.gulden.util.javasource;
018:
019: import de.gulden.util.javasource.jjt.Node;
020: import de.gulden.util.javasource.jjt.*;
021: import de.gulden.util.xml.XMLToolbox;
022: import javax.xml.parsers.*;
023: import org.w3c.dom.*;
024: import java.io.*;
025: import java.util.*;
026:
027: /**
028: * Class DocumentationDeclared.
029: *
030: * @author Jens Gulden
031: * @version 1.1
032: */
033: public class DocumentationDeclared extends Documentation {
034:
035: // ------------------------------------------------------------------------
036: // --- final static field ---
037: // ------------------------------------------------------------------------
038:
039: /**
040: * Constant workaroundReplaceSingleStar.
041: */
042: private static final String workaroundReplaceSingleStar = "###SINGLE-STAR###";
043:
044: // ------------------------------------------------------------------------
045: // --- fields ---
046: // ------------------------------------------------------------------------
047:
048: /**
049: * The my documentation tagged.
050: */
051: public Vector myDocumentationTagged;
052:
053: /**
054: * The my source object declared.
055: */
056: public SourceObjectDeclared mySourceObjectDeclared;
057:
058: // ------------------------------------------------------------------------
059: // --- constructor ---
060: // ------------------------------------------------------------------------
061:
062: /**
063: * Creates a new instance of DocumentationDeclared.
064: */
065: public DocumentationDeclared() {
066: myDocumentationTagged = new Vector();
067: }
068:
069: // ------------------------------------------------------------------------
070: // --- methods ---
071: // ------------------------------------------------------------------------
072:
073: /**
074: * Returns the tags.
075: */
076: public Enumeration getTags() {
077: return myDocumentationTagged.elements();
078: }
079:
080: public DocumentationTagged findTag(String tag, String item) {
081: for (Enumeration e = myDocumentationTagged.elements(); e
082: .hasMoreElements();) {
083: DocumentationTagged dt = (DocumentationTagged) e
084: .nextElement();
085: if (dt.getTag().equals(tag)
086: && (((item == null) && (dt.getItem() == null)) || ((item != null)
087: && (dt.getItem() != null) && (item
088: .equals(dt.getItem()))))) {
089: return dt;
090: }
091: }
092: return null;
093: }
094:
095: /**
096: * Adds a tag.
097: */
098: public void addTag(DocumentationTagged tag) {
099: myDocumentationTagged.addElement(tag);
100: }
101:
102: /**
103: * Removes a tag.
104: */
105: public void removeTag(DocumentationTagged tag) {
106: myDocumentationTagged.removeElement(tag);
107: }
108:
109: /**
110: * Removes all tags.
111: */
112: public void removeAllTags() {
113: myDocumentationTagged.removeAllElements();
114: }
115:
116: /**
117: * Returns the source object declared.
118: */
119: public SourceObjectDeclared getSourceObjectDeclared() {
120: return mySourceObjectDeclared;
121: }
122:
123: /**
124: * Sets the source object declared.
125: */
126: public void setSourceObjectDeclared(
127: SourceObjectDeclared sourceObjectDeclared) {
128: this .mySourceObjectDeclared = sourceObjectDeclared;
129: }
130:
131: /**
132: * Extends Documentation.setRaw(String raw).
133: */
134: public void setRaw(String raw) {
135: super .setRaw(raw);
136: try {
137: raw = raw.trim();
138: // workaround 1: a Javadoc-comment might end with ***..**/ (multiple stars). Remove all additional stars so that comments ends cleanly with "*/" (otherwise stars will be seen as part of the comment text, which is very most likely not intended in such case)
139: while (raw.charAt(raw.length() - 3) == '*') {
140: raw = raw.substring(0, raw.length() - 3) + "*/";
141: }
142: // workaround 2: Javadoc-parser fails if no blank before ending */, so insert if needed (will not distort parse results, will be trimmed anyway)
143: if (raw.charAt(raw.length() - 3) != ' ') {
144: raw = raw.substring(0, raw.length() - 2) + " */";
145: }
146: // workaround 3: avoid single " * " occurrences in Javadoc, replace now and replace-back later
147: raw = workaroundAvoidSingleStar(raw);
148: // parse
149: Node docnode = JavadocParser.parse(raw);
150: this .text = getTextFromNode(
151: docnode
152: .getChild(JavadocParserTreeConstants.JJTDESCRIPTION))
153: .trim();
154: Node[] tags = docnode
155: .getChildren(JavadocParserTreeConstants.JJTTAG);
156: for (int i = 0; i < tags.length; i++) {
157: String tag;
158: String tagItem;
159: String tagText;
160: tag = tags[i].getValue();
161: Node itemNode = tags[i]
162: .getChild(JavadocParserTreeConstants.JJTTAGITEM);
163: if (itemNode != null) {
164: tagItem = itemNode.getChild(
165: JavadocParserTreeConstants.JJTWORD)
166: .getValue();
167: } else {
168: tagItem = null;
169: }
170: tagText = getTextFromNode(tags[i]).trim();
171: DocumentationTagged dt = new DocumentationTagged();
172: dt.setTag(tag);
173: dt.setItem(tagItem);
174: dt.setText(tagText);
175: this .addTag(dt);
176: }
177: return;
178: } catch (TokenMgrError te) {
179: // fallthrough
180: } catch (ParseException pe) {
181: // fallthrough
182: }
183: text = "... warning: could not parse javadoc comment ...";
184: String msg = "warning: could not parse javadoc comment, warning message inserted instead";
185: SourceObjectDeclared sourceObjectDeclared = getSourceObjectDeclared();
186: if (sourceObjectDeclared != null) {
187: Class declaringClass = sourceObjectDeclared
188: .getDeclaringClass();
189: String n = sourceObjectDeclared.getName();
190: msg += " ["
191: + (declaringClass != null ? declaringClass
192: .getName()
193: + (n != null ? "." : "") : "")
194: + (n != null ? n : "") + "]";
195: }
196: System.err.println(msg);
197: }
198:
199: /**
200: * Initialize this object from XML.
201: *
202: * @param element The corresponding XML tag.
203: * @throws IOException if an i/o error occurs
204: */
205: public void initFromXML(Element element) throws IOException {
206: // to be extended (not overwritten) by subclasses
207: name = element.getAttribute("name"); // adjust name
208: setText(XMLToolbox.getText(element));
209: myDocumentationTagged.removeAllElements();
210: NodeList nl = XMLToolbox.getChildren(element, "tag");
211: for (int i = 0; i < nl.getLength(); i++) {
212: DocumentationTagged dt = new DocumentationTagged();
213: dt.initFromXML((Element) nl.item(i));
214: myDocumentationTagged.addElement(dt);
215: }
216: }
217:
218: /**
219: * Output this object as XML.
220: *
221: * @return The XML tag.
222: * @see #initFromXML
223: */
224: public Element buildXML(Document d) {
225: Element e = super .buildXML(d);
226: for (Enumeration ee = getTags(); ee.hasMoreElements();) {
227: DocumentationTagged dt = (DocumentationTagged) ee
228: .nextElement();
229: String tag = dt.getTag();
230: if (!(tag.equals("@param") // these are handled at the referenced SourceObjectDeclared's
231: || tag.equals("@exception") || tag
232: .equals("@throws"))) {
233: e.appendChild(dt.buildXML(d));
234: }
235: }
236: return e;
237: }
238:
239: // ------------------------------------------------------------------------
240: // --- static methods ---
241: // ------------------------------------------------------------------------
242:
243: protected static String workaroundAvoidSingleStar(String s) {
244: int pos = s.indexOf('*');
245: while (pos != -1) {
246: if (s.charAt(pos + 1) != '/') { // not the very end of the comment
247: int linestart = s.lastIndexOf(nl, pos) + 1; // will result in 0 for 'not found' which is wanted
248: String beforeStar = s.substring(linestart, pos);
249: //if (containsText(beforeStar)) { // found a star to replace
250: if ((beforeStar.indexOf('*') != -1)
251: && (!beforeStar.equals("/*"))) {
252: s = s.substring(0, pos)
253: + workaroundReplaceSingleStar
254: + s.substring(pos + 1);
255: return workaroundAvoidSingleStar(s);
256: }
257: pos = s.indexOf('*', pos + 1);
258: } else {
259: pos = -1;
260: }
261: }
262: return s;
263: }
264:
265: protected static String workaroundRestoreSingleStar(String s) {
266: int pos = s.indexOf(workaroundReplaceSingleStar);
267: if (pos != -1) {
268: return s.substring(0, pos)
269: + "*"
270: + workaroundRestoreSingleStar(s.substring(pos
271: + workaroundReplaceSingleStar.length()));
272: } else {
273: return s;
274: }
275: }
276:
277: /**
278: * Returns the text from node.
279: */
280: private static String getTextFromNode(Node n) {
281: StringBuffer sb = new StringBuffer();
282: Node[] lines = n
283: .getChildren(JavadocParserTreeConstants.JJTLINE);
284: for (int i = 0; i < lines.length; i++) {
285: Node[] words = lines[i]
286: .getChildren(JavadocParserTreeConstants.JJTWORD);
287: for (int j = 0; j < words.length; j++) {
288: sb.append(workaroundRestoreSingleStar(words[j]
289: .getValue()));
290: if (j < words.length - 1) {
291: sb.append(" ");
292: }
293: }
294: sb.append("\n");
295: }
296: return sb.toString();
297: }
298:
299: } // end DocumentationDeclared
|