 
 
 
Chapter 6  Application Programming Interfaces (APIS)
The quickest way to learn how to use the APIs is as follows:
- 
Read Section 6.1 ``Galax API Support''.
- Read Section 6.3 ``Quick Start to the Galax APIs''.
- Read the example programs in the galax/examples/ directory
 while reading Section 6.3. 
6.1  Galax API Support
Galax currently supports application-program interfaces for the
 O'Caml, C, and Java programming languages. 
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/galax.mli
- C
-  $GALAXHOME/lib/c/galax,galax_util,galax_types,itemlist.h
- Java
-  $GALAXHOME/lib/java/doc/*.html
If you use the C API, see Section 6.6.1 ``Memory Management in C API''.
Example programs that use these APIs are in:
- 
O'Caml
-  $GALAXHOME/examples/caml_api
- C
-  $GALAXHOME/examples/c_api
- Java
-  $GALAXHOME/examples/java_api
Edit examples/Makefile.config to set up your environment, then
 execute:
    make all
 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.
6.1.1  Linking and Running
There are two kinds of Galax libraries: byte code and native code. 
 The C and Java libraries require native code libraries, and Java
 requires dynamically linked libraries. Here are the libraries:
O'Caml in $GALAXHOME/lib/caml:
- 
glx.cma byte code
- glx.cmxa native code
C in $GALAXHOME/lib/c:- 
libgalaxopt.a native code, statically linked
- libgalaxopt.so native code, dynamically linked
Java in $GALAXHOME/lib/java:- 
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:$GALAXHOME/lib/java.
The Makefiles in examples/c_api and examples/java_api show how to
 compile, link, and run applications that use the C and Java APIs.
6.2  General Galax API
Every Galax API has functions for:
- 
Converting values in XQuery data model to/from values in native
 language
 
 
- Accessing values in XQuery data model 
 
 
- Loading XML documents into the XQuery data model
 
 
- Creating and modifying the query evaluation environment (also
 known as the [evaluation context])
 
 
- Evaluating queries given an evaluation context
 
 
- Serializing XQuery data model values as XML documents
This document describes how to use each set of functions.
6.3  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
 the empty list, otherwise if it is an expression, they return a list
 of XML values.
Galax takes input from files, string buffers, channels and HTTP. See
$(GALAXHOME)/lib/caml/galax_io.mli. 
There are three variants of these functions:
    val eval_statement_with_context_item : 
      Processing_context.processing_context -> Galax_io.input_spec -> 
          Galax_io.input_spec -> item list
Bind the context item (the XPath "." expression) to the XML
 document in the resource named by the second argument, and
 evaluate the XQuery statement in the third argument.
    val eval_statement_with_context_item_as_xml : 
      Processing_context.processing_context -> item -> 
        Galax_io.input_spec -> item list
Bind the context item (the XPath "." expression) to the XML value
 in the second argument and evaluate the XQuery statement in
 the third argument. 
  val eval_statement_with_variables_as_xml : Processing_context.processing_context -> (string * item list) list -> Galax_io.input_spec -> item list
The secondd 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 third 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.
6.4  XQuery Data Model
6.4.1  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 [xs:untypedAtomic].
The Galax APIs provide constructors for the following data model
 values: 
- 
lists/sequences of items
- element, attribute, text, comment, and processing instruction
 nodes
- xs:string, xs:boolean, xs:int, xs:integer, xs:decimal, xs:float,
 xs:double, xs:anyURI, xs:QName, xs:dateTime, xs:date, xs:time,
 xs:yearMonthDuration, xs:dayTimeDuration, and xs: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 atomicFloat   : float -> atomicFloat
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 galax_err galax_atomicDecimal(int i, atomicDecimal *decimal);
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 elementNode : atomicQName * attribute list * node list * atomicQName -> 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 galax_err galax_textNode(atomicString str, text *);
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 -> 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 galax_err galax_parent(node n, node_list *);
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 galax_err galax_children(node n, node_list *); /* C */
The XQuery data model accessors are described in detail in the
 [XQuery 1.0 and XPath 2.0 Data Model] document.
