Fixed XQDoc.

Fixed XQDoc.

xquery version "1.0";

(:
 : Copyright 2006-2012 The FLWOR Foundation.
 :
 : Licensed under the Apache License, Version 2.0 (the "License");
 : you may not use this file except in compliance with the License.
 : You may obtain a copy of the License at
 :
 : http://www.apache.org/licenses/LICENSE-2.0
 :
 : Unless required by applicable law or agreed to in writing, software
 : distributed under the License is distributed on an "AS IS" BASIS,
 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 : See the License for the specific language governing permissions and
 : limitations under the License.
:)

(:~
 : This module provides the functions defined by the JSONiq specification,
 : sections 1.7 (Functions) and 1.10 (Update Primitives). JSONiq extends
 : the XQuery specification to also deal with JSON data natively. See
 :
 :     http://www.jsoniq.org/
 :
 : for details.
 :
 : This module depends on having the JSONiq feature enabled in Zorba,
 : i.e., Zorba must be compiled with ZORBA_WITH_JSON.
 :
 : @author Markos Zaharioudakis, Matthias Brantner, Ghislain Fourny
 :)
module namespace jn = "http://www.jsoniq.org/functions";

import module namespace schema = "http://www.zorba-xquery.com/modules/schema";

declare namespace jdm = "http://www.jsoniq.org/";

declare namespace err = "http://www.w3.org/2005/xqt-errors";

declare namespace ver = "http://www.zorba-xquery.com/options/versioning";
declare option ver:module-version "1.0";

(:~
 : This function has the same semantics as fn:parse-xml(), except that
 : it parses the string as JSON (not XML), and returns an Object or
 : Array rather than an XML document.
 :
 : @param $j A string containing a valid JSON text.
 : @return a JSON Object or Array item.
 :)
declare function jn:parse-json($j as xs:string) as json-item()? external;

(:~
 : Returns the names used in the object.
 : The names will be returned in an implementation-defined order
 :
 : @param $o A JSON Object.
 : @return The names of pairs in the object.
 :)
declare function jn:keys($o as object()) as xs:string* external;

(:~
 : Returns the value of a JSON Pair with a given name within a given JSON object.
 : If no such pair exists in the object, returns the empty sequence.
 :
 : @param $o A JSON Object.
 : @param $name The name of the pair whose value is to be retrieved
 : @return the value of specified pair within the given object, or the empty sequence.
 :)
(: obsolete - use $o($name) instead :)
declare function jn:value($o as object(), $name as xs:string) as item()? external;

(:~
 : Returns the size of a JSON Array. The size of an Array is
 : the number of members contained within it.
 :
 : @param $j A JSON Array.
 : @return The number of items in $j.
 :)
declare function jn:size($j as array()) as xs:integer external;

(:~
 : Returns the member of an Array at the specified position (starting from 1).
 : If the position is out of bounds of the array, returns the empty sequence.
 :
 : @param $a A JSON Array.
 : @param $p The position in the array.
 : @return The member at the specified position, or empty sequence.
 :)
(: obsolete - use $a($p) instead :)
declare function jn:member($a as array(), $p as xs:integer) as item()? external;

(:~
 : Creates an object from the specified pairs of another given object.
 : Specifically, for each name in $names, if the object $o has a pair with
 : that name, then a copy of that pair is included in the new object.
 :
 : @param $o A JSON Object.
 : @param $names The names of the pairs to copy out of $o and insert into the new object
 : @return The new object.
 :)
declare function jn:project($o as object(), $names as xs:string*) as object() external;

(:~
 : Returns the members of an Array.
 :
 : @param $a A JSON Array.
 : @return The members of the specified array.
 :)
declare function jn:members($o as array()) as item()* external;

(:~
 : Recursively "flatten" a JSON Array, by replacing any arrays with their
 : members. Equivalent to
 :
 :   define function jn:flatten($arg as array()) {
 :     for $value in jn:values($arg)
 :     return
 :       if ($value instance of array())
 :       then jn:flatten($value)
 :       else $value
 :   };
 :
 : @param $a A JSON Array.
 : @return The flattened version of $a.
 :)
declare function jn:flatten($a as array()) as item()* external;

(:~
 : This function allows dynamic object construction by merging all
 : its object parameters into a single object with a so-called "simple
 : object union". A simple object union creates a new object, the pairs
 : property of which is obtained by accumulating the pairs of all operand
 : objects. An error jerr:JNDY0003 is raised if two pairs with the same
 : name are encountered.
 :
 : @param $o A sequence of objects.
 : @return The simple object union.
 :)
declare function jn:object($o as object()*) as object()
{
  {| $o |}
};

(:~
 : This function dynamically builds an object, like jn:object, except that
 : it does not throw an error upon pair collision. Instead, it aggregates them
 : into an array.
 :
 : @param $o A sequence of objects.
 : @return The accumulated object.
 :)
declare function jn:accumulate($o as object()*) as object()
{
  {[ $o ]}
};

(:~
 : This function returns all Objects contained within a JSON item, regardless of
 : depth.
 :
 : @param $i A JSON item.
 : @return Its descendant objects.
 :)
declare function jn:descendant-objects($i as json-item()) as object()*
{
  if ($i instance of object())
  then
    (
      $i,
      for $v in jn:values($i)
      where $v instance of json-item()
      return jn:descendant-objects($v)
    )
  else if ($i instance of array())
  then
    (
      for $v in jn:members($i)
      where $v instance of json-item()
      return jn:descendant-objects($v)
    )
  else
    ()
};

(:~
 : This function returns all pairs contained within an object, recursively.
 :
 : @param $o An object.
 : @return All direct and indirect descendant pairs.
 :)
declare function jn:descendant-pairs($o as object())
{
  for $k in jn:keys($o)
  return (
    { $k : $o($k) },
    if ($o($k) instance of object())
    then
      jn:descendant-pairs($o($k))
    else ()
  )
};

(:~ This function returns the intersection of two objects, and aggregates
 : values corresponding to the same name into an array.
 :
 : @param $o A sequence of objects.
 : @return Their insersection.
 :)
declare function jn:intersect($o as object()*)
{
  {|
    let $common-keys := jn:keys($o[1])[ every $object in $o[position() > 1]
                                           satisfies jn:keys($object) = . ]
    for $key in $common-keys
    let $values := $o($key)
    return
      if (count($values) eq 1)
      then { $key : $values }
      else { $key : [ $values ] }
  |}
};

(:~
 : This functions returns all values in an Object.
 : @param $i An object.
 : @return Its values.
 :)
declare function jn:values($i as object()) as item()*
{
  for $k in jn:keys($i)
  return $i($k)
};

xquery version "1.0";

(:
 : Copyright 2006-2012 The FLWOR Foundation.
 :
 : Licensed under the Apache License, Version 2.0 (the "License");
 : you may not use this file except in compliance with the License.
 : You may obtain a copy of the License at
 :
 : http://www.apache.org/licenses/LICENSE-2.0
 :
 : Unless required by applicable law or agreed to in writing, software
 : distributed under the License is distributed on an "AS IS" BASIS,
 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 : See the License for the specific language governing permissions and
 : limitations under the License.
:)

(:~
 : This module provides the functions defined by the JSONiq specification,
 : sections 1.7 (Functions) and 1.10 (Update Primitives). JSONiq extends
 : the XQuery specification to also deal with JSON data natively. See
 :
 :     http://www.jsoniq.org/
 :
 : for details.
 :
 : This module depends on having the JSONiq feature enabled in Zorba,
 : i.e., Zorba must be compiled with ZORBA_WITH_JSON.
 :
 : @author Markos Zaharioudakis, Matthias Brantner, Ghislain Fourny
 :)
module namespace jn = "http://www.jsoniq.org/functions";

import module namespace schema = "http://www.zorba-xquery.com/modules/schema";

declare namespace jdm = "http://www.jsoniq.org/";

declare namespace err = "http://www.w3.org/2005/xqt-errors";

declare namespace ver = "http://www.zorba-xquery.com/options/versioning";
declare option ver:module-version "1.0";

(:~
 : This function has the same semantics as fn:parse-xml(), except that
 : it parses the string as JSON (not XML), and returns an Object or
 : Array rather than an XML document.
 :
 : @param $j A string containing a valid JSON text.
 : @return a JSON Object or Array item.
 :)
declare function jn:parse-json($j as xs:string) as json-item()? external;

(:~
 : Returns the names used in the object.
 : The names will be returned in an implementation-defined order
 :
 : @param $o A JSON Object.
 : @return The names of pairs in the object.
 :)
declare function jn:keys($o as object()) as xs:string* external;

(:~
 : Returns the value of a JSON Pair with a given name within a given JSON object.
 : If no such pair exists in the object, returns the empty sequence.
 :
 : @param $o A JSON Object.
 : @param $name The name of the pair whose value is to be retrieved
 : @return the value of specified pair within the given object, or the empty sequence.
 :)
(: obsolete - use $o($name) instead :)
declare function jn:value($o as object(), $name as xs:string) as item()? external;

(:~
 : Returns the size of a JSON Array. The size of an Array is
 : the number of members contained within it.
 :
 : @param $j A JSON Array.
 : @return The number of items in $j.
 :)
declare function jn:size($j as array()) as xs:integer external;

(:~
 : Returns the member of an Array at the specified position (starting from 1).
 : If the position is out of bounds of the array, returns the empty sequence.
 :
 : @param $a A JSON Array.
 : @param $p The position in the array.
 : @return The member at the specified position, or empty sequence.
 :)
(: obsolete - use $a($p) instead :)
declare function jn:member($a as array(), $p as xs:integer) as item()? external;

(:~
 : Creates an object from the specified pairs of another given object.
 : Specifically, for each name in $names, if the object $o has a pair with
 : that name, then a copy of that pair is included in the new object.
 :
 : @param $o A JSON Object.
 : @param $names The names of the pairs to copy out of $o and insert into the new object
 : @return The new object.
 :)
declare function jn:project($o as object(), $names as xs:string*) as object() external;

(:~
 : Returns the members of an Array.
 :
 : @param $a A JSON Array.
 : @return The members of the specified array.
 :)
declare function jn:members($o as array()) as item()* external;

(:~
 : Recursively "flatten" a JSON Array, by replacing any arrays with their
 : members. Equivalent to
 :
 :   define function jn:flatten($arg as array()) {
 :     for $value in jn:values($arg)
 :     return
 :       if ($value instance of array())
 :       then jn:flatten($value)
 :       else $value
 :   };
 :
 : @param $a A JSON Array.
 : @return The flattened version of $a.
 :)
declare function jn:flatten($a as array()) as item()* external;

(:~
 : This function allows dynamic object construction by merging all
 : its object parameters into a single object with a so-called "simple
 : object union". A simple object union creates a new object, the pairs
 : property of which is obtained by accumulating the pairs of all operand
 : objects. An error jerr:JNDY0003 is raised if two pairs with the same
 : name are encountered.
 :
 : @param $o A sequence of objects.
 : @return The simple object union.
 :)
declare function jn:object($o as object()*) as object()
{
  {| $o |}
};

(:~
 : This function dynamically builds an object, like jn:object, except that
 : it does not throw an error upon pair collision. Instead, it aggregates them
 : into an array.
 :
 : @param $o A sequence of objects.
 : @return The accumulated object.
 :)
declare function jn:accumulate($o as object()*) as object()
{
  {[ $o ]}
};

(:~
 : This function returns all Objects contained within a JSON item, regardless of
 : depth.
 :
 : @param A JSON item.
 : @return Its descendant objects.
 :)
