From dave at badgers-in-foil.co.uk Sat Mar 5 20:41:49 2005 From: dave at badgers-in-foil.co.uk (David Holroyd) Date: Sat, 05 Mar 2005 20:41:49 +0000 Subject: [as2api-dev] [CVS trunk] Initial outline of as2api documentation Message-ID:
Commit in trunk/as2api on MAIN
as2api-documentation.xml+457added 65
Initial outline of as2api documentation

trunk/as2api
as2api-documentation.xml added at 65
--- trunk/as2api/as2api-documentation.xml	2005-02-27 00:15:35 UTC (rev 64)
+++ trunk/as2api/as2api-documentation.xml	2005-03-05 20:41:47 UTC (rev 65)
@@ -0,0 +1,457 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+                         "docbook/dtd/4.3/docbookx.dtd">
+
+<?xml-stylesheet href="/home/dave/projects/docbook-css/driver.css"
+                 type="text/css"?>
+
+
+<article lang="en_GB">
+  <title>as2api Documentation</title>
+
+  <section>
+    <title>About</title>
+
+    <para>as2api parses ActionScript 2 source code and generates HTML
+    API documentation in the style of JavaDoc.  It is open source, and
+    runs on Windows, MacOSX and Linux.</para>
+  </section>
+
+  <section>
+    <title>Getting the software</title>
+
+    <para>There are three versions of the software available from the
+    project homepage,
+    <ulink url="http://www.badgers-in-foil.co.uk/projects/as2api/"/>:</para>
+
+    <itemizedlist>
+      <listitem>
+	<para>A pre-compiled GUI app for MacOSX</para>
+      </listitem>
+      <listitem>
+	<para>A pre-compiled GUI exe for Windows</para>
+      </listitem>
+      <listitem>
+	<para>The source ruby scripts, runnable from the command-line
+	under Linux (or anywhere else that Ruby is available)</para>
+      </listitem>
+    </itemizedlist>
+  </section>
+
+  <section>
+    <title>Installing and running the software</title>
+
+    <section>
+      <title>MacOSX</title>
+
+      <para><remark>TODO</remark></para>
+    </section>
+
+    <section>
+      <title>Windows</title>
+
+      <para><remark>TODO</remark></para>
+    </section>
+
+    <section>
+      <title>Command-line</title>
+
+      <para><remark>TODO</remark></para>
+    </section>
+  </section>
+
+  <section>
+    <title>How to Write Documentation Comments for as2api</title>
+
+    <section>
+      <title>Overview</title>
+
+      <section>
+	<title>ActionScript Comments</title>
+	<para>ActionScript 2 provides two kinds of
+	<wordasword>comment</wordasword> marker, for denoting text which
+	is not part of the executable program code.  There is the C++
+	style single-line comment,</para>
+	<programlisting><emphasis role="strong">//</emphasis> everything on the line after the two slashes is ignored</programlisting>
+	<para>and the C style multi-line comment,</para>
+	<programlisting><emphasis role="strong">/*</emphasis> text between start and end markers is
+ignored, and the comment may continue across multiple lines
+in the source code <emphasis role="strong">*/</emphasis></programlisting>
+      </section>
+
+      <section>
+	<title>as2api Documentation Comments</title>
+	<para>as2api ignores the single-line comments, but it will
+	read text from the multi-line comments if both the following
+	conditions are true,</para>
+	<itemizedlist>
+	  <listitem>
+	    <para>The start-of-comment marker has two asterisks, not
+	    just one: "<literal>/**</literal>"</para>
+	  </listitem>
+	  <listitem>
+	    <para>The comment immediately precedes the definition
+	    of part of the public API of an ActionScript 2 class
+	    (e.g. just before the class definition itself)</para>
+	  </listitem>
+	</itemizedlist>
+
+	<example>
+	  <title>A Simple class definition with as2api
+	  documentation</title>
+
+	  <programlisting>/*
+ * MyFirstClass.as
+ *
+ * Copyright (c) __MyEmployer__ 2005
+ *
+ * <lineannotation>The contents of this comment are ignored</lineannotation>
+ */
+
+import "otherpackage.MyOtherClass";
+
+<emphasis role="strong">/**
+ * Objects of this class are responsible for serving as an example
+ * to others.
+ */</emphasis>
+class thispackage.MyFirstClass {
+
+  <emphasis role="strong">/**
+   * When called, this method puts into motion a plan so cunning
+   * that words cannot describe it.
+   */</emphasis>
+  public function enactCunningPlan():Void {
+      // TODO: implement cunning plan
+  }
+}</programlisting>
+	</example>
+      </section>
+    </section>
+
+    <section>
+      <title>Writing Useful Documentation</title>
+
+      <para>Here are a few guidelines</para>
+
+      <section>
+	<title>Empathy!</title>
+	<para>Take a deep breath.</para>
+	<para>Take five (mental) paces back from your code.</para>
+	<para>Try to see the API from someone else's point of view.  It will
+	help if you imagine that this other person is lazy, but
+	<emphasis>not</emphasis> stupid.  They want to gain the maximum
+	understanding with the minimum amount of reading.</para>
+      </section>
+
+      <section>
+	<title>Describe the Interface, not the Implementation</title>
+
+	<para>Classes are useful because they can hide the complicated details
+	of how things are achieved behind a simple, black-box interface.</para>
+
+	<para>If part of a class's implementation can be changed, and no code
+	making use of the class would notice, then this is an implementation
+	detail, not part of the API which must be documented.</para>
+      </section>
+
+      <section>
+	<title>Avoid Repeating the Code in English</title>
+	<para>This kind of annotation is not useful:</para>
+	<programlisting>/**
+ * Set the name property
+ * @param name the name to set
+ */
+public function setName(name:String):Void {
+  // ...
+}</programlisting>
+	<para>Method and class names are an integral part of the API
+	documentation, and should already convey a useful overview of their
+	own purpose.</para>
+      </section>
+    </section>
+
+    <section>
+      <title>Syntax Reference</title>
+
+      <para><remark>TODO</remark></para>
+
+      <section>
+	<title>Supported JavaDoc Features</title>
+
+	<informaltable>
+	  <thead>
+	    <row>
+	      <entry>Feature</entry>
+	      <entry>Description</entry>
+	    </row>
+	  </thead>
+	  <tbody>
+	    <row>
+	      <entry><link linkend="type_description">Type
+	      Description</link></entry>
+	      <entry>Describe a class or interface</entry>
+	    </row>
+	    <row>
+	      <entry><link linkend="method_description">Method
+	      Description</link></entry>
+	      <entry>Describe a method of a class or interface</entry>
+	    </row>
+	    <row>
+	      <entry><link linkend="param_tag"><literal>@param</literal></link></entry>
+	      <entry>Describe a method parameter</entry>
+	    </row>
+	    <row>
+	      <entry><link linkend="return_tag"><literal>@return</literal></link></entry>
+	      <entry>Describe the value returned by a method</entry>
+	    </row>
+	    <row>
+	      <entry><link linkend="see_tag"><literal>@see</literal></link></entry>
+	      <entry>Partially supported. Link to additional
+	      information.</entry>
+	    </row>
+	    <row>
+	      <entry><link linkend="throws_tag"><literal>@throws</literal></link></entry>
+	      <entry>Describe an exception thrown by a method</entry>
+	    </row>
+	  </tbody>
+	</informaltable>
+      </section>
+
+      <section>
+	<title>Unsupported JavaDoc Features</title>
+
+	<informaltable>
+	  <thead>
+	    <row>
+	      <entry>Feature</entry>
+	      <entry>Commentary</entry>
+	    </row>
+	  </thead>
+	  <tbody>
+	    <row>
+	      <entry><literal>@author</literal></entry>
+	      <entry></entry>
+	    </row>
+	    <row>
+	      <entry><literal>{@code}</literal></entry>
+	      <entry></entry>
+	    </row>
+	    <row>
+	      <entry><literal>{@docRoot}</literal></entry>
+	      <entry></entry>
+	    </row>
+	    <row>
+	      <entry><literal>@depricated</literal></entry>
+	      <entry></entry>
+	    </row>
+	    <row>
+	      <entry><literal>@exception</literal></entry>
+	      <entry><literal>@throws</literal> is supported, but this synonym is not, yet</entry>
+	    </row>
+	    <row>
+	      <entry><literal>{@inheritDoc}</literal></entry>
+	      <entry></entry>
+	    </row>
+	    <row>
+	      <entry><literal>{@link}</literal></entry>
+	      <entry>To be implemented soon-ish</entry>
+	    </row>
+	    <row>
+	      <entry><literal>{@linkPlain}</literal></entry>
+	      <entry></entry>
+	    </row>
+	    <row>
+	      <entry><literal>{@literal}</literal></entry>
+	      <entry></entry>
+	    </row>
+	    <row>
+	      <entry><literal>@serial</literal></entry>
+	      <entry></entry>
+	    </row>
+	    <row>
+	      <entry><literal>@serialData</literal></entry>
+	      <entry></entry>
+	    </row>
+	    <row>
+	      <entry><literal>@serialField</literal></entry>
+	      <entry></entry>
+	    </row>
+	    <row>
+	      <entry><literal>@since</literal></entry>
+	      <entry></entry>
+	    </row>
+	    <row>
+	      <entry><literal>{@value}</literal></entry>
+	      <entry></entry>
+	    </row>
+	    <row>
+	      <entry><literal>@version</literal></entry>
+	      <entry></entry>
+	    </row>
+	  </tbody>
+	</informaltable>
+      </section>
+
+      <section>
+	<title>Unsupported ActionScript Features</title>
+
+	<informaltable>
+	  <thead>
+	    <row>
+	      <entry>Feature</entry>
+	      <entry>Commentary</entry>
+	    </row>
+	  </thead>
+	  <tbody>
+	    <row>
+	      <entry><literal>#include "<replaceable>filename</replaceable>"</literal></entry>
+	      <entry>includes are ignored</entry>
+	    </row>
+	    <row>
+	      <entry><literal>[<replaceable>attributes</replaceable>]</literal></entry>
+	      <entry>attributes on types/members are not documented</entry>
+	    </row>
+	  </tbody>
+	</informaltable>
+      </section>
+
+      <section id="type_description">
+	<title>Class/Interface Description</title>
+
+	<para>A doc-comment immediately before a class or interface is taken to
+	be a description of that class.  The text here will be placed at the
+	top of the page documenting the class's public fields and
+	methods.</para>
+
+	<para>The first sentence of the class description will also be
+	included in the package-level index of classes and interfaces.  It
+	should therefore try to give a brief overview of the class's
+	purpose</para>
+
+	<example>
+	  <title>Class Description</title>
+	  <programlisting><emphasis role="strong">/**
+ * An immutable, type-safe wrapper around the String value of the
+ * user identifier.
+ * The constructor will raise an exception if the given value is not
+ * of the correct format, asserting that the GUI validation code has
+ * done its job, and preventing invalid data being sent to the
+ * backend.
+ */</emphasis>
+class thispackage.UserId {
+    // ...
+}</programlisting>
+	</example>
+
+	<formalpara>
+	  <title>May contain</title>
+	  <para><link linkend="see_tag">@see</link></para>
+	</formalpara>
+      </section>
+
+      <section id="method_description">
+	<title>Method Description</title>
+
+	<para><remark>TODO</remark></para>
+
+	<example>
+	  <title>Method Description</title>
+	  <programlisting><emphasis role="strong">/**
+ * Clears all data that has previously been collected in this
+ * object, and returns it to its initial state.  Subclasses are
+ * expected to override this method to clear any state of their
+ * own, and use super() ensure that data defined by this class is
+ * cleared too.
+ */</emphasis>
+public function clear() {
+    // ...
+}</programlisting>
+	</example>
+
+	<formalpara>
+	  <title>May contain</title>
+	  <para><link linkend="param_tag">@param</link>, <link linkend="return_tag">@return</link>, <link linkend="see_tag">@see</link></para>
+	</formalpara>
+      </section>
+
+      <section id="param_tag">
+	<title>Method Parameters</title>
+
+	<para><remark>TODO</remark></para>
+
+	<example>
+	  <title>Method Parameters</title>
+	  <programlisting>/**
+ * For each value contained by this object, invoke the given
+ * callback function, passing the value as an argument.
+ *
+ * <emphasis role="strong">@param callback</emphasis> callback function to be invoked for each object.
+ *        The function must accept one parameter (or two, if index
+ *        is true).
+ * <emphasis role="strong">@param index</emphasis> if true, each invocation of the callback function
+ *        will be passed an additional second parameter giving the
+ *        index of the current value (starting with 0 for the first
+ *        value, 1 for the second, and so on).
+ */
+public function each(callback:Function, index:Boolean):Void {
+    // ...
+}</programlisting>
+	</example>
+      </section>
+
+      <section id="return_tag">
+	<title>Method Return Values</title>
+
+	<para><remark>TODO</remark></para>
+	<example>
+	  <title>Method Return Values</title>
+	  <programlisting>/**
+ * Get the value corresponding to the given key
+ *
+ * <emphasis role="strong">@return</emphasis> either the value for the given key, or null if 
+ *         there is no such mapping.
+ */
+public function get(key:String):String {
+    // ...
+}</programlisting>
+	</example>
+      </section>
+
+      <section id="see_tag">
+	<title>Links to Related Information</title>
+
+	<para><remark>TODO</remark></para>
+	<example>
+	  <title>Class Related information</title>
+	  <programlisting>/**
+ * See-also tags will be copied to the output HTML, but are not actually
+ * turned into links to other classes/methods as they should be.
+ *
+ * <emphasis role="strong">@see "some stuff"</emphasis>
+ */
+class somepackage.ThisClass {
+    // ...
+}</programlisting>
+	</example>
+      </section>
+
+      <section id="throws_tag">
+	<title>Exceptions Thrown by a Method</title>
+
+	<para><remark>TODO</remark></para>
+	<example>
+	  <title>Class Related information</title>
+	  <programlisting>/**
+ * Causes this message to be sent
+ *
+ * <emphasis role="strong">@throws MessagingException if there is a failure in
+ *         the underlying communications medium</emphasis>
+ */
+public function send():Void {
+    // ...
+}</programlisting>
+	</example>
+      </section>
+    </section>
+  </section>
+</article>
CVSspam 0.2.11
From dave at badgers-in-foil.co.uk Sat Mar 5 20:53:46 2005 From: dave at badgers-in-foil.co.uk (David Holroyd) Date: Sat, 05 Mar 2005 20:53:46 +0000 Subject: [as2api-dev] [CVS trunk] Targets to build documentation Message-ID:
Commit in trunk/as2api on MAIN
Makefile+23-365 -> 66
Targets to build documentation

