restructured the whole helma.doc-package.

- implemented latest helma features (function_action for actions etc)
- removed double code, nicer hierarchy, all elements can be used alone
- removed possibility to run from command line, rendering is now only done through
manage application
- streamlined supported tags
This commit is contained in:
stefanp 2002-11-20 16:00:41 +00:00
parent b9b7e9988d
commit 9bd47012c5
15 changed files with 904 additions and 1274 deletions

View file

@ -5,112 +5,103 @@ import helma.main.Server;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
public class DocApplication extends DocElement implements IPathElement { public class DocApplication extends DocDirElement {
private DocPrototype[] prototypes; public static void main (String args[]) {
// DocApplication app;
// app = new DocApplication (args[0], args[1]);
// app.readApplication ();
/** read all prototypes // DocPrototype el = DocPrototype.newInstance (new File(args[0]));
* @param name application to be documented // el.readFiles ();
* @param appDir directory of this application */
public DocApplication(String name, String appDir) throws DocException { // DocFunction func = DocFunction.newTemplate (new File(args[0]));
super( name, appDir, APPLICATION ); // DocFunction func = DocFunction.newAction (new File(args[0]));
checkCommentFile();
readPrototypes(); DocFunction[] func = DocFunction.newFunctions (new File (args[0]));
// DocSkin skin = DocSkin.newInstance (new File (args[0]));
// System.out.println (func.getContent ());
// System.out.println ("\n\n\ncomment = " + func.getComment ());
}
public DocApplication (String name, File location) throws DocException {
super (name, location, APPLICATION);
} }
public String getFullName() { public DocApplication (String name, String appDir) throws DocException {
return ( "Application " + name ); super (name, new File (appDir), APPLICATION);
} }
/** return number of prototypes */
public int countPrototypes() {
return prototypes.length;
}
/** return a single prototype */ /**
public DocPrototype getDocPrototype(String name) { * reads all prototypes and files of the application
for ( int i=0; i<prototypes.length; i++ ) { */
if ( prototypes[i].getName().equalsIgnoreCase(name) ) public void readApplication () {
return prototypes[i]; String arr[] = location.list ();
} children.clear ();
return null; for (int i=0; i<arr.length; i++) {
} if (Util.isExcluded (arr[i]))
continue;
/** return array of prototypes */ File f = new File (location.getAbsolutePath (), arr[i]);
public DocPrototype[] listPrototypes() { if (!f.isDirectory ())
return prototypes; continue;
} try {
DocPrototype pt = DocPrototype.newInstance (f, this);
public DocFunction[] listFunctions() { addChild (pt);
return listFunctions(-1); pt.readFiles ();
} } catch (DocException e) {
debug ("Couldn't read prototype " + arr[i] + ": " + e.getMessage ());
public DocFunction[] listFunctions(int type) {
Vector funcVec = new Vector();
for ( int i=0; i<prototypes.length; i++ ) {
DocFunction[] tmp = prototypes[i].listFunctions();
for ( int j=0; j<tmp.length; j++ ) {
if ( type==-1 || tmp[j].getType()==type )
funcVec.addElement(tmp[j]);
} }
System.out.println (f);
} }
DocFunction[] funcArr = (DocFunction[])funcVec.toArray(new DocFunction[funcVec.size()]); for (Iterator i=children.values ().iterator (); i.hasNext ();) {
Arrays.sort(funcArr,new DocComparator(DocComparator.BY_NAME,this)); ((DocPrototype) i.next ()).checkInheritance ();
return funcArr;
}
/** read prototypes, create them and make them parse their functions */
private void readPrototypes() {
File d = new File ( location );
String pt[] = d.list();
Vector ptVec = new Vector();
for ( int i=0; i<pt.length; i++ ) {
File f = new File ( d.getAbsolutePath(), pt[i] );
if ( f.isDirectory() && DocRun.prototypeAllowed(pt[i]) ) {
try {
DocPrototype p = new DocPrototype(pt[i],f.getAbsolutePath(),this);
ptVec.addElement(p);
//break;
} catch ( DocException e ) {
DocRun.log( "couldn't read prototype " + pt[i] + ": " + e.getMessage() );
}
}
} }
prototypes = (DocPrototype[])ptVec.toArray(new DocPrototype[ptVec.size()]);
Arrays.sort(prototypes,new DocComparator(this));
}
public String toString() {
return ( "[DocApplication " + name + "]" );
} }
//////////////////////////////////// // FIXME: function to retrieve all functions across all prototypes still to be done
// from helma.framework.IPathElement
////////////////////////////////////
// public DocFunction[] listFunctions() {
// return listFunctions(-1);
// }
//
// public DocFunction[] listFunctions(int type) {
// Vector funcVec = new Vector();
// for ( int i=0; i<prototypes.length; i++ ) {
// DocFunction[] tmp = prototypes[i].listFunctions();
// for ( int j=0; j<tmp.length; j++ ) {
// if ( type==-1 || tmp[j].getType()==type )
// funcVec.addElement(tmp[j]);
// }
// }
// DocFunction[] funcArr = (DocFunction[])funcVec.toArray(new DocFunction[funcVec.size()]);
// Arrays.sort(funcArr,new DocComparator(DocComparator.BY_NAME,this));
// return funcArr;
// }
//
/**
* from helma.framework.IPathElement, overridden with "api"
* to work in manage-application
*/
public String getElementName() { public String getElementName() {
return "api"; return "api";
} }
public IPathElement getChildElement(String name) {
for( int i=0; i<prototypes.length; i++ ) {
if ( prototypes[i].getElementName().equals(name) ) {
return prototypes[i];
}
}
return null;
}
/**
* from helma.framework.IPathElement, overridden with
* Server.getServer() to work in manage-application
*/
public IPathElement getParentElement() { public IPathElement getParentElement() {
Server s = helma.main.Server.getServer(); Server s = helma.main.Server.getServer();
return s.getChildElement(this.name); return s.getChildElement(this.name);
} }
public java.lang.String getPrototype() {
return "docapplication";
}
} }

View file

@ -1,46 +0,0 @@
package helma.doc;
import java.util.Comparator;
public class DocComparator implements Comparator {
public static final int BY_TYPE = 0;
public static final int BY_NAME = 1;
int mode;
DocElement docEl;
public DocComparator(int mode, DocElement docEl) {
this.mode = mode;
this.docEl = docEl;
}
public DocComparator(DocElement docEl) {
this.mode = 0;
this.docEl = docEl;
}
public int compare(Object obj1, Object obj2) {
DocElement e1 = (DocElement)obj1;
DocElement e2 = (DocElement)obj2;
if ( mode==BY_TYPE && e1.getType()>e2.getType() )
return 1;
else if ( mode==BY_TYPE && e1.getType()<e2.getType() )
return -1;
else {
return e1.name.compareTo(e2.name);
}
}
public boolean equals(Object obj) {
DocElement el = (DocElement)obj;
if ( el.name.equals(docEl.name) && el.getType()==docEl.getType() ) {
return true;
} else {
return false;
}
}
}

View file

@ -0,0 +1,36 @@
package helma.doc;
import java.io.*;
import java.util.*;
import FESI.Parser.*;
public abstract class DocDirElement extends DocElement {
// a default file that is read as comment for applications
// and prototypes if found in their directories
public static final String[] DOCFILES = {
"doc.html", "doc.htm",
"app.html", "app.htm",
"prototype.html", "prototype.htm",
"index.html", "index.htm"
};
protected DocDirElement (String name, File location, int type) {
super (name, location, type);
checkCommentFiles ();
}
private void checkCommentFiles () throws DocException {
for (int i=0; i<DOCFILES.length; i++) {
File f = new File (location, DOCFILES[i]);
if (f.exists ()) {
String rawComment = readFile (f);
parseComment (rawComment);
return;
}
}
}
}

View file