declare function jn:descendant-objects($i as json-item()) as object()*
{
  if ($i instance of object())
  then
    (
      $i,
      for $v in jn:values($i)
      where $v instance of json-item()
      return jn:descendant-objects($v)
    )
  else if ($i instance of array())
  then
    (
      for $v in jn:members($i)
      where $v instance of json-item()
      return jn:descendant-objects($v)
    )
  else
    ()
};

(:~
 : This function returns all pairs contained within an object, recursively.
 :
 : @param An object.
 : @return All direct and indirect descendant pairs.
 :)
declare function jn:descendant-pairs($o as object())
{
  for $k in jn:keys($o)
  return (
    { $k : $o($k) },
    if ($o($k) instance of object())
    then
      jn:descendant-pairs($o($k))
    else ()
  )
};

(:~ This function returns the intersection of two objects, and aggregates
 : values corresponding to the same name into an array.
 :
 : @param $o A sequence of objects.
 : @return Their insersection.
 :)
declare function jn:intersect($o as object()*)
{
  {|
    let $common-keys := jn:keys($o[1])[ every $object in $o[position() > 1]
                                           satisfies jn:keys($object) = . ]
    for $key in $common-keys
    let $values := $o($key)
    return
      if (count($values) eq 1)
      then { $key : $values }
      else { $key : [ $values ] }
  |}
};

(:~
 : This functions returns all values in an Object.
 : @param $i An object.
 : @return Its values.
 :)
declare function jn:values($i as object()) as item()*
{
  for $k in jn:keys($i)
  return $i($k)
};


fixed query

fixed query

import module namespace ddl = "http://www.zorba-xquery.com/module/ddl";
import module namespace dc = "http://www.zorba-xquery.com/module/dynamic-context";
import datamodule namespace ns = "http://example.org/datamodule/" at "modifier_1.xqdata";

declare sequential function local:init() {
  (
    ddl:create-collection($ns:coll_1, (<x/>,<y/>)),
    ddl:create-collection($ns:coll_2, (<x/>,<y/>)),
    ddl:create-collection($ns:coll_3, (<x/>,<y/>))
  );
};

declare sequential function local:testa_1() {
  try {
    block {
      ddl:insert-nodes-first($ns:coll_1, <a/>);
    }
  } catch * ($error) {
    ("a",$error)
  }
};

declare sequential function local:testa_2() {
  try {
    block {
      ddl:insert-nodes-first($ns:coll_2, <a/>);
    }
  } catch * ($error) {
    ("a",$error)
  }
};

declare sequential function local:testa_3() {
  try {
    block {
      ddl:insert-nodes-first($ns:coll_3, <a/>);
    }
  } catch * ($error) {
    ("a",$error)
  }
};

declare sequential function local:testb_1() {
  try {
    block {
      ddl:insert-nodes-last($ns:coll_1, <b/>);
    }
  } catch * ($error) {
    ("b",$error)
  }
};

declare sequential function local:testb_2() {
  ddl:insert-nodes-last($ns:coll_2, <b/>);
};

declare sequential function local:testb_3() {
  ddl:insert-nodes-last($ns:coll_3, <b/>);
};

declare sequential function local:testc_1() {
  try {
    block {
      ddl:insert-nodes-before($ns:coll_1, dc:collection($ns:coll_1)[1], <c/>);
    }
  } catch * ($error) {
    ("c",$error)
  }
};

declare sequential function local:testc_2() {
  try {
    block {
      ddl:insert-nodes-before($ns:coll_2, dc:collection($ns:coll_2)[1], <c/>);
    }
  } catch * ($error) {
    ("c",$error)
  }
};

declare sequential function local:testc_3() {
  try {
    block {
      ddl:insert-nodes-before($ns:coll_3, dc:collection($ns:coll_3)[1], <c/>);
    }
  } catch * ($error) {
    ("c",$error)
  }
};

declare sequential function local:testd_1() {
  try {
    block {
      ddl:insert-nodes-after($ns:coll_1, dc:collection($ns:coll_1)[last()], <d/>);
    }
  } catch * ($error) {
    ("d",$error)
  }
};

declare sequential function local:testd_2() {
  try {
    block {
      ddl:insert-nodes-after($ns:coll_2, dc:collection($ns:coll_2)[last()], <d/>);
    }
  } catch * ($error) {
    ("d",$error)
  }
};

declare sequential function local:testd_3() {
  try {
    block {
      ddl:insert-nodes-after($ns:coll_3, dc:collection($ns:coll_3)[last()], <d/>);
    }
  } catch * ($error) {
    ("d",$error)
  }
};

declare sequential function local:teste_1() {
  try {
    block {
      ddl:insert-nodes-at($ns:coll_1, 1, <e/>);
    }
  } catch * ($error) {
    ("e",$error)
  }
};

declare sequential function local:teste_2() {
  try {
    block {
      ddl:insert-nodes-at($ns:coll_2, 1, <e/>);
    }
  } catch * ($error) {
    ("e",$error)
  }
};

declare sequential function local:teste_3() {
  try {
    block {
      ddl:insert-nodes-at($ns:coll_3, 1, <e/>);
    }
  } catch * ($error) {
    ("e",$error)
  }
};

declare sequential function local:main() {
  local:init();
  (
    local:testa_1(),
    local:testa_2(),
    local:testa_3(),
    local:testb_1(),
    local:testb_2(),
    local:testb_3(),
    local:testc_1(),
    local:testc_2(),
    local:testc_3(),
    local:testd_1(),
    local:testd_2(),
    local:testd_3(),
    local:teste_1(),
    local:teste_2(),
    local:teste_3(),
    <coll_1>{dc:collection($ns:coll_1)}</coll_1>,
    <coll_2>{dc:collection($ns:coll_2)}</coll_2>,
    <coll_3>{dc:collection($ns:coll_3)}</coll_3>
  );
};

local:main()

import module namespace ddl = "http://www.zorba-xquery.com/module/ddl";
import module namespace dc = "http://www.zorba-xquery.com/module/dynamic-context";
import datamodule namespace ns = "http://example.org/datamodule/" at "modifier_1.xqdata";

declare sequential function local:init() {
  (
    ddl:create-collection($ns:coll_1, (<x/>,<y/>)),
    ddl:create-collection($ns:coll_2, (<x/>,<y/>)),
    ddl:create-collection($ns:coll_3, (<x/>,<y/>))
  );
};

declare function local:testa_1() {
  try {
    block {
      ddl:insert-nodes-first($ns:coll_1, <a/>);
    }
  } catch * ($error) {
    ("a",$error)
  }
};

declare function local:testa_2() {
  try {
    block {
      ddl:insert-nodes-first($ns:coll_2, <a/>);
    }
  } catch * ($error) {
    ("a",$error)
  }
};

declare function local:testa_3() {
  try {
    block {
      ddl:insert-nodes-first($ns:coll_3, <a/>);
    }
  } catch * ($error) {
    ("a",$error)
  }
};

declare function local:testb_1() {
  try {
    block {
      ddl:insert-nodes-last($ns:coll_1, <b/>);
    }
  } catch * ($error) {
    ("b",$error)
  }
};

declare sequential function local:testb_2() {
  ddl:insert-nodes-last($ns:coll_2, <b/>);
};

declare sequential function local:testb_3() {
  ddl:insert-nodes-last($ns:coll_3, <b/>);
};

declare function local:testc_1() {
  try {
    block {
      ddl:insert-nodes-before($ns:coll_1, dc:collection($ns:coll_1)[1], <c/>);
    }
  } catch * ($error) {
    ("c",$error)
  }
};

declare function local:testc_2() {
  try {
    block {
      ddl:insert-nodes-before($ns:coll_2, dc:collection($ns:coll_2)[1], <c/>);
    }
  } catch * ($error) {
    ("c",$error)
  }
};

declare function local:testc_3() {
  try {
    block {
      ddl:insert-nodes-before($ns:coll_3, dc:collection($ns:coll_3)[1], <c/>);
    }
  } catch * ($error) {
    ("c",$error)
  }
};

declare function local:testd_1() {
  try {
    block {
      ddl:insert-nodes-after($ns:coll_1, dc:collection($ns:coll_1)[last()], <d/>);
    }
  } catch * ($error) {
    ("d",$error)
  }
};

declare function local:testd_2() {
  try {
    block {
      ddl:insert-nodes-after($ns:coll_2, dc:collection($ns:coll_2)[last()], <d/>);
    }
  } catch * ($error) {
    ("d",$error)
  }
};

declare function local:testd_3() {
  try {
    block {
      ddl:insert-nodes-after($ns:coll_3, dc:collection($ns:coll_3)[last()], <d/>);
    }
  } catch * ($error) {
    ("d",$error)
  }
};

declare function local:teste_1() {
  try {
    block {
      ddl:insert-nodes-at($ns:coll_1, 1, <e/>);
    }
  } catch * ($error) {
    ("e",$error)
  }
};

declare function local:teste_2() {
  try {
    block {
      ddl:insert-nodes-at($ns:coll_2, 1, <e/>);
    }
  } catch * ($error) {
    ("e",$error)
  }
};

declare function local:teste_3() {
  try {
    block {
      ddl:insert-nodes-at($ns:coll_3, 1, <e/>);
    }
  } catch * ($error) {
    ("e",$error)
  }
};

declare sequential function local:main() {
  local:init();
  (
    local:testa_1(),
    local:testa_2(),
    local:testa_3(),
    local:testb_1(),
    local:testb_2(),
    local:testb_3(),
    local:testc_1(),
    local:testc_2(),
    local:testc_3(),
    local:testd_1(),
    local:testd_2(),
    local:testd_3(),
    local:teste_1(),
    local:teste_2(),
    local:teste_3(),
    <coll_1>{dc:collection($ns:coll_1)}</coll_1>,
    <coll_2>{dc:collection($ns:coll_2)}</coll_2>,
    <coll_3>{dc:collection($ns:coll_3)}</coll_3>
  );
};

local:main()


ordering in one test

ordering in one test

import module namespace ddl = "http://www.zorba-xquery.com/modules/store/static/collections/ddl";
import module namespace dml = "http://www.zorba-xquery.com/modules/store/static/collections/dml";
import module namespace ns = "http://example.org/datamodule/" at "collections.xqdata";
import module namespace ref = "http://www.zorba-xquery.com/modules/node-reference";

declare namespace ann = "http://www.zorba-xquery.com/annotations";

declare function local:order($items)
{
  for $item in $items
  order by fn:local-name($item)
  return $item
};

declare %ann:sequential function local:test()
{
  ddl:create(xs:QName("ns:test2"));
  dml:insert-nodes(xs:QName("ns:test2"), <a/>);
  dml:insert-nodes(xs:QName("ns:test2"), <b/>);
  dml:insert-nodes(xs:QName("ns:test2"), (<c/>, <d/>, <e/>));
  (
    local:order(dml:collection(xs:QName("ns:test2"), 3)), <delim/>,
    local:order(dml:collection(xs:QName("ns:test2"), -1)), <delim/>,
    let $ref := ref:node-reference(dml:collection(xs:QName("ns:test2"))[3])
    return local:order(dml:collection(xs:QName("ns:test2"), $ref, 0))
  )
};

local:test()

import module namespace ddl = "http://www.zorba-xquery.com/modules/store/static/collections/ddl";
import module namespace dml = "http://www.zorba-xquery.com/modules/store/static/collections/dml";
import module namespace ns = "http://example.org/datamodule/" at "collections.xqdata";
import module namespace ref = "http://www.zorba-xquery.com/modules/node-reference";