trunk/as2api
Makefile 65 -> 66
--- trunk/as2api/Makefile	2005-03-05 20:41:47 UTC (rev 65)
+++ trunk/as2api/Makefile	2005-03-05 20:53:45 UTC (rev 66)
@@ -1,6 +1,11 @@
 
+xsltproc=xsltproc
+docbook_stylesheet=/usr/share/sgml/docbook/stylesheet/xsl/nwalsh/fo/docbook.xsl
+java_home=~/opt/j2sdk1.4.2_05
+fop=~/incoming/fop-0.20.5/fop.sh
+
 sources = documenter.rb doc_comment.rb xmlwriter.rb html_output.rb parse/lexer.rb parse/parser.rb parse/as_io.rb api_loader.rb api_model.rb
-dist_files = ${sources} style.css
+dist_files = ${sources} style.css as2api-documentation.pdf
 
 version = 0.2
 
@@ -11,13 +16,13 @@
 
 dist: tgz zip
 
-tgz:
+tgz: docs
 	mkdir -p ${dist_dir}
 	cp --parents ${dist_files} ${dist_dir}
 	tar czvf ${tgz_name} ${dist_dir}
 	rm -r ${dist_dir}
 
-zip:
+zip: docs
 	mkdir -p ${w32_dist_dir}
 	cp as2api_win32.exe style.css ${w32_dist_dir}
 	zip -r ${zip_name} ${w32_dist_dir}
@@ -28,3 +33,18 @@
 
 clean:
 	rm -rf ${tgz_name} ${zip_name} ${w32_dist_dir} ${dist_dir}
+
+
+docs: as2api-documentation.pdf
+
+
+as2api-documentation.fo: as2api-documentation.xml
+	${xsltproc} --stringparam shade.verbatim 1 \
+	            --stringparam fop.extensions 1 \
+		    ${docbook_stylesheet} \
+		    as2api-documentation.xml \
+				> as2api-documentation.fo
+
+as2api-documentation.pdf: as2api-documentation.fo
+	JAVA_HOME=${java_home} \
+	${fop} as2api-documentation.fo -pdf as2api-documentation.pdf
CVSspam 0.2.11
From dave at badgers-in-foil.co.uk Sun Mar 6 14:24:20 2005 From: dave at badgers-in-foil.co.uk (David Holroyd) Date: Sun, 06 Mar 2005 14:24:20 +0000 Subject: [as2api-dev] [CVS trunk] Ignore leading whitespace at start of param description Message-ID:
Commit in trunk/as2api on MAIN
doc_comment.rb+1-166 -> 67
Ignore leading whitespace at start of param description

trunk/as2api
doc_comment.rb 66 -> 67
--- trunk/as2api/doc_comment.rb	2005-03-05 20:53:45 UTC (rev 66)
+++ trunk/as2api/doc_comment.rb	2005-03-06 14:24:11 UTC (rev 67)
@@ -46,7 +46,7 @@
       text = strip_stars(text)
       unless text =~ /^\s*$/
         case text
-          when /^\s*@param\s+([^\s]+)/
+          when /^\s*@param\s+([^\s]+)\s+/
 	    state = :PARAM
 	    desc_param = $'
 	    add_param($1, desc_param)
CVSspam 0.2.11
From dave at badgers-in-foil.co.uk Sun Mar 6 14:25:37 2005 From: dave at badgers-in-foil.co.uk (David Holroyd) Date: Sun, 06 Mar 2005 14:25:37 +0000 Subject: [as2api-dev] [CVS trunk] Oops; update unit test to track DocComment API change Message-ID:
Commit in trunk/as2api on MAIN
tc_doc_comment.rb+8-967 -> 68
Oops; update unit test to track DocComment API change

trunk/as2api
tc_doc_comment.rb 67 -> 68
--- trunk/as2api/tc_doc_comment.rb	2005-03-06 14:24:11 UTC (rev 67)
+++ trunk/as2api/tc_doc_comment.rb	2005-03-06 14:25:34 UTC (rev 68)
@@ -1,39 +1,38 @@
 require 'test/unit'
 require 'doc_comment'
+require 'api_loader'
 
-
 class TC_DocComment < Test::Unit::TestCase
   def test_strip_stars()
