open Galapi
(*
  
    This snippet of code illustrates how to call an XQuery function 
    from ML. 

    IF YOU ADD TESTS TO THIS FILE, YOU MUST ALSO ADD THEM TO: 
      examples/c_api/c-test.c
      examples/java_api/Test.java

 *)

let example1 () =
  try 

    (* CONSTRUCTORS *)
    (* xs:int *)
    let i = xs_int 20 in
    let s =  Galapi.serialize_to_string [i] in
    let _ = if (int_of_xs_int i != 20) then print_string "Error! roundtripping int\n" in
    let _ = print_string (s^"\n") in
 
    (* xs:integer *)
    let i' = xs_integer (Big_int.big_int_of_int 20) in
    let s =  Galapi.serialize_to_string [i'] in
    let _ = if (not(Big_int.eq_big_int (integer_of_xs_integer i') (Big_int.big_int_of_int 20))) then print_string "Error! roundtripping integer\n" in
    let _ = print_string (s^"\n") in
 
    (* xs:decimal *)
    let i'' = xs_decimal (Num.num_of_int 20) in
    let s =  Galapi.serialize_to_string [i''] in
    let _ = if (not((decimal_of_xs_decimal i'') = (Num.num_of_int 20))) then print_string "Error! roundtripping decimal\n" in
    let _ = print_string (s^"\n") in

    (* xs:string *)
    let st = xs_string "user test" in
    let s =  Galapi.serialize_to_string [st] in
    let _ = if (not(string_of_atomicvalue st = "user test")) then print_string "Error! roundtripping string\n" in
    let _ = print_string (s^"\n") in
 
    (* xs:boolean *)
    let b = xs_boolean false in
    let s =  Galapi.serialize_to_string [b] in
    let _ = if (not(boolean_of_xs_boolean b = false)) then print_string "Error! roundtripping boolean\n" in
    let _ = print_string (s^"\n") in
 
    (* xs:float *)
    let d = xs_float 98.549 in
    let s =  Galapi.serialize_to_string [d] in
    let _ = if (not(float_of_xs_float d = 98.549)) then print_string "Error! roundtripping float\n" in
    let _ = print_string (s^"\n") in

    (* xs:double *)
    let db = xs_double 98.549 in
    let s =  Galapi.serialize_to_string [db] in
    let _ = if (not(float_of_xs_double db = 98.549)) then print_string "Error! roundtripping double\n" in
    let _ = print_string (s^"\n") in

    (* load_standard_library *)
    let pc = default_processing_context () in
    let sc = load_standard_library pc in
    let cn = import_library_module sc "xq-example1.xq" in

    (* xs:QName *)
    let q = xs_QName (cn, "foo:bar") in
    let s =  Galapi.serialize_to_string [q] in
    (* No round trip for QName yet *)
    let _ = print_string (s^"\n") in
 
    (* ROUND TRIPPING *)
    (* comment *)
    let c = comment(xs_string("This is a comment")) in
    let s =  Galapi.serialize_to_string [c] in
    let _ = print_string(node_kind(c)^"\n") in
    let _ = if not(node_kind(c) = "comment") then print_string "Error! node kind != comment\n" in
    let _ = print_string (s^"\n") in
 
    (* PI *)
    let p = processing_instruction(xs_string("target"), xs_string("This is a processing instruction")) in
    let s =  Galapi.serialize_to_string [p] in
    let _ = if not(node_kind(p) = "processing instruction") then print_string "Error! node kind != processing instruction\n" in
    let _ = print_string (s^"\n") in

    (* element *)
    let e = element (q, [], [], q) in
    let s =  Galapi.serialize_to_string [e] in
    let _ = if not(node_kind(e) = "element") then print_string "Error! node kind != element\n" in
    let _ = print_string (s^"\n") in
 
    (* QName *)
    let q1 = xs_QName (cn, "baz") in
    let s =  Galapi.serialize_to_string [q1] in
    (* No round trip for QName yet *)
    let _ = print_string (s^"\n") in
 
    (* document *)
    let doc = document ("http://db.bell-labs.com/galax",[p; c; e]) in
    let s =  Galapi.serialize_to_string [doc] in
    let _ = if not(node_kind(doc) = "document") then print_string "Error! node kind != document\n" in
    let _ = print_string (s^"\n") in
 
    (* attribute *)
    let a = attribute (q1, xs_string("attribute value"), q) in
    let s =  Galapi.serialize_to_string [a] in
    let _ = if not(node_kind(a) = "attribute") then print_string "Error! node kind != attribute\n" in
    let _ = print_string (s^"\n") in
 
    (* element *)
    let e = element (q, [a], [e;e], q) in
    let s =  Galapi.serialize_to_string [e] in
    let _ = print_string (s^"\n") in

    (* node name *)
    let q1opt = node_name e in
    let _ = 
      match q1opt with 
      | None -> print_string "Error! node name is empty\n" 
      | Some q1 -> 
	  begin
	    let s =  Galapi.serialize_to_string [q1] in
	    print_string (s^"\n") 
	  end
    in

    (* children  *)
    let k = children e in 
    let s =  Galapi.serialize_to_string k in
    let _ = print_string (s^"\n") in
 
    (* parent *)
    let pr = parent (List.hd k) in 
    let s =  Galapi.serialize_to_string pr in
    let _ = print_string (s^"\n") in
 
    (* attributes *)
    let ats = attributes e in 
    let s =  Galapi.serialize_to_string ats in
    let _ = print_string (s^"\n") in
 
    (* text node *)
    let t = text (xs_string("this is a text node")) in
    let s =  Galapi.serialize_to_string [t] in
    let _ = if not(node_kind(t) = "text") then print_string "Error! node kind != text\n" in
    let _ = print_string (s^"\n") in
 
    (* serialization *)
    let docitems = Galapi.load_document "xml-example.xml" in
    let _  = Galapi.serialize_to_formatter Format.std_formatter docitems in
    let s =  Galapi.serialize_to_string docitems in
    print_string (s^"\n"); 

    (* base_uri of a document node *)
    let b = Galapi.base_uri (List.hd docitems) in
    let _  = 
      match b with 
      |	None -> print_string "Error! base uri is empty\n"
      |	Some u -> 
	  begin
	    let s =  Galapi.serialize_to_string [u] in
	    print_string (s^"\n") 
	  end
    in

    (* base_uri of an element node *)
    let b = Galapi.base_uri(List.hd(Galapi.children (List.hd docitems))) in
    let _  = 
      match b with 
      |	None -> print_string "Error! base uri is empty\n"
      |	Some u -> 
	  begin
	    let s =  Galapi.serialize_to_string [u] in
	    print_string (s^"\n") 
	  end
    in

    (* QUICK START FUNCTIONS *)
    begin
      let v = eval_statement_with_context_item_from_document "xml-example.xml" "./html/ul/li" in
      match v with 
      | None -> ()
      | Some v -> 
	  let s =  Galapi.serialize_to_string v in
	  print_string (s^"\n")
    end;

    begin
      let v = eval_statement_with_context_item_from_xml (List.hd docitems) "./html/ul/li" in
      match v with 
      | None -> ()
      | Some v -> 
	  let s =  Galapi.serialize_to_string v in
	  print_string (s^"\n")
    end; 

    begin
      let v = eval_statement_from_file_with_context_item_from_xml (List.hd docitems) "htmlpath.xq" in
      match v with
      | None -> ()
      | Some v ->
	  let s =  Galapi.serialize_to_string v in
	  print_string (s^"\n")
    end;

    begin
      let v = eval_statement_with_variables_from_xml [("v", docitems)] "$v/html/ul/li" in
      match v with 
      | None -> ()
      | Some v -> 
	  let s =  Galapi.serialize_to_string v in
	  print_string (s^"\n")
    end; 

    (* eval_query_function *)

    let v = eval_query_function cn "test2" [ [i]; [st] ] in 
    let s =  Galapi.serialize_to_string v in
    print_string (s^"\n"); 

    let v = eval_query_function cn "to_html" [ [List.hd docitems]; [i]; [st]; [d] ] in 
    let s =  Galapi.serialize_to_string v in
    print_string (s^"\n"); 

    let nv = get_node (List.hd v) in 

    let _ = Galapi.serialize_to_file "to_html.xml" v in

    (* import_main_module *)
    let (cn', stmts) = import_main_module cn "xq-example2.xq" in
    List.iter (fun s -> 
      let v = eval_statement cn s in 
      match v with 
      | None -> ()
      | Some v -> 
	  let s =  Galapi.serialize_to_string v in
	  print_string (s^"\n"))
      stmts; 

    (* eval_statement_from_string *)
    let v = eval_statement_from_string cn "test0()" in 
    match v with 
    | None -> ()
    | Some v ->
	let s =  Galapi.serialize_to_string v in
	print_string (s^"\n"); 

    let atv = get_atomicvalue (List.hd v) in

    (* eval_statement_from_string *)
    let v = eval_statement_from_string sc "20.0 * 3.3" in 
    match v with 
    | None -> ()
    | Some v ->
	let s =  Galapi.serialize_to_string v in
	print_string (s^"\n"); 

    (* import_library_module *)
    let cn2 = import_library_module sc "xmlschema_context.xq" in
    let cn3 = eval_global_variables cn2 in
    let v = eval_statement_from_string cn3 "$po/HisPo:purchaseOrder/HisPo:items/HisPo:item/HisPo:quantity" in     
    match v with 
    | None -> ()
    | Some v ->
	let s =  Galapi.serialize_to_string v in
	print_string (s^"\n"); 
  
    (* typed_value *)
    let atv = typed_value(List.hd(v)) in 
    let s =  Galapi.serialize_to_string atv in
    print_string (s^":"^(item_kind(List.hd atv))^"\n"); 

    (* external context *)
    let exc = build_external_context None [("x", docitems); ("y", [i])] in
    let cn4 = add_external_context cn3 exc in
    let v = eval_statement_from_string cn4 "$x" in
    match v with 
    | None -> ()
    | Some v ->
	let s =  Galapi.serialize_to_string v in
	print_string (s^"\n"); 

    let v = eval_statement_from_string cn4 "$y" in
    match v with 
    | None -> ()
    | Some v ->
	let s =  Galapi.serialize_to_string v in
	print_string (s^"\n"); 

    (* Raise an error intentionally -- always do this last *)
    print_string("Raise an error intentionally:\n"); 
    let docitems = Galapi.load_document "no-such-file.xml" in
    print_string("We shouldn't be here!\n");

  with

    (* Any errors raised by Galax are printed to stderr *)
    | exn -> Error.printf_error "" exn; print_string("\n")
	
let _ =
  example1 ()