declare namespace ann = "http://www.zorba-xquery.com/annotations";

declare %ann:sequential function local:test()
{
  ddl:create(xs:QName("ns:test2"));
  dml:insert-nodes(xs:QName("ns:test2"), <a/>);
  dml:insert-nodes(xs:QName("ns:test2"), <b/>);
  dml:insert-nodes(xs:QName("ns:test2"), (<c/>, <d/>, <e/>));
  (
    dml:collection(xs:QName("ns:test2"), 3), <delim/>,
    dml:collection(xs:QName("ns:test2"), -1), <delim/>,
    let $ref := ref:node-reference(dml:collection(xs:QName("ns:test2"))[3])
    return dml:collection(xs:QName("ns:test2"), $ref, 0)
  )
};

local:test()


More verbose explanation of return.

More verbose explanation of return.

xquery version "3.0";

(:
 : Copyright 2006-2011 The FLWOR Foundation.
 :
 : Licensed under the Apache License, Version 2.0 (the "License");
 : you may not use this file except in compliance with the License.
 : You may obtain a copy of the License at
 :
 : http://www.apache.org/licenses/LICENSE-2.0
 :
 : Unless required by applicable law or agreed to in writing, software
 : distributed under the License is distributed on an "AS IS" BASIS,
 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 : See the License for the specific language governing permissions and
 : limitations under the License.
 :)

(:===========================================================================:)

(:~
 : This module provides an XQuery API to full-text functions.
 : For general information about Zorba's implementation of the
 : XQuery and XPath Full Text 1.0 specification
 : as well as instructions for building an installing a thesaurus,
 : see the Full Text Thesaurus documentation.
 :
Notes on languages

 : To refer to paricular human languages,
 : Zorba uses both the
 : ISO 639-1
 : and
 : ISO 639-2
 : languages codes.
 : Note that Zorba supports only a subset of the
 : complete list of language codes
 : and not every function supports the same subset.
 :

 : Most functions in this module take a language as a parameter
 : using the
 : xs:language
 : XML schema data type.
 :
Notes on stemming

 : The stem() functions return the
 : stem
 : of a word.
 : In Zorba,
 : the stem of a word itself, however, is not guaranteed to be a word.
 : It is best to consider a stem as an opaque byte sequence.
 : All that is guaranteed about a stem is that,
 : for a given word,
 : the stem of that word will always be the same byte sequence.
 : Hence,
 : you sould never compare the result of one of the stem()
 : functions against a non-stemmed string,
 : for example:
 :

 :  if ( ft:stem( "apples" ) eq "apple" )             ** WRONG **
 :

 : Instead do:
 :

 :  if ( ft:stem( "apples" ) eq ft:stem( "apple" ) )  ** CORRECT **
 :

 :
Notes on the thesaurus

 : The thesaurus-lookup() functions have "levels"
 : and "relationship" parameters.
 : The values for these are implementation-defined.
 : Zorba's default implementation uses the
 : WordNet lexical database,
 : version 3.0.
 :

 : In WordNet,
 : the number of "levels" that two phrases are apart
 : are how many hierarchical meanings apart they are.
 : For example,
 : "canary" is 5 levels away from "vertebrate"
 : (carary > finch > oscine > passerine > bird > vertebrate).
 :

 : When using the WordNet implementation,
 : Zorba supports all of the relationships (and their abbreviations)
 : specified by
 : ISO 2788
 : and
 : ANSI/NISO Z39.19-2005
 : with the exceptions of "HN" (history note)
 : and "X SN" (see scope note for).
 : These relationships are:
 :

 :

 :      Rel.
 :      Meaning
 :      WordNet Rel.
 :

 :

 :      BT
 :      broader term
 :      hypernym
 :

 :

 :      BTG
 :      broader term generic
 :      hypernym
 :

 :

 :      BTI
 :      broader term instance
 :      instance hypernym
 :

 :

 :      BTP
 :      broader term partitive
 :      part meronym
 :

 :

 :      NT
 :      narrower term
 :      hyponym
 :

 :

 :      NTG
 :      narrower term generic
 :      hyponym
 :

 :

 :      NTI
 :      narrower term instance
 :      instance hyponym
 :

 :

 :      NTP
 :      narrower term partitive
 :      part holonym
 :

 :

 :      RT
 :      related term
 :      also see
 :

 :

 :      SN
 :      scope note
 :      n/a
 :

 :

 :      TT
 :      top term
 :      hypernym
 :

 :

 :      UF
 :      non-preferred term
 :      n/a
 :

 :

 :      USE
 :      preferred term
 :      n/a
 :

 :

 : Note that you can specify relationships
 : either by their abbreviation
 : or their meaning.
 : Relationships are case-insensitive.
 :
 : In addition to the
 : ISO 2788
 : and
 : ANSI/NISO Z39.19-2005
 : relationships,
 : Zorba also supports all of the relationships offered by WordNet.
 : These relationships are:
 :

 :

 :      Relationship
 :      Meaning
 :

 :

 :      also see
 :
 :        A word that is related to another,
 :        e.g., for "varnished" (furniture)
 :        one should also see "finished."
 :
 :

 :

 :      antonym
 :
 :        A word opposite in meaning to another,
 :        e.g., "light" is an antonym for "heavy."
 :
 :

 :

 :      attribute
 :
 :        A noun for which adjectives express values,
 :        e.g., "weight" is an attribute
 :        for which the adjectives "light" and "heavy"
 :        express values.
 :
 :

 :

 :      cause
 :
 :        A verb that causes another,
 :        e.g., "show" is a cause of "see."
 :
 :

 :

 :      derivationally related form
 :
 :        A word that is derived from a root word,
 :        e.g., "metric" is a derivationally related form of "meter."
 :
 :

 :

 :      derived from adjective
 :
 :        An adverb that is derived from an adjective,
 :        e.g., "correctly" is derived from the adjective "correct."
 :
 :

 :

 :      entailment
 :
 :        A verb that presupposes another,
 :        e.g., "snoring" entails "sleeping."
 :
 :

 :

 :      hypernym
 :
 :        A word with a broad meaning that more specific words fall under,
 :        e.g., "meal" is a hypernym of "breakfast."
 :
 :

 :

 :      hyponym
 :
 :        A word of more specific meaning than a general term applicable to it,
 :        e.g., "breakfast" is a hyponym of "meal."
 :
 :

 :

 :      instance hypernym
 :
 :        A word that denotes a category of some specific instance,
 :        e.g., "author" is an instance hypernym of "Asimov."
 :
 :

 :

 :      instance hyponym
 :
 :        A term that donotes a specific instance of some general category,
 :        e.g., "Asimov" is an instance hyponym of "author."
 :
 :

 :

 :      member holonym
 :
 :        A word that denotes a collection of individuals,
 :        e.g., "faculty" is a member holonym of "professor."
 :
 :

 :

 :      member meronym
 :
 :        A word that denotes a member of a larger group,
 :        e.g., a "person" is a member meronym of a "crowd."
 :
 :

 :

 :      part holonym
 :
 :        A word that denotes a larger whole comprised of some part,
 :        e.g., "car" is a part holonym of "engine."
 :
 :

 :

 :      part meronym
 :
 :        A word that denotes a part of a larger whole,
 :        e.g., an "engine" is part meronym of a "car."
 :
 :

 :

 :      participle of verb
 :
 :        An adjective that is the participle of some verb,
 :        e.g., "breaking" is the participle of the verb "break."
 :
 :

 :

 :      pertainym
 :
 :        An adjective that classifies its noun,
 :        e.g., "musical" is a pertainym in "musical instrument."
 :
 :

 :

 :      similar to
 :
 :        Similar, though not necessarily interchangeable, adjectives.
 :        For example, "shiny" is similar to "bright",
 :        but they have subtle differences.
 :
 :

 :

 :      substance holonym
 :
 :        A word that denotes a larger whole containing some constituent
 :        substance, e.g., "bread" is a substance holonym of "flour."
 :
 :

 :

 :      substance meronym
 :
 :        A word that denotes a constituant substance of some larger whole,
 :        e.g., "flour" is a substance meronym of "bread."
 :
 :

 :

 :      verb group
 :
 :        A verb that is a member of a group of similar verbs,
 :        e.g., "live" is in the verb group
 :        of "dwell", "live", "inhabit", etc.
 :
 :

 :

 :
Notes on tokenization

 : For general information about Zorba's implementation of tokenization,
 : including what constitutes a token,
 : see the Full Text Tokenizer documentation.
 : @author Paul J. Lucas
 :)
module namespace ft = "http://www.zorba-xquery.com/modules/full-text";

import schema namespace ft-schema =
  "http://www.zorba-xquery.com/modules/full-text";

declare namespace err = "http://www.w3.org/2005/xqt-errors";
declare namespace zerr = "http://www.zorba-xquery.com/errors";

declare namespace ver = "http://www.zorba-xquery.com/options/versioning";
declare option ver:module-version "2.0";

(:===========================================================================:)

(:~
 : Predeclared constant for the Danish
 : xs:language.
 :)
declare variable $ft:lang-da as xs:language := xs:language("da");

(:~
 : Predeclared constant for the German
 : xs:language.
 :)
declare variable $ft:lang-de as xs:language := xs:language("de");

(:~
 : Predeclared constant for the English
 : xs:language.
 :)
declare variable $ft:lang-en as xs:language := xs:language("en");

(:~
 : Predeclared constant for the Spanish
 : xs:language.
 :)
declare variable $ft:lang-es as xs:language := xs:language("es");

(:~
 : Predeclared constant for the Finnish
 : xs:language.
 :)
declare variable $ft:lang-fi as xs:language := xs:language("fi");

(:~
 : Predeclared constant for the French
 : xs:language.
 :)
declare variable $ft:lang-fr as xs:language := xs:language("fr");

(:~
 : Predeclared constant for the Hungarian
 : xs:language.
 :)
declare variable $ft:lang-hu as xs:language := xs:language("hu");

(:~
 : Predeclared constant for the Italian
 : xs:language.
 :)
declare variable $ft:lang-it as xs:language := xs:language("it");

(:~
 : Predeclared constant for the Dutch
 : xs:language.
 :)
declare variable $ft:lang-nl as xs:language := xs:language("nl");

(:~
 : Predeclared constant for the Norwegian
 : xs:language.
 :)
declare variable $ft:lang-no as xs:language := xs:language("no");

(:~
 : Predeclared constant for the Portuguese
 : xs:language.
 :)
declare variable $ft:lang-pt as xs:language := xs:language("pt");

(:~
 : Predeclared constant for the Romanian
 : xs:language.
 :)
declare variable $ft:lang-ro as xs:language := xs:language("ro");

(:~
 : Predeclared constant for the Russian
 : xs:language.
 :)
declare variable $ft:lang-ru as xs:language := xs:language("ru");

(:~
 : Predeclared constant for the Swedish
 : xs:language.
 :)
declare variable $ft:lang-sv as xs:language := xs:language("sv");

(:~
 : Predeclared constant for the Turkish
 : xs:language.
 :)
declare variable $ft:lang-tr as xs:language := xs:language("tr");

(:===========================================================================:)

(:~
 : Gets the current compare options.
 :
 : @return said compare options.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-current-compare-options-1.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-current-compare-options-2.xq
 :)
declare function ft:current-compare-options()
  as element(ft-schema:compare-options) external;