-    doc = DocComment.new
+    doc = DocComment.new(LocalTypeResolver.new)
     initial = "foo = a * b\nbar!"
     with_stars = "\t **#{initial}"
     assert_equal(initial, doc.strip_stars(with_stars))
   end
 
   def test_description()
-    doc = DocComment.new
+    doc = DocComment.new(LocalTypeResolver.new)
     text = "foo bar\n *blat\n * @param foo bar\n blat ping pong\n *"
     doc.parse(text)
     assert_equal("foo bar\nblat", doc.description)
   end
 
   def test_params()
-    doc = DocComment.new
+    doc = DocComment.new(LocalTypeResolver.new)
     text = "*\n * @param foo bar\n blat ping pong\n *"
     doc.parse(text)
-    assert_equal("bar", doc.param("foo"))
-    assert_equal("ping pong", doc.param("blat"))
+    assert_equal("bar\nblat ping pong", doc.param("foo"))
   end
 
   def test_return()
-    doc = DocComment.new
+    doc = DocComment.new(LocalTypeResolver.new)
     text = "*\n * @return foo bar\n blat\n *"
     doc.parse(text)
     assert_equal("foo bar\nblat", doc.desc_return)
   end
 
   def test_see()
-    doc = DocComment.new
+    doc = DocComment.new(LocalTypeResolver.new)
     text = "*\n * @see foo bar\n blat\n *"
     doc.parse(text)
     expected = "foo bar\nblat"
@@ -41,7 +40,7 @@
   end
 
   def test_throws()
-    doc = DocComment.new
+    doc = DocComment.new(LocalTypeResolver.new)
     text = "*\n * @throws foo.Bbar blat\nping\n *"
     doc.parse(text)
     assert("blat\nping", doc.describe_exception("foo.Bar"))
CVSspam 0.2.11
From dave at badgers-in-foil.co.uk Tue Mar 8 23:42:49 2005 From: dave at badgers-in-foil.co.uk (David Holroyd) Date: Tue, 08 Mar 2005 23:42:49 +0000 Subject: [as2api-dev] [CVS trunk] An HTML-specific abstraction, atop the previous, generic XML API Message-ID:
Commit in trunk/as2api on MAIN
html_output.rb+189-18868 -> 69
xhtmlwriter.rb+131added 69
+320-188
1 added + 1 modified, total 2 files
An HTML-specific abstraction, atop the previous, generic XML API

trunk/as2api
html_output.rb 68 -> 69
--- trunk/as2api/html_output.rb	2005-03-06 14:25:34 UTC (rev 68)
+++ trunk/as2api/html_output.rb	2005-03-08 23:42:46 UTC (rev 69)
@@ -1,5 +1,6 @@
 
 require 'xmlwriter'
+require 'xhtmlwriter'
 require 'doc_comment'
 
 def link_type_proxy(out, type_proxy, qualified=false)
@@ -8,12 +9,12 @@
   else
     if type_proxy.resolved?
       if type_proxy.resolved_type.instance_of?(ASInterface)
-        out.simple_element("span", type_proxy.local_name, {"class"=>"interface_name"})
+        out.element_span(type_proxy.local_name, {"class"=>"interface_name"})
       else
-        out.simple_element("span", type_proxy.local_name, {"class"=>"class_name"})
+        out.element_span(type_proxy.local_name, {"class"=>"class_name"})
       end
     else
-      out.simple_element("span", type_proxy.local_name, {"class"=>"unresolved_type_name"})
+      out.element_span(type_proxy.local_name, {"class"=>"unresolved_type_name"})
     end
   end
 end
@@ -32,18 +33,18 @@
     attr_title = "Class #{type.qualified_name}"
   end
   if qualified
-    out.simple_element("a", type.qualified_name, {"href"=>href,
-                                                  "class"=>attr_class,
-                                                  "title"=>attr_title})
+    out.element_a(type.qualified_name, {"href"=>href,
+                                        "class"=>attr_class,
+                                        "title"=>attr_title})
   else
-    out.simple_element("a", type.unqualified_name, {"href"=>href,
-                                                    "class"=>attr_class,
-                                                    "title"=>attr_title})
+    out.element_a(type.unqualified_name, {"href"=>href,
+                                          "class"=>attr_class,
+                                          "title"=>attr_title})
   end
 end
 
 def method_synopsis(out, method)
-  out.element("code", {"class", "method_synopsis"}) do
+  out.element_code("class"=>"method_synopsis") do
     if method.access.is_static
       out.pcdata("static ")
     end
@@ -51,7 +52,7 @@
       out.pcdata("#{method.access.visibility.body} ")
     end
     out.pcdata("function ")
-    out.element("strong", {"class"=>"method_name"}) do
+    out.element_strong("class"=>"method_name") do
       out.pcdata(method.name)
     end
     out.pcdata("(")
@@ -72,7 +73,7 @@
 end
 
 def field_synopsis(out, field)
-  out.element("code", {"class", "field_synopsis"}) do
+  out.element_code("class"=>"field_synopsis") do
     if field.instance_of?(ASImplicitField)
       implicit_field_synopsis(out, field)
     else
@@ -88,7 +89,7 @@
   unless field.access.visibility.nil?
     out.pcdata("#{field.access.visibility.body} ")
   end
-  out.element("strong", {"class"=>"field_name"}) do
+  out.element_strong("class"=>"field_name") do
     out.pcdata(field.name)
   end
   if field.field_type
@@ -104,7 +105,7 @@
   unless field.access.visibility.nil?
     out.pcdata("#{field.access.visibility.body} ")
   end
-  out.element("strong", {"class"=>"field_name"}) do
+  out.element_strong("class"=>"field_name") do
     out.pcdata(field.name)
   end
   field_type = field.field_type
@@ -114,7 +115,7 @@
   end
   unless field.readwrite?
     out.pcdata(" ")
-    out.element("em", {"class"=>"read_write_only"}) do
+    out.element_em("class"=>"read_write_only") do
       if field.read?
 	out.pcdata("[Read Only]")
       else
@@ -126,42 +127,42 @@
 
 
 def class_navigation(out)
-  out.element("div", {"class", "main_nav"}) do
-    out.simple_element("a", "Overview", {"href"=>base_path("overview-summary.html")})
-    out.simple_element("a", "Package", {"href"=>"package-summary.html"})
-    out.simple_element("span", "Class", {"class"=>"nav_current"})
-    out.simple_element("a", "Index", {"href"=>base_path("index-files/index.html")})
+  out.element_div("class"=>"main_nav") do
+    out.element_a("Overview", {"href"=>base_path("overview-summary.html")})
+    out.element_a("Package", {"href"=>"package-summary.html"})
+    out.element_span("Class", {"class"=>"nav_current"})
+    out.element_a("Index", {"href"=>base_path("index-files/index.html")})
   end
 end
 
 def document_method(out, type, method, alt_row=false)
   css_class = "method_details"
   css_class << " alt_row" if alt_row
-  out.element("div", {"class"=>css_class}) do
-    out.empty_tag("a", {"name"=>"method_#{method.name}"})
-    out.simple_element("h3", method.name)
+  out.element_div("class"=>css_class) do
+    out.element_a("name"=>"method_#{method.name}")
+    out.element_h3(method.name)
     method_synopsis(out, method)
     if method.comment
-      out.element("blockquote") do
+      out.element_blockquote do
 	docs = DocComment.new(type.type_resolver)
 	docs.parse(method.comment.body)
         out.pcdata(docs.description)
-        out.element("dl", {"class"=>"method_additional_info"}) do
+        out.element_dl("class"=>"method_additional_info") do
 	  # TODO: assumes that params named in docs match formal arguments
 	  #       should really filter out those that don't match before this
 	  #       test
 	  if docs.parameters?
-	    out.simple_element("dt", "Parameters")
-	    out.element("dd") do
-	      out.element("table", {"class"=>"arguments", "summary"=>""}) do
+	    out.element_dt("Parameters")
+	    out.element_dd do
+	      out.element_table("class"=>"arguments", "summary"=>"") do
 		method.arguments.each do |arg|
 		  desc = docs.param(arg.name)
 		  if desc
-		    out.element("tr") do
-		      out.element("td") do
-			out.simple_element("code", arg.name)
+		    out.element_tr do
+		      out.element_td do
+			out.element_code(arg.name)
 		      end
-		      out.simple_element("td", desc)
+		      out.element_td(desc)
 		    end
 		  end
 		end
@@ -169,29 +170,29 @@
 	    end
 	  end
 	  unless docs.desc_return.nil?
-	    out.simple_element("dt", "Return")
-	    out.element("dd") do
+	    out.element_dt("Return")
+	    out.element_dd do
 	      out.pcdata(docs.desc_return)
 	    end
 	  end
 	  if docs.exceptions?
-            out.simple_element("dt", "throws")
-            out.element("dd") do
-	      out.element("table", {"class"=>"exceptions", "summary"=>""}) do
+            out.element_dt("throws")
+            out.element_dd do
+	      out.element_table("class"=>"exceptions", "summary"=>"") do
 	        docs.each_exception do |type, desc|
-		  out.element("tr") do
-		    out.element("td") do
+		  out.element_tr do
+		    out.element_td do
 		      link_type_proxy(out, type)
 		    end
-		    out.simple_element("td", desc)
+		    out.element_td(desc)
 		  end
 	        end
 	      end
 	    end
 	  end
 	  if docs.seealso?
-	    out.simple_element("dt", "See Also")
-	    out.element("dd") do
+	    out.element_dt("See Also")
+	    out.element_dd do
 	      list_see_also(out, docs)
 	    end
 	  end