6.4.3  Loading documents
Galax provides the [load_document] function for loading documents.
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 : Processing_context.processing_context -> 
    Galax_io.input_spec -> node list (* O'Caml *)
  extern galax_err galax_load_document(char* filename, node_list *);
  extern galax_err galax_load_document_from_string(char* string, node_list *); 
6.5  Query Evaluation
The general model for evaluating an XQuery expression or statement
 proceeds as follows (each function is described in detail below):
- 
Create default processing context:
 
 let proc_ctxt = default_processing_context() in
 
 
- Load Galax's standard library:
 
 let mod_ctxt = load_standard_library(proc_ctxt) in
 
 
- (Optionally) load any imported library modules:
     let library_input = File_Input "some-xquery-library.xq" in
     let mod_ctxt = import_library_module pc mod_ctxt library_input in
 
 
- (Optionally) load one main XQuery module:
 
 let (mod_ctxt, stmts) = import_main_module mod_ctxt (File_Input "some-main-module.xq") in
 
 
- (Optionally) initialize the context item and/or global variables
 defined in application (i.e., external environment):
     let ext_ctxt = build_external_context proc_ctxt opt_context_item var_value_list in
     let mod_ctxt = add_external_context mod_ctxt ext_ctxt in
 
 
- 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. **
 
 
- Finally, evaluate a statement from the main module or one defined
 in the application or call some XQuery function defined in the
 module context:
 
 let result = eval_statement proc_ctxt mod_ctxt stmt in
 
 let result = eval_statement_from_io proc_ctxt mod_ctxt
 (Buffer_Input some-XQuery-statement) in
 
 let result = eval_query_function proc_ctxt mod_ctxt
 "some-function" argument-values in
6.5.1  Module context
 Every query is evaluated in a [module context], which includes:
- 
the built-in types, namespaces, and functions; 
- the user-defined types, namespaces, and functions specified in
 any imported library modules; and
- 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 : processing_context -> module_context -> input_spec -> module_context
 If you need to import other library modules, this function
 returns the module_context argument extended with the module
 in the second argument.
   val import_main_module    : processing_context -> module_context -> input_spec -> 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 second argument and a list of
 statements to evaluate.
The functions for creating an external context (context item and
 global variable values):
   val build_external_context : processing_context -> (item option) ->
        (atomicDayTimeDuration option) -> (string * item list) list ->  external_context
The external context includes an optional value for the context
 item (known as "."), the (optional) local timezone, 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 : processing_context -> xquery_module -> xquery_module 
 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.
6.5.2  Evaluating queries/expressions
The APIs support three functions for evaluating a query:
 [eval_statement_from_io], [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_io : processing_context -> xquery_module -> Galax_io.input_spec -> item list
 Given the module context, evaluates the XQuery statement in
 the third 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 	   : processing_context -> xquery_module -> xquery_statement -> item list
 Given the module context, evaluates the XQuery statement 
  val eval_query_function  : processing_context -> xquery_module -> 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.
6.5.3  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           : processing_context -> Galax_io.output_spec -> item list -> unit
 (* [serialize gout x] serializes an XML value to the given
 galax output *)
    val serialize_to_string : processing_context -> item list -> string
 (* [serialize_to_string x] serializes an XML value to a string *)
Analogous functions are defined in the C API.
6.6  C API Specifics
6.6.1  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.
6.6.2  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 galax_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
6.7  Java API Specifics
6.7.1  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:6.7.2  Exceptions
All Galax Java API functions can raise the exception class
 GalapiException, which must be handled by the Java application.
6.7.3  Memory Management
All Java-C-O'Caml memory management is handled automatically in the
 Java API.
6.8  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. 
 
 