(:~
 : Gets the current
 : language:
 : either the language specified by the
 : declare ft-option using
 : language
 : statement (if any)
 : or the one returned by ft:host-lang() (if none).
 :
 : @return said language.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-current-lang-true-1.xq
 :)
declare function ft:current-lang()
  as xs:language external;

(:~
 : Gets the host's current
 : language.
 : The "host" is the computer on which Zorba is running.
 : The host's current language is obtained as follows:
 :

 :

 :      For *nix systems:
 :

 :

 :          If setlocale(3) returns non-null,
 :          the language corresponding to that locale is used.
 :

 :

 :          Else, if the LANG environment variable is set,
 :          that language is ued.
 :

 :

 :          Otherwise, there is no default language.
 :

 :

 :

 :

 :      For Windows systems,
 :      the language corresponding to the locale returned by the
 :      GetLocaleInfo()
 :      function is used.
 :

 :

 :
 : @return said language.
 :)
declare function ft:host-lang()
  as xs:language external;

(:~
 : Checks whether the given
 : language
 : is supported for stemming.
 :
 : @param $lang The language to check.
 : @return true only if the language is supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stem-lang-es-supported-true.xq
 :)
declare function ft:is-stem-lang-supported( $lang as xs:language )
  as xs:boolean external;

(:~
 : Checks whether the given word is a stop-word.
 :
 : @param $word The word to check.
 : @param $lang The
 : language
 : of $word.
 : @return true only if $word is a stop-word.
 : @error err:FTST0009 if $lang is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-true-1.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-true-3.xq
 :)
declare function ft:is-stop-word( $word as xs:string, $lang as xs:language )
  as xs:boolean external;

(:~
 : Checks whether the given word is a stop-word.
 :
 : @param $word The word to check.
 : The word's language
 : is assumed to be the one returned by ft:current-lang().
 : @return true only if $word is a stop-word.
 : @error err:FTST0009 if ft:current-lang() is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-true-2.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-true-4.xq
 :)
declare function ft:is-stop-word( $word as xs:string )
  as xs:boolean external;

(:~
 : Checks whether the given
 : language
 : is supported for stop words.
 :
 : @param $lang The language to check.
 : @return true only if the language is supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-lang-en-supported-true.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-lang-supported-false-1.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-lang-supported-false-2.xq
 :)
declare function ft:is-stop-word-lang-supported( $lang as xs:language )
  as xs:boolean external;

(:~
 : Checks whether the given
 : language
 : is supported for look-up using the default thesaurus.
 :
 : @param $lang The language to check.
 : @return true only if the language is supported.
 :)
declare function ft:is-thesaurus-lang-supported( $lang as xs:language )
  as xs:boolean external;

(:~
 : Checks whether the given
 : language
 : is supported for look-up using the thesaurus specified by the given URI.
 :
 : @param $uri The URI specifying the thesaurus to use.
 : @param $lang The language to check.
 : @return true only if the language is supported.
 : @error err:FTST0018 if $uri refers to a thesaurus
 : that is not found in the statically known thesauri.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-thesaurus-lang-supported-true-1.xq
 :)
declare function ft:is-thesaurus-lang-supported( $uri as xs:string,
                                                 $lang as xs:language )
  as xs:boolean external;

(:~
 : Checks whether the given
 : language
 : is supported for tokenization.
 :
 : @param $lang The language to check.
 : @return true only if the language is supported.
 :)
declare function ft:is-tokenizer-lang-supported( $lang as xs:language )
  as xs:boolean external;

(:~
 : Stems the given word.
 :
 : @param $word The word to stem.
 : @param $lang The
 : language
 : of $word.
 : @return the stem of $word.
 : @error err:FTST0009 if $lang is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-stem-1.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-stem-2.xq
 :)
declare function ft:stem( $word as xs:string, $lang as xs:language )
  as xs:string external;

(:~
 : Stems the given word.
 :
 : @param $word The word to stem.
 : The word's language
 : is assumed to be the one returned by ft:current-lang().
 : @return the stem of $word.
 : @error err:FTST0009 if ft:current-lang() is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-stem-3.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-stem-4.xq
 :)
declare function ft:stem( $word as xs:string )
  as xs:string external;

(:~
 : Strips all diacritical marks from all characters.
 :
 : @param $string The string to strip diacritical marks from.
 : @return $string with diacritical marks stripped.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-strip-diacritics-1.xq
 :)
declare function ft:strip-diacritics( $string as xs:string )
  as xs:string external;

(:~
 : Looks-up the given phrase in the default thesaurus.
 :
 : @param $phrase The phrase to look up.
 : The phrase's
 : language
 : is assumed to be the one returned by ft:current-lang().
 : @return the related phrases if $phrase is found in the
 : thesaurus or the empty sequence if not.
 : @error err:FTST0009 if ft:current-lang() is not supported.
 : @error zerr:ZXQP8401 if the thesaurus data file's version is not supported
 : by the currently running version of Zorba.
 : @error zerr:ZXQP8402 if the thesaurus data file's endianness does not match
 : that of the CPU on which Zorba is currently running.
 : @error zerr:ZXQP8403 if there was an error reading the thesaurus data.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-thesaurus-lookup-1.xq
 :)
declare function ft:thesaurus-lookup( $phrase as xs:string )
  as xs:string* external;

(:~
 : Looks-up the given phrase in the thesaurus specified by the given URI.
 :
 : @param $uri The URI specifying the thesaurus to use.
 : @param $phrase The phrase to look up.
 : @param $lang The
 : language
 : of $phrase.
 : @return the related phrases if $phrase is found in the
 : thesaurus or the empty sequence if not.
 : @error err:FTST0009 if $lang is not supported.
 : @error err:FTST0018 if $uri refers to a thesaurus
 : that is not found in the statically known thesauri.
 : @error zerr:ZOSE0001 if the thesaurus data file could not be found.
 : @error zerr:ZOSE0002 if the thesaurus data file is not a plain file.
 : @error zerr:ZXQP8401 if the thesaurus data file's version is not supported
 : by the currently running version of Zorba.
 : @error zerr:ZXQP8402 if the thesaurus data file's endianness does not match
 : that of the CPU on which Zorba is currently running.
 : @error zerr:ZXQP8403 if there was an error reading the thesaurus data file.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-thesaurus-lookup-2.xq
 :)
declare function ft:thesaurus-lookup( $uri as xs:string, $phrase as xs:string,
                                      $lang as xs:language )
  as xs:string* external;

(:~
 : Looks-up the given phrase in a thesaurus.
 :
 : @param $uri The URI specifying the thesaurus to use.
 : @param $phrase The phrase to look up.
 : The phrase's
 : language
 : is assumed to be the one the one returned by ft:current-lang().
 : @return the related phrases if $phrase is found in the
 : thesaurus or the empty sequence if not.
 : @error err:FTST0009 if ft:current-lang() is unsupported.
 : @error err:FTST0018 if $uri refers to a thesaurus
 : that is not found in the statically known thesauri.
 : @error zerr:ZOSE0001 if the thesaurus data file could not be found.
 : @error zerr:ZOSE0002 if the thesaurus data file is not a plain file.
 : @error zerr:ZXQP8401 if the thesaurus data file's version is not supported
 : by the currently running version of Zorba.
 : @error zerr:ZXQP8402 if the thesaurus data file's endianness does not match
 : that of the CPU on which Zorba is currently running.
 : @error zerr:ZXQP8403 if there was an error reading the thesaurus data file.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-thesaurus-lookup-3.xq
 :)
declare function ft:thesaurus-lookup( $uri as xs:string, $phrase as xs:string )
  as xs:string* external;

(:~
 : Looks-up the given phrase in a thesaurus.
 :
 : @param $uri The URI specifying the thesaurus to use.
 : @param $phrase The phrase to look up.
 : @param $lang The
 : language
 : of $phrase.
 : @param $relationship The relationship the results are to have to
 : $phrase.
 : @return the related phrases if $phrase is found in the
 : thesaurus or the empty sequence if not.
 : @error err:FTST0018 if $uri refers to a thesaurus
 : that is not found in the statically known thesauri.
 : @error err:FTST0009 if $lang is not supported.
 : @error zerr:ZOSE0001 if the thesaurus data file could not be found.
 : @error zerr:ZOSE0002 if the thesaurus data file is not a plain file.
 : @error zerr:ZXQP8401 if the thesaurus data file's version is not supported
 : by the currently running version of Zorba.
 : @error zerr:ZXQP8402 if the thesaurus data file's endianness does not match
 : that of the CPU on which Zorba is currently running.
 : @error zerr:ZXQP8403 if there was an error reading the thesaurus data file.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-thesaurus-lookup-4.xq
 :)
declare function ft:thesaurus-lookup( $uri as xs:string, $phrase as xs:string,
                                      $lang as xs:language,
                                      $relationship as xs:string )
  as xs:string* external;

(:~
 : Looks-up the given phrase in a thesaurus.
 :
 : @param $uri The URI specifying the thesaurus to use.
 : @param $phrase The phrase to look up.
 : @param $lang The
 : language
 : of $phrase.
 : @param $relationship The relationship the results are to have to
 : $phrase.
 : @param $level-least The minimum number of levels within the thesaurus to be
 : travers$ed.
 : @param $level-most The maximum number of levels within the thesaurus to be
 : traversed.
 : @return the related phrases if $phrase is found in the
 : thesaurus or the empty sequence if not.
 : @error err:FOCA0003 if either $level-least or
 : $level-most is either negative or too large.
 : @error err:FTST0018 if $uri refers to a thesaurus
 : that is not found in the statically known thesauri.
 : @error err:FTST0009 if $lang is not supported.
 : @error zerr:ZOSE0001 if the thesaurus data file could not be found.
 : @error zerr:ZOSE0002 if the thesaurus data file is not a plain file.
 : @error zerr:ZXQP8401 if the thesaurus data file's version is not supported
 : by the currently running version of Zorba.
 : @error zerr:ZXQP8402 if the thesaurus data file's endianness does not match
 : that of the CPU on which Zorba is currently running.
 : @error zerr:ZXQP8403 if there was an error reading the thesaurus data file.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-thesaurus-lookup-5.xq
 :)
declare function ft:thesaurus-lookup( $uri as xs:string, $phrase as xs:string,
                                      $lang as xs:language,
                                      $relationship as xs:string,
                                      $level-least as xs:integer,
                                      $level-most as xs:integer )
  as xs:string* external;

(:~
 : Tokenizes the given node and all of its descendants.
 :
 : @param $node The node to tokenize.
 : @param $lang The default
 : language
 : of $node.
 : @return a (possibly empty) sequence of tokens.
 : @error err:FTST0009 if $lang is not supported in general.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-node-1.xq
 :)
declare function ft:tokenize-node( $node as node(), $lang as xs:language )
  as element(ft-schema:token)* external;

(:~
 : Tokenizes the given node and all of its descendants.
 :
 : @param $node The node to tokenize.
 : The document's default
 : language
 : is assumed to be the one returned by ft:current-lang().
 : @return a (possibly empty) sequence of tokens.
 : @error err:FTST0009 if ft:current-lang() is not supported in
 : general.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-node-2.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-node-3.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-node-4.xq
 :)
declare function ft:tokenize-node( $node as node() )
  as element(ft-schema:token)* external;

(:~
 : Tokenizes the given string.
 :
 : @param $string The string to tokenize.
 : @param $lang The default
 : language
 : of $string.
 : @return a (possibly empty) sequence of tokens.
 : @error err:FTST0009 if $lang is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-string-1.xq
 :)