@@ -202,19 +203,19 @@
 end
 
 def document_field(out, type, field)
-  out.empty_tag("a", {"name"=>"field_#{field.name}"})
-  out.simple_element("h3", field.name)
-  out.element("div", {"class"=>"field_details"}) do
+  out.element_a("name"=>"field_#{field.name}")
+  out.element_h3(field.name)
+  out.element_div("class"=>"field_details") do
     field_synopsis(out, field)
     if field.comment
-      out.element("blockquote") do
+      out.element_blockquote do
 	docs = DocComment.new(type.type_resolver)
 	docs.parse(field.comment.body)
         out.pcdata(docs.description)
-        out.element("dl", {"class"=>"field_additional_info"}) do
+        out.element_dl("class"=>"field_additional_info") do
 	  if docs.seealso?
-	    out.simple_element("dt", "See Also")
-	    out.element("dd") do
+	    out.element_dt("See Also")
+	    out.element_dd do
 	      list_see_also(out, docs)
 	    end
 	  end
@@ -263,16 +264,16 @@
 
 def html_file(name, title, encoding=nil)
   write_file("#{name}.html") do |io|
-    out = XMLWriter.new(io)
+    out = XHTMLWriter.new(XMLWriter.new(io))
     encoding = "iso-8859-1" if encoding.nil?
     out.pi("xml version=\"1.0\" encoding=\"#{encoding}\"")
-    out.element("html") do
-      out.element("head") do
-        out.simple_element("title", title)
-        out.empty_tag("link", {"rel"=>"stylesheet",
-	                       "type"=>"text/css",
-			       "href"=>base_path("style.css")})
-        out.empty_tag("meta", {"name"=>"generator", "content"=>"http://www.badgers-in-foil.co.uk/projects/as2api/"})
+    out.element_html do
+      out.element_head do
+        out.element_title(title)
+        out.element_link("rel"=>"stylesheet",
+	                 "type"=>"text/css",
+	                 "href"=>base_path("style.css"))
+        out.element_meta("name"=>"generator", "content"=>"http://www.badgers-in-foil.co.uk/projects/as2api/")
 	yield out
       end
     end
@@ -281,7 +282,7 @@
 
 def html_body(name, title, encoding=nil)
   html_file(name, title, encoding) do |out|
-    out.element("body") do
+    out.element_body do
       yield out
       footer(out)
     end
@@ -289,8 +290,8 @@
 end
 
 def footer(out)
-  out.element("div", {"class"=>"footer"}) do
-    out.simple_element("a", "as2api", {"href"=>"http://www.badgers-in-foil.co.uk/projects/as2api/", "title"=>"ActionScript 2 API Documentation Generator"})
+  out.element_div("class"=>"footer") do
+    out.element_a("as2api", {"href"=>"http://www.badgers-in-foil.co.uk/projects/as2api/", "title"=>"ActionScript 2 API Documentation Generator"})
   end
 end
 
@@ -298,7 +299,7 @@
   # TODO: ASCII art is an accessability problem.  Replace with images that have
   #       alt-text, or use CSS to generate content, e.g.
   #          <span class="inherit_relation" title="inherited by"></span>
-  out.element("pre", {"class"=>"type_hierachy"}) do
+  out.element_pre("class"=>"type_hierachy") do
     count = 0
     unless type.extends.nil?
       count = type_hierachy_recursive(out, type.extends)
@@ -307,7 +308,7 @@
       out.pcdata("   " * count)
       out.pcdata("+--")
     end
-    out.simple_element("strong", type.qualified_name)
+    out.element_strong(type.qualified_name)
   end
 end
 
@@ -332,17 +333,17 @@
 end
 
 def field_index_list(out, type)
-  out.element("div", {"class"=>"field_index"}) do
-    out.simple_element("h2", "Field Index")
+  out.element_div("class"=>"field_index") do
+    out.element_h2("Field Index")
     list_fields(out, type)
-    out.element("dl") do
+    out.element_dl do
       type.each_ancestor do |type|
 	if type.fields?
-	  out.element("dt") do
+	  out.element_dt do
 	    out.pcdata("Inherited from ")
 	    link_type(out, type)
 	  end
-	  out.element("dd") do
+	  out.element_dd do
 	    list_fields(out, type, link_for_type(type))
 	  end
 	end
@@ -355,8 +356,8 @@
   fields = type.fields.sort
   fields.each_with_index do |field, index|
     out.pcdata(", ") if index > 0
-    out.element("code") do
-      out.element("a", {"href"=>"#{href_prefix}#field_#{field.name}"}) do
+    out.element_code do
+      out.element_a("href"=>"#{href_prefix}#field_#{field.name}") do
 	out.pcdata(field.name)
       end
     end
@@ -364,8 +365,8 @@
 end
 
 def field_detail_list(out, type)
-  out.element("div", {"class"=>"field_detail_list"}) do
-    out.simple_element("h2", "Field Detail")
+  out.element_div("class"=>"field_detail_list") do
+    out.element_h2("Field Detail")
     type.each_field do |field|
       document_field(out, type, field)
     end
@@ -374,13 +375,13 @@
 
 
 def method_index_list(out, type)
-  out.element("div", {"class"=>"method_index"}) do
-    out.simple_element("h2", "Method Index")
+  out.element_div("class"=>"method_index") do
+    out.element_h2("Method Index")
     if type.constructor?
-      out.element("p") do
-        out.element("code") do
+      out.element_p do
+        out.element_code do
           out.pcdata("new ")
-	    out.element("a", {"href"=>"#method_#{type.constructor.name}"}) do
+	    out.element_a("href"=>"#method_#{type.constructor.name}") do
 	      out.pcdata(type.constructor.name+"()")
 	    end
         end
@@ -388,14 +389,14 @@
     end
     known_method_names = []
     list_methods(out, type, known_method_names)
-    out.element("dl") do
+    out.element_dl do
       type.each_ancestor do |type|
 	if type.methods?
-	  out.element("dt") do
+	  out.element_dt do
 	    out.pcdata("Inherited from ")
 	    link_type(out, type)
 	  end
-	  out.element("dd") do
+	  out.element_dd do
 	    list_methods(out, type, known_method_names, link_for_type(type))
 	  end
 	end
@@ -412,15 +413,15 @@
   methods.each_with_index do |method, index|
     known_method_names << method.name
     out.pcdata(", ") if index > 0
-    out.element("a", {"href"=>"#{href_prefix}#method_#{method.name}"}) do
+    out.element_a("href"=>"#{href_prefix}#method_#{method.name}") do
       out.pcdata(method.name+"()")
     end
   end
 end
 
 def method_detail_list(out, type)
-  out.element("div", {"class"=>"method_detail_list"}) do
-    out.simple_element("h2", "Method Detail")
+  out.element_div("class"=>"method_detail_list") do
+    out.element_h2("Method Detail")
     count = 0
     type.each_method do |method|
       document_method(out, type, method, count%2==0)
@@ -430,8 +431,8 @@
 end
 
 def constructor_detail(out, type)
-  out.element("div", {"class"=>"constructor_detail_list"}) do
-    out.simple_element("h2", "Constructor Detail")
+  out.element_div("class"=>"constructor_detail_list") do
+    out.element_h2("Constructor Detail")
     document_method(out, type, type.constructor)
   end
 end
@@ -443,42 +444,42 @@
     "iso-8859-1"
   end
   html_body(type.unqualified_name, type.qualified_name, encoding) do |out|
-    out.simple_element("a", "", {"href"=>"#skip_nav", "title"=>"Skip navigation"})  # accessability
+    out.element_a("", {"href"=>"#skip_nav", "title"=>"Skip navigation"})  # accessability
     class_navigation(out)
-    out.simple_element("a", "", {"name"=>"skip_nav"})
+    out.element_a("", {"name"=>"skip_nav"})
     if type.instance_of?(ASClass)
-      out.simple_element("h1", "Class "+type.qualified_name)
+      out.element_h1("Class "+type.qualified_name)
     elsif type.instance_of?(ASInterface)
-      out.simple_element("h1", "Interface "+type.qualified_name)
+      out.element_h1("Interface "+type.qualified_name)
     end
 
     type_hierachy(out, type)
 
     if type.implements_interfaces?
-      out.element("div", {"class"=>"interfaces"}) do
-	out.simple_element("h2", "Implemented Interfaces")
+      out.element_div("class"=>"interfaces") do
+	out.element_h2("Implemented Interfaces")
 	type.each_interface do |interface|
 	  # TODO: need to resolve interface name, make links
-	  out.element("code") do
+	  out.element_code do
 	    link_type_proxy(out, interface)
 	  end
 	  out.pcdata(" ")
 	end
       end
     end
-    out.element("div", {"class"=>"type_description"}) do
+    out.element_div("class"=>"type_description") do
       if type.comment
 	docs = DocComment.new(type.type_resolver)
 	docs.parse(type.comment.body)
 
-	out.simple_element("h2", "Description")
-	out.element("p") do
+	out.element_h2("Description")
+	out.element_p do
 	  out.pcdata(docs.description)
 	end
-	out.element("dl", {"class"=>"type_details"}) do
+	out.element_dl("class"=>"type_details") do
 	  if docs.seealso?
-	    out.simple_element("dt", "See Also")
-	    out.element("dd") do
+	    out.element_dt("See Also")
+	    out.element_dd do
 	      list_see_also(out, docs)
 	    end
 	  end
@@ -499,7 +500,7 @@
 def list_see_also(out, docs)
   docs.each_see_also do |see|
     out.comment(" parsing for see-also not done yet ")
