                    Galax: An XQuery 1.0 Implementation
                     -----------------------------------
                   Application Programming Interfaces (APIS)

** Galax Release: 0.3.1
May 2003

INDEX
=====
   I. Galax API Support
      Example O'Caml, C, and Java programs that use Galapi
  II. General Galax API
 III. Quick Start to the Galax APIs
  IV. XQuery Data Model
   V. Query Evaluation
  VI. C-API Specifics
 VII. Java-API Specifics
VIII. CAVEATS

QUICK START TO USING THE GALAX APIS
===================================
  Read "I. Galax API Support"
  Read "III. Quick Start to the Galax APIs" below.
  Read the examples in galax/examples/ directory.

  A quick way to learn the apis is to look at the examples while
  reading this README file.

I. Galax API Support
====================

  Galax currently supports application-program interfaces for the
  O'Caml, C, and Java.  

  All APIs support the same set of functions; only their names differ
  in each language API.  This file describes the API functions.  The
  interfaces for each language are defined in:

  O'Caml: $GALAXHOME/lib/caml/galapi.mli
  C:      $GALAXHOME/lib/c/{glx.h,itemlist.h}
  Java:   $GALAXHOME/lib/java/doc/*.html

  If you use the C API, see "V.  Memory Management in C API" below.

  Example programs that use these APIs are in:
  
  O'Caml: $GALAXHOME/examples/caml_api
  C:      $GALAXHOME/examples/c_api
  Java:   $GALAXHOME/examples/java_api

  In each directory, edit Makefile to set up your environment, then
  execute:

    make run

  to compile and run examples.  Each directory contains a "test"
  program that exercises every function in the API and an "example"
  function that gives some simple uses of the API.

  The Galax query engine is implemented in O'Caml.  This means that
  values in the native language (C or Java) are converted into
  values in the XQuery data model (which represented are by O'Caml
  objects) before sending them to the Galax engine.  The APIs provide
  functions for converting between native-language values and XQuery
  data-model values.

IA. Linking and Running
-----------------------

  There are two kinds of Galax libraries: byte code and native code. 
  The C libraries have one variant for statically linked or
  dynamically linked.  Here are the libraries:

  O'Caml in $GALAXHOME/lib/caml:
     glx.cma       byte code
     glx.cmxa      native coe

  C in $GALAXHOME/lib/c:
     libglx.a      byte code, statically linked
     libglx.so     byte code, dynamically linked
     libglxopt.a   native code, statically linked
     libglxopt.so  native code, dynamically linked

  Java in $GALAXHOME/lib/java:
    libglxj.so	   byte code, dynamically linked
    libglxoptj.so  native code, dynamically linked

  Note that Java applications MUST link with a dynamically linked
  libraries and that C applications MAY link with a dynamically linked
  library.  

  For Linux users, set LD_LIBRARY_PATH to $GALAXHOME/lib/c (for C
  apps) or $GALAXHOME/lib/java (for Java apps). 

  The Makefiles in examples/c_api and examples/java_api show how to
  link and run applications that use the C and Java APIs.

II. General Galax API
=====================

Every Galax API has functions for:

  o Converting values in XQuery data model to/from values in native
    language

  o Accessing values in XQuery data model 

  o Loading XML documents into the XQuery data model

  o Creating and modifying the query evaluation environment (also
    known as the [evaluation context])

  o Evaluating queries given an evaluation context

  o Serializing XQuery data model values as XML documents

This document describes how to use each set of functions. 

III. Quick Start to the Galax APIs
==================================

  The simplest API functions allow you to evaluate an XQuery statement
  in a string.  If the statement is an update, these functions return
  None, otherwise if it is an expression, they return an XML value.

There are four variants of these functions:

  val eval_statement_with_context_item_from_document : string -> string -> item list option
    Bind the context item (the XPath "." expression) to the XML
    document in the resource named by the first string argument,
    and evaluate the XQuery statement in the second string argument. 
  
  val eval_statement_with_context_item_from_xml : item -> string -> item list option 
    Bind the context item (the XPath "." expression) to the XML value
    in the item list argument and evaluate the XQuery statement in
    the string argument. 
  
  val eval_statement_with_variables_from_xml : (string * item list) list -> string -> item list option
    The first argument is a list of variable name and XML value pairs.
    Bind each variable to the corresponding XML value and evaluate the
    XQuery statement in the string argument.

  Sometimes you need more control over query evaluation, because, for
  example, you want to load XQuery libraries and/or main modules and
  evaluate statements incrementally.    The following two sections
  describe the API functions that provide finer-grained control:

    IV. XQuery Data Model
     V. Query Evaluation


IV. XQuery Data Model
=====================

IVA. Types and Constructors

  In the XQuery data model, a value is a [sequence] (or list) of
  [items].  An [item] is either an [node] or an [atomic value].  An
  node is an [element], [attribute], [text], [comment], or
  [processing-instruction].  An [atomic value] is one of the nineteen
  XML Schema data types plus the XQuery type [xdt:untypedAtomic].

  The Galax APIs provide constructors for the following data model
  values: 

  o sequences of items
  o element, attribute, text, comment, and processing instruction
    nodes
  o xs:string, xs:boolean, xs:int, xs:integer, xs:decimal, xs:float,
    xs:double, xs:anyURI, xs:QName, and xdt:untypedAtomic.

  Atomic values:
  --------------
  The constructor functions for atomic values take values in the
  native language and return atomic values in the XQuery data
  model.  For example, the O'Caml constructor:

    val xs_float   : Datatypes.xs_float -> xs_float

  takes an O'Caml float value (as defined in the Datatypes module) and
  returns a float in the XQuery data model.  Similarly, the C
  constructor: 

    extern glx_err glx_xs_decimal(int i, xs_decimal *return_value); 

  takes a C integer value and returns a decimal in the XQuery data
  model. 

  Nodes:
  ------
  The constructor functions for nodes typically take other data model
  values as arguments.  For example, the O'Caml constructor for
  elements: 

     val element : (xs_QName * attribute list * node list * xs_QName)
                 -> element

  takes a QName value, a list of attribute nodes, a list of children
  nodes, and the QName of the element's type.  Simliarly, the C
  constructor for text nodes takes an XQuery string value:

    extern glx_err glx_text(xs_string str, text *return_value);

  Sequences:
  ----------
  The constructor functions for sequences are language specific.  In
  O'Caml, the sequence constructor is simply the O'Caml list
  constructor.  In C, the sequence constructor is defined in
  galapi/itemlist.h as: 

    extern itemlist itemlist_cons(item i, itemlist cdr);

IVB. Using XQuery data model values

  The APIs are written in an "object-oriented" style, meaning that any
  use of a type in a function signature denotes any value of that type
  or a value derived from that type.  For example, the function
  [string_of_atomicvalue] takes any atomic value (i.e., xs_string,
  xs_boolean, xs_int, xs_float, etc.) and returns an O'Caml string
  value:

    val string_of_atomicvalue  : atomicvalue -> Datatypes.xs_string 

  Similarly, the function [glx_parent] takes any node value (i.e., an
  element, attribute, text, comment, or processing instruction node)
  and returns a list of nodes:

    extern glx_err glx_parent(node n, nodelist *return_value);

IVC. Accessors 

  The accessor functions take XQuery values and return constituent
  parts of the value.  For example, the [children] accessor takes an
  element node and returns the sequence of children nodes contained in
  that element: 

    val children : node -> node list      (* O'Caml *)
    extern glx_err glx_children(node n, nodelist *return_value); /* C */

  The XQuery data model accessors are described in detail in the
  [XQuery 1.0 and XPath 2.0 Data Model] document.