declare function ft:tokenize-string( $string as xs:string,
                                     $lang as xs:language )
  as xs:string* external;

(:~
 : Tokenizes the given string.
 :
 : @param $string The string to tokenize.
 : The string's default
 : language
 : is assumed to be the one returned by ft:current-lang().
 : @return a (possibly empty) sequence of tokens.
 : @error err:FTST0009 if ft:current-lang() is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-string-2.xq
 :)
declare function ft:tokenize-string( $string as xs:string )
  as xs:string* external;

(:~
 : Gets properties of the tokenizer for the given
 : language.
 :
 : @param $lang The language of the tokenizer to get the properties of.
 : @return said properties.
 : @error err:FTST0009 if $lang is not supported.
 : tokenization specifically.
 :)
declare function ft:tokenizer-properties( $lang as xs:language )
  as element(ft-schema:tokenizer-properties) external;

(:~
 : Gets properties of the tokenizer for the
 : language
 : returned by ft:current-lang().
 :
 : @return said properties.
 : @error err:FTST0009 if ft:current-lang() is not supported.
 :)
declare function ft:tokenizer-properties()
  as element(ft-schema:tokenizer-properties) external;

(:===========================================================================:)

(: vim:set et sw=2 ts=2: :)

xquery version "3.0";

(:
 : Copyright 2006-2011 The FLWOR Foundation.
 :
 : Licensed under the Apache License, Version 2.0 (the "License");
 : you may not use this file except in compliance with the License.
 : You may obtain a copy of the License at
 :
 : http://www.apache.org/licenses/LICENSE-2.0
 :
 : Unless required by applicable law or agreed to in writing, software
 : distributed under the License is distributed on an "AS IS" BASIS,
 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 : See the License for the specific language governing permissions and
 : limitations under the License.
 :)

(:===========================================================================:)

(:~
 : This module provides an XQuery API to full-text functions.
 : For general information about Zorba's implementation of the
 : XQuery and XPath Full Text 1.0 specification
 : as well as instructions for building an installing a thesaurus,
 : see the Full Text Thesaurus documentation.
 :
Notes on languages

 : To refer to paricular human languages,
 : Zorba uses both the
 : ISO 639-1
 : and
 : ISO 639-2
 : languages codes.
 : Note that Zorba supports only a subset of the
 : complete list of language codes
 : and not every function supports the same subset.
 :

 : Most functions in this module take a language as a parameter
 : using the
 : xs:language
 : XML schema data type.
 :
Notes on stemming

 : The stem() functions return the
 : stem
 : of a word.
 : In Zorba,
 : the stem of a word itself, however, is not guaranteed to be a word.
 : It is best to consider a stem as an opaque byte sequence.
 : All that is guaranteed about a stem is that,
 : for a given word,
 : the stem of that word will always be the same byte sequence.
 : Hence,
 : you sould never compare the result of one of the stem()
 : functions against a non-stemmed string,
 : for example:
 :

 :  if ( ft:stem( "apples" ) eq "apple" )             ** WRONG **
 :

 : Instead do:
 :

 :  if ( ft:stem( "apples" ) eq ft:stem( "apple" ) )  ** CORRECT **
 :

 :
Notes on the thesaurus

 : The thesaurus-lookup() functions have "levels"
 : and "relationship" parameters.
 : The values for these are implementation-defined.
 : Zorba's default implementation uses the
 : WordNet lexical database,
 : version 3.0.
 :

 : In WordNet,
 : the number of "levels" that two phrases are apart
 : are how many hierarchical meanings apart they are.
 : For example,
 : "canary" is 5 levels away from "vertebrate"
 : (carary > finch > oscine > passerine > bird > vertebrate).
 :

 : When using the WordNet implementation,
 : Zorba supports all of the relationships (and their abbreviations)
 : specified by
 : ISO 2788
 : and
 : ANSI/NISO Z39.19-2005
 : with the exceptions of "HN" (history note)
 : and "X SN" (see scope note for).
 : These relationships are:
 :

 :

 :      Rel.
 :      Meaning
 :      WordNet Rel.
 :

 :

 :      BT
 :      broader term
 :      hypernym
 :

 :

 :      BTG
 :      broader term generic
 :      hypernym
 :

 :

 :      BTI
 :      broader term instance
 :      instance hypernym
 :

 :

 :      BTP
 :      broader term partitive
 :      part meronym
 :

 :

 :      NT
 :      narrower term
 :      hyponym
 :

 :

 :      NTG
 :      narrower term generic
 :      hyponym
 :

 :

 :      NTI
 :      narrower term instance
 :      instance hyponym
 :

 :

 :      NTP
 :      narrower term partitive
 :      part holonym
 :

 :

 :      RT
 :      related term
 :      also see
 :

 :

 :      SN
 :      scope note
 :      n/a
 :

 :

 :      TT
 :      top term
 :      hypernym
 :

 :

 :      UF
 :      non-preferred term
 :      n/a
 :

 :

 :      USE
 :      preferred term
 :      n/a
 :

 :

 : Note that you can specify relationships
 : either by their abbreviation
 : or their meaning.
 : Relationships are case-insensitive.
 :
 : In addition to the
 : ISO 2788
 : and
 : ANSI/NISO Z39.19-2005
 : relationships,
 : Zorba also supports all of the relationships offered by WordNet.
 : These relationships are:
 :

 :

 :      Relationship
 :      Meaning
 :

 :

 :      also see
 :
 :        A word that is related to another,
 :        e.g., for "varnished" (furniture)
 :        one should also see "finished."
 :
 :

 :

 :      antonym
 :
 :        A word opposite in meaning to another,
 :        e.g., "light" is an antonym for "heavy."
 :
 :

 :

 :      attribute
 :
 :        A noun for which adjectives express values,
 :        e.g., "weight" is an attribute
 :        for which the adjectives "light" and "heavy"
 :        express values.
 :
 :

 :

 :      cause
 :
 :        A verb that causes another,
 :        e.g., "show" is a cause of "see."
 :
 :

 :

 :      derivationally related form
 :
 :        A word that is derived from a root word,
 :        e.g., "metric" is a derivationally related form of "meter."
 :
 :

 :

 :      derived from adjective
 :
 :        An adverb that is derived from an adjective,
 :        e.g., "correctly" is derived from the adjective "correct."
 :
 :

 :

 :      entailment
 :
 :        A verb that presupposes another,
 :        e.g., "snoring" entails "sleeping."
 :
 :

 :

 :      hypernym
 :
 :        A word with a broad meaning that more specific words fall under,
 :        e.g., "meal" is a hypernym of "breakfast."
 :
 :

 :

 :      hyponym
 :
 :        A word of more specific meaning than a general term applicable to it,
 :        e.g., "breakfast" is a hyponym of "meal."
 :
 :

 :

 :      instance hypernym
 :
 :        A word that denotes a category of some specific instance,
 :        e.g., "author" is an instance hypernym of "Asimov."
 :
 :

 :

 :      instance hyponym
 :
 :        A term that donotes a specific instance of some general category,
 :        e.g., "Asimov" is an instance hyponym of "author."
 :
 :

 :

 :      member holonym
 :
 :        A word that denotes a collection of individuals,
 :        e.g., "faculty" is a member holonym of "professor."
 :
 :

 :

 :      member meronym
 :
 :        A word that denotes a member of a larger group,
 :        e.g., a "person" is a member meronym of a "crowd."
 :
 :

 :

 :      part holonym
 :
 :        A word that denotes a larger whole comprised of some part,
 :        e.g., "car" is a part holonym of "engine."
 :
 :

 :

 :      part meronym
 :
 :        A word that denotes a part of a larger whole,
 :        e.g., an "engine" is part meronym of a "car."
 :
 :

 :

 :      participle of verb
 :
 :        An adjective that is the participle of some verb,
 :        e.g., "breaking" is the participle of the verb "break."
 :
 :

 :

 :      pertainym
 :
 :        An adjective that classifies its noun,
 :        e.g., "musical" is a pertainym in "musical instrument."
 :
 :

 :

 :      similar to
 :
 :        Similar, though not necessarily interchangeable, adjectives.
 :        For example, "shiny" is similar to "bright",
 :        but they have subtle differences.
 :
 :

 :

 :      substance holonym
 :
 :        A word that denotes a larger whole containing some constituent
 :        substance, e.g., "bread" is a substance holonym of "flour."
 :
 :

 :

 :      substance meronym
 :
 :        A word that denotes a constituant substance of some larger whole,
 :        e.g., "flour" is a substance meronym of "bread."
 :
 :

 :

 :      verb group
 :
 :        A verb that is a member of a group of similar verbs,
 :        e.g., "live" is in the verb group
 :        of "dwell", "live", "inhabit", etc.
 :
 :

 :

 :
Notes on tokenization

 : For general information about Zorba's implementation of tokenization,
 : including what constitutes a token,
 : see the Full Text Tokenizer documentation.
 : @author Paul J. Lucas
 :)
module namespace ft = "http://www.zorba-xquery.com/modules/full-text";

import schema namespace ft-schema =
  "http://www.zorba-xquery.com/modules/full-text";

declare namespace err = "http://www.w3.org/2005/xqt-errors";
declare namespace zerr = "http://www.zorba-xquery.com/errors";

declare namespace ver = "http://www.zorba-xquery.com/options/versioning";
declare option ver:module-version "2.0";

(:===========================================================================:)

(:~
 : Predeclared constant for the Danish
 : xs:language.
 :)
declare variable $ft:lang-da as xs:language := xs:language("da");

(:~
 : Predeclared constant for the German
 : xs:language.
 :)
declare variable $ft:lang-de as xs:language := xs:language("de");

(:~
 : Predeclared constant for the English
 : xs:language.
 :)
declare variable $ft:lang-en as xs:language := xs:language("en");

(:~
 : Predeclared constant for the Spanish
 : xs:language.
 :)
declare variable $ft:lang-es as xs:language := xs:language("es");

(:~
 : Predeclared constant for the Finnish
 : xs:language.
 :)
declare variable $ft:lang-fi as xs:language := xs:language("fi");

(:~
 : Predeclared constant for the French
 : xs:language.
 :)
declare variable $ft:lang-fr as xs:language := xs:language("fr");

(:~
 : Predeclared constant for the Hungarian
 : xs:language.
 :)
declare variable $ft:lang-hu as xs:language := xs:language("hu");

(:~
 : Predeclared constant for the Italian
 : xs:language.
 :)
declare variable $ft:lang-it as xs:language := xs:language("it");

(:~
 : Predeclared constant for the Dutch
 : xs:language.
 :)
declare variable $ft:lang-nl as xs:language := xs:language("nl");

(:~
 : Predeclared constant for the Norwegian
 : xs:language.
 :)
declare variable $ft:lang-no as xs:language := xs:language("no");

(:~
 : Predeclared constant for the Portuguese
 : xs:language.
 :)
declare variable $ft:lang-pt as xs:language := xs:language("pt");

(:~
 : Predeclared constant for the Romanian
 : xs:language.
 :)
declare variable $ft:lang-ro as xs:language := xs:language("ro");

(:~
 : Predeclared constant for the Russian
 : xs:language.
 :)
declare variable $ft:lang-ru as xs:language := xs:language("ru");

(:~
 : Predeclared constant for the Swedish
 : xs:language.
 :)
declare variable $ft:lang-sv as xs:language := xs:language("sv");

(:~
 : Predeclared constant for the Turkish
 : xs:language.
 :)
declare variable $ft:lang-tr as xs:language := xs:language("tr");

(:===========================================================================:)