@ -3,182 +3,301 @@ package helma.doc;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
public abstract class DocElement { import helma.framework.IPathElement;
public abstract class DocElement implements IPathElement {
// identifiers of this element // identifiers of this element
String name; String name;
int type; int type;
String location; File location;
DocElement parent = null;
Map children = new HashMap ();
// comment-content // content
DocTag tags[]; String content = "";
String comment; String comment = "";
List tags = new Vector ();
List parameters = new Vector ();
public static final int DOCROOT = 0; public static final int APPLICATION = 0;
public static final int APPLICATION = 1; public static final int PROTOTYPE = 1;
public static final int PROTOTYPE = 2; public static final int ACTION = 2;
public static final int METHOD = 3; public static final int TEMPLATE = 3;
public static final int ACTION = 4; public static final int FUNCTION = 4;
public static final int TEMPLATE = 5; public static final int MACRO = 5;
public static final int FUNCTION = 6; public static final int SKIN = 6;
public static final int MACRO = 7; public static final int PROPERTIES = 7;
public static final int SKIN = 8;
public static final int PROPERTY = 9; // to be implemented
public static final String[] typeNames = {"DocRoot","Application","Prototype","Method","Action","Template","Function","Macro","Skin","Property"}; // above constants are used as array indices
public static final String[] typeNames = {
"Application",
"Prototype",
"Action",
"Template",
"Function",
"Macro",
"Skin",
"Properties"
};
/** a default file that is read as comment for applications and prototypes if found in their directories */ protected DocElement (String name, String location, int type) throws DocException {
public static final String DOCFILENAME = "doc.html"; this (name, new File (location), type);
}
public DocElement(String name, String location, int type) throws DocException { protected DocElement (String name, File location, int type) throws DocException {
if ( (new File(location)).exists()==false ) if (location.exists()==false)
throw new DocException( name + " not found in " + location ); throw new DocException( name + " not found in " + location.toString ());
this.name = name; this.name = name;
this.location = location; this.location = location;
this.type = type; this.type = type;
} }
public DocElement(String name, File location, int type) throws DocException { /**
if ( location.exists()==false ) * the simple name of the element
throw new DocException( name + " not found in " + location.toString() ); */
this.name = name;
this.location = location.getAbsolutePath();
this.type = type;
}
/** @return the name of the element */
public String getName() { public String getName() {
return name; return name;
} }
abstract public String getFullName(); /**
* @return absolute path to location of element
/** @return absolute path to location of element (directory for apps and prototypes, file for methods) */ * (directory for apps and prototypes, file for
public String getLocation() { * methods and properties files)
*/
public File getLocation() {
return location; return location;
} }
public boolean isApplication() { return (type==APPLICATION)?true:false; } public int getType() {
public boolean isPrototype() { return (type==PROTOTYPE)?true:false; } return type;
public boolean isMethod() { if ( type>=METHOD && type<=SKIN ) return true; else return false; }
public boolean isAction() { return (type==ACTION)?true:false; }
public boolean isTemplate() { return (type==TEMPLATE)?true:false; }
public boolean isFunction() { return (type==FUNCTION)?true:false; }
public boolean isMacro() { return (type==MACRO)?true:false; }
public boolean isSkin() { return (type==SKIN)?true:false; }
public int getType() { return type; }
public String getTypeName() { return typeNames[type]; }
public String getDocFileName() { return (typeNames[type] + "_" + name).toLowerCase() + ".html"; }
/** @return the text of the comment */
public String getComment() { return (comment!=null)?comment:""; }
public int countTags() { return countTags(-1); }
public int countTags(int kind) {
int ct=0;
for ( int i=0; i<tags.length; i++ ) {
if ( kind==-1 || tags[i].getKind()==kind ) {
ct++;
}
}
return ct;
} }
public DocTag[] listTags() { return tags; } public String getTypeName () {
/** @return an array of tags that should get a special format return typeNames [type];
* expects a -1 if it should retrieve all tags! */
public DocTag[] listTags(int kind) {
Vector vec = new Vector();
for ( int i=0; i<tags.length; i++ ) {
if ( kind==-1 || tags[i].getKind()==kind ) {
vec.addElement(tags[i]);
}
}
DocTag[] dt = (DocTag[])vec.toArray(new DocTag[vec.size()]);
return dt;
} }
/** parse rawComment, render DocTags */
void parseComment(String rawComment) { /**
* returns the comment string, empty string if no comment is set.
*/
public String getComment () {
return comment;
}
/**
* the actual content of the doc element (the function body, the properties
* list, the file list etc.
*/
public String getContent () {
return content;
}
public void addTag (String rawContent) {
if (tags==null) {
tags = new Vector ();
}
try {
DocTag tag = DocTag.parse (rawContent);
tags.add (tag);
} catch (DocException doc) {
debug (doc.toString ());
}
}
/**
* list all tags
*/
public DocTag[] listTags () {
return (DocTag[]) tags.toArray (new DocTag[0]);
}
/**
* filter the tags according to DocTag.TYPE
*/
public DocTag[] listTags (int type) {
Vector retval = new Vector ();
for (int i=0; i<tags.size (); i++) {
if ( ((DocTag) tags.get (i)).getType() == type)
retval.add (tags.get (i));
}
return (DocTag[]) retval.toArray ();
}
public boolean hasParameter (String param) {
return parameters.contains (param);
}
/**
* the list of parameters
*/
public String[] listParameters () {
return (String[]) parameters.toArray (new String[0]);
}
/**
* add a string to the parameters-list
*/
protected void addParameter (String param) {
parameters.add (param);
}
/**
* parse rawComment, render DocTags
*/
void parseComment (String rawComment) {
try {
StringTokenizer tok = new StringTokenizer (rawComment, "\n", true);
int BLANK = 0;
int TEXT = 1;
int TAGS = 2;
boolean lastEmpty = false;
int mode = BLANK;
StringBuffer buf = new StringBuffer ();
while (tok.hasMoreTokens ()) {
String line = Util.chopDelimiters (tok.nextToken ().trim ());
if ("".equals(line)) {
// if we've already had text, store that this line was empty
lastEmpty = (mode!=BLANK) ? true : false;
continue;
}
// if we come here the first time, start with TEXT mode
mode = (mode==BLANK) ? TEXT : mode;
// check if we have a new tag
if (DocTag.isTagStart (line)) {
// if we appended to comment text until now, store that ...
if (mode==TEXT)
comment = buf.toString ();
// if we appended to a tag, store that ...
if (mode==TAGS)
addTag (buf.toString ());
// reset buffer
buf = new StringBuffer ();
mode = TAGS;
}
// append to current buffer
if (lastEmpty==true)
buf.append ("\n");
buf.append (line);
buf.append (" ");
lastEmpty = false;
}
// store the last element, if there was at least one element ...
if (mode==TEXT)
comment = buf.toString ();
else if (mode==TAGS)
addTag (buf.toString ());
} catch (RuntimeException rt) {
debug ("parse error in " + location + ": " + rt.getMessage());
}
}
/**
* utility: read a complete file into a string
*/
protected static String readFile (File file) {
try { try {
// get rid of java comment tags (delimiter "/**") StringBuffer buf = new StringBuffer ();
int beg = rawComment.indexOf("/*"); BufferedReader in = new BufferedReader (new FileReader (file));
beg = ( beg<0 ) ? beg=0 : beg+3; String line = in.readLine ();
int end = rawComment.indexOf("*/");
end = ( end<0 ) ? rawComment.length()-1 : end;
end = ( end<0 ) ? 0 : end;
rawComment = rawComment.substring(beg,end).trim();
// separate comment from tags:
StringBuffer commentBuf = new StringBuffer();
StringBuffer tagBuf = new StringBuffer();
boolean switched = false;
StringTokenizer tok = new StringTokenizer(rawComment,"\n");
while(tok.hasMoreTokens() ) {
String line = tok.nextToken().trim();
if ( line.startsWith("*") )
line = line.substring(1).trim();
if ( line.length()==0 ) continue;
if ( line.startsWith("@") && switched==false )
switched=true;
if ( switched==true )
tagBuf.append(line + "\n" );
else
commentBuf.append(line + "\n" );
}
comment = commentBuf.toString();
// now create taglist:
tok = new StringTokenizer(tagBuf.toString(),"@");
tags = new DocTag[tok.countTokens()];
int i = 0;
while(tok.hasMoreTokens() ) {
tags[i++] = new DocTag(tok.nextToken().trim());
}
} catch ( DocException e ) {
DocRun.log("parse error in " + location + ": " + e.getMessage() );
}
}
/** read properties file (app.props || type.props), format of comments has to be discussed! */
static Properties readPropertiesFile(String filename) throws DocException {
Properties props = new Properties();
try {
props.load(new FileInputStream(filename));
} catch ( IOException e ) {
DocRun.log("couldn't read file: " + e.getMessage() );
}
return props;
}
void checkCommentFile() throws DocException {
File f = new File (location, DOCFILENAME );
if ( f.exists() ) {
String rawComment = readAFile(f.getAbsolutePath());
parseComment(rawComment);
} else {
comment = "";
tags = new DocTag[0];
}
}
/** read a complete file into a string */
public static String readAFile(String str) {
StringBuffer buf = new StringBuffer();
try {
BufferedReader in = new BufferedReader(new FileReader(new File(str)));
String line = in.readLine();
while(line!=null) { while(line!=null) {
buf.append(line+"\n"); buf.append (line+"\n");
line = in.readLine(); line = in.readLine ();
} }
return ( buf.toString() ); return buf.toString();
} catch ( IOException e ) { } catch (IOException e) {
return (""); return ("");
} }
} }
public void setParent (DocElement parent) {
this.parent = parent;
}
public void addChild (DocElement child) {
if (child==null)
return;
children.put (child.getElementName (), child);
}
public int countChildren () {
return children.size ();
}
public Map getChildren () {
return children;
}
/**
* returns an array of doc elements, sorted by their name
*/
public DocElement[] listChildren () {
String[] keys = (String[]) children.keySet ().toArray (new String[0]);
Arrays.sort (keys);
DocElement[] arr = new DocElement [keys.length];
for (int i=0; i<keys.length; i++) {
arr [i] = (DocElement) children.get (keys[i]);
}
return arr;
}
/**
* from helma.framework.IPathElement. Elements are named
* like this: typename_name
*/
public String getElementName() {
return typeNames[type].toLowerCase() + "_" + name;
}
/**
* from helma.framework.IPathElement. Retrieves a child from the
* children map.
*/
public IPathElement getChildElement (String name) {
try {
return (IPathElement) children.get (name);
} catch (ClassCastException cce) {
debug (cce.toString ());
cce.printStackTrace ();
return null;
}
}
/**
* from helma.framework.IPathElement. Returns the parent object
* of this instance if assigned.
*/
public IPathElement getParentElement () {
return parent;
}
/**
* from helma.framework.IPathElement. Prototypes are assigned like
* this: "doc" + typename (e.g. docapplication, docprototype etc)
*/
public java.lang.String getPrototype () {
return "doc" + typeNames[type].toLowerCase ();
}
public String toString () {
return "[" + typeNames [type] + " " + name + "]";
}
public static void debug (String msg) {
System.out.println(msg);
}
} }

