next up previous
Next: Related CGI Applications Up: The Application Protocol Information Previous: Other APIB Gateway Features

APIB Gateway Implementation

 

The APIB gateway's CGI scripts are written in Tcl[OUST], a scripting language for controlling and extending applications. Tcl was chosen as the CGI programming language mainly because the Tcl language is flexible, portable, easy to use, and because several extensions useful to the APIB have already been implemented. The Tcl extensions the APIB gateway uses are:

This section illustrates how the APIB gateway was implemented, using a single CGI script -- the script for creating schema object web pages -- as an example.

An APIB gateway CGI script has three basic tasks to perform. First, it must assemble all of the input data. Some of this input data is entered in HTML forms by the user. Other input data is state information which must be passed to the script because HTTP[BLEE96], the communication protocol used by web servers and clients, is stateless. Each HTTP request/response chain has no knowledge of previous HTTP communications. Therefore, it is up to the APIB gateway implementation to keep track of any necessary history information. Fortunately, HTML provides a way to accomplish this using HIDDEN fields in forms. HIDDEN fields contain values that get passed to CGI scripts, but they are invisible to the user.

To illustrate how the APIB gateway keeps track of the APIB browser's state, consider the CGI script that generated the web page in Figure 6. In order for this web page to provide the backtracking functionality shown in Figure 9, the CGI script must be aware of how the entity dimension_curve_directed_callout fits into the overall structure of the APIB. Specifically, the CGI script needs to know dimension_curve_directed_callout's schema, the STEP document containing this schema, and the document type being browsed. The following Tcl code obtains this information:

cgi_import doctype
catch {cgi_import ir}
catch {cgi_import irsec}

The cgi_import command, part of the CGI library, retrieves an input value from a form. The last two calls to cgi_import are enclosed in catch commands in order to prevent the CGI script from exiting if either $ir or $irsec are undefined. After the commands above are executed, the CGI script has access to information concerning the type of the document to which the entity belongs and, if available, the entity's STEP Part number and schema. The CGI library also has a command, cgi_export, for specifying HIDDEN values in a form. In order for a variable to be imported into a CGI script, it must either have a value obtained from input to the form that invoked the CGI script, or it must have been exported from the form that invoked the CGI script.

The second task an APIB gateway CGI script must perform is to query the APIB for the information it needs. This is done in the CGI script that generated the web page for dimension_curve_directed_callout as follows:

	start_pat
	set qresult [express_definition [set $expitem] $expabbrev]
	if {![info exists irsec]} {
	    set irsec [schema_name [set $expitem] $expabbrev]
	    if {![info exists ir]} {
		set ir [lindex [part $irsec] 0]
	    }
	}
	quit_pat

This code uses several commands from the Tcl extension for controlling and making queries to Pat[OTC], the APIB's retrieval engine. start_pat starts up Pat and sets up a communications pipeline between Pat and the APIB. quit_pat exits Pat and closes the communications pipeline. express_definition, schema_name, and part are commands which perform APIB queries. express_definition returns the raw SGML text from the APIB describing a schema object. schema_name returns the name of the schema to which the object belongs. part returns a schema's STEP Part name and Part number. All of these APIB Tcl commands make use of the Tcl extension for tokenizing and scanning output from Pat.

If this CGI script was invoked by means of the user clicking a ``View'' button on a form from a schema web page (as in Figure 5), $irsec and $ir will contain whatever query result values they were assigned in the schema web page's CGI script. On the other hand, if this CGI script was invoked though the IR Query form (see Figure 7), $irsec and $ir will be undefined because IR Query's CGI script does not compute these values. Therefore, the Tcl code above tests to see if these variables are undefined and, if they are, queries the APIB to obtain the schema name and Part number.

The argument [set $expitem] passed to the express_definition and schema_name commands specifies the name of a schema object. $expitem has as its value the schema object type and contains one of the following four strings: ``entity'', ``type'', ``function'', ``rule''. Its value is determined by the context under which the CGI script is invokedgif. This value is used to construct the name of the SGML element to pass to Pat. In the case of dimension_curve_directed_callout, $expitem's value is ``entity'', and [set $expitem]'s value is ``dimension_curve_directed_callout''.