IVD. Loading documents 

  Galax provides two functions for loading XML documents:
  [load_document] and [load_document_validate].  

  The [load_document] function takes the name of an XML file in the
  local file system and returns a sequence of nodes that are the
  top-level nodes in the document (this may includes zero or more
  comments and processing instructions and zero or one element node.)

    val load_document : string -> node list  (* O'Caml *)
    extern glx_err glx_load_document(char* filename, nodelist *return_value);  /* C */

  The [load_document_validate] function takes a module context (which
  includes any imported schemas -- see IV.A. below) and the name of
  an XML file in the local file system, and validates the input
  document with respect to the imported schemas in the evaluation
  context.  It returns a sequence of nodes.

   val load_document_validate : module_context -> string -> node list  
     (* O'Caml *)
   extern glx_err glx_load_document_validate(module_context context, char*
     filename, nodelist *return_value);  /* C */

V.  Query Evaluation
====================

  The general model for evaluating an XQuery expression or statement
  proceeds as follows (each function is described in detail below):

  1. Create default processing context:

     let proc_ctxt = default_processing_context() in

  2. Load Galax's standard library:

     let mod_ctxt = load_standard_library(proc_ctxt) in

  3. (Optionally) load any imported library modules:

     let mod_ctxt = import_library_module mod_ctxt "some-xquery-library.xq" in

  4. (Optionally) load one main XQuery module:

     let (mod_ctxt, stmts) = import_main_module mod_ctxt "some-main-module.xq" in

  5. (Optionally) initialize the context item and/or global variables
     defined in application (i.e., external environment):

     let ext_ctxt = build_external_context opt_context_item var_value_list in
     let mod_ctxt = add_external_context mod_ctxt ext_ctxt in

  6. Evaluate all global variables in module context:

     let mod_ctxt = eval_global_variables mod_ctxt

     ** NB: This step is necessary if the module contains *any*
       global variables, whether defined in the XQuery module or
       defined externally by the application. **

  7. Finally, evaluate a statement from the main module or one defined
     in the application or call some XQuery function defined in the
     module context:

     7a. let result = eval_statement  mod_ctxt stmt

     7b. let result = eval_statement_from_string mod_ctxt some-XQuery-statement

     7c. let result = eval_query_function  mod_ctxt "some-function" argument-values

VA. Module context 

   Every query is evaluated in a [module context], which includes:

   o the  built-in types, namespaces, and functions; 
   o the user-defined types, namespaces, and functions specified in
     any imported library modules; and
   o any additional context defined by the application (e.g., the values of
     the context item and any global variables).  

   The functions for creating a module context include:

   val default_processing_context : unit -> processing_context
      The default processing context, which just contains flags for
      controlling debugging, printing, and the processing phases.  You
      can change the default processing context yourself if you want
      to print out debugging info.

   val load_standard_library : processing_context -> module_context
      Load the standard Galax library, which contains the built-in
      types, namespaces, and functions.

   val import_library_module : module_context -> string -> module_context
      If you need to import other library modules, this function
      returns the module_context argument extended with the module
      in the string filename argument.

   val import_main_module    : module_context -> string -> module_context * (Xquery_ast.cstatement list)
      If you want to import a main module defined in a file, this
      function returns the module_context argument extended with the
      main module in the string filename argument and a list of
      statements to evaluate.

   val import_main_module_from_string : module_context -> string -> module_context * (Xquery_ast.cstatement list)
      Same as import_main_module, but module definition is provided in
      a string instead of a file.

   The functions for creating an external context (context item and
   global variable values):

   val build_external_context : 
     The external context includes an optional value for the context
     item (known as ".") and a list of variable name, item-list value
     pairs.

   val add_external_context : module_context -> external_context -> module_context
      This function extends the given module context with the external context.

   val eval_global_variables : module_context -> module_context 
      This function evaluates the expressions for all (possibly
      mutually dependent) global variables.  It must be called before
      calling the eval_* functions otherwise you will get an
      "Undefined variable" error at evaluation time. **

   Analogous functions are defined in the C API.

VB. Evaluating queries/expressions

  The APIs support three functions for evaluating a query:
  [eval_statement_from_string], [eval_statement], and [eval_query_function].

     ** NB: If the module context contains (possibly mutually
       dependent) global variables, the function [eval_global_variables] must be called before
       calling the eval_* functions otherwise you will get an
       "Undefined variable" error at evaluation time. **

  val eval_statement_from_string : module_context -> string -> item list option
       Given the module context, evaluates the XQuery statement  in
       the string argument.  If the statement is an XQuery expression,
       returns Some (item list); otherwise if the statement is an
       XQuery update, returns None (because update statements have
       side effects on the data model store, but do not return values).

  val eval_statement : module_context -> Xquery_ast.cstatement -> item list option
       Given the module context, evaluates the XQuery statement 

  val eval_query_function  : module_context -> string -> (item list) list -> item list
       Given the module context, evaluates the function with name in the
       string argument applied to the list of item-list arguments.
       NOTE: Each actual function argument is bound to one item list.

   Analogous functions are defined in the C API.

C. Serializing XQuery data model values

  Once an application program has a handle on the result of evaluating
  a query, it can either use the accessor functions in the API or it
  can serialize the result value into an XML document.  There are
  three serialization functions: [serialize_to_string],
  [serialize_to_output_channel] and [serialize_to_file]. 

    val serialize_to_string : item list -> string  
      Serializes an XML value to a string.

    val serialize_to_output_channel : out_channel -> item list -> unit
      Serializes an XML value to the output channel argument.

    val serialize_to_file : string -> item list -> unit
      Serializes an XML value to the file with name in the string
      argument. 

   Analogous functions are defined in the C API.

VI. C-API Specifics
===================

VI.A Memory Management

  The Galax query engine is implemented in O'Caml.  This means that
  values in the native language (C or Java) are converted into
  values in the XQuery data model (which represented are by O'Caml
  objects) before sending them to the Galax engine.  Similarly, the
  values returned from the Galax engine are also O'Caml values -- the
  native language values are "opaque handles" to the O'Caml values.

  All O'Caml values live in the O'Caml memory heap and are therefore
  managed by the O'Caml garbage collector.  The C API guarantees that
  any items returned from Galax to a C application will not be
  de-allocated by the O'Caml garbage collector, unless the C
  appliation explicitly frees those items, indicating that they are no
  longer accessible in the C appliation.  The C API provides two
  functions in galapi/itemlist.h for freeing XQuery item values: 
  
    extern void item_free(item i);
      Frees one XQuery item value.
 
    extern void itemlist_free(itemlist il);
      Frees every XQuery item value in the given item list.
  
VI.B Exceptions 

  The Galax query engine may raise an exception in O'Caml, which must
  be conveyed to the C application.  Every function in the C API
  returns an integer error value : 
     0 if no exception was raised or
    -1 if an exception was raised.

  The global variable glx_error_string contains the string value of
  the exception raised in Galax.  In future APIs, we will provide a
  better mapping between error codes and Galax exceptions

VII. Java-API Specifics
=======================

VII.A  General Info 

  The Galax query engine is implemented in O'Caml.  This means that
  values in the native language (C or Java) are converted into values
  in the XQuery data model (which represented are by O'Caml objects)
  before sending them to the Galax engine.

  The Java API uses JNI to call the C API, which in turn calls the
  O'Caml API (it's not as horrible as it sounds).  

  There is one class for each of the built-in XML Schema types
  supported by Galax and one class for each kind of node:

    Atomic	   Node                    Item
    xsAnyURI       Attribute
    xsBoolean      Comment		
    xsDecimal      Element		
    xsDouble       ProcessingInstruction
    xsFloat        Text                 
    xsInt
    xsInteger
    xsQName
    xsString
    xsUntyped

  There is one class for each kind of sequence:
    ItemList
    AtomicList
    NodeList		    
    AttributeList    

  There is one class for each kind of context used by Galax:
  
    ExternalContext  
    ModuleContext	    
    ProcessingContext	    
    QueryContext	    

  Finally, the procedures for loading documents, constructing new
  contexts and running queries are in the class:

    Galax	   
	       
VII.B Exceptions 

  All Galax Java API functions can raise the exception class
  GalapiException, which must be handled by the Java application.

VII.C Memory Management

  All Java-C-O'Caml memory management is handled automatically in the
  Java API.

VIII. CAVEATS
=============

  Currently, Galax is not re-entrant, which means multi-threaded
  applications cannot create multiple, independent instances of the
  Galax query engine to evaluate queries. 