-    out.simple_element("p", see)
+    out.element_p(see)
   end
 end
 
@@ -518,11 +519,11 @@
 end
 
 def package_navigation(out)
-  out.element("div", {"class", "main_nav"}) do
-    out.simple_element("a", "Overview", {"href"=>base_path("overview-summary.html")})
-    out.simple_element("span", "Package", {"class"=>"nav_current"})
-    out.simple_element("span", "Class")
-    out.simple_element("a", "Index", {"href"=>base_path("index-files/index.html")})
+  out.element_div("class"=>"main_nav") do
+    out.element_a("Overview", {"href"=>base_path("overview-summary.html")})
+    out.element_span("Package", {"class"=>"nav_current"})
+    out.element_span("Class")
+    out.element_a("Index", {"href"=>base_path("index-files/index.html")})
   end
 end
 
@@ -535,24 +536,24 @@
 
 def package_index(package)
   html_body("package-summary", "Package #{package_display_name_for(package)} API Documentation") do |out|
-    out.simple_element("a", "", {"href"=>"#skip_nav", "title"=>"Skip navigation"})  # accessability
+    out.element_a("", {"href"=>"#skip_nav", "title"=>"Skip navigation"})  # accessability
     package_navigation(out)
-    out.simple_element("a", "", {"name"=>"skip_nav"})
-    out.simple_element("h1", "Package "+package_display_name_for(package))
+    out.element_a("", {"name"=>"skip_nav"})
+    out.element_h1("Package "+package_display_name_for(package))
     interfaces = package.interfaces
     unless interfaces.empty?
       interfaces.sort!
-      out.element("table", {"class"=>"summary_list", "summary"=>""}) do
-	out.element("tr") do
-	  out.simple_element("th", "Interface Summary", {"colspan"=>"2"})
+      out.element_table("class"=>"summary_list", "summary"=>"") do
+	out.element_tr do
+	  out.element_th("Interface Summary", {"colspan"=>"2"})
 	end
 	interfaces.each do |type|
-	  out.element("tr") do
+	  out.element_tr do
       
-	    out.element("td") do
-	      out.simple_element("a", type.unqualified_name, {"href"=>type.unqualified_name+".html"})
+	    out.element_td do
+	      out.element_a(type.unqualified_name, {"href"=>type.unqualified_name+".html"})
 	    end
-	    out.element("td") do
+	    out.element_td do
 	      # TODO: package description
 	    end
 	  end
@@ -562,17 +563,17 @@
     classes = package.classes
     unless classes.empty?
       classes.sort!
-      out.element("table", {"class"=>"summary_list", "summary"=>""}) do
-	out.element("tr") do
-	  out.simple_element("th", "Class Summary", {"colspan"=>"2"})
+      out.element_table("class"=>"summary_list", "summary"=>"") do
+	out.element_tr do
+	  out.element_th("Class Summary", {"colspan"=>"2"})
 	end
 	classes.each do |type|
-	  out.element("tr") do
+	  out.element_tr do
       
-	    out.element("td") do
-	      out.simple_element("a", type.unqualified_name, {"href"=>type.unqualified_name+".html"})
+	    out.element_td do
+	      out.element_a(type.unqualified_name, {"href"=>type.unqualified_name+".html"})
 	    end
-	    out.element("td") do
+	    out.element_td do
 	      # TODO: package description
 	    end
 	  end
@@ -585,23 +586,23 @@
 
 def package_frame(package)
   html_file("package-frame", "Package #{package_display_name_for(package)} API Naviation") do |out|
-    out.element("body") do
+    out.element_body do
       # TODO: don't use <strong>
-      out.element("strong") do
-	out.simple_element("a", package_display_name_for(package), {"href"=>"package-summary.html", "target"=>"type_frame"})
+      out.element_strong do
+	out.element_a(package_display_name_for(package), {"href"=>"package-summary.html", "target"=>"type_frame"})
       end
       interfaces = package.interfaces
       unless interfaces.empty?
 	interfaces.sort!
-	out.element("table", {"class"=>"navigation_list"}) do
-	  out.element("tr") do
-	    out.simple_element("th", "Interfaces")
+	out.element_table("class"=>"navigation_list") do
+	  out.element_tr do
+	    out.element_th("Interfaces")
 	  end
 	  interfaces.each do |type|
-	    out.element("tr") do
+	    out.element_tr do
 	
-	      out.element("td") do
-		out.simple_element("a", type.unqualified_name, {"href"=>type.unqualified_name+".html", "target"=>"type_frame", "title"=>type.qualified_name})
+	      out.element_td do
+		out.element_a(type.unqualified_name, {"href"=>type.unqualified_name+".html", "target"=>"type_frame", "title"=>type.qualified_name})
 	      end
 	    end
 	  end
@@ -610,15 +611,15 @@
       classes = package.classes
       unless classes.empty?
 	classes.sort!
-	out.element("table", {"class"=>"navigation_list"}) do
-	  out.element("tr") do
-	    out.simple_element("th", "Classes")
+	out.element_table("class"=>"navigation_list") do
+	  out.element_tr do
+	    out.element_th("Classes")
 	  end
 	  classes.each do |type|
-	    out.element("tr") do
+	    out.element_tr do
 	
-	      out.element("td") do
-		out.simple_element("a", type.unqualified_name, {"href"=>type.unqualified_name+".html", "target"=>"type_frame", "title"=>type.qualified_name})
+	      out.element_td do
+		out.element_a(type.unqualified_name, {"href"=>type.unqualified_name+".html", "target"=>"type_frame", "title"=>type.qualified_name})
 	      end
 	    end
 	  end
@@ -629,33 +630,33 @@
 end
 
 def overview_navigation(out)
-  out.element("div", {"class", "main_nav"}) do
-    out.simple_element("span", "Overview", {"class"=>"nav_current"})
-    out.simple_element("span", "Package")
-    out.simple_element("span", "Class")
-    out.simple_element("a", "Index", {"href"=>"index-files/index.html"})
+  out.element_div("class"=>"main_nav") do
+    out.element_span("Overview", {"class"=>"nav_current"})
+    out.element_span("Package")
+    out.element_span("Class")
+    out.element_a("Index", {"href"=>"index-files/index.html"})
   end
 end
 
 def overview(type_agregator)
   html_body("overview-summary", "API Overview") do |out|
-    out.simple_element("a", "", {"href"=>"#skip_nav", "title"=>"Skip navigation"})  # accessability
+    out.element_a("", {"href"=>"#skip_nav", "title"=>"Skip navigation"})  # accessability
     overview_navigation(out)
-    out.simple_element("a", "", {"name"=>"skip_nav"})
-    out.simple_element("h1", "API Overview")
-    out.element("table", {"class"=>"summary_list", "summary"=>""}) do
-      out.element("tr") do
-	out.simple_element("th", "Packages", {"colspan"=>"2"})
+    out.element_a("", {"name"=>"skip_nav"})
+    out.element_h1("API Overview")
+    out.element_table("class"=>"summary_list", "summary"=>"") do
+      out.element_tr do
+	out.element_th("Packages", {"colspan"=>"2"})
       end
       packages = type_agregator.packages.sort
       packages.each do |package|
-	out.element("tr") do
+	out.element_tr do
     
-	  out.element("td") do
+	  out.element_td do
 	    name = package_display_name_for(package)
-	    out.simple_element("a", name, {"href"=>package_link_for(package, "package-summary.html")})
+	    out.element_a(name, {"href"=>package_link_for(package, "package-summary.html")})
 	  end
-	  out.element("td") do
+	  out.element_td do
 	    # TODO: package description
 	  end
 	end
@@ -667,25 +668,25 @@
 
 def overview_frame(type_agregator)
   html_file("overview-frame", "API Overview") do |out|
-    out.element("body") do
-      out.element("table", {"class"=>"navigation_list"}) do
-	out.element("tr") do
-	  out.simple_element("th", "Packages")
+    out.element_body do
+      out.element_table("class"=>"navigation_list") do
+	out.element_tr do
+	  out.element_th("Packages")
 	end
-	  out.element("tr") do
+	  out.element_tr do
       
-	    out.element("td") do
-	      out.simple_element("a", "(All Types)", {"href"=>"all-types-frame.html", "target"=>"current_package_frame"})
+	    out.element_td do
+	      out.element_a("(All Types)", {"href"=>"all-types-frame.html", "target"=>"current_package_frame"})
 	    end
 	  end
 	packages = type_agregator.packages.sort
 	packages.each do |package|
-	  out.element("tr") do
+	  out.element_tr do
       
-	    out.element("td") do
+	    out.element_td do
 	      name = package_display_name_for(package)
 	      
-	      out.simple_element("a", name, {"href"=>package_link_for(package, "package-frame.html"), "target"=>"current_package_frame", "title"=>name})
+	      out.element_a(name, {"href"=>package_link_for(package, "package-frame.html"), "target"=>"current_package_frame", "title"=>name})
 	    end
 	  end
 	end
@@ -709,10 +710,10 @@
 
 def all_types_frame(type_agregator)
   html_file("all-types-frame", "as2api") do |out|
-    out.element("body") do
-      out.element("table", {"class"=>"navigation_list"}) do
-        out.element("tr") do
-	  out.simple_element("th", "All Types")
+    out.element_body do
+      out.element_table("class"=>"navigation_list") do
+        out.element_tr do
+	  out.element_th("All Types")
 	end
 	types = type_agregator.types.sort do |a,b|
 	  cmp = a.unqualified_name.downcase <=> b.unqualified_name.downcase