(:~
 : Gets the current compare options.
 :
 : @return said compare options.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-current-compare-options-1.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-current-compare-options-2.xq
 :)
declare function ft:current-compare-options()
  as element(ft-schema:compare-options) external;

(:~
 : Gets the current
 : language:
 : either the language specified by the
 : declare ft-option using
 : language
 : statement (if any)
 : or the one returned by ft:host-lang() (if none).
 :
 : @return said language.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-current-lang-true-1.xq
 :)
declare function ft:current-lang()
  as xs:language external;

(:~
 : Gets the host's current
 : language.
 : The "host" is the computer on which Zorba is running.
 : The host's current language is obtained as follows:
 :

 :

 :      For *nix systems:
 :

 :

 :          If setlocale(3) returns non-null,
 :          the language corresponding to that locale is used.
 :

 :

 :          Else, if the LANG environment variable is set,
 :          that language is ued.
 :

 :

 :          Otherwise, there is no default language.
 :

 :

 :

 :

 :      For Windows systems,
 :      the language corresponding to the locale returned by the
 :      GetLocaleInfo()
 :      function is used.
 :

 :

 :
 : @return said language.
 :)
declare function ft:host-lang()
  as xs:language external;

(:~
 : Checks whether the given
 : language
 : is supported for stemming.
 :
 : @param $lang The language to check.
 : @return true only if the language is supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stem-lang-es-supported-true.xq
 :)
declare function ft:is-stem-lang-supported( $lang as xs:language )
  as xs:boolean external;

(:~
 : Checks whether the given word is a stop-word.
 :
 : @param $word The word to check.
 : @param $lang The
 : language
 : of $word.
 : @return true only if $word is a stop-word.
 : @error err:FTST0009 if $lang is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-true-1.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-true-3.xq
 :)
declare function ft:is-stop-word( $word as xs:string, $lang as xs:language )
  as xs:boolean external;

(:~
 : Checks whether the given word is a stop-word.
 :
 : @param $word The word to check.
 : The word's language
 : is assumed to be the one returned by ft:current-lang().
 : @return true only if $word is a stop-word.
 : @error err:FTST0009 if ft:current-lang() is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-true-2.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-true-4.xq
 :)
declare function ft:is-stop-word( $word as xs:string )
  as xs:boolean external;

(:~
 : Checks whether the given
 : language
 : is supported for stop words.
 :
 : @param $lang The language to check.
 : @return true only if the language is supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-lang-en-supported-true.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-lang-supported-false-1.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-stop-word-lang-supported-false-2.xq
 :)
declare function ft:is-stop-word-lang-supported( $lang as xs:language )
  as xs:boolean external;

(:~
 : Checks whether the given
 : language
 : is supported for look-up using the default thesaurus.
 :
 : @param $lang The language to check.
 : @return true only if the language is supported.
 :)
declare function ft:is-thesaurus-lang-supported( $lang as xs:language )
  as xs:boolean external;

(:~
 : Checks whether the given
 : language
 : is supported for look-up using the thesaurus specified by the given URI.
 :
 : @param $uri The URI specifying the thesaurus to use.
 : @param $lang The language to check.
 : @return true only if the language is supported.
 : @error err:FTST0018 if $uri refers to a thesaurus
 : that is not found in the statically known thesauri.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-is-thesaurus-lang-supported-true-1.xq
 :)
declare function ft:is-thesaurus-lang-supported( $uri as xs:string,
                                                 $lang as xs:language )
  as xs:boolean external;

(:~
 : Checks whether the given
 : language
 : is supported for tokenization.
 :
 : @param $lang The language to check.
 : @return true only if the language is supported.
 :)
declare function ft:is-tokenizer-lang-supported( $lang as xs:language )
  as xs:boolean external;

(:~
 : Stems the given word.
 :
 : @param $word The word to stem.
 : @param $lang The
 : language
 : of $word.
 : @return the stem of $word.
 : @error err:FTST0009 if $lang is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-stem-1.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-stem-2.xq
 :)
declare function ft:stem( $word as xs:string, $lang as xs:language )
  as xs:string external;

(:~
 : Stems the given word.
 :
 : @param $word The word to stem.
 : The word's language
 : is assumed to be the one returned by ft:current-lang().
 : @return the stem of $word.
 : @error err:FTST0009 if ft:current-lang() is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-stem-3.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-stem-4.xq
 :)
declare function ft:stem( $word as xs:string )
  as xs:string external;

(:~
 : Strips all diacritical marks from all characters.
 :
 : @param $string The string to strip diacritical marks from.
 : @return $string with diacritical marks stripped.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-strip-diacritics-1.xq
 :)
declare function ft:strip-diacritics( $string as xs:string )
  as xs:string external;

(:~
 : Looks-up the given phrase in the default thesaurus.
 :
 : @param $phrase The phrase to look up.
 : The phrase's
 : language
 : is assumed to be the one returned by ft:current-lang().
 : @return the related phrases.
 : @error err:FTST0009 if ft:current-lang() is not supported.
 : @error zerr:ZXQP8401 if the thesaurus data file's version is not supported
 : by the currently running version of Zorba.
 : @error zerr:ZXQP8402 if the thesaurus data file's endianness does not match
 : that of the CPU on which Zorba is currently running.
 : @error zerr:ZXQP8403 if there was an error reading the thesaurus data.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-thesaurus-lookup-1.xq
 :)
declare function ft:thesaurus-lookup( $phrase as xs:string )
  as xs:string* external;

(:~
 : Looks-up the given phrase in the thesaurus specified by the given URI.
 :
 : @param $uri The URI specifying the thesaurus to use.
 : @param $phrase The phrase to look up.
 : @param $lang The
 : language
 : of $phrase.
 : @return the related phrases.
 : @error err:FTST0009 if $lang is not supported.
 : @error err:FTST0018 if $uri refers to a thesaurus
 : that is not found in the statically known thesauri.
 : @error zerr:ZOSE0001 if the thesaurus data file could not be found.
 : @error zerr:ZOSE0002 if the thesaurus data file is not a plain file.
 : @error zerr:ZXQP8401 if the thesaurus data file's version is not supported
 : by the currently running version of Zorba.
 : @error zerr:ZXQP8402 if the thesaurus data file's endianness does not match
 : that of the CPU on which Zorba is currently running.
 : @error zerr:ZXQP8403 if there was an error reading the thesaurus data file.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-thesaurus-lookup-2.xq
 :)
declare function ft:thesaurus-lookup( $uri as xs:string, $phrase as xs:string,
                                      $lang as xs:language )
  as xs:string* external;

(:~
 : Looks-up the given phrase in a thesaurus.
 :
 : @param $uri The URI specifying the thesaurus to use.
 : @param $phrase The phrase to look up.
 : The phrase's
 : language
 : is assumed to be the one the one returned by ft:current-lang().
 : @return the related phrases.
 : @error err:FTST0009 if ft:current-lang() is unsupported.
 : @error err:FTST0018 if $uri refers to a thesaurus
 : that is not found in the statically known thesauri.
 : @error zerr:ZOSE0001 if the thesaurus data file could not be found.
 : @error zerr:ZOSE0002 if the thesaurus data file is not a plain file.
 : @error zerr:ZXQP8401 if the thesaurus data file's version is not supported
 : by the currently running version of Zorba.
 : @error zerr:ZXQP8402 if the thesaurus data file's endianness does not match
 : that of the CPU on which Zorba is currently running.
 : @error zerr:ZXQP8403 if there was an error reading the thesaurus data file.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-thesaurus-lookup-3.xq
 :)
declare function ft:thesaurus-lookup( $uri as xs:string, $phrase as xs:string )
  as xs:string* external;

(:~
 : Looks-up the given phrase in a thesaurus.
 :
 : @param $uri The URI specifying the thesaurus to use.
 : @param $phrase The phrase to look up.
 : @param $lang The
 : language
 : of $phrase.
 : @param $relationship The relationship the results are to have to
 : $phrase.
 : @return the related phrases.
 : @error err:FTST0018 if $uri refers to a thesaurus
 : that is not found in the statically known thesauri.
 : @error err:FTST0009 if $lang is not supported.
 : @error zerr:ZOSE0001 if the thesaurus data file could not be found.
 : @error zerr:ZOSE0002 if the thesaurus data file is not a plain file.
 : @error zerr:ZXQP8401 if the thesaurus data file's version is not supported
 : by the currently running version of Zorba.
 : @error zerr:ZXQP8402 if the thesaurus data file's endianness does not match
 : that of the CPU on which Zorba is currently running.
 : @error zerr:ZXQP8403 if there was an error reading the thesaurus data file.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-thesaurus-lookup-4.xq
 :)
declare function ft:thesaurus-lookup( $uri as xs:string, $phrase as xs:string,
                                      $lang as xs:language,
                                      $relationship as xs:string )
  as xs:string* external;

(:~
 : Looks-up the given phrase in a thesaurus.
 :
 : @param $uri The URI specifying the thesaurus to use.
 : @param $phrase The phrase to look up.
 : @param $lang The
 : language
 : of $phrase.
 : @param $relationship The relationship the results are to have to
 : $phrase.
 : @param $level-least The minimum number of levels within the thesaurus to be
 : travers$ed.
 : @param $level-most The maximum number of levels within the thesaurus to be
 : traversed.
 : @return the related phrases.
 : @error err:FOCA0003 if either $level-least or
 : $level-most is either negative or too large.
 : @error err:FTST0018 if $uri refers to a thesaurus
 : that is not found in the statically known thesauri.
 : @error err:FTST0009 if $lang is not supported.
 : @error zerr:ZOSE0001 if the thesaurus data file could not be found.
 : @error zerr:ZOSE0002 if the thesaurus data file is not a plain file.
 : @error zerr:ZXQP8401 if the thesaurus data file's version is not supported
 : by the currently running version of Zorba.
 : @error zerr:ZXQP8402 if the thesaurus data file's endianness does not match
 : that of the CPU on which Zorba is currently running.
 : @error zerr:ZXQP8403 if there was an error reading the thesaurus data file.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-thesaurus-lookup-5.xq
 :)
declare function ft:thesaurus-lookup( $uri as xs:string, $phrase as xs:string,
                                      $lang as xs:language,
                                      $relationship as xs:string,
                                      $level-least as xs:integer,
                                      $level-most as xs:integer )
  as xs:string* external;

(:~
 : Tokenizes the given node and all of its descendants.
 :
 : @param $node The node to tokenize.
 : @param $lang The default
 : language
 : of $node.
 : @return a (possibly empty) sequence of tokens.
 : @error err:FTST0009 if $lang is not supported in general.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-node-1.xq
 :)
declare function ft:tokenize-node( $node as node(), $lang as xs:language )
  as element(ft-schema:token)* external;

(:~
 : Tokenizes the given node and all of its descendants.
 :
 : @param $node The node to tokenize.
 : The document's default
 : language
 : is assumed to be the one returned by ft:current-lang().
 : @return a (possibly empty) sequence of tokens.
 : @error err:FTST0009 if ft:current-lang() is not supported in
 : general.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-node-2.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-node-3.xq
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-node-4.xq
 :)
declare function ft:tokenize-node( $node as node() )
  as element(ft-schema:token)* external;

(:~
 : Tokenizes the given string.
 :
 : @param $string The string to tokenize.
 : @param $lang The default
 : language
 : of $string.
 : @return a (possibly empty) sequence of tokens.
 : @error err:FTST0009 if $lang is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-string-1.xq
 :)