View file

@ -1,6 +1,6 @@
package helma.doc; package helma.doc;
public class DocException extends Exception { public class DocException extends RuntimeException {
String str; String str;

View file

@ -0,0 +1,84 @@
package helma.doc;
import java.io.*;
import java.util.*;
import FESI.Parser.*;
public abstract class DocFileElement extends DocElement {
/**
* extracts the function name from a file. basically chops the given suffix
* and throws an error if the file name doesn't fit.
*/
static protected String nameFromFile (File f, String suffix) throws DocException {
String filename = f.getName ();
if (!filename.endsWith (suffix))
throw new DocException ("file doesn't have suffix " + suffix + ": " + f.toString());
return filename.substring (0, filename.lastIndexOf(suffix));
}
/**
* creates fesi token manager for a given file.
*/
static protected EcmaScriptTokenManager createTokenManager (File f) {
try {
ASCII_CharStream is = new ASCII_CharStream(new FileReader(f), 1, 1);
EcmaScriptTokenManager mgr = new EcmaScriptTokenManager(is,0);
return mgr;
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace ();
throw new DocException (fnfe.toString ());
}
}
protected DocFileElement (String name, File location, int type) {
super (name, location, type);
}
/**
* extracts a part of the source code, used to get the code for a
* single function from a function file. sets the field "content".
*/
protected void parseSource (File sourceFile, int beginLine, int beginColumn, int endLine, int endColumn) {
StringBuffer buf = new StringBuffer ();
int ct=0;
try {
BufferedReader in = new BufferedReader (new FileReader (sourceFile));
String line="";
while (line!=null) {
line = in.readLine();
if (line==null) break;
ct++;
if (ct==beginLine)
buf.append (line.substring(beginColumn-1, line.length())+"\n");
else if ( ct>beginLine && ct<endLine )
buf.append (line+"\n");
else if (ct==endLine)
buf.append (line.substring(0,endColumn));
}
} catch (Exception e) {
debug (e.getMessage ());
}
content = buf.toString ();
}
/**
* connects all available specialTokens starting at the given token.
*/
protected void parseCommentFromToken (Token tok) {
StringBuffer buf = new StringBuffer();
while (tok.specialToken!=null) {
buf.append (tok.specialToken.toString() );
tok = tok.specialToken;
}
parseComment (buf.toString().trim());
}
}

View file

@ -1,100 +1,150 @@
package helma.doc; package helma.doc;
import helma.framework.IPathElement;
import java.io.*; import java.io.*;
import java.util.*;
public class DocFunction extends DocElement implements IPathElement { import FESI.Parser.*;
import helma.framework.IPathElement;
public static final String[] typeSuffix = {"_action","_as_string","","_macro",""}; public class DocFunction extends DocFileElement {
private DocPrototype prototype; /**
private String source; * creates a new independent DocFunction object of type ACTION
*/
public DocFunction( String name, String location, int type, DocPrototype prototype, String rawComment ) throws DocException { public static DocFunction newAction (File location) {
super(name,location, type); return newAction (location, null);
this.prototype = prototype;
parseComment(rawComment);
} }
public String getFullName() {
switch(type) { /**
case ACTION: return ( "Action " + name ); * creates a new DocFunction object of type ACTION connected to another DocElement
case TEMPLATE: return ( "Template " + name ); */
case FUNCTION: return ( "Function " + name ); public static DocFunction newAction (File location, DocElement parent) {
case MACRO: return ( "Macro " + name ); String name = nameFromFile (location, ".hac");
case SKIN: return ( "Skin " + name ); DocFunction func = new DocFunction (name, location, parent, ACTION);
func.parseActionFile ();
return func;
}
/**
* creates a new independent DocFunction object of type TEMPLATE
*/
public static DocFunction newTemplate (File location) {
return newTemplate (location, null);
}
/**
* creates a new DocFunction object of type TEMPLATE connected to another DocElement
*/
public static DocFunction newTemplate (File location, DocElement parent) {
String name = nameFromFile (location, ".hsp");
DocFunction func = new DocFunction (name, location, parent, TEMPLATE);
func.parseTemplateFile ();
return func;
}
/**
* reads a function file and creates independent DocFunction objects of type FUNCTION
*/
public static DocFunction[] newFunctions (File location) {
return newFunctions (location, null);
}
/**
* reads a function file and creates DocFunction objects of type FUNCTION
* connected to another DocElement.
*/
public static DocFunction[] newFunctions (File location, DocElement parent) {
Vector vec = new Vector ();
EcmaScriptTokenManager mgr = createTokenManager(location);
Token tok = mgr.getNextToken();
while (tok.kind!=0) {
if (tok.kind == EcmaScriptConstants.FUNCTION) {
// store the start position of the function:
int beginLine = tok.beginLine;
int beginColumn = tok.beginColumn;
// the name is stored in the next token:
String funcName = mgr.getNextToken().toString();
// create the function object
DocFunction func;
if (funcName.endsWith("_action"))
func = new DocFunction (funcName, location, parent, ACTION);
else if (funcName.endsWith("_macro"))
func = new DocFunction (funcName, location, parent, MACRO);
else
func = new DocFunction (funcName, location, parent, FUNCTION);
// parse the comment from the special token(s) before this token:
func.parseCommentFromToken (tok);
// find the parameters of this function, but only if it's
// neither macro nor action:
if (func.type==FUNCTION) {
while (tok.kind!=0 && tok.kind!=EcmaScriptConstants.RPAREN) {
if (tok.kind==EcmaScriptConstants.IDENTIFIER) {
func.addParameter (tok.image);
}
tok = mgr.getNextToken ();
}
} else {
tok = mgr.getNextToken ();
}
// now find the end of the function:
int endLine=0, endColumn=0;
while (tok.kind!=0 && tok.kind!=EcmaScriptConstants.FUNCTION) {
endLine = tok.endLine;
endColumn = tok.endColumn;
tok = mgr.getNextToken ();
}
// now we know the exact position of the function in the file,
// re-read it and extract the source code:
func.parseSource (location, beginLine, beginColumn, endLine, endColumn);
vec.add (func);
}
tok = mgr.getNextToken();
} }
return ( "Method " + name ); return (DocFunction[]) vec.toArray (new DocFunction[0]);
} }
public DocPrototype getDocPrototype() { return prototype; } protected DocFunction (String name, File location, DocElement parent, int type) {
super (name, location, type);
public void readSource(String sourceFile, int beginLine, int beginColumn, int endLine, int endColumn ) { this.parent = parent;
StringBuffer buf = new StringBuffer ();
int ct=0;
try {
BufferedReader in = new BufferedReader(new FileReader(sourceFile));
String line="";
while ( line!=null ) {
line = in.readLine();
if ( line==null ) break;
ct++;
if ( ct==beginLine )
buf.append(line.substring(beginColumn-1, line.length())+"\n");
else if ( ct>beginLine && ct<endLine )
buf.append(line+"\n");
else if ( ct==endLine )
buf.append(line.substring(0,endColumn));
}
} catch ( FileNotFoundException e ) {
} catch ( StringIndexOutOfBoundsException e ) {
} catch ( IOException e ) {
DocRun.log(e.getMessage());
}
source = buf.toString();
} }
public void readSource(String sourceFile) {
StringBuffer buf = new StringBuffer (); /**
try { * reads the content of a .hac file and parses the comment before the first
BufferedReader in = new BufferedReader(new FileReader(sourceFile)); * javascript element
String line=""; */
while ( line!=null ) { private void parseActionFile () {
line = in.readLine(); EcmaScriptTokenManager mgr = createTokenManager(location);
if ( line==null ) break; Token tok = mgr.getNextToken();
buf.append(line+"\n"); parseCommentFromToken (tok);
} content = readFile (location);
} catch ( FileNotFoundException e ) {
} catch ( IOException e ) {
DocRun.log(e.getMessage());
}
source = buf.toString();
} }
public void setSource(String source) { this.source = source; }
public String getSource() { return (source!=null)?source:""; }
public String toString() { /**
return ( "[DocFunction " + getTypeName() + " " + name + "]" ); * reads the content of a .hsp file and parses the comment before the first
* javascript element (only if file starts with &gt;%-tag!).
*/
private void parseTemplateFile () {
content = readFile (location);
StringReader str = new StringReader (content.substring (content.indexOf("<%") + 2, content.indexOf ("%>")));
ASCII_CharStream ascii = new ASCII_CharStream (str,1,1);
EcmaScriptTokenManager mgr = new EcmaScriptTokenManager (ascii);
Token tok = mgr.getNextToken();
parseCommentFromToken (tok);
} }
////////////////////////////////////
// from helma.framework.IPathElement
////////////////////////////////////
public String getElementName() { /**
return getTypeName().toLowerCase()+"_"+name; * from helma.framework.IPathElement. All macros, templates, actions etc
} * have the same prototype.
*/
public IPathElement getChildElement(String name) { public java.lang.String getPrototype () {
return null;
}
public IPathElement getParentElement() {
return prototype;
}
public java.lang.String getPrototype() {
return "docfunction"; return "docfunction";
} }

View file

@ -1,328 +0,0 @@
package helma.doc;
import java.io.*;
import java.util.*;
import helma.util.*;
public class DocHtmlWriter extends PrintWriter {
public static DocApplication app;
public static final int APPLICATION = 0;
public static final int PROTOTYPE = 1;
public static final int INDEX = 2;
public static final int METHOD = 3;
public DocHtmlWriter(String filename) throws FileNotFoundException {
super(new FileOutputStream(filename));
}
public void printHeader( String title ) { printHeader(title,false); }
/** print header, slightly different for frameset file **/
public void printHeader( String title, boolean frameset ) {
if ( frameset==true )
print("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Frameset//EN\"\"http://www.w3.org/TR/REC-html40/frameset.dtd\">");
else
print("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\">");
print("<HTML><HEAD>");
print("<!-- Generated by helmadoc on " + (new Date()).toString() + " -->");
println("<TITLE>" + title + "</TITLE>");
if ( frameset==true )
print("<LINK REL=\"stylesheet\" TYPE=\"text/css\" HREF=\"stylesheet.css\" TITLE=Style>");
println("</HEAD>");
}
public void printFrameSet() {
println ("<FRAMESET cols=\"20%,80%\">");
println ("<FRAME src=\"app-frame.html\" name=appFrame>");
println ("<FRAME src=\"app.html\" name=prototypeFrame>");
println ("</FRAMESET><NOFRAMES>sorry, your browser doesn't understand frames!</NOFRAMES></HTML>");
}
/** print app title for left frame */
public void printAppIndexTitle(String title) {
print("<table border=0 width=\"100%\"><tr><td nowrap>");
print("<FONT size=+1 ID=FrameTitleFont><b>");
print("Application " + title + "</b></font></td></tr></table>" );
}
/** print prototype list for left frame */
public void printAppIndexList(DocElement[] pt) {
print("<TABLE BORDER=0 WIDTH=\"100%\"><TR><TD NOWRAP>");
print("<P><FONT size=+1 ID=FrameHeadingFont>Prototypes</FONT><BR><BR>");
for ( int i=0; i<pt.length; i++ ) {
print ("<FONT ID=FrameItemFont><A HREF=\"" + pt[i].getDocFileName() + "\" TARGET=prototypeFrame>" + pt[i].getName() + "</A></FONT><BR>");
}
print ("</TD></TR></TABLE>");
}
/** navigation on top of the page **/
public void printNavBar(String name, DocPrototype pt, int page ) {
String urlPrefix = ( page==METHOD ) ? "../" : "";
print("<!-- ========== START OF NAVBAR ========== -->");
print("<A NAME=navbar_top><!-- --></A>");
print("<TABLE BORDER=0 WIDTH=100% CELLPADDING=1 CELLSPACING=0>");
print("<TR><TD COLSPAN=2 BGCOLOR=#EEEEFF ID=NavBarCell1>");
print("<A NAME=navbar_top_firstrow><!-- --></A>");
print("<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=3>");
print("<TR ALIGN=center VALIGN=top>");
if ( page==APPLICATION )
print("<TD BGCOLOR=#EEEEFF ID=NavBarCell1Rev><FONT ID=NavBarFont1Rev><B>Application</B></FONT>&nbsp;</TD>");
else
print("<TD BGCOLOR=#EEEEFF ID=NavBarCell1><A HREF=\"" + urlPrefix + "app.html\"><FONT ID=NavBarFont1><B>Application</B></FONT></A>&nbsp;</TD>");
if ( page==PROTOTYPE )
print("<TD BGCOLOR=#EEEEFF ID=NavBarCell1Rev>&nbsp;<FONT ID=NavBarFont1Rev><B>Prototype</B></FONT>&nbsp;</TD>");
else if ( page==METHOD )
print("<TD BGCOLOR=#EEEEFF ID=NavBarCell1>&nbsp;<a href=\"" + urlPrefix + "prototype_" + pt.getName() + ".html\"><FONT ID=NavBarFont1><B>Prototype</B></A></FONT>&nbsp;</TD>");
else
print("<TD BGCOLOR=#EEEEFF ID=NavBarCell1>&nbsp;<FONT ID=NavBarFont1><B>Prototype</B></FONT>&nbsp;</TD>");
if ( page==INDEX )
print("<TD BGCOLOR=#EEEEFF ID=NavBarCell1Rev><FONT ID=NavBarFont1><B>Index</B></FONT>&nbsp;</TD>");
else
print("<TD BGCOLOR=#EEEEFF ID=NavBarCell1><A HREF=\"" + urlPrefix + "index-1.html\"><FONT ID=NavBarFont1><B>Index</B></FONT></A>&nbsp;</TD>");
print("</TR></TABLE>");
print("</TD><TD ALIGN=right VALIGN=top ROWSPAN=3><EM><b>Application " + name + "</b><br><font size=-1></font></EM>");
print("</TD></TR>");
if ( pt!=null && page!=METHOD ) {
print("<TR><TD VALIGN=top ID=NavBarCell3><FONT SIZE=-2>");
print("<a href=\"#Actions\">ACTIONS</a>&nbsp;|&nbsp;");
print("<a href=\"#Templates\">TEMPLATES</a>&nbsp;|&nbsp;");
print("<a href=\"#Functions\">FUNCTIONS</a>&nbsp;|&nbsp;");
print("<a href=\"#Macros\">MACROS</a>&nbsp;|&nbsp;");
print("<a href=\"#Skins\">SKINS</a>&nbsp;");
print("</TD></TR>");
}
print("</TABLE>");
print("<!-- =========== END OF NAVBAR =========== -->");
}
public void printElementTitle(DocElement docEl) {
print("<HR><H2>" + docEl.getName() + "<BR>");
print(docEl.getFullName() + "</H2>");
print("<HR>");
}
public void printComment(DocElement docEl) {
if( docEl.getComment().length()>0 || docEl.countTags()>0 ) {
print("<DL><DT>" + docEl.getComment() + "</DT>");
print("<DT>");
for ( int i=0; i<DocTag.TYPE_COUNT; i++ ) {
if ( docEl.countTags(i)>0 ) {
print("<DT><b>" + DocTag.kindDesc[i] + "</b><DT>");
DocTag[] dt = docEl.listTags(i);
for ( int j=0; j<dt.length; j++ ) {
print("<DD>" + renderTag(dt[j],j) + "</DD>");
}
}
}
print("</DL>");
}
}
private String renderFunctionName(DocFunction func) {
StringBuffer buf = new StringBuffer ();
buf.append("<CODE><B>");
if ( DocRun.getOption("-f").equals("true") )
buf.append("<a href=\"" + func.getDocPrototype().getName().toLowerCase()+"/"+func.getDocFileName() + "\">" );
if ( func.isMacro() ) {
buf.append( func.getDocPrototype().getName()+"."+func.getName().substring(0,func.getName().length()-6) );
} else {
buf.append(func.getName().trim());
if( func.isTemplate() || func.isFunction() ) {
buf.append("(");
int ct = func.countTags(DocTag.ARG);
for ( int i=0; i<ct; i++ ) {
buf.append("arg"+i);
if ( i<ct-1 )
buf.append(", ");
}
buf.append(")");
}
}
buf.append("</a></B></CODE>");
if ( func.isFunction() || func.isMacro() )
buf.append(" <small><i>in " + (new File(func.getLocation())).getName() + "</i></small>" );
return buf.toString();
}
private String renderTag(DocTag tag) {
return renderTag(tag,0);
}
private String renderTag(DocTag tag, int i) {
int kind = tag.getKind();
String text = tag.getText();
String name = tag.getName();
switch (kind) {
case DocTag.ARG:
return( "<b>Argument " + i + ":</b> " + text );
case DocTag.PARAM:
return( "<b>Parameter " + name + "</b> " + text );
case DocTag.RETURNS:
case DocTag.AUTHOR:
case DocTag.VERSION:
case DocTag.RELEASE:
return( text );
case DocTag.SEE:
if ( text.startsWith("http://") ) {
StringTokenizer tok = new StringTokenizer (text.trim()," ");
String url = (tok.countTokens()>1)?tok.nextToken():text;
return( "<a href=\"" + url + "\">" + ((tok.countTokens()>0)?text.substring(url.length(),text.length()):text) + "</a>" );
} else {
StringBuffer buf = new StringBuffer();
StringTokenizer tok = new StringTokenizer (text.trim(),".");
if ( tok.countTokens()==0 ) return text;
DocPrototype dp = app.getDocPrototype( tok.nextToken() );
if ( dp==null ) return text;
buf.append("<a href=\"" );
DocFunction df = null;
if ( tok.countTokens()>0 )
df = dp.getFunction( tok.nextToken() );
if ( df==null )
buf.append( link(dp) + "\">" + dp.getName() );
else
buf.append( link(df) + "\">" + dp.getName() + "." + df.getName() );
return(buf.toString()+"</a>");
}
}
return text;
}
public void printListHeader(String title) {
print("<A NAME=\"" + title + "\"><!-- --></A>");
print("<TABLE BORDER=1 CELLPADDING=3 CELLSPACING=0 WIDTH=100%>");
print("<TR BGCOLOR=#CCCCFF ID=TableHeadingColor><TD COLSPAN=2><FONT SIZE=+2><B>" + title + "</B></FONT></TD></TR>");
}
public void printPrototypeList(DocPrototype[] dl, String title) {
if ( dl.length==0 ) return;
printListHeader(title);
for ( int i=0; i<dl.length; i++ ) {
print("<TR BGCOLOR=white ID=TableRowColor><TD ALIGN=right VALIGN=top WIDTH=1%><FONT SIZE=-1>");
print("<a name=\"" + dl[i].getName() + "\"><!-- --></a>");
print("<CODE>&nbsp;" + dl[i].getTypeName() + "</CODE></FONT></TD>");
print("<TD><CODE><B><A HREF=\"" + dl[i].getDocFileName() + "\">" + dl[i].getName() + "</A></B></CODE>");
print("<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" + dl[i].getComment() + "<br>" );
print("</TD></TR>");
}
print("</TABLE><BR>");
}
public void printFunctionList(DocFunction[] dl, String title) {
if ( dl.length==0 ) return;
printListHeader(title);
for ( int i=0; i<dl.length; i++ ) {
print("<TR BGCOLOR=white ID=TableRowColor>");
print("<TD ALIGN=right VALIGN=top WIDTH=50><FONT SIZE=-1>");
print("<a name=\"" + dl[i].getName() + "\"><!-- --></a>");
print("<CODE>&nbsp;" + dl[i].getTypeName() + "</CODE></FONT></TD>");
print("<TD><DL><DT>" + renderFunctionName(dl[i]) );
print("<DT>");
printComment(dl[i]);
print("</DL></TD></TR>");
}
print("</TABLE><BR>");
}
public void printFunctionIndex(DocFunction[] dl) {
if ( dl.length==0 ) return;
String curChar = " ";
print("<DL>");
for ( int i=0; i<dl.length; i++ ) {
String name = dl[i].getName();
if ( !name.toLowerCase().startsWith(curChar) ) {
print ( "</DL><h2>" + name.substring(0,1).toUpperCase() + "</h2><dl>");
curChar = name.substring(0,1).toLowerCase();
}
print("<DT><a href=\"" + link(dl[i]) + "\">" + dl[i].getName() + "</a> - " + dl[i].getTypeName() + " in <a href=\"" + link(dl[i].getDocPrototype()) + "\">" + dl[i].getDocPrototype().getName() + "</a>" );
}
print("</DL>");
}
public void printInheritance(DocPrototype pt) {
if ( pt.getName().equalsIgnoreCase("hopobject") )
return;
DocApplication app = pt.getApplication();
DocPrototype hopobject = (DocPrototype)app.getDocPrototype("hopobject");
if ( hopobject==null || hopobject.countFunctions()==0 )
return;
print("<TABLE BORDER=1 CELLPADDING=3 CELLSPACING=0 WIDTH=100%>");
print("<TR BGCOLOR=\"#EEEEFF\" CLASS=TableSubHeadingColor>");
print("<TD><B>Methods inherited from Prototype <a href=\"" + link(hopobject) + "\">hopobject</A></B></TD>");
print("</TR>");
print("<TR BGCOLOR=\"white\" CLASS=TableRowColor><TD><code>");
DocFunction[] df = hopobject.listFunctions();
int lastType = -1;
StringBuffer buf1 = new StringBuffer();
StringBuffer buf2 = new StringBuffer();
for ( int i=0; i<df.length; i++ ) {
if ( df[i].getType()!=lastType && i>0 && buf2.length()>0 ) {
buf1.append("<b>" + DocElement.typeNames[lastType] + ":</b> <code>" );
buf1.append( buf2.toString().substring(0, buf2.toString().length()-2) );
buf1.append("</code><br>");
buf2 = new StringBuffer();
}
lastType = df[i].getType();
buf2.append ( "<a href=\"" + link(df[i]) + "\">" + df[i].getName() + "</a>, " );
}
if ( buf2.length()>0 ) {
buf1.append("<b>" + DocElement.typeNames[lastType] + ":</b> <code>" );
buf1.append( buf2.toString().substring(0, buf2.toString().length()-2) );
buf1.append("</code><br>");
}
print ( buf1.toString() );
print("</TR></TABLE>");
}
public void printFunction(DocFunction func) {
print( "<br><br><small><i>in " + func.getDocPrototype().getName() + "/" + (new File(func.getLocation())).getName() + ":</i></small>" );
print( "<br><pre>");
print( HtmlEncoder.encodeAll(func.getSource()) );
print( "</pre>" );
}
public void printStyleSheet() {
println( "/* Javadoc style sheet */");
println( "/* Define colors, fonts and other style attributes here to override the defaults */");
println( "* Page background color */");
println( "body { background-color: #FFFFFF }");
println( "/* Table colors */");
println( "#TableHeadingColor { background: #CCCCFF } /* Dark mauve */");
println( "#TableSubHeadingColor { background: #EEEEFF } /* Light mauve */");
println( "#TableRowColor { background: #FFFFFF } /* White */");
println( "/* Font used in left-hand frame lists */");
println( "#FrameTitleFont { font-size: normal; font-family: normal }");
println( "#FrameHeadingFont { font-size: normal; font-family: normal }");
println( "#FrameItemFont { font-size: normal; font-family: normal }");
println( "/* Example of smaller, sans-serif font in frames */");
println( "/* #FrameItemFont { font-size: 10pt; font-family: Helvetica, Arial, sans-serif } */");
println( "/* Navigation bar fonts and colors */");
println( "#NavBarCell1 { background-color:#EEEEFF;}/* Light mauve */");
println( "#NavBarCell1Rev { background-color:#00008B;}/* Dark Blue */");
println( "#NavBarFont1 { font-family: Arial, Helvetica, sans-serif; color:#000000;}");
println( "#NavBarFont1Rev { font-family: Arial, Helvetica, sans-serif; color:#FFFFFF;}");
println( "#NavBarCell2 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF;}");
println( "#NavBarCell3 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF;}");
}
public String link(DocElement docEl) {
if ( docEl.isPrototype() ) {
return "prototype_" + docEl.getName() + ".html";
} else if ( docEl.isMethod() ) {
DocFunction df = (DocFunction)docEl;
return "prototype_" + df.getDocPrototype().getName() + ".html#" + df.getName();
} else {
return "";
}
}
}

View file

@ -0,0 +1,49 @@
package helma.doc;
import helma.framework.IPathElement;
import helma.util.SystemProperties;
import java.io.*;
import java.util.*;
public class DocProperties extends DocFileElement {
Properties props = null;
/**
* creates a new independent DocProperties object
*/
public static DocProperties newInstance (File location) {
return newInstance (location, null);
}
/**
* creates a new DocProperties object connected to another DocElement
*/
public static DocProperties newInstance (File location, DocElement parent) {
try {
return new DocProperties (location, parent);
} catch (DocException doc) {
return null;
}
}
protected DocProperties (File location, DocElement parent) throws DocException {
super (location.getName (), location, PROPERTIES);
this.parent = parent;
content = readFile (location);
props = new SystemProperties ();
try {
props.load (new FileInputStream (location));
} catch (IOException e) {
debug ("couldn't read file: " + e.toString ());
} catch (Exception e) {
throw new DocException (e.toString ());
}
}
protected Properties getProperties () {
return props;
}
}

View file

@ -6,215 +6,89 @@ import java.util.*;
import FESI.Parser.*; import FESI.Parser.*;
public class DocPrototype extends DocElement implements IPathElement { public class DocPrototype extends DocDirElement {
DocFunction[] functions; private DocProperties typeProperties = null;
DocApplication app; private DocPrototype parentPrototype = null;
public DocPrototype( String name, String location, DocApplication app ) throws DocException { /**
super( name, location, PROTOTYPE ); * creates a prototype that is independent of an
this.app = app; * application object
if ( name.equals("hopobject")==false && name.equals("global")==false ) * @param homedirectory
readPropertiesFile( new File(location,"type.properties").getAbsolutePath()); */
checkCommentFile(); public static DocPrototype newInstance (File location) {
readFunctions(); return newInstance (location, null);
} }
public String getFullName() { return ( "Prototype " + name ); } /**
* creates a prototype that is connected to an
* application object and resides in app's home dir.
* @param application
* @param name
*/
public static DocPrototype newInstance (File location, DocElement parent) {
DocPrototype pt = new DocPrototype (location.getName (), location, parent);
return pt;
}
/** return number of functions */ private DocPrototype (String name, File location, DocElement parent) {
public int countFunctions() { return functions.length; } super (name, location, PROTOTYPE);
this.parent = parent;
typeProperties = DocProperties.newInstance (new File (location, "type.properties"));
}
/** return array of functions of a special type */
public int countFunctions(int type) { /**
int ct = 0; * checks the type.properites for _extend values and connected a possible
for ( int i=0; i<functions.length; i++ ) { * parent prototype with this prototype. this can't be successfull at construction
if ( functions[i].getType()==type ) { * time but only -after- all prototypes are parsed and attached to a parent
ct++; * DocApplication object.
*/
public void checkInheritance () {
// hopobject is the top prototype:
if (name.equals("hopobject"))
return;
if (typeProperties!=null) {
// check for "_extends" in the the type.properties
String ext = typeProperties.getProperties ().getProperty ("_extends");
if (ext!=null && parent!=null) {
// try to get the prototype if available
parentPrototype = (DocPrototype) parent.getChildElement ("prototype_" + ext);
} }
} }
return ct; if (parentPrototype==null && parent!=null) {
} // if no _extend was set, get the hopobject prototype
parentPrototype = (DocPrototype) parent.getChildElement ("prototype_hopobject");
/** return a single function */
public DocFunction getFunction(String name) {
for ( int i=0; i<functions.length; i++ ) {
if ( functions[i].getName().equals(name) )
return functions[i];
} }
return null;
} }
/** return array of functions */ /**
public DocFunction[] listFunctions() { * runs through the prototype directory and parses all helma files
return functions; */
} public void readFiles () {
children.clear ();
/** return array of functions of a special type */ String arr[] = location.list ();
public DocFunction[] listFunctions(int type) { for (int i=0; i<arr.length; i++) {
Vector funcVec = new Vector(); if (Util.isExcluded (arr[i]))
for ( int i=0; i<functions.length; i++ ) { continue;
if ( functions[i].getType()==type ) { File f = new File (location.getAbsolutePath (), arr[i]);
funcVec.addElement(functions[i]); if (f.isDirectory ())
} continue;
} if (arr[i].endsWith (".skin")) {
return (DocFunction[])funcVec.toArray(new DocFunction[funcVec.size()]); addChild (DocSkin.newInstance (f, this));
} } else if (arr[i].endsWith (".properties")) {
continue;
} else if (arr[i].endsWith (".hac")) {
/** return the application */ addChild (DocFunction.newAction (f, this));
public DocApplication getApplication() { return app; } } else if (arr[i].endsWith (".hsp")) {
addChild (DocFunction.newTemplate (f, this));
} else if (arr[i].endsWith (".js")) {
/** create the function list & read all valid files */ DocElement[] elements = DocFunction.newFunctions (f, this);
private void readFunctions() { for (int j=0; j<elements.length; j++) {
DocRun.debug("parsing Prototype " + name + " using " + location ); addChild (elements[j]);
String files[] = (new File(location)).list();
Vector funcVec = new Vector();;
for ( int i=0; i<files.length; i++ ) {
DocRun.debug("reading " + files[i] );
try {
if ( files[i].endsWith(DocRun.actionExtension) ) {
readAction(new File(location,files[i]).getAbsolutePath(),funcVec);
} else if ( files[i].endsWith(DocRun.scriptExtension) ) {
readFunctionFile(new File(location,files[i]).getAbsolutePath(),funcVec);
} else if ( files[i].endsWith(DocRun.templateExtension) ) {
readTemplate(new File(location,files[i]).getAbsolutePath(),funcVec);
} else if ( files[i].endsWith(DocRun.skinExtension) ) {
readSkin(new File(location,files[i]).getAbsolutePath(),funcVec);
} }
} catch ( DocException e ) {
DocRun.log ( "couldn't read function " + name + "." + files[i] + ": " + e.getMessage() );
} }
} }
functions = (DocFunction[])funcVec.toArray(new DocFunction[funcVec.size()]);
DocRun.debug( name + " has " + functions.length + " functions" );
Arrays.sort(functions,new DocComparator(this));
}
private void readAction(String f, Vector funcVec) throws DocException {
EcmaScriptTokenManager mgr = createTokenManager(new File(f));
Token tok = mgr.getNextToken();
DocFunction func = new DocFunction( fileToFuncName(f), f, DocElement.ACTION, this, getCommentFromToken(tok) );
func.readSource(f);
funcVec.addElement( func );
}
private void readFunctionFile(String f, Vector funcVec) throws DocException {
EcmaScriptTokenManager mgr = createTokenManager(new File(f));
Token tok = mgr.getNextToken();
while( tok.kind!=0 ) {
if( tok.kind == EcmaScriptConstants.FUNCTION ) {
int beginLine = tok.beginLine;
int beginColumn = tok.beginColumn;
String funcName = mgr.getNextToken().toString();
DocFunction func;
if ( funcName.endsWith("_macro") )
func = new DocFunction( funcName, f, DocElement.MACRO, this, getCommentFromToken(tok) );
else
func = new DocFunction( funcName, f, DocElement.FUNCTION, this, getCommentFromToken(tok) );
funcVec.addElement(func);
tok = mgr.getNextToken();
int endLine=0, endColumn=0;
while( tok.kind!=0 && tok.kind!=EcmaScriptConstants.FUNCTION ) {
endLine = tok.endLine;
endColumn = tok.endColumn;
tok = mgr.getNextToken();
}
func.readSource(f,beginLine,beginColumn,endLine,endColumn);
//DocRun.log("going from " + beginLine +"." + beginColumn + " to " + endLine + "." + endColumn );
//DocRun.log("============================here starts a new one");
}
if ( tok.kind!=0 && tok.kind!=EcmaScriptConstants.FUNCTION )
tok = mgr.getNextToken();
}
}
private void readTemplate(String f, Vector funcVec) throws DocException {
String content = readAFile(f);
// get the first scripting zone and tokenize it
DocFunction func;
try {
StringReader str = new StringReader( content.substring(content.indexOf("<%")+2,content.indexOf("%>")) );
EcmaScriptTokenManager mgr = new EcmaScriptTokenManager(new ASCII_CharStream(str,1,1),0);
Token tok = mgr.getNextToken();
func = new DocFunction( fileToFuncName(f), f, DocElement.TEMPLATE, this, getCommentFromToken(tok) );
} catch ( IndexOutOfBoundsException e ) {
func = new DocFunction( fileToFuncName(f), f, DocElement.TEMPLATE, this, "" );
}
func.setSource(content);
funcVec.addElement(func);
}
private void readSkin(String f, Vector funcVec) throws DocException {
// can't be commented yet
// simply add them
DocFunction func = new DocFunction(fileToFuncName(f),f,DocElement.SKIN, this,"");
func.readSource(f);
funcVec.addElement(func);
}
/** create token manager for a file */
private EcmaScriptTokenManager createTokenManager(File f) {
try {
ASCII_CharStream is = new ASCII_CharStream(new FileReader(f), 1, 1);
EcmaScriptTokenManager mgr = new EcmaScriptTokenManager(is,0);
return mgr;
} catch ( FileNotFoundException shouldnotappear ) { }
return null;
}
/** connect all available specialTokens */
private String getCommentFromToken(Token tok) {
StringBuffer buf = new StringBuffer();
while( tok.specialToken!=null ) {
buf.append(tok.specialToken.toString() );
tok = tok.specialToken;
}
return ( buf.toString().trim() );
}
private String fileToFuncName(String f) {
return fileToFuncName(new File(f));
}
private String fileToFuncName(File f) {
String tmp = f.getName();
return tmp.substring(0,tmp.indexOf("."));
}
public String toString() {
return ( "[DocPrototype " + name + "]" );
}
////////////////////////////////////
// from helma.framework.IPathElement
////////////////////////////////////
public String getElementName() {
return name;
}
public IPathElement getChildElement(String name) {
for ( int i=0; i<functions.length; i++ ) {
if ( name.equals( functions[i].getTypeName().toLowerCase()+"_"+functions[i].getName() ) )
return functions[i];
}
return null;
}
// return getFunction(name);
// }
public IPathElement getParentElement() {
return app;
}
public java.lang.String getPrototype() {
return "docprototype";
} }
} }

View file

@ -1,227 +0,0 @@
package helma.doc;
import java.io.*;
import java.util.*;
import helma.util.SystemProperties;
/**
* Description of the Class
*
*@author Stefan Pollach
*@created August 20, 2001
*/
public class DocRun {
/**
* Description of the Field
*/
public static String propfile;
/**
* Description of the Field
*/
public static SystemProperties sysProps, dbProps;
/**
* Description of the Field
*/
public static String actionExtension = ".hac";
/**
* Description of the Field
*/
public static String scriptExtension = ".js";
/**
* Description of the Field
*/
public static String templateExtension = ".hsp";
/**
* Description of the Field
*/
public static String skinExtension = ".skin";
/**
* Description of the Field
*/
public static String hopHomeDir;
public static Hashtable options = new Hashtable();
String appName;
DocApplication app;
/**
* Constructor for the DocRun object
*
*@param appDir Description of Parameter
*@exception DocException Description of Exception
*/
public DocRun(String appDir) throws DocException {
File d = new File(appDir);
if (!d.exists()) {
throw new DocException(d.toString() + " doesn't exist");
}
if (!d.isDirectory()) {
throw new DocException(d.toString() + " is not a directory");
}
log("parsing application " + d.getName() + " located in " + d.getAbsolutePath());
log("writing output to " + getOption("-d", new File(hopHomeDir, "/appdocs/" + d.getName()).getAbsolutePath()));
app = new DocApplication(d.getName(), d.getAbsolutePath());
DocWriter.start(getOption("-d", new File(hopHomeDir, "/appdocs/" + d.getName()).getAbsolutePath()), app);
}
/**
* Gets the option attribute of the DocRun class
*
*@param name Description of Parameter
*@return The option value
*/
public static String getOption(String name) {
return getOption(name, "");
}
/**
* Gets the option attribute of the DocRun class
*
*@param name Description of Parameter
*@param def Description of Parameter
*@return The option value
*/
public static String getOption(String name, String def) {
if (options.containsKey(name)) {
return (String) options.get(name);
} else {
return (def);
}
}
/**
* Description of the Method
*
*@param args Description of Parameter
*/
public static void main(String args[]) {
boolean usageError = false;
// parse options from command line
options = new Hashtable();
StringBuffer buf = new StringBuffer();
String name = "";
for (int i = 0; i < args.length; i++) {
if (args[i].startsWith("-")) {
if (i > 0) {
if (buf.toString().length() == 0) {
usageError = true;
} else {
options.put(name, buf.toString());
}
}
name = args[i];
buf = new StringBuffer();
} else {
buf.append(((buf.toString().length() > 0) ? " " : "") + args[i]);
}
}
options.put(name, buf.toString());
// include last option
// now check parameter
if (options.containsKey("-h")) {
hopHomeDir = (String) options.get("-h");
} else {
hopHomeDir = System.getProperty("user.dir");
}
readHopProperties(hopHomeDir);
String parAppDir = "";
if (options.containsKey("-a")) {
parAppDir = (String) options.get("-a");
} else {
usageError = true;
}
if (usageError == true) {
help();
System.exit(0);
}
try {
new DocRun(parAppDir);
} catch (DocException e) {
System.out.println("doc error: " + e.getMessage());
}
}
/**
* Description of the Method
*/
public static void help() {
System.out.println("usage: java helma.doc.DocApplication -a appdir [-f] [-h hopdir] [-d docdir] [-i ignore]");
System.out.println(" -a appdir Specify source directory");
System.out.println(" -h hopdir Specify hop home directory");
System.out.println(" -d docdir Specify destination directory");
System.out.println(" -f true Link functions to source code");
System.out.println(" -i ignore Specify prototypes to ignore (like: \"-i CVS mistsack\")");
System.out.println(" -debug");
System.out.println("\n");
}
/**
* Description of the Method
*
*@param name Description of Parameter
*@return Description of the Returned Value
*/
public static boolean prototypeAllowed(String name) {
String ig = " " + getOption("-i").toLowerCase() + " ";
if (ig.equals("")) {
return true;
}
name = name.toLowerCase();
if (ig.indexOf(" " + name + " ") > -1) {
return false;
} else {
return true;
}
}
/**
* reads server.properties, apps.properties and db.properties from
* hop-home-directory TBD: should be cleaned up to work exactly like the
* helma server
*
*@param hopHomeDir Description of Parameter
*/
public static void readHopProperties(String hopHomeDir) {
propfile = new File(hopHomeDir, "server.properties").getAbsolutePath();
sysProps = new SystemProperties(propfile);
dbProps = new SystemProperties(new File(hopHomeDir, "db.properties").getAbsolutePath());
actionExtension = sysProps.getProperty("actionExtension", ".hac");
scriptExtension = sysProps.getProperty("scriptExtension", ".js");
templateExtension = sysProps.getProperty("templateExtension", ".hsp");
}
/**
* Description of the Method
*
*@param msg Description of Parameter
*/
public static void debug(String msg) {
if (options.containsKey("-debug")) {
System.out.println(msg);
}
}
/**
* Description of the Method
*
*@param msg Description of Parameter
*/
public static void log(String msg) {
System.out.println(msg);
}
}

View file

@ -0,0 +1,78 @@
package helma.doc;
import helma.framework.IPathElement;
import java.io.*;
import java.util.*;
public class DocSkin extends DocFileElement {
/**
* creates a new independent DocSkin object
*/
public static DocSkin newInstance (File location) {
return newInstance (location, null);
}
/**
* creates a new DocSkin object connected to another DocElement
*/
public static DocSkin newInstance (File location, DocElement parent) {
String skinname = nameFromFile (location, ".skin");
DocSkin skin = new DocSkin (skinname, location, parent);
return skin;
}
protected DocSkin (String name, File location, DocElement parent) {
super (name, location, SKIN);
this.parent = parent;
content = readFile (location);
parseHandlers ();
}
/**
* parses the source code of the skin and
* extracts all included macros. code taken
* from helma.framework.core.Skin
* @see helma.framework.core.Skin
*/
private void parseHandlers () {
ArrayList partBuffer = new ArrayList ();
char[] source = content.toCharArray ();
int sourceLength = source.length;
int start = 0;
for (int i = 0; i < sourceLength-1; i++) {
if (source[i] == '<' && source[i+1] == '%') {
// found macro start tag
int j = i+2;
// search macro end tag
while (j < sourceLength-1 && (source[j] != '%' || source[j+1] != '>')) {
j++;
}
if (j > i+2) {
String str = (new String (source, i+2, j-i)).trim ();
str = str.substring (0, str.indexOf(" "));
if (!partBuffer.contains(str))
partBuffer.add (str);
start = j+2;
}
i = j+1;
}
}
String[] strArr = (String[]) partBuffer.toArray (new String [0]);
Arrays.sort (strArr);
for (int i=0; i<strArr.length; i++) {
addParameter (strArr[i]);
}
}
/**
* from helma.framework.IPathElement. Use the same prototype as functions etc.
*/
public java.lang.String getPrototype () {
return "docfunction";
}
}

View file

@ -2,58 +2,98 @@ package helma.doc;
import java.util.*; import java.util.*;
public class DocTag { public final class DocTag {
public static final int ARG = 0; // for public use we have less types than
public static final int PARAM = 1; // internally. eg, we're combining "return" and "returns"
public static final int RETURNS = 2; // or "arg" and "param".
public static final int AUTHOR = 3; // those that aren't combined, need to match the index of
public static final int VERSION = 4; // the tags-array!
public static final int RELEASE = 5; public static final int PARAMETER = 0;
public static final int RETURN = 2;
public static final int AUTHOR = 4;
public static final int VERSION = 5;
public static final int SEE = 6; public static final int SEE = 6;
/** number of different tag-types **/ public static final String[][] tags = {
public static final int TYPE_COUNT = 7; {"@arg","Argument"},
{"@param","Parameter"},
/** constants are used as array indices! **/ {"@return","Returns"},
public static final String[] kindNames = {"arg","param","return","author","version","release","see"}; {"@returns","Returns"},
public static final String[] kindDesc = {"Arguments","Parameter","Returns","Author","Version","Release","See also"}; {"@author","Author"},
{"@version","Version"},
{"@see","See also"}
};
private String name; private String name;
// kind is for internal use, type is external
private int kind; private int kind;
private String text; private String text;
public DocTag( String rawTag ) throws DocException { public static boolean isTagStart (String rawLine) {
//DocRun.log(rawTag); rawLine = rawLine.trim ();
try { for (int i=0; i<tags.length; i++) {
StringTokenizer tok = new StringTokenizer(rawTag); if (rawLine.startsWith (tags[i][0])) {
String kindstr = tok.nextToken().toLowerCase(); return true;
for ( int i=0; i<kindNames.length; i++ ) {
if ( kindstr.startsWith(kindNames[i]) ) {
kind = i;
break;
}
} }
StringBuffer buf = new StringBuffer(); }
if ( kind==PARAM ) { return false;
name = tok.nextToken();
}
while ( tok.hasMoreTokens() ) {
buf.append( tok.nextToken() + " " );
}
text = buf.toString();
} catch ( Exception e ) { }
} }
public String getName() { return (name!=null && !name.equals("null"))?name:""; } public static DocTag parse (String rawTag) throws DocException {
public int getKind() { return kind; } rawTag = rawTag.trim ();
public String getText() { return (text!=null && !text.equals("null"))?text:""; } int kind = -1;
for (int i=0; i<tags.length; i++) {
if (rawTag.startsWith (tags[i][0])) {
kind = i;
break;
}
}
if (kind == -1)
throw new DocException ("unsupported tag type: " + rawTag);
String content = rawTag.substring (tags[kind][0].length ()).trim ();
if (kind == 0 || kind==1) {
StringTokenizer tok = new StringTokenizer (content);
String name = "";
if (tok.hasMoreTokens ())
name = tok.nextToken ();
return new DocTag (kind, name, content.substring (name.length ()).trim ());
} else {
return new DocTag (kind, "", content);
}
}
private DocTag (int kind, String name, String text) {
this.kind = kind;
this.name = (name!=null) ? name : "";
this.text = (text!=null) ? text : "";
}
public String getName () {
return name;
}
public int getType () {
if (kind==0 || kind==1)
return PARAMETER;
else if (kind==2 || kind==3)
return RETURN;
else
return kind;
}
public String getTag () {
return tags[kind][0];
}
public String getText () {
return text;
}
public String toString() { public String toString() {
return "[" + ((name!=null)?name+" ":"" ) + text + "]"; return tags [kind][1] + ": " + name + " " + text;
} }
} }

View file

@ -1,128 +0,0 @@
package helma.doc;
import java.io.*;
import java.util.Arrays;
public class DocWriter extends DocHtmlWriter {
public static String docDir;
public DocWriter( String filename ) throws FileNotFoundException {
super( new File(docDir,filename).getAbsolutePath() );
DocRun.log("creating " + filename );
}
public static void start( String parDocDir, DocApplication parApp ) {
app = parApp;
docDir = parDocDir;
if ( !(new File(parDocDir).exists()) ) {
DocRun.log("creating directory " + parDocDir );
(new File(parDocDir)).mkdirs();
}
printStyleSheet(app);
printFrameSet(app);
printAppDoc(app);
printAppIndex(app);
printPrototypes(app);
printFunctionIndex(app);
if ( DocRun.getOption("-f").equals("true") )
printFunctions(app);
}
/** print index-1.html .. alphabetical list of all functions */
public static void printFunctionIndex(DocApplication app) {
try {
DocWriter dw = new DocWriter("index-1.html");
dw.printHeader("Application " + app.getName() );
dw.printNavBar(app.getName(), null, INDEX );
DocFunction[] df = app.listFunctions();
Arrays.sort(df,new DocComparator(1,df[0]));
dw.printFunctionIndex(df);
dw.close();
} catch ( FileNotFoundException e ) { DocRun.log( e.getMessage() ); }
}
/** print stylesheet.css */
public static void printStyleSheet(DocApplication app) {
try {
DocWriter dw = new DocWriter("stylesheet.css");
dw.printStyleSheet();
dw.close();
} catch ( FileNotFoundException e ) { DocRun.log( e.getMessage() ); }
}
/** print index.html */
public static void printFrameSet(DocApplication app) {
try {
DocWriter dw = new DocWriter("index.html");
dw.printHeader("Application " + app.getName() );
dw.printFrameSet();
dw.close();
} catch ( FileNotFoundException e ) { DocRun.log( e.getMessage() ); }
}
/** print app.html, list of prototypes */
public static void printAppDoc(DocApplication app) {
try {
DocWriter dw = new DocWriter("app.html");
dw.printHeader("Application " + app.getName() );
dw.printNavBar(app.getName(), null, APPLICATION );
dw.printElementTitle(app);
dw.printComment(app);
dw.printPrototypeList(app.listPrototypes(),"Prototypes");
dw.close();
} catch ( FileNotFoundException e ) { DocRun.log( e.getMessage() ); }
}
/** print app-frame.html, content of left frame */
public static void printAppIndex(DocApplication app) {
try {
DocWriter dw = new DocWriter("app-frame.html");
dw.printHeader("Application " + app.getName() );
dw.printAppIndexTitle(app.getName());
dw.printAppIndexList((DocPrototype[])app.listPrototypes());
dw.close();
} catch ( FileNotFoundException e ) { DocRun.log( e.getMessage() ); }
}
/** print all prototype-files, lists of functions */
public static void printPrototypes(DocApplication app) {
DocPrototype[] pt = app.listPrototypes();
for ( int i=0; i<pt.length; i++ ) {
try {
DocWriter dw = new DocWriter( pt[i].getDocFileName());
dw.printHeader("Application " + app.getName() + " / Prototype " + pt[i].getName());
dw.printNavBar(app.getName(), pt[i], PROTOTYPE );
dw.printElementTitle(pt[i]);
dw.printComment(pt[i]);
dw.printFunctionList(pt[i].listFunctions(DocElement.ACTION), "Actions");
dw.printFunctionList(pt[i].listFunctions(DocElement.TEMPLATE), "Templates");
dw.printFunctionList(pt[i].listFunctions(DocElement.FUNCTION), "Functions");
dw.printFunctionList(pt[i].listFunctions(DocElement.MACRO), "Macros");
dw.printFunctionList(pt[i].listFunctions(DocElement.SKIN), "Skins");
dw.printInheritance(pt[i]);
dw.close();
} catch ( FileNotFoundException e ) { DocRun.log( e.getMessage() ); }
}
}
/** print all function sources */
public static void printFunctions(DocApplication app) {
DocFunction[] df = app.listFunctions();
for ( int i=0;i<df.length; i++ ) {
try {
File d = new File ( docDir, df[i].getDocPrototype().getName().toLowerCase() );
if ( !d.exists() )
d.mkdir();
DocWriter dw = new DocWriter( df[i].getDocPrototype().getName().toLowerCase() + "/" + df[i].getDocFileName() );
dw.printHeader( app.getName() + "." + df[i].getDocPrototype().getName() + "." + df[i].getName() );
dw.printNavBar( app.getName(), df[i].getDocPrototype(), DocHtmlWriter.METHOD);
dw.printFunction( df[i] );
dw.close();
} catch ( FileNotFoundException e ) { DocRun.log( e.getMessage() ); }
}
}
}

38
src/helma/doc/Util.java Normal file
View file

@ -0,0 +1,38 @@
package helma.doc;
import java.io.*;
import java.util.*;
public final class Util {
static Vector excluded = new Vector ();
public static void addExlude (String str) {
excluded.add (str.toLowerCase ());
}
public static boolean isExcluded (String str) {
if (excluded.size ()==0)
excluded.add ("cvs");
return (excluded.contains (str.toLowerCase ()));
}
public static String chopDelimiters (String line) {
if (line==null)
return null;
else if (line.startsWith("/**"))
return line.substring (3).trim ();
else if (line.startsWith("/*"))
return line.substring (2).trim ();
else if (line.endsWith ("*/"))
return line.substring (0, line.length ()-2);
else if (line.startsWith("*"))
return line.substring (1).trim ();
else if (line.startsWith("//"))
return line.substring (2).trim ();
else
return line;
}
}