@@ -725,9 +726,9 @@
 	types.each do |type|
 	  if type.document?
 	    href = type.qualified_name.gsub(/\./, "/") + ".html"
-            out.element("tr") do
-              out.element("td") do
-	        out.simple_element("a", type.unqualified_name, {"href"=>href, "title"=>type.qualified_name, "target"=>"type_frame"})
+            out.element_tr do
+              out.element_td do
+	        out.element_a(type.unqualified_name, {"href"=>href, "title"=>type.qualified_name, "target"=>"type_frame"})
 	      end
 	    end
 	  end
@@ -739,21 +740,21 @@
 
 def frameset
   html_file("frameset", "as2api") do |out|
-    out.element("frameset", {"cols"=>"20%,80%"}) do
-      out.element("frameset", {"rows"=>"30%,70%"}) do
-	out.empty_tag("frame", {"src"=>"overview-frame.html",
-	                        "name"=>"all_packages_frame",
-				"title"=>"All Packages"})
-	out.empty_tag("frame", {"src"=>"all-types-frame.html",
-	                        "name"=>"current_package_frame",
-                                "title"=>"All types"})
+    out.element_frameset("cols"=>"20%,80%") do
+      out.element_frameset("rows"=>"30%,70%") do
+	out.element_frame("src"=>"overview-frame.html",
+	                  "name"=>"all_packages_frame",
+	                  "title"=>"All Packages")
+	out.element_frame("src"=>"all-types-frame.html",
+	                  "name"=>"current_package_frame",
+                          "title"=>"All types")
       end
-      out.empty_tag("frame", {"src"=>"overview-summary.html",
-                              "name"=>"type_frame",
-                              "title"=>"Package and type descriptions"})
+      out.element_frame("src"=>"overview-summary.html",
+                        "name"=>"type_frame",
+                        "title"=>"Package and type descriptions")
     end
-    out.element("noframes") do
-      out.simple_element("a", "Non-frameset overview page", {"href"=>"overview-summary.html"})
+    out.element_noframes do
+      out.element_a("Non-frameset overview page", {"href"=>"overview-summary.html"})
     end
   end
 end
@@ -796,7 +797,7 @@
 class MethodIndexTerm < MemberIndexTerm
   def link(out)
     href_prefix = link_for_type(@astype)
-    out.element("a", {"href"=>"#{href_prefix}#method_#{@asmember.name}"}) do
+    out.element_a("href"=>"#{href_prefix}#method_#{@asmember.name}") do
       out.pcdata(@asmember.name + "()")
     end
     out.pcdata(" method in ")
@@ -807,7 +808,7 @@
 class FieldIndexTerm < MemberIndexTerm
   def link(out)
     href_prefix = link_for_type(@astype)
-    out.element("a", {"href"=>"#{href_prefix}#field_#{@asmember.name}"}) do
+    out.element_a("href"=>"#{href_prefix}#field_#{@asmember.name}") do
       out.pcdata(@asmember.name)
     end
     out.pcdata(" field in ")
@@ -816,11 +817,11 @@
 end
 
 def index_navigation(out)
-  out.element("div", {"class", "main_nav"}) do
-    out.simple_element("a", "Overview", {"href"=>base_path("overview-summary.html")})
-    out.simple_element("span", "Package")
-    out.simple_element("span", "Class")
-    out.simple_element("span", "Index", {"class"=>"nav_current"})
+  out.element_div("class"=>"main_nav") do
+    out.element_a("Overview", {"href"=>base_path("overview-summary.html")})
+    out.element_span("Package")
+    out.element_span("Class")
+    out.element_span("Index", {"class"=>"nav_current"})
   end
 end
 
@@ -847,7 +848,7 @@
     html_file("index", "Alphabetical Index") do |out|
       index_navigation(out)
       index.each do |element|
-	out.element("p") do
+	out.element_p do
 	  element.link(out)
 	end
       end

trunk/as2api
xhtmlwriter.rb added at 69
--- trunk/as2api/xhtmlwriter.rb	2005-03-06 14:25:34 UTC (rev 68)
+++ trunk/as2api/xhtmlwriter.rb	2005-03-08 23:42:46 UTC (rev 69)
@@ -0,0 +1,131 @@
+class XHTMLWriter
+  def initialize(io)
+    @io = io
+  end
+
+  private
+
+  TAGS = [
+    "br",
+    "span",
+    "abbr",
+    "acronym",
+    "cite",
+    "code",
+    "dfn",
+    "em",
+    "kbd",
+    "q",
+    "samp",
+    "strong",
+    "var",
+    "div",
+    "p",
+    "address",
+    "blockquote",
+    "pre",
+    "h1",
+    "h2",
+    "h3",
+    "h4",
+    "h5",
+    "h6",
+    "a",
+    "dl",
+    "dt",
+    "dd",
+    "ol",
+    "ul",
+    "li",
+    "ins",
+    "del",
+    "bdo",
+    "ruby",
+    "rbc",
+    "rtc",
+    "rb",
+    "rt",
+    "rp",
+    "b",
+    "big",
+    "i",
+    "small",
+    "sub",
+    "sup",
+    "tt",
+    "hr",
+    "link",
+    "meta",
+    "base",
+    "script",
+    "noscript",
+    "style",
+    "img",
+    "area",
+    "map",
+    "param",
+    "object",
+    "table",
+    "caption",
+    "thead",
+    "tfoot",
+    "tbody",
+    "colgroup",
+    "col",
+    "tr",
+    "th",
+    "td",
+    "form",
+    "label",
+    "input",
+    "select",
+    "optgroup",
+    "option",
+    "textarea",
+    "fieldset",
+    "legend",
+    "button",
+    "title",
+    "head",
+    "body",
+    "html"
+  ]
+
+  TAGS << "frameset" << "noframes" << "frame"
+
+  TAGS.each do |name|
+    class_eval <<-HERE
+      def element_#{name}(*args)
+	if block_given?
+	  @io.element("#{name}", *args) { yield }
+	else
+	  if args.length == 0
+	    @io.empty_tag("#{name}")
+	  else
+	    if args[0].instance_of?(String)
+	      @io.simple_element("#{name}", *args)
+	    else
+	      @io.empty_tag("#{name}", *args)
+	    end
+	  end
+	end
+      end
+    HERE
+  end
+
+  public
+
+  def pcdata(text)
+    @io.pcdata(text)
+  end
+
+  def pi(text)
+    @io.pi(text)
+  end
+
+  def comment(text)
+    @io.comment(text)
+  end
+end
+
+# vim:sw=2
CVSspam 0.2.11
From dave at badgers-in-foil.co.uk Sat Mar 12 10:36:00 2005 From: dave at badgers-in-foil.co.uk (David Holroyd) Date: Sat, 12 Mar 2005 10:36:00 +0000 Subject: [as2api-dev] [CVS trunk] Don't document private members of a class Message-ID:
Commit in trunk/as2api on MAIN
html_output.rb+11-369 -> 70
Don't document private members of a class

trunk/as2api
html_output.rb 69 -> 70
--- trunk/as2api/html_output.rb	2005-03-08 23:42:46 UTC (rev 69)
+++ trunk/as2api/html_output.rb	2005-03-12 10:35:57 UTC (rev 70)
@@ -352,15 +352,22 @@
   end
 end
 
+def document_member?(member)
+  !member.access.private?
+end
+
 def list_fields(out, type, href_prefix="")
   fields = type.fields.sort
-  fields.each_with_index do |field, index|
+  index = 0
+  fields.each do |field|
+    next unless document_member?(field)
     out.pcdata(", ") if index > 0
     out.element_code do
       out.element_a("href"=>"#{href_prefix}#field_#{field.name}") do
 	out.pcdata(field.name)
       end
     end
+    index += 1
   end
 end
 
@@ -368,7 +375,7 @@
   out.element_div("class"=>"field_detail_list") do
     out.element_h2("Field Detail")
     type.each_field do |field|
-      document_field(out, type, field)
+      document_field(out, type, field) if document_member?(field)
     end
   end
 end
@@ -407,7 +414,7 @@
 
 def list_methods(out, type, known_method_names, href_prefix="")
   methods = type.methods.select do |method|
-    !known_method_names.include?(method.name)
+    !known_method_names.include?(method.name) && document_member?(method)
   end
   methods.sort!
   methods.each_with_index do |method, index|
@@ -424,6 +431,7 @@
     out.element_h2("Method Detail")
     count = 0
     type.each_method do |method|
+      next unless document_member?(method)
       document_method(out, type, method, count%2==0)
       count += 1
     end