declare function ft:tokenize-string( $string as xs:string,
                                     $lang as xs:language )
  as xs:string* external;

(:~
 : Tokenizes the given string.
 :
 : @param $string The string to tokenize.
 : The string's default
 : language
 : is assumed to be the one returned by ft:current-lang().
 : @return a (possibly empty) sequence of tokens.
 : @error err:FTST0009 if ft:current-lang() is not supported.
 : @example test/rbkt/Queries/zorba/fulltext/ft-module-tokenize-string-2.xq
 :)
declare function ft:tokenize-string( $string as xs:string )
  as xs:string* external;

(:~
 : Gets properties of the tokenizer for the given
 : language.
 :
 : @param $lang The language of the tokenizer to get the properties of.
 : @return said properties.
 : @error err:FTST0009 if $lang is not supported.
 : tokenization specifically.
 :)
declare function ft:tokenizer-properties( $lang as xs:language )
  as element(ft-schema:tokenizer-properties) external;

(:~
 : Gets properties of the tokenizer for the
 : language
 : returned by ft:current-lang().
 :
 : @return said properties.
 : @error err:FTST0009 if ft:current-lang() is not supported.
 :)
declare function ft:tokenizer-properties()
  as element(ft-schema:tokenizer-properties) external;

(:===========================================================================:)

(: vim:set et sw=2 ts=2: :)


Added a regression report. ALso the CTest integration is able to spot the regressions.

(:
 : Copyright 2006-2011 The FLWOR Foundation.
 :
 : Licensed under the Apache License, Version 2.0 (the "License");
 : you may not use this file except in compliance with the License.
 : You may obtain a copy of the License at
 :
 : http://www.apache.org/licenses/LICENSE-2.0
 :
 : Unless required by applicable law or agreed to in writing, software
 : distributed under the License is distributed on an "AS IS" BASIS,
 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 : See the License for the specific language governing permissions and
 : limitations under the License.
 :)

(:~
 : Zorba FOTS driver reporting
 : @author Sorin Nasoi
 :)

module namespace reporting =
  "http://www.zorba-xquery.com/fots-driver/reporting";

import module namespace file =
  "http://expath.org/ns/file";

import module namespace driver =
  "http://www.zorba-xquery.com/fots-driver" at "fots-driver.xq";
import module namespace util =
  "http://www.zorba-xquery.com/fots-driver/util" at "util.xq";
import module namespace fots-err =
  "http://www.zorba-xquery.com/fots-driver/errors" at "errors.xq";
import module namespace functx =
  "http://www.functx.com/";

declare namespace err =
  "http://www.w3.org/2005/xqt-errors";
declare namespace fots =
  "http://www.w3.org/2010/09/qt-fots-catalog";

declare namespace ann =
  "http://www.zorba-xquery.com/annotations";

(:~
 : Loops through the test-sets, runs then and creates statistics.
 : @param $FOTSCatalogFilePath path to the FOTS catalog file.
 : @param $FOTSZorbaManifestPath path to the FOTS Zorba manifest file.
 : @param $testSetPrefixes name/criteria for the test sets( empty string means
 : all).
 : @param $testCasePrefixes name/criteria for the test cases(empty string means
 : all).
 : @param $exceptedTestCases lists of test cases that are not run( empty string
 : means all tests will be run).
 : @param $exceptedTestSets lists of test sets that are not run(empty string
 : means all tests will be run).
 : @param $verbose if set to TRUE it will also output the actual failures.
 : @return a report of tests run.
 :)
declare %ann:sequential function reporting:run-and-report(
  $FOTSCatalogFilePath    as xs:string,
  $FOTSZorbaManifestPath  as xs:string,
  $exceptedTestCases      as xs:string*,
  $exceptedTestSets       as xs:string*,
  $verbose                as xs:boolean
) {
try {
  {
    variable $FOTSCatalog := doc(trace(resolve-uri($FOTSCatalogFilePath),
                                "Path to FOTS catalog.xml set to: "));

    variable $catalogBaseURI := resolve-uri(util:parent-folder($FOTSCatalogFilePath));

    variable $FOTSZorbaManifest := doc(trace(resolve-uri($FOTSZorbaManifestPath),
                                      "Path to FOTSZorbaManifest set to:"));

    variable $failures := <fots:FOTS-test-suite-result>{
                          ( $FOTSZorbaManifest//fots:implementation,
                            $FOTSZorbaManifest//fots:dependencies-satisfied,
                            driver:run($FOTSCatalog,
                                       $catalogBaseURI,
                                       $FOTSZorbaManifest,
                                       '',
                                       '',
                                       $exceptedTestCases,
                                       $exceptedTestSets,
                                       $verbose,
                                       ())
                             )
                             }</fots:FOTS-test-suite-result>;

    file:write("failures.xml",
              $failures,
              $util:writeXML);

    reporting:do-reporting($FOTSCatalog,
                           $catalogBaseURI,
                           $failures,
                           $exceptedTestCases,
                           $exceptedTestSets,
                           $verbose)
  }
}
catch *
{
  error($err:code,
        $err:description,
        concat("
Please make sure the passed 'fotsPath' points to the ",
               "exact location of the FOTS catalog.xml:
",
               resolve-uri($FOTSCatalogFilePath),
               "
and that the passed 'fotsZorbaManifestPath' points to",
               " a file in the same folder as cli.xq:
",
               resolve-uri($FOTSZorbaManifestPath)))
}
};

(:~
 : Loops through the test cases report and creates statistics.
 : @param $pathFOTSCatalog path to the FOTS catalog file.
 : @param $pathResults path to the FOTS results.
 : @param $exceptedTestCases lists of test cases that are not run( empty string
 : means all tests will be run).
 : @param $exceptedTestSets lists of test sets that are not run(empty string
 : means all tests will be run).
 : @param $verbose if set to TRUE it will also output the actual failures.
 : @param $showResult if set to TRUE it will also show the actual result of the
 : Query run.
 : @return a report of tests run.
 :)
declare %ann:nondeterministic function reporting:report(
  $FOTSCatalogFilePath  as xs:string,
  $pathResults          as xs:string,
  $exceptedTestCases    as xs:string*,
  $exceptedTestSets     as xs:string*,
  $verbose              as xs:boolean
) as element(fots:report) {
  try {
    {
      if(not(file:is-file($pathResults)))
      then
      {
        error($fots-err:errNA,
              "The file results file was not found. Suggestion: use driver:run-fots to generate it or use reporting:run-and-report function.");
      }
      else ();

      variable $results := parse-xml(file:read-text($pathResults));

      variable $FOTSCatalog := doc(trace(resolve-uri($FOTSCatalogFilePath),
                                  "Path to FOTS catalog.xml set to: "));

      variable $catalogBaseURI := resolve-uri(util:parent-folder($FOTSCatalogFilePath));

      reporting:do-reporting($FOTSCatalog,
                             $catalogBaseURI,
                             $results,
                             $exceptedTestCases,
                             $exceptedTestSets,
                             $verbose)
    }
  }
  catch *
  {
    error($err:code, $err:description)
  }
};

(:~
 : Loops through the test-sets and creates statistics.
 : @param $FOTSCatalog  FOTS catalog file.
 : @param $failures the test reported by Zorba as failed.
 : @param $exceptedTestCases lists of test cases that are not run(empty string
 : means all tests will be run).
 : @param $exceptedTestSets lists of test sets that are not run(empty string
 : means all tests will be run).
 : @param $verbose is set to TRUE it will also output the actual failures.
 : @return a report of tests run.
 :)
