/***********************************************************************/
/*                                                                     */
/*                                 GALAX                               */
/*                              XQuery Engine                          */
/*                                                                     */
/*  Copyright 2001-2003, Lucent Technologies.                          */
/*  Distributed only by permission.                                    */
/*                                                                     */
/*  IF YOU ADD TESTS TO THIS FILE, YOU MUST ALSO ADD THEM TO:          */
/*    examples/c_api/c-test.c                                          */
/*    examples/caml_api/ml-test.ml                                     */
/***********************************************************************/

/* $Id: c-test.c,v 1.7 2003/06/27 16:52:00 mff Exp $ */

/* A sample C client for the Caml functions */

#include <stdio.h>

#include "glx.h"

#define exit_on_error(_Expr) {err = _Expr; if (err != 0) {printf("%s\n", glx_error_string); exit(err);}}	

int main(int argc, char ** argv)
{
  char *fake_argv[2], *vars[4];

  itemlist items, docitems, dl, il, fl, sl, args[4], el, ats, k, pr, v, bl, nl;
  item i, i1, i2, s, s1, s2, b, d, db, t, c, p, q, e, a, av, nv, q1, doc;

  module_context cn, cn2, cn3, cn4, sc;
  processing_context pc; 
  query_context qc;
  external_context exc;
  char *str, *str1;
  int j;
  double f;
  glx_err err;

  glx_init();

  /* CONSTRUCTORS */
  /* xs:int */
  err = glx_xs_int(20, &i);
  err = glx_serialize_to_string(itemlist_cons(i, itemlist_empty()), &str);
  err = glx_int_of_xs_int(i, &j);
  if (j != 20) printf("Error! roundtripping int\n");
  printf("%s\n", str); fflush(stdout); 

    /* xs:integer */
  err = glx_xs_integer(20, &i1);
  err = glx_serialize_to_string(itemlist_cons(i1, itemlist_empty()), &str);
  err = glx_integer_of_xs_integer(i1, &j);
  if (j != 20)  printf("Error! roundtripping integer\n");
  printf("%s\n", str); fflush(stdout); 

    /* xs:decimal */
  err = glx_xs_decimal(20, &i2);
  err = glx_serialize_to_string(itemlist_cons(i2, itemlist_empty()), &str);
  err = glx_decimal_of_xs_decimal(i2, &j);
  if (j != 20)  printf("Error! roundtripping decimal\n");
  printf("%s\n", str); fflush(stdout); 

  /* xs:string */
  err = glx_xs_string("user test", &s);
  err = glx_string_of_atomicvalue(s, &str);
  if (strcmp(str, "user test") != 0)  printf("Error! roundtripping string\n");
  err = glx_serialize_to_string(itemlist_cons(s, itemlist_empty()), &str);
  printf("%s\n", str); fflush(stdout); 

    /* xs:boolean */
  err = glx_xs_boolean(0, &b );
  err = glx_serialize_to_string(itemlist_cons(b, itemlist_empty()), &str);
  err = glx_boolean_of_xs_boolean(b, &j);
  if (j != 0)  printf("Error! roundtripping boolean\n");
  printf("%s\n", str); fflush(stdout); 
  
    /* xs:float */
  err = glx_xs_float(98.549, &d);
  err = glx_serialize_to_string(itemlist_cons(d, itemlist_empty()), &str);
  err = glx_float_of_xs_float(d, &f);
  if (f != 98.549)  printf("Error! roundtripping float\n");
  printf("%s\n", str); fflush(stdout); 

    /* xs:double */
  err = glx_xs_double(98.549, &db);
  err = glx_serialize_to_string(itemlist_cons(db, itemlist_empty()), &str);
  err = glx_float_of_xs_double(db, &f);
  if (f != 98.549)  printf("Error! roundtripping double\n");
  printf("%s\n", str); fflush(stdout); 

  /* load_standard_library */
  err = glx_default_processing_context(&pc); 
  err = glx_load_standard_library(pc, &sc); 
  err = glx_import_library_module(sc, "xq-example1.xq", &cn);

    /* xs:QName */
  err = glx_xs_QName(cn, "foo:bar", &q);
  err = glx_serialize_to_string(itemlist_cons(q, itemlist_empty()), &str);
  printf("%s\n", str);  fflush(stdout); 

    /* ROUND TRIPPING */
    /* comment */
  err = glx_xs_string("This is a comment", &s1);
  err = glx_comment (s1, &c); 
  err = glx_node_kind(c, &str); 
  printf("%s\n", str);  fflush(stdout); 
  err = glx_node_kind(c, &str);
  if (strcmp(str, "comment") != 0)  printf ("Error! node kind != comment\n");

  err = glx_serialize_to_string(itemlist_cons(c, itemlist_empty()), &str);
  printf("%s\n", str);  fflush(stdout); 

    /* PI */
  err = glx_xs_string("target", &s2);
  err = glx_xs_string("This is a processing instruction", &s1);
  err = glx_processing_instruction (s2, s1, &p); 
  err = glx_node_kind(p, &str);
  if (strcmp(str, "processing instruction") != 0)  printf ("Error! node kind != processing instruction\n");
  err = glx_serialize_to_string(itemlist_cons(p, itemlist_empty()), &str);
  printf("%s\n", str);  fflush(stdout); 
 
    /* element */
  err = glx_element (q, itemlist_empty(), itemlist_empty() ,q, &e ); 
  err = glx_node_kind(e, &str);
  if (strcmp(str, "element") != 0)  printf ("Error! node kind != element\n");
  err = glx_serialize_to_string(itemlist_cons(e, itemlist_empty()), &str);
  printf("%s\n", str);  fflush(stdout); 

  /* QName */ 
  err = glx_xs_QName(cn, "baz", &q1);
  err = glx_serialize_to_string(itemlist_cons(q1, itemlist_empty()), &str);
  printf("%s\n", str);  fflush(stdout); 

  /* attribute */
  err = glx_xs_string("attribute value", &s1);
  err = glx_attribute(q1, s1, q1, &a); 
  err = glx_node_kind(a, &str);
  if (strcmp(str, "attribute") != 0)  printf ("Error! node kind != attribute\n");
  err = glx_serialize_to_string(itemlist_cons(a, itemlist_empty()), &str);
  printf("%s\n", str);  fflush(stdout); 

  /* element */
  el = itemlist_cons(e, itemlist_empty()); 
  err = glx_element (q, itemlist_cons(a, itemlist_empty()), el ,q, &e); 
  err = glx_serialize_to_string(itemlist_cons(e, itemlist_empty()), &str);
  printf("%s\n", str);  fflush(stdout); 

  /* document */
  el = itemlist_cons(p, itemlist_cons(c, itemlist_cons(e, itemlist_empty())));
  err = glx_document("http://db.bell-labs.com/galax", el, &doc); 
  err = glx_serialize_to_string(itemlist_cons(doc, itemlist_empty()), &str);
  printf("%s\n", str);  fflush(stdout); 
 
  /* node name */
  err = glx_node_name(e, &nl); 
  if (is_empty(nl)) 
    printf ("Error! node name is empty\n"); 
  else {
    err = glx_serialize_to_string(nl, &str);
    printf("%s\n", str); fflush(stdout); 
  }	

  /* children */
  err = glx_children(e, &k); 
  err = glx_serialize_to_string(k, &str);
  printf("%s\n", str); fflush(stdout); 

  /* parent */
  err = glx_parent(items_first(k), &pr); 
  err = glx_serialize_to_string(pr, &str);
  printf("%s\n", str); fflush(stdout); 

  /* attributes */
  err = glx_attributes(e, &ats); 
  err = glx_serialize_to_string(ats, &str);
  printf("%s\n", str); fflush(stdout); 

  /* text node */
  err = glx_xs_string("this is a text node", &s1);
  err = glx_text (s1, &t); 
  err = glx_node_kind(t, &str);
  if (strcmp(str, "text") != 0)  printf ("Error! node kind != text\n");
  err = glx_serialize_to_string(itemlist_cons(t, itemlist_empty()), &str);
  printf("%s\n", str);  fflush(stdout); 

  /* serialization */
  err = glx_load_document("xml-example.xml", &docitems); 
  err = glx_serialize_to_output_channel(docitems);
  err = glx_serialize_to_string(docitems, &str);
  printf("%s\n", str); fflush(stdout); 

  /* base_uri of a document node */
  err = glx_base_uri(items_first(docitems), &bl);
  if (is_empty(bl)) 
    printf ("Error! base uri is empty\n"); 
  else {
    err = glx_serialize_to_string(bl, &str);
    printf("%s\n", str); fflush(stdout); 
  }	

  /* base_uri of an element node */
  err = glx_children(items_first(docitems), &k);
  err = glx_base_uri(items_first(k), &bl);
  if (is_empty(bl)) 
    printf ("Error! base uri is empty\n"); 
  else {
    err = glx_serialize_to_string(bl, &str);
    printf("%s\n", str); fflush(stdout); 
  }	

  /* QUICK START FUNCTIONS */
  err = glx_eval_statement_with_context_item_from_document("xml-example.xml", "/html/ul/li", &v);
  err = glx_serialize_to_string(v, &str);
  printf("%s\n", str); fflush(stdout); 

  err = glx_eval_statement_with_context_item_from_xml(items_first(docitems), "/html/ul/li", &v);
  err = glx_serialize_to_string(v, &str);
  printf("%s\n", str); fflush(stdout); 

  err = glx_eval_statement_from_file_with_context_item_from_xml(items_first(docitems), "htmlpath.xq", &v);
  err = glx_serialize_to_string(v, &str);
  printf("%s\n", str); fflush(stdout); 

  vars[0] = "v"; 
  args[0] = docitems;  
  err = glx_eval_statement_with_variables_from_xml(vars, args, 1, "$v/html/ul/li", &v);
  err = glx_serialize_to_string(v, &str);
  printf("%s\n", str); fflush(stdout); 

  /* eval_query_function */
  args[0] = itemlist_cons(i, NULL); 
  args[1] = itemlist_cons(s, NULL); 
  err  = glx_eval_query_function(cn, "test2", args, 2, &items);
  err = glx_serialize_to_string(items, &str);
  printf("%s\n", str); fflush(stdout); 

  args[0] = docitems;
  args[1] = itemlist_cons(i, NULL); 
  args[2] = itemlist_cons(s, NULL); 
  args[3] = itemlist_cons(d, NULL);
  err  = glx_eval_query_function(cn, "to_html", args, 4, &items);
  err = glx_serialize_to_string(items, &str);
  printf("%s\n", str); fflush(stdout); 

  err = glx_get_node (items_first(items), &nv); 

  err = glx_serialize_to_file("to_html.xml", items);

    /* import_main_module */
  err = glx_import_main_module(cn, "xq-example2.xq", &qc); 
  err = glx_eval_statements(qc, &items);
  err = glx_serialize_to_string(items, &str);
  printf("%s\n", str); fflush(stdout); 

  /* eval_statement_from_string */
  err  = glx_eval_statement_from_string(cn, "test0()", &items);
  err = glx_serialize_to_string(items, &str);
  printf("%s\n", str); fflush(stdout); 

  err = glx_get_atomicvalue (items_first(items), &av); 

  /* eval_statement_from_string */
  err = glx_eval_statement_from_string(cn, "20.0 * 3.3", &items);
  err = glx_serialize_to_string(items, &str);
  printf("%s\n", str); fflush(stdout); 

  /* import_main_module */
  err = glx_import_library_module(sc, "xmlschema_context.xq", &cn2);
  err = glx_eval_global_variables(cn2, &cn3);
  err = glx_eval_statement_from_string(cn3, "$po/HisPo:purchaseOrder/HisPo:items/HisPo:item/HisPo:quantity", &items );
  err = glx_serialize_to_string(items, &str);
  printf("%s\n", str); fflush(stdout); 

  /* typed value */
  err = glx_typed_value(items_first(items), &ats);
  err = glx_serialize_to_string(ats, &str);
  err = glx_item_kind(items_first(ats), &str1);
  printf("%s:%s\n", str, str1);
  fflush(stdout); 

  /* external context */
  vars[0] = "x";
  args[0] = docitems;
  vars[1] = "y"; 
  args[1] = itemlist_cons(i, NULL); 
  err = glx_build_external_context (itemlist_empty(), vars, args, 2, &exc); 
  err = glx_add_external_context(cn3, exc, &cn4);

  err = glx_eval_statement_from_string(cn4, "$x", &items);
  err = glx_serialize_to_string(items, &str);
  printf("%s\n", str); fflush(stdout); 

  err = glx_eval_statement_from_string(cn4, "$y", &items);
  err = glx_serialize_to_string(items, &str);
  printf("%s\n", str); fflush(stdout); 

  /* Raise an error intentionally */
  printf("Raise an error intentionally:\n"); 
  exit_on_error(glx_load_document("no-such-file.xml", &docitems)); 
  return 0;
}