The CGI script's third and final task is to create a web page using the input from forms and the APIB query results. Much of this involves using Tcl commands in the CGI library for creating HTML elements such as headings, paragraphs, forms, and so on. However, the CGI script must invoke the APIB gateway's SGML-to-HTML translator in order to convert the raw SGML data in $qresult into HTML.

The translator is implemented using NSGMLS, an application of the SP[CLARK] SGML parser, and SGMLSpm[MEGG], a perl[VROM] class library for processing the output from NSGMLS. NSGMLS validates the SGML data and converts it into a format which a structure-controlled conforming SGML application can act upon. An application of SGMLSpm called ``sgmlspl'' uses the output from NSGMLS to build a set of objects representing the structure of the SGML data as defined by its DTD. sgmlspl takes as a second argument a specification file. The specification file used for the APIB gateway contains perl instructions for converting every SGML construct that can appear in an APIB query result into HTML. This specification file, although fairly long, was simple to write. The following excerpt from the specification file shows how the ENTITY.DEF element from the DTD is translated to HTML. When the translator encounters the beginning tag for ENTITY.DEF, it obtains the value of ENTITY.DEF's NAME attribute and outputs an HTML heading with the name of the EXPRESS entity. The translator performs no action when it encounters ENTITY.DEF's ending tag.

sgml('<ENTITY.DEF>', sub{
    my ($element,$event) = @_;
    my ($entname) = $element->attribute(NAME)->value;
    output "<h1>ENTITY " . $entname . "</h1>";
});
sgml('</ENTITY.DEF>', "");

The following Tcl procedure, render_html, invokes the translator and returns the HTML-tagged result. render_html takes three arguments: the raw SGML data to be translated, an argument used to identify the SGML document type, and the name of the raw SGML data's top level element. For example, to generate HTML for dimension_curve_directed_callout's entity definition, render_html would be called with the entity definition's SGML fragment (obtained by querying the APIB), ir, and ENTITY.DEF.

proc render_html {qresult parttype doctype} {

# Uses an SGML parser, the SGMLSpm perl library, and an sgmlspl spec
# file to translate raw SGML data to HTML

    global env

    # get the SGML declaration

    set f [open $env(SGMLDEC)]
    set sgmldoc [read $f]
    close $f

    # append the appropriate DTD fragment to the SGML declaration.
    # The QUERY.RESULT element is needed to capture the general
    # inclusions (such as figures, examples, etc.) declared in the
    # content models for the AP and IR top level elements.

    append sgmldoc "<!DOCTYPE QUERY.RESULT \["
    if {[string compare $parttype ap] == 0} {
        append sgmldoc "<!ENTITY % apdtd PUBLIC \"-//NIST//DTD Publish - "
        append sgmldoc "STEP Application Protocols V 2.1//EN\">"
        append sgmldoc "%apdtd;"
    } else {
        append sgmldoc "<!ENTITY % irdtd PUBLIC \"-//NIST//DTD "
        append sgmldoc "STEP Integrated Resources V 2.1//EN\">"
        append sgmldoc "%irdtd;"
    }
    append sgmldoc "<!ELEMENT Query.Result - - (${doctype}) "
    append sgmldoc "+(%General.Inclusions)>"
    append sgmldoc "\]>"

    # wrap QUERY.RESULT tags around the SGML-tagged query result,
    # append it to the SGML declaration and DTD, parse the whole
    # thing, and pipe the Element Structure Information Set to
    # sgmlspl.

    append sgmldoc "<query.result>" $qresult "</query.result>"
    safe_exec result $env(BIN_DIR)/$env(PARSER) <<$sgmldoc | \
	    $env(BIN_DIR)/sgmlspl ./$env(TRANSLATOR)

    puts $result
}

The bulk of the code in render_html assembles an SGML document to send to the translator. A complete SGML document consists of the following:

The instruction beginning with safe_exec runs the SGML document through NSGMLS and pipes the output to sgmlspl. $env(TRANSLATOR) is the sgmlspl specification file. safe_exec, a wrapper for the exec Tcl command, saves the result in the variable result and catches any error codes.


next up previous
Next: Related CGI Applications Up: The Application Protocol Information Previous: Other APIB Gateway Features

Josh Lubell
Mon Sep 30 15:19:35 EDT 1996