CVSspam 0.2.11
From dave at badgers-in-foil.co.uk Sat Mar 12 11:57:55 2005 From: dave at badgers-in-foil.co.uk (David Holroyd) Date: Sat, 12 Mar 2005 11:57:55 +0000 Subject: [as2api-dev] [CVS trunk] Don't document private members of a class In-Reply-To: <72432ef5473dbe492316cf9f21f21d76@dotgeek.org> References: <72432ef5473dbe492316cf9f21f21d76@dotgeek.org> Message-ID: <20050312115754.GC4317@vhost.badgers-in-foil.co.uk> On Sat, Mar 12, 2005 at 11:54:50AM +0100, erixtekila wrote: > >Don't document private members of a class > > > Nice. > Won't there be a switch to choose if one wants to document private > members ? Not for the moment; maybe later, when there's more general support for command-line / gui options. Right now, this will produce the results that most people actually need. dave From dave at badgers-in-foil.co.uk Sat Mar 12 12:37:41 2005 From: dave at badgers-in-foil.co.uk (David Holroyd) Date: Sat, 12 Mar 2005 12:37:41 +0000 Subject: [as2api-dev] [CVS trunk] Don't document private members of a class In-Reply-To: <4d525c0772856639f72903dcd7473dc0@dotgeek.org> References: <4d525c0772856639f72903dcd7473dc0@dotgeek.org> Message-ID: <20050312123741.GD4317@vhost.badgers-in-foil.co.uk> On Sat, Mar 12, 2005 at 12:11:40PM +0100, erixtekila wrote: > Sorry Dave, > > But it seems that it still documents my private members? Well, it worked for me for a couple of simple examples. Could you provide some sample ActionScript that doesn't get the expected results? dave From erixtekila at dotgeek.org Sat Mar 12 12:51:34 2005 From: erixtekila at dotgeek.org (erixtekila) Date: Sat, 12 Mar 2005 13:51:34 +0100 Subject: [as2api-dev] [CVS trunk] Don't document private members of a class In-Reply-To: <20050312123741.GD4317@vhost.badgers-in-foil.co.uk> References: <4d525c0772856639f72903dcd7473dc0@dotgeek.org> <20050312123741.GD4317@vhost.badgers-in-foil.co.uk> Message-ID: >> Sorry Dave, >> >> But it seems that it still documents my private members? > > Well, it worked for me for a couple of simple examples. Could you > provide some sample ActionScript that doesn't get the expected results? Yes of course. You'll find a full fledged example there : http://www.v-i-a.net/download/?Oregano Inside the archive, you'll find a mtasc.sh where the commandline call resides. Just get rid of mtasc and correct the pathes to be complaint with your. HTH. ----------- erixtekila http://blog.v-i-a.net/ From dave at badgers-in-foil.co.uk Sat Mar 12 13:09:19 2005 From: dave at badgers-in-foil.co.uk (David Holroyd) Date: Sat, 12 Mar 2005 13:09:19 +0000 Subject: [as2api-dev] [CVS trunk] Exclude private constructors from documentation Message-ID:
Commit in trunk/as2api on MAIN
html_output.rb+2-270 -> 71
Exclude private constructors from documentation

trunk/as2api
html_output.rb 70 -> 71
--- trunk/as2api/html_output.rb	2005-03-12 10:35:57 UTC (rev 70)
+++ trunk/as2api/html_output.rb	2005-03-12 13:09:16 UTC (rev 71)
@@ -384,7 +384,7 @@
 def method_index_list(out, type)
   out.element_div("class"=>"method_index") do
     out.element_h2("Method Index")
-    if type.constructor?
+    if type.constructor? && document_member?(type.constructor)
       out.element_p do
         out.element_code do
           out.pcdata("new ")
@@ -497,7 +497,7 @@
     
     field_index_list(out, type) if type.fields?
     method_index_list(out, type) if type.methods?
-    constructor_detail(out, type) if type.constructor?
+    constructor_detail(out, type) if type.constructor? && document_member?(type.constructor)
     field_detail_list(out, type) if type.fields?
     method_detail_list(out, type) if type.methods?
 
