<?xml version='1.0' ?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
               "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
<!ENTITY % myvars SYSTEM "../variables.ent">
%myvars;
]>
<sect1 id="tcl-doc" xreflabel="Documenting Tcl Files: Page Contracts and Libraries">
<title>Documenting Tcl Files: Page Contracts and Libraries</title>


<authorblurb>
<para>By <ulink url="mailto:jsalz@mit.edu">Jon Salz</ulink> on 3 July 2000 </para>
</authorblurb>

<itemizedlist>
<listitem><para>Tcl procedures: /packages/acs-kernel/tcl-documentation-procs.tcl</para></listitem>
</itemizedlist>


<sect2 id="tcl-doc-bigpicture">
<title>The Big Picture</title>


<para>In versions of the OpenACS prior to 3.4, <ulink url="/doc/standards">the standard
place</ulink> to document Tcl files (both Tcl pages and Tcl library files) was in
a comment at the top of the file:</para>

 

<programlisting>
#
# <emphasis>path from server home</emphasis>/<emphasis>filename</emphasis>
#
# <emphasis>Brief description of the file&#39;s purpose</emphasis>
#
# <emphasis>author&#39;s email address</emphasis>, <emphasis>file creation date</emphasis>
#
# <ulink url="http://www.loria.fr/~molli/cvs/doc/cvs_12.html#SEC93">$Id: tcl-doc.xml,v 1.7 2006/07/17 05:38:38 torbenb Exp $</ulink>
#
</programlisting>

<para>
In addition, the inputs expected by a Tcl page (i.e., form variables) would
be enumerated in a call to <computeroutput>ad_page_variables</computeroutput>, in effect,
documenting the page&#39;s argument list. 
</para>

<para>The problem with these practices is that the documentation is only
accessible by reading the source file itself. For this reason, ACS 3.4
introduces a new API for documenting Tcl files and, on top of that, a
web-based user interface for browsing the documentation:</para>

<itemizedlist>
<listitem><para><emphasis role="strong"><computeroutput><link linkend="tcl-doc-ad-page-contract">ad_page_contract</link></computeroutput></emphasis>: Every Tcl page
has a <emphasis role="strong">contract</emphasis> that explicitly defines what inputs the page
expects (with more precision than <computeroutput>ad_page_variables</computeroutput>) and
incorporates metadata about the page (what used to live in the top-of-page
comment). Like <computeroutput>ad_page_variables</computeroutput>, <computeroutput>ad_page_contract</computeroutput>
also sets the specified variables in the context of the Tcl page.</para></listitem>

<listitem><para><emphasis role="strong"><computeroutput><link linkend="tcl-doc-ad-library">ad_library</link></computeroutput></emphasis>: To be
called at the top of every library file (i.e., all files in the
<computeroutput>/tcl/</computeroutput> directory under the server root and
<computeroutput>*-procs.tcl</computeroutput> files under <computeroutput>/packages/</computeroutput>).</para></listitem>
</itemizedlist>

<para>
This has the following benefits: 
</para>

<itemizedlist>
<listitem><para>Facilitates automatic generation of human-readable documentation.</para></listitem>

<listitem><para>Promotes security, by introducing a standard and automated way to check
inputs to scripts for correctness.</para></listitem>

<listitem><para>Allows graphical designers to determine easily how to customize
sites&#39; UIs, e.g., what properties are available in templates.</para></listitem>

