001: /*
002: * Helma License Notice
003: *
004: * The contents of this file are subject to the Helma License
005: * Version 2.0 (the "License"). You may not use this file except in
006: * compliance with the License. A copy of the License is available at
007: * http://adele.helma.org/download/helma/license.txt
008: *
009: * Copyright 1998-2003 Helma Software. All Rights Reserved.
010: *
011: * $RCSfile$
012: * $Author: root $
013: * $Revision: 8604 $
014: * $Date: 2007-09-28 15:16:38 +0200 (Fre, 28 Sep 2007) $
015: */
016:
017: package helma.doc;
018:
019: import java.util.*;
020:
021: /**
022: *
023: */
024: public abstract class DocElement {
025: public static final int APPLICATION = 0;
026: public static final int PROTOTYPE = 1;
027: public static final int ACTION = 2;
028: public static final int TEMPLATE = 3;
029: public static final int FUNCTION = 4;
030: public static final int MACRO = 5;
031: public static final int SKIN = 6;
032: public static final int PROPERTIES = 7;
033:
034: // above constants are used as array indices
035: public static final String[] typeNames = { "Application",
036: "Prototype", "Action", "Template", "Function", "Macro",
037: "Skin", "Properties" };
038:
039: // identifiers of this element
040: String name;
041: int type;
042: DocElement parent = null;
043: Map children = new HashMap();
044:
045: // content
046: String content = "";
047: String comment = "";
048: List tags = new Vector();
049: List parameters = new Vector();
050:
051: protected DocElement(String name, int type) {
052: this .name = name;
053: this .type = type;
054: }
055:
056: /**
057: * the simple name of the element
058: */
059: public String getName() {
060: return name;
061: }
062:
063: /**
064: *
065: *
066: * @return ...
067: */
068: public int getType() {
069: return type;
070: }
071:
072: /**
073: *
074: *
075: * @return ...
076: */
077: public String getTypeName() {
078: return typeNames[type];
079: }
080:
081: /**
082: * returns the comment string, empty string if no comment is set.
083: */
084: public String getComment() {
085: return comment;
086: }
087:
088: /**
089: * the actual content of the doc element (the function body, the properties
090: * list, the file list etc.
091: */
092: public String getContent() {
093: return content;
094: }
095:
096: /**
097: *
098: *
099: * @param rawContent ...
100: */
101: public void addTag(String rawContent) {
102: if (tags == null) {
103: tags = new Vector();
104: }
105:
106: try {
107: DocTag tag = DocTag.parse(rawContent);
108:
109: tags.add(tag);
110: } catch (DocException doc) {
111: debug(doc.toString());
112: }
113: }
114:
115: /**
116: * list all tags
117: */
118: public DocTag[] listTags() {
119: return (DocTag[]) tags.toArray(new DocTag[0]);
120: }
121:
122: /**
123: * filter the tags according to their type
124: */
125: public DocTag[] listTags(String type) {
126: Vector retval = new Vector();
127:
128: for (int i = 0; i < tags.size(); i++) {
129: if (((DocTag) tags.get(i)).getType().equals(type)) {
130: retval.add(tags.get(i));
131: }
132: }
133:
134: return (DocTag[]) retval.toArray();
135: }
136:
137: /**
138: *
139: *
140: * @param param ...
141: *
142: * @return ...
143: */
144: public boolean hasParameter(String param) {
145: return parameters.contains(param);
146: }
147:
148: /**
149: * the list of parameters
150: */
151: public String[] listParameters() {
152: return (String[]) parameters.toArray(new String[0]);
153: }
154:
155: /**
156: * add a string to the parameters-list
157: */
158: protected void addParameter(String param) {
159: parameters.add(param);
160: }
161:
162: /**
163: * parse rawComment, render DocTags
164: */
165: void parseComment(String rawComment) {
166: try {
167: rawComment = rawComment.trim();
168: StringTokenizer tok = new StringTokenizer(rawComment, "\n",
169: true);
170: int BLANK = 0;
171: int TEXT = 1;
172: int TAGS = 2;
173: boolean lastEmpty = false;
174: int mode = BLANK;
175: StringBuffer buf = new StringBuffer();
176:
177: while (tok.hasMoreTokens()) {
178: String line = Util.chopDelimiters(tok.nextToken()
179: .trim());
180:
181: if ("".equals(line)) {
182: // if we've already had text, store that this line was empty
183: lastEmpty = (mode != BLANK);
184:
185: continue;
186: }
187:
188: // if we come here the first time, start with TEXT mode
189: mode = (mode == BLANK) ? TEXT : mode;
190:
191: // check if we have a new tag
192: if (DocTag.isTagStart(line)) {
193: // if we appended to comment text until now, store that ...
194: if (mode == TEXT) {
195: comment = buf.toString();
196: }
197:
198: // if we appended to a tag, store that ...
199: if (mode == TAGS) {
200: addTag(buf.toString());
201: }
202:
203: // reset buffer
204: buf = new StringBuffer();
205: mode = TAGS;
206: }
207:
208: // append to current buffer
209: if (lastEmpty) {
210: buf.append("\n");
211: }
212:
213: buf.append(line);
214: buf.append(" ");
215: lastEmpty = false;
216: }
217:
218: // store the last element, if there was at least one element ...
219: if (mode == TEXT) {
220: comment = buf.toString().trim();
221: } else if (mode == TAGS) {
222: addTag(buf.toString());
223: }
224: } catch (RuntimeException rt) {
225: debug("parse error in " + name + ": " + rt.getMessage());
226: }
227: }
228:
229: /**
230: *
231: *
232: * @param parent ...
233: */
234: public void setParent(DocElement parent) {
235: this .parent = parent;
236: }
237:
238: /**
239: *
240: *
241: * @param child ...
242: */
243: public void addChild(DocElement child) {
244: if (child == null) {
245: return;
246: }
247:
248: children.put(child.getElementName(), child);
249: }
250:
251: /**
252: *
253: *
254: * @return ...
255: */
256: public int countChildren() {
257: return children.size();
258: }
259:
260: /**
261: *
262: *
263: * @return ...
264: */
265: public Map getChildren() {
266: return children;
267: }
268:
269: /**
270: * returns an array of doc elements, sorted by their name
271: */
272: public DocElement[] listChildren() {
273: String[] keys = (String[]) children.keySet().toArray(
274: new String[0]);
275:
276: Arrays.sort(keys);
277:
278: DocElement[] arr = new DocElement[keys.length];
279:
280: for (int i = 0; i < keys.length; i++) {
281: arr[i] = (DocElement) children.get(keys[i]);
282: }
283:
284: return arr;
285: }
286:
287: /**
288: * walks up the tree and tries to find a DocApplication object
289: */
290: public DocApplication getDocApplication() {
291: DocElement el = this ;
292:
293: while (el != null) {
294: if (el instanceof DocApplication) {
295: return (DocApplication) el;
296: }
297:
298: el = (DocElement) el.getParentElement();
299: }
300:
301: return null;
302: }
303:
304: /**
305: * from helma.framework.IPathElement. Elements are named
306: * like this: typename_name
307: */
308: public String getElementName() {
309: return typeNames[type].toLowerCase() + "_" + name;
310: }
311:
312: /**
313: * from helma.framework.IPathElement. Retrieves a child from the
314: * children map.
315: */
316: public DocElement getChildElement(String name) {
317: try {
318: return (DocElement) children.get(name);
319: } catch (ClassCastException cce) {
320: debug(cce.toString());
321: cce.printStackTrace();
322:
323: return null;
324: }
325: }
326:
327: /**
328: * from helma.framework.IPathElement. Returns the parent object
329: * of this instance if assigned.
330: */
331: public Object getParentElement() {
332: return parent;
333: }
334:
335: /**
336: * from helma.framework.IPathElement. Prototypes are assigned like
337: * this: "doc" + typename (e.g. docapplication, docprototype etc)
338: */
339: public java.lang.String getPrototype() {
340: return "doc" + typeNames[type].toLowerCase();
341: }
342:
343: /**
344: *
345: *
346: * @return ...
347: */
348: public String toString() {
349: return "[" + typeNames[type] + " " + name + "]";
350: }
351:
352: /**
353: *
354: *
355: * @param msg ...
356: */
357: public static void debug(String msg) {
358: System.out.println(msg);
359: }
360: }
|