declare %ann:nondeterministic function reporting:do-reporting(
  $FOTSCatalog        as document-node(),
  $catalogBaseURI     as xs:anyURI,
  $failures,
  $exceptedTestCases  as xs:string*,
  $exceptedTestSets   as xs:string*,
  $verbose            as xs:boolean
) as element(fots:report) {
  let $excepted := count($exceptedTestCases)
  return
  <fots:report>
  {
    let $totalNoTests := count($failures//fots:test-set//fots:test-case),
        $totalPass := sum(for $testSet in $failures//fots:test-set
                          return count($testSet//fots:test-case[@result ='pass'])),
        $totalFail := sum(for $testSet in $failures//fots:test-set
                          return count($testSet//fots:test-case[@result ='fail'])),
        $totalNotApplicable := sum(for $testSet in $failures//fots:test-set
                                   return count($testSet//fots:test-case[@result ='not applicable'])),
        $totalNotRun := sum(for $testSet in $failures//fots:test-set
                            return count($testSet//fots:test-case[@result ='notRun'])),
        $executionTime := sum(for $testCase in $failures//fots:test-set//fots:test-case return xs:dayTimeDuration($testCase/@executionTime))
    return
    <fots:brief totalTests="{$totalNoTests}"
                totalPass="{$totalPass}"
                totalFail="{$totalFail}"
                totalNotApplicable="{$totalNotApplicable}"
                totalNotRun="{$totalNotRun}"
                totalExecutionTime="{$executionTime}"/>
  }
  {
    for $testSetFile in $FOTSCatalog//fots:test-set
    let $testSetURI := resolve-uri($testSetFile/@file,
                                   $catalogBaseURI),
        $testSetDoc := doc($testSetURI),
        $testSetName := data($testSetDoc/fots:test-set/@name),
        $totalNoTestCases := count($testSetDoc//fots:test-case),
        $totalFailures := for $testCase in $failures//fots:test-set[@name = $testSetName]//fots:test-case[@result ="fail"]
                          return $testCase,
        $percent := round((1 - (count($totalFailures) div $totalNoTestCases))*100,2),
        $executionTime := sum(for $testCase in $failures//fots:test-set[@name = $testSetName]//fots:test-case
                              return xs:dayTimeDuration($testCase/@executionTime))
    order by count($totalFailures) descending
    return
    <fots:test-set  name="{$testSetName}"
                    executionTime="{$executionTime}"
                    noFailures="{count($totalFailures)}"
                    noTestCases="{$totalNoTestCases}"
                    percent="{$percent}"
                  failedTestNames="{string-join(for $failure in $totalFailures
                                                order by data($failure/@name)
                                                return data($failure/@name)
                                              ,",")}">
   {if (not($verbose)) then $totalFailures else ()}
    </fots:test-set>
   }
   </fots:report>
};

(:~
 : Loops through the results and creates ExpectedFailures.xml.
 : @param $pathResults path to the FOTS results.
 : @return ExpectedFailures.xml.
 :)
declare %ann:nondeterministic function reporting:generate-expected-failures(
  $pathResults  as xs:string
) as element(failures) {
  try {
    {
      if(not(file:is-file($pathResults)))
      then
      {
        error($fots-err:errNA,
              "The file results file was not found. Suggestion: use driver:run-fots to generate it.");
      }
      else ();

      variable $results := parse-xml(file:read-text($pathResults));

      <failures>{
      for $testSet in $results//fots:test-set
      let $countFailures := count($testSet//fots:test-case[@result ="fail"])
      let $countNotRun := count($testSet//fots:test-case[@result ="notRun"])
      let $testSetName := xs:string($testSet/@name)
      where ($countFailures gt xs:integer(0)) or
            ($countNotRun gt xs:integer(0))
      return
        <TestSet name="{$testSetName}"> {
          (for $testCase in $testSet//fots:test-case[@result ="fail"]
           return
             <Test name="{xs:string($testCase/@name)}"
                   bug="0" />
          ,
           for $testCase in $testSet//fots:test-case[@result ="notRun"]
           return
             <Test name="{xs:string($testCase/@name)}"
                   notRun="true"
                   bug="0" />
          )}</TestSet>}</failures>
    }
  }
  catch *
  {
    error($err:code, $err:description)
  }
};

declare function reporting:regressions(
) as xs:string* {
  let $old_report:=fn:parse-xml(file:read-text('/home/spungi/work/zorba/repo/fots-ctest/build/bin/report_04_Dec.xml'))
  let $new_report:=fn:parse-xml(file:read-text('/home/spungi/work/zorba/repo/fots-ctest/build/bin/report_17_Dec.xml'))

  for $testSetOld in $old_report/*:report/*:test-set
  let $testSetNew := $new_report/*:report/*:test-set[@name = data($testSetOld/@name)]
  let $regression := if (exists($testSetNew))
                     then xs:decimal(data($testSetOld/@noFailures)) - xs:decimal(data($testSetNew/@noFailures))
                     else xs:decimal(0)
  let $testsOld as xs:string* := tokenize(data($testSetOld/@failedTestNames),",")
  let $testsNew as xs:string* := tokenize(data($testSetNew/@failedTestNames),",")
  where $regression < xs:decimal(0)
  order by $regression ascending
  return
    concat(data($testSetOld/@name),
           " ",
           $regression,
           " ",
           string-join((functx:value-except($testsNew, $testsOld)),","),
           "
")
};

(:
 : Copyright 2006-2011 The FLWOR Foundation.
 :
 : Licensed under the Apache License, Version 2.0 (the "License");
 : you may not use this file except in compliance with the License.
 : You may obtain a copy of the License at
 :
 : http://www.apache.org/licenses/LICENSE-2.0
 :
 : Unless required by applicable law or agreed to in writing, software
 : distributed under the License is distributed on an "AS IS" BASIS,
 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 : See the License for the specific language governing permissions and
 : limitations under the License.
 :)

(:~
 : Zorba FOTS driver reporting
 : @author Sorin Nasoi
 :)

module namespace reporting =
  "http://www.zorba-xquery.com/fots-driver/reporting";

import module namespace file =
  "http://expath.org/ns/file";

import module namespace driver =
  "http://www.zorba-xquery.com/fots-driver" at "fots-driver.xq";
import module namespace util =
  "http://www.zorba-xquery.com/fots-driver/util" at "util.xq";
import module namespace fots-err =
  "http://www.zorba-xquery.com/fots-driver/errors" at "errors.xq";

declare namespace err =
  "http://www.w3.org/2005/xqt-errors";
declare namespace fots =
  "http://www.w3.org/2010/09/qt-fots-catalog";

declare namespace ann =
  "http://www.zorba-xquery.com/annotations";

(:~
 : Loops through the test-sets, runs then and creates statistics.
 : @param $FOTSCatalogFilePath path to the FOTS catalog file.
 : @param $FOTSZorbaManifestPath path to the FOTS Zorba manifest file.
 : @param $testSetPrefixes name/criteria for the test sets( empty string means
 : all).
 : @param $testCasePrefixes name/criteria for the test cases(empty string means
 : all).
 : @param $exceptedTestCases lists of test cases that are not run( empty string
 : means all tests will be run).
 : @param $exceptedTestSets lists of test sets that are not run(empty string
 : means all tests will be run).
 : @param $verbose if set to TRUE it will also output the actual failures.
 : @return a report of tests run.
 :)
declare %ann:sequential function reporting:run-and-report(
  $FOTSCatalogFilePath    as xs:string,
  $FOTSZorbaManifestPath  as xs:string,
  $exceptedTestCases      as xs:string*,
  $exceptedTestSets       as xs:string*,
  $verbose                as xs:boolean
) {
try {
  {
    variable $FOTSCatalog := doc(trace(resolve-uri($FOTSCatalogFilePath),
                                "Path to FOTS catalog.xml set to: "));

    variable $catalogBaseURI := resolve-uri(util:parent-folder($FOTSCatalogFilePath));

    variable $FOTSZorbaManifest := doc(trace(resolve-uri($FOTSZorbaManifestPath),
                                      "Path to FOTSZorbaManifest set to:"));

    variable $failures := <fots:FOTS-test-suite-result>{
                          ( $FOTSZorbaManifest//fots:implementation,
                            $FOTSZorbaManifest//fots:dependencies-satisfied,
                            driver:run($FOTSCatalog,
                                       $catalogBaseURI,
                                       $FOTSZorbaManifest,
                                       '',
                                       '',
                                       $exceptedTestCases,
                                       $exceptedTestSets,
                                       $verbose,
                                       ())
                             )
                             }</fots:FOTS-test-suite-result>;

    file:write("failures.xml",
              $failures,
              $util:writeXML);

    reporting:do-reporting($FOTSCatalog,
                           $catalogBaseURI,
                           $failures,
                           $exceptedTestCases,
                           $exceptedTestSets,
                           $verbose)
  }
}
catch *
{
  error($err:code,
        $err:description,
        concat("
Please make sure the passed 'fotsPath' points to the ",
               "exact location of the FOTS catalog.xml:
",
               resolve-uri($FOTSCatalogFilePath),
               "
and that the passed 'fotsZorbaManifestPath' points to",
               " a file in the same folder as cli.xq:
",
               resolve-uri($FOTSZorbaManifestPath)))
}
};

(:~
 : Loops through the test cases report and creates statistics.
 : @param $pathFOTSCatalog path to the FOTS catalog file.
 : @param $pathResults path to the FOTS results.
 : @param $exceptedTestCases lists of test cases that are not run( empty string
 : means all tests will be run).
 : @param $exceptedTestSets lists of test sets that are not run(empty string
 : means all tests will be run).
 : @param $verbose if set to TRUE it will also output the actual failures.
 : @param $showResult if set to TRUE it will also show the actual result of the
 : Query run.
 : @return a report of tests run.
 :)
declare %ann:nondeterministic function reporting:report(
  $FOTSCatalogFilePath  as xs:string,
  $pathResults          as xs:string,
  $exceptedTestCases    as xs:string*,
  $exceptedTestSets     as xs:string*,
  $verbose              as xs:boolean
) as element(fots:report) {
  try {
    {
      if(not(file:is-file($pathResults)))
      then
      {
        error($fots-err:errNA,
              "The file results file was not found. Suggestion: use driver:run-fots to generate it or use reporting:run-and-report function.");
      }
      else ();

      variable $results := parse-xml(file:read-text($pathResults));

      variable $FOTSCatalog := doc(trace(resolve-uri($FOTSCatalogFilePath),
                                  "Path to FOTS catalog.xml set to: "));

      variable $catalogBaseURI := resolve-uri(util:parent-folder($FOTSCatalogFilePath));

      reporting:do-reporting($FOTSCatalog,
                             $catalogBaseURI,
                             $results,
                             $exceptedTestCases,
                             $exceptedTestSets,
                             $verbose)
    }
  }
  catch *
  {
    error($err:code, $err:description)
  }
};

(:~
 : Loops through the test-sets and creates statistics.
 : @param $FOTSCatalog  FOTS catalog file.
 : @param $failures the test reported by Zorba as failed.
 : @param $exceptedTestCases lists of test cases that are not run(empty string
 : means all tests will be run).
 : @param $exceptedTestSets lists of test sets that are not run(empty string
 : means all tests will be run).
 : @param $verbose is set to TRUE it will also output the actual failures.
 : @return a report of tests run.
 :)
declare %ann:nondeterministic function reporting:do-reporting(
  $FOTSCatalog        as document-node(),
  $catalogBaseURI     as xs:anyURI,
  $failures,
  $exceptedTestCases  as xs:string*,
  $exceptedTestSets   as xs:string*,
  $verbose            as xs:boolean
) as element(fots:report) {
  let $excepted := count($exceptedTestCases)
  return
  <fots:report>
  {
    let $totalNoTests := count($failures//fots:test-set//fots:test-case),
        $totalPass := sum(for $testSet in $failures//fots:test-set
                          return count($testSet//fots:test-case[@result ='pass'])),
        $totalFail := sum(for $testSet in $failures//fots:test-set
                          return count($testSet//fots:test-case[@result ='fail'])),
        $totalNotApplicable := sum(for $testSet in $failures//fots:test-set
                                   return count($testSet//fots:test-case[@result ='not applicable'])),
        $totalNotRun := sum(for $testSet in $failures//fots:test-set
                            return count($testSet//fots:test-case[@result ='notRun'])),
        $executionTime := sum(for $testCase in $failures//fots:test-set//fots:test-case return xs:dayTimeDuration($testCase/@executionTime))
    return
    <fots:brief totalTests="{$totalNoTests}"
                totalPass="{$totalPass}"
                totalFail="{$totalFail}"
                totalNotApplicable="{$totalNotApplicable}"
                totalNotRun="{$totalNotRun}"
                totalExecutionTime="{$executionTime}"/>
  }
  {
    for $testSetFile in $FOTSCatalog//fots:test-set
    let $testSetURI := resolve-uri($testSetFile/@file,
                                   $catalogBaseURI),
        $testSetDoc := doc($testSetURI),
        $testSetName := data($testSetDoc/fots:test-set/@name),
        $totalNoTestCases := count($testSetDoc//fots:test-case),
        $totalFailures := for $testCase in $failures//fots:test-set[@name = $testSetName]//fots:test-case[@result ="fail"]
                          return $testCase,
        $percent := round((1 - (count($totalFailures) div $totalNoTestCases))*100,2),
        $executionTime := sum(for $testCase in $failures//fots:test-set[@name = $testSetName]//fots:test-case
                              return xs:dayTimeDuration($testCase/@executionTime))
    order by count($totalFailures) descending
    return
    <fots:test-set  name="{$testSetName}"
                    executionTime="{$executionTime}"
                    noFailures="{count($totalFailures)}"
                    noTestCases="{$totalNoTestCases}"
                    percent="{$percent}"
                  failedTestNames="{string-join(for $failure in $totalFailures
                                                order by data($failure/@name)
                                                return data($failure/@name)
                                              ,",")}">
   {if (not($verbose)) then $totalFailures else ()}
    </fots:test-set>
   }
   </fots:report>
};

(:~
 : Loops through the results and creates ExpectedFailures.xml.
 : @param $pathResults path to the FOTS results.
 : @return ExpectedFailures.xml.
 :)
declare %ann:nondeterministic function reporting:generate-expected-failures(
  $pathResults  as xs:string
) as element(failures) {
  try {
    {
      if(not(file:is-file($pathResults)))
      then
      {
        error($fots-err:errNA,
              "The file results file was not found. Suggestion: use driver:run-fots to generate it.");
      }
      else ();

      variable $results := parse-xml(file:read-text($pathResults));

      <failures>{
      for $testSet in $results//fots:test-set
      let $countFailures := count($testSet//fots:test-case[@result ="fail"])
      let $countNotRun := count($testSet//fots:test-case[@result ="notRun"])
      let $testSetName := xs:string($testSet/@name)
      where ($countFailures gt xs:integer(0)) or
            ($countNotRun gt xs:integer(0))
      return
        <TestSet name="{$testSetName}"> {
          (for $testCase in $testSet//fots:test-case[@result ="fail"]
           return
             <Test name="{xs:string($testCase/@name)}"
                   bug="0" />
          ,
           for $testCase in $testSet//fots:test-case[@result ="notRun"]
           return
             <Test name="{xs:string($testCase/@name)}"
                   notRun="true"
                   bug="0" />
          )}</TestSet>}</failures>
    }
  }
  catch *
  {
    error($err:code, $err:description)
  }
};