CVSspam 0.2.11
From erixtekila at dotgeek.org Sat Mar 12 13:56:26 2005 From: erixtekila at dotgeek.org (erixtekila) Date: Sat, 12 Mar 2005 14:56:26 +0100 Subject: [as2api-dev] [CVS trunk] Exclude private constructors from documentation In-Reply-To: References: Message-ID: Dave, private members are still included here. Here the error ouput : ./html_output.rb:356:in `document_member?': undefined method `private?' for # (NoMethodError) from ./html_output.rb:363:in `list_fields' from ./html_output.rb:362:in `each' from ./html_output.rb:362:in `list_fields' from ./html_output.rb:338:in `field_index_list' from ./html_output.rb:336:in `element_div' from (eval):3:in `element' from (eval):3:in `element_div' from ./html_output.rb:336:in `field_index_list' ... 27 levels... from ./html_output.rb:882:in `document_types' from ./html_output.rb:869:in `in_subdir' from ./html_output.rb:869:in `document_types' from documenter.rb:79 > Commit in trunk/as2api on MAIN > > html_output.rb > +2 > -2 > 70 -> 71 > Exclude private constructors from documentation > > trunk/as2api > > html_output.rb 70 -> 71 ----------- erixtekila http://blog.v-i-a.net/ From dave at badgers-in-foil.co.uk Sat Mar 12 20:03:27 2005 From: dave at badgers-in-foil.co.uk (David Holroyd) Date: Sat, 12 Mar 2005 20:03:27 +0000 Subject: [as2api-dev] [CVS trunk] Add test for 'private' access Message-ID:
Commit in trunk/as2api/parse on MAIN
parser.rb+471 -> 72
Add test for 'private' access

trunk/as2api/parse
parser.rb 71 -> 72
--- trunk/as2api/parse/parser.rb	2005-03-12 13:09:16 UTC (rev 71)
+++ trunk/as2api/parse/parser.rb	2005-03-12 20:03:25 UTC (rev 72)
@@ -10,6 +10,10 @@
   end
 
   attr_accessor :visibility, :is_static
+
+  def private?
+    @visibility.to_s == "private"
+  end
 end
 
 class Argument
CVSspam 0.2.11
From dave at badgers-in-foil.co.uk Sat Mar 12 20:16:34 2005 From: dave at badgers-in-foil.co.uk (David Holroyd) Date: Sat, 12 Mar 2005 20:16:34 +0000 Subject: [as2api-dev] [CVS trunk] Exclude private members from the index too Message-ID:
Commit in trunk/as2api on MAIN
html_output.rb+6-272 -> 73
Exclude private members from the index too

trunk/as2api
html_output.rb 72 -> 73
--- trunk/as2api/html_output.rb	2005-03-12 20:03:25 UTC (rev 72)
+++ trunk/as2api/html_output.rb	2005-03-12 20:16:34 UTC (rev 73)
@@ -840,11 +840,15 @@
     if astype.document?
       index << TypeIndexTerm.new(astype)
       astype.each_method do |asmethod|
-	index << MethodIndexTerm.new(astype, asmethod)
+      	if document_member?(asmethod)
+	  index << MethodIndexTerm.new(astype, asmethod)
+	end
       end
       if astype.is_a?(ASClass)
 	astype.each_field do |asfield|
-	  index << FieldIndexTerm.new(astype, asfield)
+      	  if document_member?(asfield)
+	    index << FieldIndexTerm.new(astype, asfield)
+	  end
 	end
       end
     end
CVSspam 0.2.11
From erixtekila at dotgeek.org Sat Mar 12 20:41:29 2005 From: erixtekila at dotgeek.org (erixtekila) Date: Sat, 12 Mar 2005 21:41:29 +0100 Subject: [as2api-dev] Dot files disappeared ? In-Reply-To: References: Message-ID: Hi Dave, Private members are excluded now from the documentation and index. But also the beautiful png diagrams ? I still have the .png inside the folders, but they appear no more in the Package's page. Normal behavior ? regards. ----------- erixtekila http://blog.v-i-a.net/ From dave at badgers-in-foil.co.uk Sun Mar 13 14:05:15 2005 From: dave at badgers-in-foil.co.uk (David Holroyd) Date: Sun, 13 Mar 2005 14:05:15 +0000 Subject: [as2api-dev] [CVS trunk] Provide access to the underlying XMLWriter Message-ID:
Commit in trunk/as2api on MAIN
xhtmlwriter.rb+273 -> 74
Provide access to the underlying XMLWriter

trunk/as2api
xhtmlwriter.rb 73 -> 74
--- trunk/as2api/xhtmlwriter.rb	2005-03-12 20:16:34 UTC (rev 73)
+++ trunk/as2api/xhtmlwriter.rb	2005-03-13 14:05:12 UTC (rev 74)
@@ -126,6 +126,8 @@
   def comment(text)
     @io.comment(text)
   end
+
+  def xml; @io end
 end
 
 # vim:sw=2
CVSspam 0.2.11
From dave at badgers-in-foil.co.uk Sun Mar 13 14:10:11 2005 From: dave at badgers-in-foil.co.uk (David Holroyd) Date: Sun, 13 Mar 2005 14:10:11 +0000 Subject: [as2api-dev] Dot files disappeared ? In-Reply-To: References: Message-ID: <20050313141010.GA28756@vhost.badgers-in-foil.co.uk> --X1bOJ3K7DJ5YkBrT Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Sat, Mar 12, 2005 at 09:41:29PM +0100, erixtekila wrote: > Private members are excluded now from the documentation and index. > But also the beautiful png diagrams ? > I still have the .png inside the folders, but they appear no more in > the Package's page. Package diagram code isn't committed yet; it's not really in a fit state. I've updated the patch to work with the latest version, as attached. dave -- http://david.holroyd.me.uk/ --X1bOJ3K7DJ5YkBrT Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="package_diagrams-patch.diff" Index: html_output.rb =================================================================== --- html_output.rb (revision 73) +++ html_output.rb (working copy) @@ -2,6 +2,7 @@ require 'xmlwriter' require 'xhtmlwriter' require 'doc_comment' +require 'rexml/document' def link_type_proxy(out, type_proxy, qualified=false) if type_proxy.resolved? && type_proxy.resolved_type.document? @@ -537,6 +538,7 @@ def package_pages(package) in_subdir(package_dir_for(package)) do + package_diagrams(package) package_index(package) package_frame(package) end @@ -588,6 +590,42 @@ end end end + if FileTest.exists?(File.join($path, "package-classes.png")) + out.element_h1("Class Inheritance Diagram") + out.element_div("class"=>"diagram") do + if FileTest.exists?(File.join($path, "package-classes.cmapx")) + map = true + File.open(File.join($path, "package-classes.cmapx")) do |io| + copy_xml(io, out.xml) + end + else + map = false + end + attr = {"src"=>"package-classes.png"} + if map + attr["usemap"] = "class_diagram" + end + out.element_img(attr) + end + end + if FileTest.exists?(File.join($path, "package-interfaces.png")) + out.element_h1("Interface Inheritance Diagram") + out.element_div("class"=>"diagram") do + if FileTest.exists?(File.join($path, "package-interfaces.cmapx")) + map = true + File.open(File.join($path, "package-interfaces.cmapx")) do |io| + copy_xml(io, out.xml) + end + else + map = false + end + attr = {"src"=>"package-interfaces.png"} + if map + attr["usemap"] = "interface_diagram" + end + out.element_img(attr) + end + end package_navigation(out) end end @@ -637,6 +675,93 @@ end end +def package_diagrams(package) + asclasses = package.classes + unless asclasses.empty? + write_file("classes.dot") do |io| + io.puts("strict digraph class_diagram {") + io.puts(" rankdir=LR;") + asclasses.each do |astype| + io.puts(" #{astype.unqualified_name}[") + io.puts(" label=\"#{astype.unqualified_name}\",") + io.puts(" URL=\"#{astype.unqualified_name}.html\",") + io.puts(" tooltip=\"#{astype.qualified_name}\",") + io.puts(" fontname=\"Times-Italic\",") if astype.is_a?(ASInterface) + io.puts(" shape=\"record\"") + io.puts(" ];") + end + asclasses.each do |astype| + parent = astype.extends + if !parent.nil? && parent.resolved? + if parent.resolved_type.package_name == package.name + io.puts(" #{parent.resolved_type.unqualified_name} -> #{astype.unqualified_name};") + end + end + end + io.puts("}") + end + system("dot", "-Tpng", "-o", File.join($path, "package-classes.png"), File.join($path, "classes.dot")) + system("dot", "-Tcmapx", "-o", File.join($path, "package-classes.cmapx"), File.join($path, "classes.dot")) + #File.delete(File.join($path, "types.dot")) + end + + asinterfaces = package.interfaces + unless asinterfaces.empty? + write_file("interfaces.dot") do |io| + io.puts("strict digraph interface_diagram {") + io.puts(" rankdir=LR;") + asinterfaces.each do |astype| + io.puts(" #{astype.unqualified_name}[") + io.puts(" label=\"#{astype.unqualified_name}\",") + io.puts(" URL=\"#{astype.unqualified_name}.html\",") + io.puts(" tooltip=\"#{astype.qualified_name}\",") + io.puts(" fontname=\"Times-Italic\",") if astype.is_a?(ASInterface) + io.puts(" shape=\"record\"") + io.puts(" ];") + end + asinterfaces.each do |astype| + parent = astype.extends + if !parent.nil? && parent.resolved? + if parent.resolved_type.package_name == package.name + io.puts(" #{parent.resolved_type.unqualified_name} -> #{astype.unqualified_name};") + end + end + end + io.puts("}") + end + system("dot", "-Tpng", "-o", File.join($path, "package-interfaces.png"), File.join($path, "interfaces.dot")) + system("dot", "-Tcmapx", "-o", File.join($path, "package-interfaces.cmapx"), File.join($path, "interfaces.dot")) + #File.delete(File.join($path, "types.dot")) + end +end + +class XMLAdapter + def initialize(out) + @out = out + end + + def tag_start(name, attrs) + attr_map = {} + attrs.each do |el| + attr_map[el[0]] = el[1] + end + @out.start_tag(name, attr_map) + end + + def tag_end(name) + @out.end_tag(name) + end + + def text(text) + @out.pcdata(text) + end +end + +def copy_xml(io, out) + listener = XMLAdapter.new(out) + REXML::Document.parse_stream(io, listener) +end + def overview_navigation(out) out.element_div("class"=>"main_nav") do out.element_span("Overview", {"class"=>"nav_current"}) @@ -894,3 +1019,4 @@ index_files(type_agregator) end end + --X1bOJ3K7DJ5YkBrT-- From erixtekila at dotgeek.org Mon Mar 14 00:15:44 2005 From: erixtekila at dotgeek.org (erixtekila) Date: Mon, 14 Mar 2005 01:15:44 +0100 Subject: [as2api-dev] Package level short description Message-ID: <801d3d3be00194be6cd7f442695dde94@dotgeek.org> Hi Dave, In your xml doc, you notice : The first sentence of the class description will also be included in the package-level index of classes and interfaces. It should therefore try to give a brief overview of the class's purpose How do this feature work, actually ? Is it a future feature not implemented now ? Thanks. ----------- erixtekila http://blog.v-i-a.net/ From dave at badgers-in-foil.co.uk Mon Mar 14 10:20:03 2005 From: dave at badgers-in-foil.co.uk (David Holroyd) Date: Mon, 14 Mar 2005 10:20:03 +0000 Subject: [as2api-dev] Package level short description In-Reply-To: <801d3d3be00194be6cd7f442695dde94@dotgeek.org> References: <801d3d3be00194be6cd7f442695dde94@dotgeek.org> Message-ID: <20050314102001.GA12454@vhost.badgers-in-foil.co.uk> On Mon, Mar 14, 2005 at 01:15:44AM +0100, erixtekila wrote: > Hi Dave, > > > In your xml doc, you notice : > The first sentence of the class description will also be > included in the package-level index of classes and interfaces. It > should therefore try to give a brief overview of the class's > purpose > > How do this feature work, actually ? > Is it a future feature not implemented now ? Unfortunately, you are correct; this is not implemented yet. There's a placeholder in the generated files, but we don't calculate the text for it yet. For everyone's information, I've not really been able to get the time after work to play with the OSX port -- I've been working late in the office anyway, so I've not felt like sticking around even longer to play with the G4. There is some possibility of me getting hold of the 'spare' powerbook so that I work on this at home, but everyone denies knowledge of its whereabouts. Instead, I'm going to rewrite the doc-comment parser to make it easier to add support for new {@tags}. dave -- http://david.holroyd.me.uk/ From erixtekila at dotgeek.org Mon Mar 14 10:41:25 2005 From: erixtekila at dotgeek.org (erixtekila) Date: Mon, 14 Mar 2005 11:41:25 +0100 Subject: [as2api-dev] Package level short description In-Reply-To: <20050314102001.GA12454@vhost.badgers-in-foil.co.uk> References: <801d3d3be00194be6cd7f442695dde94@dotgeek.org> <20050314102001.GA12454@vhost.badgers-in-foil.co.uk> Message-ID: > Instead, I'm going to rewrite the doc-comment parser to make it easier > to add support for new {@tags}. Actually, since OSX already comes with ruby installed, I think it's a good alternative. Anyone that is interested could run the source with a commandline. I've already set up my environnement to code with Eclipse enabling as2api javadocs via builders. Everythink works just fine. Perhaps will we hear from Phil soon ? He seems to get the experience to port a ruby app to Mac OSX app : http://www.philsgaff.co.uk/2005/02/22/as2api-mac-01-re-release/ 'Till that point, I just can assure you that you've made a good choice. Once, you've get more more javadocs compliant system, it'll be really interesting for all. regards. ----------- erixtekila http://blog.v-i-a.net/ From phil at produxion.net Mon Mar 14 17:52:10 2005 From: phil at produxion.net (Phil Powell) Date: Mon, 14 Mar 2005 17:52:10 +0000 Subject: [as2api-dev] Package level short description In-Reply-To: References: <801d3d3be00194be6cd7f442695dde94@dotgeek.org> <20050314102001.GA12454@vhost.badgers-in-foil.co.uk> Message-ID: <1a1ca05f6863461991b6f6f04c53399a@produxion.net> Hello all - apologies for being off the radar: I've been away for the past five days, in the North of England and haven't been able to get access to my email. Once I get up to speed with things back in London, I'll try to find the time to implement a new release of the OSX app with the latest code, and pass on a fe more details about how it can be built with XCode. Point to note: don't assume that Ruby is installed with every OSX installation. I have tested on two new PowerBooks and a G5 which have standard 10.3 installs, and they DON'T have ruby installed. Also note that the version of Ruby currently installed with the Developer Tools is 1.6 - I've upgraded my installation to 1.8 now. Phil On 14 Mar 2005, at 10:41 am, erixtekila wrote: >> Instead, I'm going to rewrite the doc-comment parser to make it easier >> to add support for new {@tags}. > > Actually, since OSX already comes with ruby installed, I think it's a > good alternative. > Anyone that is interested could run the source with a commandline. > I've already set up my environnement to code with Eclipse enabling > as2api javadocs via builders. > Everythink works just fine. > > Perhaps will we hear from Phil soon ? > He seems to get the experience to port a ruby app to Mac OSX app : > http://www.philsgaff.co.uk/2005/02/22/as2api-mac-01-re-release/ > > 'Till that point, I just can assure you that you've made a good > choice. > Once, you've get more more javadocs compliant system, it'll be really > interesting for all. > > > regards. > > ----------- > erixtekila > http://blog.v-i-a.net/ > > > > _______________________________________________ > as2api-dev mailing list > as2api-dev@lists.badgers-in-foil.co.uk > http://lists.badgers-in-foil.co.uk/mailman/listinfo/as2api-dev > >