<listitem><para>Allows the request processor to be intelligent: a script can specify in
its contract which type of abstract document it
returns, and the request processor can transform it automatically into
something useful to a particular user agent. (Don&#39;t worry about this for
now - it&#39;s not complete for ACS 3.4.)</para></listitem>
</itemizedlist>

</sect2>

<sect2 id="tcl-doc-ad-page-contract" xreflabel="ad_page_contract">
<title>ad_page_contract</title>

<para>
Currently <computeroutput>ad_page_contract</computeroutput> serves mostly as a replacement for
<computeroutput>ad_page_variables</computeroutput>. Eventually, it will be integrated closely
with the documents API so that each script&#39;s contract will document
precisely the set of properties available to graphical designers in
templates. (Document API integration is subject to change, so we don&#39;t
decsribe it here yet; for now, you can just consider
<computeroutput>ad_page_contract</computeroutput> a newer, better, documented
<computeroutput>ad_page_variables</computeroutput>.) 
</para>

<para>Let&#39;s look at an example usage of <computeroutput>ad_page_contract</computeroutput>:</para>

 

<programlisting>

# /packages/acs-kernel/api-doc/www/package-view.tcl
ad_page_contract {
    version_id:integer
    public_p:optional
    kind
    { format &quot;html&quot; }
} {
    Shows APIs for a particular package.

    @param version_id the ID of the version whose API to view.
    @param public_p view only public APIs?
    @param kind view the type of API to view. One of &lt;code&gt;procs_files&lt;/code&gt;,
        &lt;code&gt;procs&lt;/code&gt;, &lt;code&gt;content&lt;/code&gt;, &lt;code&gt;types&lt;/code&gt;, or
        &lt;code&gt;gd&lt;/code&gt;.
    @param format the format for the documentation. One of &lt;code&gt;html&lt;/code&gt; or &lt;code&gt;xml&lt;/code&gt;.

    @author Jon Salz (jsalz@mit.edu)
    @creation-date 3 Jul 2000
    @cvs-id &#x0024;Id$
}

</programlisting>

<para>
Note that: 
</para>

<itemizedlist>
<listitem><para><emphasis role="strong">By convention, <computeroutput>ad_page_contract</computeroutput> should be preceded
by a comment line containing the file&#39;s path</emphasis>. The comment is on
line 1, and the contract starts on line 2.
</para></listitem>

<listitem><para><emphasis role="strong"><computeroutput>ad_page_contract</computeroutput></emphasis>&#39;s first argument is
the list of expected arguments from the HTTP query (<computeroutput>version_id</computeroutput>,
<computeroutput>public_p</computeroutput>, <computeroutput>kind</computeroutput>, and <computeroutput>format</computeroutput>). Like
<computeroutput>ad_page_variables</computeroutput>, <computeroutput>ad_page_contract</computeroutput> sets the
corresponding Tcl variables when the page is executed.
</para></listitem>

<listitem><para><emphasis role="strong">Arguments can have defaults</emphasis>, specified using the same
syntax as in the Tcl <computeroutput>proc</computeroutput> (a two-element list where the first
element is the parameter name and the second argument is the default value).

</para></listitem>

<listitem><para><emphasis role="strong">Arguments can have flags</emphasis>, specified by following the
name of the query argument with a colon and one or more of the following
strings (separated by commas): </para>
 

<itemizedlist>
<listitem><para><emphasis role="strong"><computeroutput>optional</computeroutput></emphasis>: the query argument doesn&#39;t
need to be provided; if it&#39;s not, the variable for that argument simply
won&#39;t be set. For instance, if I call the script above without a
<computeroutput>public_p</computeroutput> in the query, then in the page body <computeroutput>[info exists
public_p]</computeroutput> will return 0.
</para></listitem>

<listitem><para><emphasis role="strong"><computeroutput>integer</computeroutput></emphasis>: the argument must be an integer
(<computeroutput>ad_page_contract</computeroutput> will fail and display and error if not). This
flag, like the next, is intended to prevent clients from fudging query
arguments to trick scripts into executing arbitrary SQL. 

</para></listitem>

<listitem><para><emphasis role="strong"><computeroutput>sql_identifier</computeroutput></emphasis>: the argument must be a SQL
identifier (i.e., <computeroutput>[string is wordchar $the_query_var]</computeroutput> must
return true). 

</para></listitem>

<listitem><para><emphasis role="strong"><computeroutput>trim</computeroutput></emphasis>: the argument will be [string
trim]&#39;ed. 

</para></listitem>

<listitem><para><emphasis role="strong"><computeroutput>multiple</computeroutput></emphasis>: the argument may be specified
arbitrarily many times in the query string, and the variable will be set to a
list of all those values (or an empty list if it&#39;s unspecified). This is
analogous to the <computeroutput>-multiple-list</computeroutput> flag to
<computeroutput>ad_page_variables</computeroutput>, and is useful for handling form input
generated by <computeroutput>&lt;SELECT MULTIPLE&gt;</computeroutput> tags and checkboxes. </para>

<para>For instance, if <computeroutput>dest_user_id:multiple</computeroutput> is specified in the
contract, and the query string is</para>

 

<programlisting>

?dest_user_id=913&amp;dest_user_id=891&amp;dest_user_id=9

</programlisting>

<para>
then <computeroutput>$dest_user_id</computeroutput> is set to <computeroutput>[list 913 891 9]</computeroutput>.


</para></listitem>

<listitem><para><emphasis role="strong"><computeroutput>array</computeroutput></emphasis>: the argument may be specified
arbitrarily many times in the query string, with parameter names with
suffixes like <computeroutput>_1</computeroutput>, <computeroutput>_2</computeroutput>, <computeroutput>_3</computeroutput>, etc. The
variable is set to a list of all those values (or an empty list if none are
specified). </para>

<para>For instance, if <computeroutput>dest_user_id:array</computeroutput> is specified in the
contract, and the query string is</para>

 

<programlisting>

?dest_user_id_0=913&amp;dest_user_id_1=891&amp;dest_user_id_2=9

</programlisting>

<para>
then <computeroutput>$dest_user_id</computeroutput> is set to <computeroutput>[list 913 891 9]</computeroutput>.</para></listitem>
</itemizedlist>



</listitem>

<listitem><para><emphasis role="strong">You can provide structured, HTML-formatted documentation for your
contract</emphasis>. Note that format is derived heavily from Javadoc: a
general description of the script&#39;s functionality, followed optionally by
a series of named attributes tagged by at symbols (<computeroutput>@</computeroutput>). You are
encouraged to provide: 
</para>
 

<itemizedlist>
<listitem><para>A description of the functionality of the page. If the description
contains more than one sentence, the first sentence should be a brief
summary. 

</para></listitem>

<listitem><para>A <emphasis role="strong"><computeroutput>@param</computeroutput></emphasis> tag for each allowable query
argument. The format is </para>

 

<programlisting>

@param <emphasis>parameter-name</emphasis> <emphasis>description...</emphasis>

</programlisting>




</listitem>

<listitem><para>An <emphasis role="strong"><computeroutput>@author</computeroutput></emphasis> tag for each author. Specify the
author&#39;s name, followed his or her email address in parentheses.</para></listitem>

<listitem><para>A <emphasis role="strong"><computeroutput>@creation-date</computeroutput></emphasis> tag indicating when the
script was first created.</para></listitem>

<listitem><para>A <emphasis role="strong"><computeroutput>@cvs-id</computeroutput></emphasis> tag containing the page&#39;s CVS
identification string. Just use <computeroutput>$Id: tcl-documentation.html,v 1.2
2000/09/19 07:22:35 ron Exp $</computeroutput> when creating the file, and CVS will
substitute an appropriate string when you check the file in.</para></listitem>
</itemizedlist>



<para>
 These <computeroutput>@</computeroutput> tags are optional, but highly recommended!</para></listitem>
</itemizedlist>

</sect2>

<sect2 id="tcl-doc-ad-library" xreflabel="ad_library">
<title>ad_library</title>

<para>
<computeroutput>ad_library</computeroutput> provides a replacement for the informal documentation
(described above) found at the beginning of every Tcl page. Instead of: 
</para>
 

<programlisting>

# /packages/acs-kernel/00-proc-procs.tcl
#
# Routines for defining procedures and libraries of procedures (-procs.tcl files).
#
# jsalz@mit.edu, 7 Jun 2000
#
# $Id: tcl-doc.xml,v 1.7 2006/07/17 05:38:38 torbenb Exp $

</programlisting>


<para>
you&#39;ll now write: 
</para>
 

<programlisting>

# /packages/acs-kernel/00-proc-procs.tcl
ad_library {

    Routines for defining procedures and libraries of procedures (&lt;code&gt;-procs.tcl&lt;/code&gt;
    files).

    @creation-date 7 Jun 2000
    @author Jon Salz (jsalz@mit.edu)
    @cvs-id &#x0024;Id$

}

</programlisting>

<para>
Note that format is derived heavily from Javadoc: a general description of
the script&#39;s functionality, followed optionally by a series of named
attributes tagged by at symbols (<computeroutput>@</computeroutput>). HTML formatting is allowed.
You are encouraged to provide: 
</para>

<itemizedlist>
<listitem><para>An <emphasis role="strong"><computeroutput>@author</computeroutput></emphasis> tag for each author. Specify the
author&#39;s name, followed his or her email address in parentheses.</para></listitem>

<listitem><para>A <emphasis role="strong"><computeroutput>@creation-date</computeroutput></emphasis> tag indicating when the
script was first created.</para></listitem>

<listitem><para>A <emphasis role="strong"><computeroutput>@cvs-id</computeroutput></emphasis> tag containing the page&#39;s CVS
identification string. Just use <computeroutput>$Id: tcl-documentation.html,v 1.2
2000/09/19 07:22:35 ron Exp $</computeroutput> when creating the file, and CVS will
substitute an appropriate string when you check the file in.</para></listitem>
</itemizedlist>


<para><phrase role="cvstag">($Id: tcl-doc.xml,v 1.7 2006/07/17 05:38:38 torbenb Exp $)</phrase></para>
</sect2>
</sect1>
