Document the builtin MarkLogic cot function.

xquery version "1.0-ml" encoding "UTF-8";
(:~
 : MarkLogic math functions
 :
 : @see https://docs.marklogic.com/math
 :
 : This documentation includes material copied from or derived from the XPath and
 : XQuery Functions and Operators 3.1 specifications. Copyright © 2017 W3C®
 : (MIT, ERCIM, Keio, Beihang).
 :)
module namespace math = "http://marklogic.com/xdmp/math";

declare namespace a = "http://reecedunn.co.uk/xquery/annotations";
declare namespace o = "http://reecedunn.co.uk/xquery/options";

declare option o:requires "marklogic/5.0";

(:~
 : Returns an approximation to the mathematical constant π.
 :
 : This function returns the xs:double value whose lexical
 : representation is 3.14159265358979e0.
 :)
declare %a:since("marklogic", "6.0") %a:until("marklogic", "7.0", "math:pi#0") function math:PI() as xs:double external;
(:~
 : Returns the arc cosine of the argument.
 :
 : The result is the arc cosine of $arg, as defined in the IEEE
 : 754-2008 specification of the acos function applied to 64-bit binary
 : floating point values. The result is in the range zero to +π radians.
 :
 :
Notes

 :
 : If $arg is outside the domain of the function, that is the
 : absolute value is greater than one, or if an overflow or underflow occurs,
 : the dynamic error XDMP-DOMAIN is produced.
 :
 : If $arg is NaN, then the result is NaN.
 :
 : In other cases the result is an xs:double value representing an
 : angle θ in radians in the range 0 <= θ <= +π.
 :)
declare %a:since("marklogic", "5.0") function math:acos($arg as xs:double) as xs:double external;
(:~
 : Returns the arc sine of the argument.
 :
 : The result is the arc sine of $arg, as defined in the IEEE
 : 754-2008 specification of the asin function applied to 64-bit binary
 : floating point values. The result is in the range -π/2 to +π/2 radians.
 :
 :
Notes

 :
 : If $arg is outside the domain of the function, that is the
 : absolute value is greater than one, or if an overflow or underflow occurs,
 : the dynamic error XDMP-DOMAIN is produced.
 :
 : If $arg is positive or negative zero, or NaN, the result
 : is $arg.
 :
 : In other cases the result is an xs:double value representing an
 : angle θ in radians in the range -π/2 <= θ <= +π/2.
 :)
declare %a:since("marklogic", "5.0") function math:asin($arg as xs:double) as xs:double external;
(:~
 : Returns the arc tangent of the argument.
 :
 : The result is the arc tangent of $arg, as defined in the IEEE
 : 754-2008 specification of the atan function applied to 64-bit binary floating
 : point values. The result is in the range -π/2 to +π/2 radians.
 :
 :
Notes

 :
 : If $arg is positive or negative infinity, the result is
 : positive or negative π/2.
 :
 : If $arg is positive or negative zero, the result is
 : $arg.
 :
 : If $arg is NaN, then the result is NaN.
 :
 : In other cases the result is an xs:double value representing an
 : angle θ in radians in the range -π/2 <= θ <= +π/2.
 :)
declare %a:since("marklogic", "5.0") function math:atan($arg as xs:double) as xs:double external;
(:~
 : Returns the angle in radians subtended at the origin by the point on a plane
 : with coordinates (x, y) and the positive x-axis.
 :
 : The result is the value of atan2(y, x) as defined in the IEEE
 : 754-2008 specification of the atan2 function applied to 64-bit
 : binary floating point values. The result is in the range -π to +π radians.
 :
 :
Notes

 :
 : If either argument is NaN then the result is NaN.
 :
 : If $y is positive or negative, and $x is positive
 : and finite, then (subject to rules for overflow, underflow and approximation)
 : the value of math:atan2($y, $x) is math:atan($y div $x).
 :
 : If $y is positive and $x is negative and finite,
 : then (subject to the same caveats) the value of math:atan2($y, $x)
 : is math:atan($y div $x) + math:pi().
 :
 : If $y is negative and $x is negative and finite,
 : then (subject to the same caveats) the value of math:atan2($y, $x)
 : is math:atan($y div $x) - math:pi().
 :)
declare %a:since("marklogic", "5.0") function math:atan2($y as xs:double, $x as xs:double) as xs:double external;
(:~
 : Rounds $arg upwards to a whole number.
 :
 : The function returns the smallest (closest to negative infinity) number with
 : no fractional part that is not less than the value of $arg.
 :
 : If the argument is positive zero, then positive zero is returned. If the
 : argument is negative zero, then negative zero is returned. If the argument
 : is less than zero and greater than -1, negative zero is returned.
 :)
declare %a:since("marklogic", "5.0") %a:see-also("xpath-functions", "1.0-20070123", "fn:ceil") function math:ceil($arg as xs:double) as xs:double external;
declare %a:since("marklogic", "6.0") function math:correlation($arg as json:array*) as xs:double? external;
(:~
 : Returns the cosine of the argument. The argument is an angle in radians.
 :
 : The result is the cosine of $θ (which is treated as an angle in
 : radians) as defined in the IEEE 754-2008 specification of the cos
 : function applied to 64-bit binary floating point values.
 :
 :
Notes

 :
 : If $θ is positive or negative zero, the result is $θ.
 :
 : If $θ is positive or negative infinity, the dynamic error
 : XDMP-DOMAIN is produced.
 :
 : If $θ is NaN, then the result is NaN.
 :
 : Otherwise the result is always in the range -1.0e0 to +1.0e0.
 :)
declare %a:since("marklogic", "5.0") function math:cos($θ as xs:double) as xs:double external;
(:~
 : Returns the hyperbolic cosine of the argument. The argument is an angle in
 : radians.
 :
 : The result is the hyperbolic cosine of $θ (which is treated as
 : an angle in radians) as defined in the IEEE 754-2008 specification of the
 : cosh function applied to 64-bit binary floating point values.
 :
 :
Notes

 :
 : If $θ is positive or negative zero, NaN, or positive
 : or negative infinity, the result is $θ.
 :)
declare %a:since("marklogic", "5.0") function math:cosh($θ as xs:double) as xs:double external;
(:~
 : Returns the cotangent of the argument. The argument is an angle in radians.
 :
 : The result is the cotangent of $θ (which is treated as an angle in
 : radians), which is the reciprocal of the argument.
 :
 : This function is equivalent to 1 div math:tan($θ).
 :
 :
Notes

 :
 : If $θ is positive or negative zero, the result is positive or
 : negative infinity, depending on the sign of $θ.
 :
 : If $θ is positive or negative infinity, the dynamic error
 : XDMP-DOMAIN is produced.
 :
 : If $θ is NaN, then the result is NaN.
 :)
declare %a:since("marklogic", "6.0") function math:cot($θ as xs:double) as xs:double external;
declare %a:since("marklogic", "6.0") function math:covariance($arg as json:array*) as xs:double? external;
declare %a:since("marklogic", "6.0") function math:covariance-p($arg as json:array*) as xs:double? external;
(:~
 : Returns the radians argument in degrees.
 :
 : This function converts $arg, specified in radians, to degrees.
 :
 :
Notes

 :
 : If $arg is NaN, positive or negative zero, or
 : positive or negative infinity, then the result is the same as the argument.
 :
 : Otherwise, the result is the argument divided by π/180.
 :
 :
Notes

 :
 : The result is not wrapped, so math:degrees(math:pi() * 4) is
 : 720.
 :)
declare %a:since("marklogic", "6.0") function math:degrees($arg as xs:double) as xs:double external;
(:~
 : Returns the value of ex.
 :
 : The result is the mathematical constant e raised to the power of
 : $arg, as defined in the IEEE 754-2008 specification of the
 : exp function applied to 64-bit binary floating point values.
 :)
declare %a:since("marklogic", "5.0") function math:exp($arg as xs:double) as xs:double external;
(:~
 : Returns the absolute value of $arg.
 :
 : If $arg is negative the function returns -$arg,
 : otherwise it returns $arg.
 :
 : If the argument is positive zero or negative zero, then positive zero is
 : returned. If the argument is positive or negative infinity, positive
 : infinity is returned.
 :)
declare %a:since("marklogic", "5.0") %a:see-also("xpath-functions", "1.0-20070123", "fn:abs") function math:fabs($x as xs:double) as xs:double external;
(:~
 : Rounds $arg downwards to a whole number.
 :
 : The return is the largest (closest to positive infinity) number with no
 : fractional part that is not greater than the value of $arg.
 :
 : If the argument is positive zero, then positive zero is returned. If the
 : argument is negative zero, then negative zero is returned.
 :)
declare %a:since("marklogic", "5.0") function math:floor($arg as xs:double) as xs:double external;
(:~
 : Returns the remainder of dividing x by y.
 :
 : This function returns the value of the expression $x mod $y.
 :
 : If $y is 0e0, the dynamic error XDMP-DOMAIN is
 : produced instead of the FOAR0001 division by zero dynamic error that
 : mod raises.
 :)
declare %a:since("marklogic", "5.0") function math:fmod($x as xs:double, $y as xs:double) as xs:double external;
declare %a:since("marklogic", "5.0") function math:frexp($x as xs:double) as (xs:double, xs:integer) external;
declare %a:since("marklogic", "5.0") function math:ldexp($y as xs:double, $i as xs:integer) as xs:double external;
declare %a:since("marklogic", "6.0") function math:linear-model($arg as json:array*) as math:linear-model? external;
declare %a:since("marklogic", "6.0") function math:linear-model-coeff($linear-model as math:linear-model) as xs:double* external;
declare %a:since("marklogic", "6.0") function math:linear-model-intercept($linear-model as math:linear-model) as xs:double external;
declare %a:since("marklogic", "6.0") function math:linear-model-rsquared($linear-model as math:linear-model) as xs:double external;
(:~
 : Returns the natural logarithm of the argument.
 :
 : The result is the natural logarithm of $arg, as defined in the
 : IEEE 754-2008 specification of the log function applied to
 : 64-bit binary floating point values.
 :)
declare %a:since("marklogic", "5.0") function math:log($arg as xs:double) as xs:double external;
(:~
 : Returns the base-ten logarithm of the argument.
 :
 : The result is the base-10 logarithm of $arg, as defined in the
 : IEEE 754-2008 specification of the log10 function applied to
 : 64-bit binary floating point values.
 :)
declare %a:since("marklogic", "5.0") function math:log10($arg as xs:double) as xs:double external;
declare %a:since("marklogic", "6.0") function math:median($arg as xs:double*) as xs:double? external;
declare %a:since("marklogic", "6.0") function math:mode($arg as xs:anyAtomicType*) as xs:anyAtomicType* external;
declare %a:since("marklogic", "6.0") function math:mode($arg as xs:anyAtomicType*, $options as xs:string*) as xs:anyAtomicType* external;
(:~
 : Returns the fraction and integral part of the argument.
 :
 : This function returns a two value sequence, where the first value is the
 : fraction of $arg and the second value is the integral part
 : of $arg.
 :
 : This function is equivalent to ($arg mod 1, math:floor($arg)).
 :)
declare %a:restrict-until("return", "marklogic", "8.0", "(xs:double,xs:double)")
        %a:restrict-since("return", "marklogic", "8.0", "(xs:double,xs:integer)")
        %a:since("marklogic", "5.0") function math:modf($arg as xs:double) as (xs:double,(xs:double|xs:integer)) external;
declare %a:since("marklogic", "6.0") function math:percent-rank($arg as xs:anyAtomicType*, $value as xs:anyAtomicType) as xs:double? external;
declare %a:since("marklogic", "6.0") function math:percent-rank($arg as xs:anyAtomicType*, $value as xs:anyAtomicType, $options as xs:string*) as xs:double? external;
declare %a:since("marklogic", "6.0") function math:percentile($arg as xs:double*, $p as xs:double*) as xs:double* external;
(:~
 : Returns an approximation to the mathematical constant π.
 :
 : This function was replaced by math:pi() in MarkLogic 7.0.
 :
 : This function returns the xs:double value whose lexical
 : representation is 3.14159265358979e0.
 :)
declare %a:since("marklogic", "7.0") function math:pi() as xs:double external;
(:~
 : Returns the value of xy.
 :
 : The result is the value of $x raised to the power of $y
 : as defined in the IEEE 754-2008 specification of the pow function
 : applied to two 64-bit binary floating point values.
 :)
declare %a:since("marklogic", "5.0") function math:pow($x as xs:double, $y as xs:double) as xs:double external;
(:~
 : Returns the degrees argument in radians.
 :
 : This function converts $arg, specified in degrees, to radians.
 :
 :
Notes

 :
 : If $arg is NaN, positive or negative zero, or
 : positive or negative infinity, then the result is the same as the argument.
 :
 : Otherwise, the result is the argument multiplied by π/180.
 :
 :
Notes

 :
 : The result is not wrapped, so math:radians(720) is
 : math:pi() * 4.
 :)
declare %a:since("marklogic", "6.0") function math:radians($x as xs:double) as xs:double external;
declare %a:since("marklogic", "6.0") function math:rank($arg1 as xs:anyAtomicType*, $arg2 as xs:anyAtomicType) as xs:integer? external;
declare %a:since("marklogic", "6.0") function math:rank($arg1 as xs:anyAtomicType*, $arg2 as xs:anyAtomicType, $options as xs:string*) as xs:integer? external;
(:~
 : Returns the sine of the argument. The argument is an angle in radians.
 :
 : The result is the sine of $θ (which is treated as an angle in
 : radians) as defined in the IEEE 754-2008 specification of the sin
 : function applied to 64-bit binary floating point values.
 :
 :
Notes

 :
 : If $θ is positive or negative zero, the result is $θ.
 :
 : If $θ is positive or negative infinity, the dynamic error
 : XDMP-DOMAIN is produced.
 :
 : If $θ is NaN, then the result is NaN.
 :
 : Otherwise the result is always in the range -1.0e0 to +1.0e0.
 :)
declare %a:since("marklogic", "5.0") function math:sin($θ as xs:double) as xs:double external;
(:~
 : Returns the hyperbolic sine of the argument. The argument is an angle in
 : radians.
 :
 : The result is the hyperbolic sine of $θ (which is treated as an
 : angle in radians) as defined in the IEEE 754-2008 specification of the
 : sinh function applied to 64-bit binary floating point values.
 :
 :
Notes

 :
 : If $θ is positive or negative zero, NaN, or positive
 : or negative infinity, the result is $θ.
 :)
declare %a:since("marklogic", "5.0") function math:sinh($θ as xs:double) as xs:double external;
(:~
 : Returns the non-negative square root of the argument.
 :
 : The result is the mathematical non-negative square root of $arg
 : as defined in the IEEE 754-2008 specification of the squareRoot
 : function applied to 64-bit binary floating point values.
 :
 :
Notes

 :
 : If $arg is positive or negative zero, positive infinity, or
 : NaN, then the result is $arg. (Negative zero is
 : the only case where the result can have negative sign.)
 :
 : If $arg is negative infinity, the dynamic error
 : XDMP-DOMAIN is produced.
 :)
declare %a:since("marklogic", "5.0") function math:sqrt($x as xs:double) as xs:double external;
declare %a:since("marklogic", "6.0") function math:stddev($arg as xs:double*) as xs:double? external;
declare %a:since("marklogic", "6.0") function math:stddev-p($arg as xs:double*) as xs:double? external;
(:~
 : Returns the tangent of the argument. The argument is an angle in radians.
 :
 : The result is the tangent of $θ (which is treated as an angle in
 : radians) as defined in the IEEE 754-2008 specification of the tan
 : function applied to 64-bit binary floating point values.
 :
 :
Notes

 :
 : If $θ is positive or negative zero, the result is $θ.
 :
 : If $θ is positive or negative infinity, the dynamic error
 : XDMP-DOMAIN is produced.
 :
 : If $θ is NaN, then the result is NaN.
 :)
declare %a:since("marklogic", "5.0") function math:tan($θ as xs:double) as xs:double external;
(:~
 : Returns the hyperbolic tangent of the argument. The argument is an angle in
 : radians.
 :
 : The result is the hyperbolic tangent of $θ (which is treated as
 : an angle in radians) as defined in the IEEE 754-2008 specification of the
 : tanh function applied to 64-bit binary floating point values.
 :
 :
Notes

 :
 : If $θ is positive or negative zero, or NaN, the
 : result is $θ.
 :
 : If $θ is positive or negative infinity, the result is positive
 : or negative one depending on the sign of $θ.
 :)
declare %a:since("marklogic", "5.0") function math:tanh($θ as xs:double) as xs:double external;
declare %a:since("marklogic", "8.0") function math:trunc($arg as xs:numeric?) as xs:numeric? external;
declare %a:since("marklogic", "6.0") function math:trunc($arg as xs:numeric?, $n as xs:integer) as xs:numeric? external;
declare %a:since("marklogic", "6.0") function math:variance($arg as xs:double*) as xs:double? external;
declare %a:since("marklogic", "6.0") function math:variance-p($arg as xs:double*) as xs:double? external;

xquery version "1.0-ml" encoding "UTF-8";
(:~
 : MarkLogic math functions
 :
 : @see https://docs.marklogic.com/math
 :
 : This documentation includes material copied from or derived from the XPath and
 : XQuery Functions and Operators 3.1 specifications. Copyright © 2017 W3C®
 : (MIT, ERCIM, Keio, Beihang).
 :)
module namespace math = "http://marklogic.com/xdmp/math";

declare namespace a = "http://reecedunn.co.uk/xquery/annotations";
declare namespace o = "http://reecedunn.co.uk/xquery/options";

declare option o:requires "marklogic/5.0";

(:~
 : Returns an approximation to the mathematical constant π.
 :
 : This function returns the xs:double value whose lexical
 : representation is 3.14159265358979e0.
 :)
declare %a:since("marklogic", "6.0") %a:until("marklogic", "7.0", "math:pi#0") function math:PI() as xs:double external;
(:~
 : Returns the arc cosine of the argument.
 :
 : The result is the arc cosine of $arg, as defined in the IEEE
 : 754-2008 specification of the acos function applied to 64-bit binary
 : floating point values. The result is in the range zero to +π radians.
 :
 :
Notes

 :
 : If $arg is outside the domain of the function, that is the
 : absolute value is greater than one, or if an overflow or underflow occurs,
 : the dynamic error XDMP-DOMAIN is produced.
 :
 : If $arg is NaN, then the result is NaN.
 :
 : In other cases the result is an xs:double value representing an
 : angle θ in radians in the range 0 <= θ <= +π.
 :)
declare %a:since("marklogic", "5.0") function math:acos($arg as xs:double) as xs:double external;
(:~
 : Returns the arc sine of the argument.
 :
 : The result is the arc sine of $arg, as defined in the IEEE
 : 754-2008 specification of the asin function applied to 64-bit binary
 : floating point values. The result is in the range -π/2 to +π/2 radians.
 :
 :
Notes

 :
 : If $arg is outside the domain of the function, that is the
 : absolute value is greater than one, or if an overflow or underflow occurs,
 : the dynamic error XDMP-DOMAIN is produced.
 :
 : If $arg is positive or negative zero, or NaN, the result
 : is $arg.
 :
 : In other cases the result is an xs:double value representing an
 : angle θ in radians in the range -π/2 <= θ <= +π/2.
 :)
declare %a:since("marklogic", "5.0") function math:asin($arg as xs:double) as xs:double external;
(:~
 : Returns the arc tangent of the argument.
 :
 : The result is the arc tangent of $arg, as defined in the IEEE
 : 754-2008 specification of the atan function applied to 64-bit binary floating
 : point values. The result is in the range -π/2 to +π/2 radians.
 :
 :
Notes

 :
 : If $arg is positive or negative infinity, the result is
 : positive or negative π/2.
 :
 : If $arg is positive or negative zero, the result is
 : $arg.
 :
 : If $arg is NaN, then the result is NaN.
 :
 : In other cases the result is an xs:double value representing an
 : angle θ in radians in the range -π/2 <= θ <= +π/2.
 :)
declare %a:since("marklogic", "5.0") function math:atan($arg as xs:double) as xs:double external;
(:~
 : Returns the angle in radians subtended at the origin by the point on a plane
 : with coordinates (x, y) and the positive x-axis.
 :
 : The result is the value of atan2(y, x) as defined in the IEEE
 : 754-2008 specification of the atan2 function applied to 64-bit
 : binary floating point values. The result is in the range -π to +π radians.
 :
 :
Notes

 :
 : If either argument is NaN then the result is NaN.
 :
 : If $y is positive or negative, and $x is positive
 : and finite, then (subject to rules for overflow, underflow and approximation)
 : the value of math:atan2($y, $x) is math:atan($y div $x).
 :
 : If $y is positive and $x is negative and finite,
 : then (subject to the same caveats) the value of math:atan2($y, $x)
 : is math:atan($y div $x) + math:pi().
 :
 : If $y is negative and $x is negative and finite,
 : then (subject to the same caveats) the value of math:atan2($y, $x)
 : is math:atan($y div $x) - math:pi().
 :)
declare %a:since("marklogic", "5.0") function math:atan2($y as xs:double, $x as xs:double) as xs:double external;
(:~
 : Rounds $arg upwards to a whole number.
 :
 : The function returns the smallest (closest to negative infinity) number with
 : no fractional part that is not less than the value of $arg.
 :
 : If the argument is positive zero, then positive zero is returned. If the
 : argument is negative zero, then negative zero is returned. If the argument
 : is less than zero and greater than -1, negative zero is returned.
 :)
declare %a:since("marklogic", "5.0") %a:see-also("xpath-functions", "1.0-20070123", "fn:ceil") function math:ceil($arg as xs:double) as xs:double external;
declare %a:since("marklogic", "6.0") function math:correlation($arg as json:array*) as xs:double? external;
(:~
 : Returns the cosine of the argument. The argument is an angle in radians.
 :
 : The result is the cosine of $θ (which is treated as an angle in
 : radians) as defined in the IEEE 754-2008 specification of the cos
 : function applied to 64-bit binary floating point values.
 :
 :
Notes

 :
 : If $θ is positive or negative zero, the result is $θ.
 :
 : If $θ is positive or negative infinity, the dynamic error
 : XDMP-DOMAIN is produced.
 :
 : If $θ is NaN, then the result is NaN.
 :
 : Otherwise the result is always in the range -1.0e0 to +1.0e0.
 :)
declare %a:since("marklogic", "5.0") function math:cos($θ as xs:double) as xs:double external;
(:~
 : Returns the hyperbolic cosine of the argument. The argument is an angle in
 : radians.
 :
 : The result is the hyperbolic cosine of $θ (which is treated as
 : an angle in radians) as defined in the IEEE 754-2008 specification of the
 : cosh function applied to 64-bit binary floating point values.
 :
 :
Notes

 :
 : If $θ is positive or negative zero, NaN, or positive
 : or negative infinity, the result is $θ.
 :)
declare %a:since("marklogic", "5.0") function math:cosh($θ as xs:double) as xs:double external;
declare %a:since("marklogic", "6.0") function math:cot($x as xs:double) as xs:double external;
declare %a:since("marklogic", "6.0") function math:covariance($arg as json:array*) as xs:double? external;
declare %a:since("marklogic", "6.0") function math:covariance-p($arg as json:array*) as xs:double? external;
(:~
 : Returns the radians argument in degrees.
 :
 : This function converts $arg, specified in radians, to degrees.
 :
 :
Notes

 :
 : If $arg is NaN, positive or negative zero, or
 : positive or negative infinity, then the result is the same as the argument.
 :
 : Otherwise, the result is the argument divided by π/180.
 :
 :
Notes

 :
 : The result is not wrapped, so math:degrees(math:pi() * 4) is
 : 720.
 :)
declare %a:since("marklogic", "6.0") function math:degrees($arg as xs:double) as xs:double external;
(:~
 : Returns the value of ex.
 :
 : The result is the mathematical constant e raised to the power of
 : $arg, as defined in the IEEE 754-2008 specification of the
 : exp function applied to 64-bit binary floating point values.
 :)
declare %a:since("marklogic", "5.0") function math:exp($arg as xs:double) as xs:double external;
(:~
 : Returns the absolute value of $arg.
 :
 : If $arg is negative the function returns -$arg,
 : otherwise it returns $arg.
 :
 : If the argument is positive zero or negative zero, then positive zero is
 : returned. If the argument is positive or negative infinity, positive
 : infinity is returned.
 :)
declare %a:since("marklogic", "5.0") %a:see-also("xpath-functions", "1.0-20070123", "fn:abs") function math:fabs($x as xs:double) as xs:double external;
(:~
 : Rounds $arg downwards to a whole number.
 :
 : The return is the largest (closest to positive infinity) number with no
 : fractional part that is not greater than the value of $arg.
 :
 : If the argument is positive zero, then positive zero is returned. If the
 : argument is negative zero, then negative zero is returned.
 :)
declare %a:since("marklogic", "5.0") function math:floor($arg as xs:double) as xs:double external;
(:~
 : Returns the remainder of dividing x by y.
 :
 : This function returns the value of the expression $x mod $y.
 :
 : If $y is 0e0, the dynamic error XDMP-DOMAIN is
 : produced instead of the FOAR0001 division by zero dynamic error that
 : mod raises.
 :)
declare %a:since("marklogic", "5.0") function math:fmod($x as xs:double, $y as xs:double) as xs:double external;
declare %a:since("marklogic", "5.0") function math:frexp($x as xs:double) as (xs:double, xs:integer) external;
declare %a:since("marklogic", "5.0") function math:ldexp($y as xs:double, $i as xs:integer) as xs:double external;
declare %a:since("marklogic", "6.0") function math:linear-model($arg as json:array*) as math:linear-model? external;
declare %a:since("marklogic", "6.0") function math:linear-model-coeff($linear-model as math:linear-model) as xs:double* external;
declare %a:since("marklogic", "6.0") function math:linear-model-intercept($linear-model as math:linear-model) as xs:double external;
declare %a:since("marklogic", "6.0") function math:linear-model-rsquared($linear-model as math:linear-model) as xs:double external;
(:~
 : Returns the natural logarithm of the argument.
 :
 : The result is the natural logarithm of $arg, as defined in the
 : IEEE 754-2008 specification of the log function applied to
 : 64-bit binary floating point values.
 :)
declare %a:since("marklogic", "5.0") function math:log($arg as xs:double) as xs:double external;
(:~
 : Returns the base-ten logarithm of the argument.
 :
 : The result is the base-10 logarithm of $arg, as defined in the
 : IEEE 754-2008 specification of the log10 function applied to
 : 64-bit binary floating point values.
 :)
declare %a:since("marklogic", "5.0") function math:log10($arg as xs:double) as xs:double external;
declare %a:since("marklogic", "6.0") function math:median($arg as xs:double*) as xs:double? external;
declare %a:since("marklogic", "6.0") function math:mode($arg as xs:anyAtomicType*) as xs:anyAtomicType* external;
declare %a:since("marklogic", "6.0") function math:mode($arg as xs:anyAtomicType*, $options as xs:string*) as xs:anyAtomicType* external;
(:~
 : Returns the fraction and integral part of the argument.
 :
 : This function returns a two value sequence, where the first value is the
 : fraction of $arg and the second value is the integral part
 : of $arg.
 :
 : This function is equivalent to ($arg mod 1, math:floor($arg)).
 :)
declare %a:restrict-until("return", "marklogic", "8.0", "(xs:double,xs:double)")
        %a:restrict-since("return", "marklogic", "8.0", "(xs:double,xs:integer)")
        %a:since("marklogic", "5.0") function math:modf($arg as xs:double) as (xs:double,(xs:double|xs:integer)) external;
declare %a:since("marklogic", "6.0") function math:percent-rank($arg as xs:anyAtomicType*, $value as xs:anyAtomicType) as xs:double? external;
declare %a:since("marklogic", "6.0") function math:percent-rank($arg as xs:anyAtomicType*, $value as xs:anyAtomicType, $options as xs:string*) as xs:double? external;
declare %a:since("marklogic", "6.0") function math:percentile($arg as xs:double*, $p as xs:double*) as xs:double* external;
(:~
 : Returns an approximation to the mathematical constant π.
 :
 : This function was replaced by math:pi() in MarkLogic 7.0.
 :
 : This function returns the xs:double value whose lexical
 : representation is 3.14159265358979e0.
 :)
declare %a:since("marklogic", "7.0") function math:pi() as xs:double external;
(:~
 : Returns the value of xy.
 :
 : The result is the value of $x raised to the power of $y
 : as defined in the IEEE 754-2008 specification of the pow function
 : applied to two 64-bit binary floating point values.
 :)
declare %a:since("marklogic", "5.0") function math:pow($x as xs:double, $y as xs:double) as xs:double external;
(:~
 : Returns the degrees argument in radians.
 :
 : This function converts $arg, specified in degrees, to radians.
 :
 :
Notes

 :
 : If $arg is NaN, positive or negative zero, or
 : positive or negative infinity, then the result is the same as the argument.
 :
 : Otherwise, the result is the argument multiplied by π/180.
 :
 :
Notes

 :
 : The result is not wrapped, so math:radians(720) is
 : math:pi() * 4.
 :)
declare %a:since("marklogic", "6.0") function math:radians($x as xs:double) as xs:double external;
declare %a:since("marklogic", "6.0") function math:rank($arg1 as xs:anyAtomicType*, $arg2 as xs:anyAtomicType) as xs:integer? external;
declare %a:since("marklogic", "6.0") function math:rank($arg1 as xs:anyAtomicType*, $arg2 as xs:anyAtomicType, $options as xs:string*) as xs:integer? external;
(:~
 : Returns the sine of the argument. The argument is an angle in radians.
 :
 : The result is the sine of $θ (which is treated as an angle in
 : radians) as defined in the IEEE 754-2008 specification of the sin
 : function applied to 64-bit binary floating point values.
 :
 :
Notes

 :
 : If $θ is positive or negative zero, the result is $θ.
 :
 : If $θ is positive or negative infinity, the dynamic error
 : XDMP-DOMAIN is produced.
 :
 : If $θ is NaN, then the result is NaN.
 :
 : Otherwise the result is always in the range -1.0e0 to +1.0e0.
 :)
declare %a:since("marklogic", "5.0") function math:sin($θ as xs:double) as xs:double external;
(:~
 : Returns the hyperbolic sine of the argument. The argument is an angle in
 : radians.
 :
 : The result is the hyperbolic sine of $θ (which is treated as an
 : angle in radians) as defined in the IEEE 754-2008 specification of the
 : sinh function applied to 64-bit binary floating point values.
 :
 :
Notes

 :
 : If $θ is positive or negative zero, NaN, or positive
 : or negative infinity, the result is $θ.
 :)
declare %a:since("marklogic", "5.0") function math:sinh($θ as xs:double) as xs:double external;
(:~
 : Returns the non-negative square root of the argument.
 :
 : The result is the mathematical non-negative square root of $arg
 : as defined in the IEEE 754-2008 specification of the squareRoot
 : function applied to 64-bit binary floating point values.
 :
 :
Notes

 :
 : If $arg is positive or negative zero, positive infinity, or
 : NaN, then the result is $arg. (Negative zero is
 : the only case where the result can have negative sign.)
 :
 : If $arg is negative infinity, the dynamic error
 : XDMP-DOMAIN is produced.
 :)
declare %a:since("marklogic", "5.0") function math:sqrt($x as xs:double) as xs:double external;
declare %a:since("marklogic", "6.0") function math:stddev($arg as xs:double*) as xs:double? external;
declare %a:since("marklogic", "6.0") function math:stddev-p($arg as xs:double*) as xs:double? external;
(:~
 : Returns the tangent of the argument. The argument is an angle in radians.
 :
 : The result is the tangent of $θ (which is treated as an angle in
 : radians) as defined in the IEEE 754-2008 specification of the tan
 : function applied to 64-bit binary floating point values.
 :
 :
Notes

 :
 : If $θ is positive or negative zero, the result is $θ.
 :
 : If $θ is positive or negative infinity, the dynamic error
 : XDMP-DOMAIN is produced.
 :
 : If $θ is NaN, then the result is NaN.
 :)
declare %a:since("marklogic", "5.0") function math:tan($θ as xs:double) as xs:double external;
(:~
 : Returns the hyperbolic tangent of the argument. The argument is an angle in
 : radians.
 :
 : The result is the hyperbolic tangent of $θ (which is treated as
 : an angle in radians) as defined in the IEEE 754-2008 specification of the
 : tanh function applied to 64-bit binary floating point values.
 :
 :
Notes

 :
 : If $θ is positive or negative zero, or NaN, the
 : result is $θ.
 :
 : If $θ is positive or negative infinity, the result is positive
 : or negative one depending on the sign of $θ.
 :)
declare %a:since("marklogic", "5.0") function math:tanh($θ as xs:double) as xs:double external;
declare %a:since("marklogic", "8.0") function math:trunc($arg as xs:numeric?) as xs:numeric? external;
declare %a:since("marklogic", "6.0") function math:trunc($arg as xs:numeric?, $n as xs:integer) as xs:numeric? external;
declare %a:since("marklogic", "6.0") function math:variance($arg as xs:double*) as xs:double? external;
declare %a:since("marklogic", "6.0") function math:variance-p($arg as xs:double*) as xs:double? external;


Adapted user-defined atomic type test to use $RBKT_SRC_DIR

import schema namespace s = "simple.xsd" at
   "$RBKT_SRC_DIR/Queries/schemas/simple.xsd";

s:HatSizeType("10")

import schema namespace s = "simple.xsd" at
   "../../../test/rbkt/Queries/schemas/simple.xsd";

s:HatSizeType("10")


slightly more robust handling of the cql-query

xquery version "1.0";
module namespace fcs = "http://clarin.eu/fcs/1.0";

declare namespace sru = "http://www.loc.gov/zing/srw/";
import module namespace diag =  "http://www.loc.gov/zing/srw/diagnostic/" at  "modules/diagnostics/diagnostics.xqm";
import module namespace repo-utils = "http://aac.ac.at/content_repository/utils" at  "repo-utils.xqm";

declare namespace tei = "http://www.tei-c.org/ns/1.0";

declare variable $fcs:explain as xs:string := "explain";
declare variable $fcs:scan  as xs:string := "scan";
declare variable $fcs:searchRetrieve as xs:string := "searchRetrieve";

declare variable $fcs:scanSortText as xs:string := "text";
declare variable $fcs:scanSortSize as xs:string := "size";
declare variable $fcs:indexXsl := doc('index.xsl');

(: meanwhile accept both MD-PID or Res-PID (MdSelfLink or ResourceRef/text
:)
declare function fcs:explain($x-context as xs:string*) as item()* {
    let $context := if ($x-context) then $x-context
                    else repo-utils:config-value('explain')
   let $explain := $repo-utils:md-collection//CMD[Header/MdSelfLink/text() eq $context or .//ResourceRef/text() eq $context]//explain (: //ResourceRef/text() :)

    return $explain
};

(:
TODO?: only read explicit indexes + create index on demand.
:)
(:
declare function fcs:scan($scanClause as xs:string, $x-context as xs:string*) {

    let $clause-tokens := tokenize($scanClause,'='),
        $index := $clause-tokens[1],
        $term := $clause-tokens[2],
        (\:$map-index := $repo-utils:mappings/map/index[@key=$index], :\)
        $index-file := concat(repo-utils:config-value('index.prefix'),$index,'.xml'),
        h$result := doc($index-file)

    return $result
};
:)

(:
  (derived from cmd:scanIndex function)
two phases:
    1. one create full index for given path/element within given collection (for now the collection is stored in the name - not perfect) (and cache)
	2. select wished subsequence (on second call, only the second step is performed)
:)
declare function fcs:scan($scan-clause  as xs:string, $x-context as xs:string+, $start-item as xs:integer, $max-items as xs:integer, $p-sort as xs:string?) as item()? {

  let $scx := tokenize($scan-clause,'='),
	 $index-name := $scx[1],
	 $index := fcs:get-mapping($index-name, $x-context ),
	 (: if no index-mapping found, dare to use the index-name as xpath :)
	 $index-xpath := if ($index/text()) then $index/text() else $index-name,
 	 $filter := ($scx[2],'')[1],
	 $sort := if ($p-sort eq $fcs:scanSortText or $p-sort eq $fcs:scanSortSize) then $p-sort else $fcs:scanSortText,
	 $data-collection := repo-utils:context-to-collection($x-context)

	 (: WATCHME: this is quite unreliable, once the id become PIDs :)
	 let $short-xcontext := substring-after($x-context, concat(repo-utils:config-value('explain'),':'))
    let $index-doc-name := repo-utils:gen-cache-id("index", ($short-xcontext, $index-name, $sort),""),

  (: get the base-index from cache, or create and cache :)
    $index-scan := if (repo-utils:is-in-cache($index-doc-name )) then
      repo-utils:get-from-cache($index-doc-name )
    else
        let $getnodes := util:eval(fn:concat("$data-collection/descendant-or-self::", $index-xpath)),
            (: to overcome problems with attributes
            this is not really reliable, but the self::text() test produced bad error,
            so it is reversed, hoping that we will select only elements or text :)
            $prenodes := if ($getnodes[1][self::element()]) then $getnodes
                            else for $t in $getnodes return <v>{$t}</v>
        let $nodes := <nodes path="{fn:concat('//', $index-xpath)}"  >{$prenodes}</nodes>,
        	(: use XSLT-2.0 for-each-group functionality to aggregate the values of a node - much, much faster, than XQuery :)
   	    $data := transform:transform($nodes,$fcs:indexXsl, <parameters><param name="scan-clause" value="{$scan-clause}"/></parameters>)

return repo-utils:store-in-cache($index-doc-name , $data)

	(: extract the required subsequence (according to given sort) :)
	let $res-nodeset := transform:transform($index-scan,$fcs:indexXsl,
			<parameters><param name="scan-clause" value="{$scan-clause}"/>
			            <param name="mode" value="subsequence"/>
						<param name="sort" value="{$sort}"/>
						<param name="filter" value="{$filter}"/>
						<param name="start-item" value="{$start-item}"/>
						<param name="max-items" value="{$max-items}"/>
			</parameters>),
		$count-items := count($res-nodeset/sru:term),
		(: $colls := if (fn:empty($collection)) then '' else fn:string-join($collection, ","), :)
        $colls := string-join( $x-context, ', ') ,
		$created := fn:current-dateTime()
		(: $scan-clause := concat($xpath, '=', $filter) :)
		(: $res := <Terms colls="{$colls}" created="{$created}" count_items="{$count-items}"
					start-item="{$start-item}" max-items="{$max-items}" sort="{$sort}" scanClause="{$scan-clause}"  >{$res-term}</Terms>
					  count_text="{$count-text}" count_distinct_text="{$distinct-text-count}" :)
        (: $res := <sru:scanResponse>
                    <sru:version>1.2</sru:version>
                    {$res-nodeset}
                    <sru:echoedScanRequest>
                        <sru:scanClause>{$scan-clause}</sru:scanClause>
                        <sru:maximumTerms>{ $count-items }</sru:maximumTerms>

                    </sru:echoedScanRequest>
    			</sru:scanResponse>
           :)
(:	let	$result-count := $doc/Term/@count,
    $result-seq := fn:subsequence($doc/Term/v, $start-item, $end-item),
	$result-frag := ($doc/Term, $result-seq),
    $seq-count := fn:count($result-seq) :)

  return $res-nodeset
   (:  repo-utils:serialise-as($res, $format)	 :)
};

declare function fcs:search-retrieve($query as xs:string, $x-context as xs:string*, $startRecord as xs:integer, $maximumRecords as xs:integer) as item()* {
    let $start-time := util:system-dateTime()
    let $data-collection := repo-utils:context-to-collection($x-context)
    (:if ($x-context) then collection($repo-utils:mappings//map[xs:string(@key) eq $x-context]/@path)
                            else $repo-utils:data-collection:)
    let $xpath-query := concat("$data-collection", fcs:transform-query ($query, $x-context))

    let $results := util:eval($xpath-query)

    let	$result-count := fn:count($results),
    $result-seq := fn:subsequence($results, $startRecord, $maximumRecords),
    $seq-count := fn:count($result-seq),
    $end-time := util:system-dateTime(),

    (:<sru:recordSchema>mods</sru:recordSchema>:)
          (:<xQuery><searchClause xmlns="http://www.loc.gov/zing/cql/xcql/">
          <index>dc.title</index>
          <relation>
          <value>=</value>
          </relation>
          <term>dinosaur</term>
          </searchClause>
          </xQuery>:)
    $result :=
    <sru:searchRetrieveResponse>
      <sru:numberOfRecords>{$result-count}</sru:numberOfRecords>
      <sru:echoedSearchRetrieveRequest>
          <sru:version>1.2</sru:version>
          <sru:query>{$query}</sru:query>
          <fcs:x-context>{$x-context}</fcs:x-context>
          <sru:startRecord>{$startRecord}</sru:startRecord>
          <sru:maximumRecords>{$maximumRecords}</sru:maximumRecords>
          <sru:query>{$query}</sru:query>
          <sru:baseUrl>{repo-utils:config-value("base.url")}</sru:baseUrl>
      </sru:echoedSearchRetrieveRequest>
      <sru:extraResponseData>
      	<fcs:returnedRecords>{$seq-count}</fcs:returnedRecords>
		<fcs:duration>{$end-time - $start-time}</fcs:duration>
		<fcs:transformedQuery>{ $xpath-query }</fcs:transformedQuery>
      </sru:extraResponseData>
      <sru:records>
	       {for $rec at $pos in $result-seq
	           let $exp-rec := util:expand($rec, "expand-xincludes=no") (: kwic:summarize($rec,<config width="40"/>) :)
	           return
	               <sru:record>
	                   <sru:recordSchema>http://clarin.eu/fcs/1.0/Resource.xsd</sru:recordSchema>
	                   <sru:recordPacking>xml</sru:recordPacking>
	                   <sru:recordData>
	                       <fcs:Resource>
	                           <fcs:ResourceFragment>
    	                         <fcs:DataView type="full">{$exp-rec}</fcs:DataView>
    	                       </fcs:ResourceFragment>
	                       </fcs:Resource>
	                   </sru:recordData>
	                   <sru:recordPosition>{$pos}</sru:recordPosition>
	                   <sru:recordIdentifier>{$rec/@xml:id}</sru:recordIdentifier>
	                </sru:record>
	       }
      </sru:records>
    </sru:searchRetrieveResponse>

    return $result

};

(: This expects a CQL-query that it (will be able to) translates to XPath
returns: XPath version of the CQL-query
currently it accepts:
term
index=term
index relation term
:)
declare function fcs:transform-query($cql-query as xs:string, $x-context as xs:string) as xs:string {

    let $query-constituents := if (contains($cql-query,'=')) then
                                        tokenize($cql-query, "=")
                                   else tokenize($cql-query, " ")
	let $index := if (count($query-constituents)=1) then
				  "cql.serverChoice"
				 else $query-constituents[1]
	let $searchTerm := if (count($query-constituents)=1) then
							$cql-query
						else if (count($query-constituents)=2) then (: tokenized with '=' :)
						    normalize-space($query-constituents[2])
						else
							$query-constituents[3]
            (: try to get a mapping specific to given context, else take the default :)
    let $context-map := fcs:get-mapping("",$x-context),

            (: try  to get a) a mapping for given index within the context-map,
                    b) in any of the mapping (if not found in the context-map) , - potentially dangerous!!
                    c) or else take the index itself :)

        $index-map := $context-map/index[xs:string(@key) eq $index],
        $resolved-index := if (exists($index-map)) then $index-map/text()
                           else if (exists($repo-utils:mappings//index[xs:string(@key) eq $index])) then
                                $repo-utils:mappings//index[xs:string(@key) eq $index]
                            else $index
            ,
            (: get either a) the specific base-element for the index,
                  b) the default for given map,
                  c) the index itself :)
        $base-elem := if (exists($index-map/@base_elem)) then xs:string($index-map/@base_elem)
                        else if (exists($context-map/@base_elem)) then xs:string($context-map/@base_elem)
                        else $index,
            (: <index status="indexed"> - flag to know if ft-indexes can be used.
            TODO?: should be checked against the actual index-configuration :)
        $indexed := (xs:string($index-map/@status) eq 'indexed'),
        $match-on := if (exists($index-map/@use) ) then xs:string($index-map/@use) else "."

	let $res := concat("//", $resolved-index, "[", if ($indexed) then "ft:query" else "contains", "(", $match-on, ",'", translate($searchTerm,'"',''), "')]",
								"/ancestor-or-self::", $base-elem)

	return $res

};

(: if $index-param = "" return the map-element,
else - if found return the index-element
:)
declare function fcs:get-mapping($index as xs:string, $x-context as xs:string+) as node()* {
    let $context-map := if (exists($repo-utils:mappings//map[xs:string(@key) eq $x-context])) then
                                $repo-utils:mappings//map[xs:string(@key) eq $x-context]
                            else $repo-utils:mappings//map[xs:string(@key) eq 'default']

    return  if ($index eq '') then
                $context-map
             else $context-map/index[xs:string(@key) eq $index]

};

xquery version "1.0";
module namespace fcs = "http://clarin.eu/fcs/1.0";

declare namespace sru = "http://www.loc.gov/zing/srw/";
import module namespace diag =  "http://www.loc.gov/zing/srw/diagnostic/" at  "modules/diagnostics/diagnostics.xqm";
import module namespace repo-utils = "http://aac.ac.at/content_repository/utils" at  "repo-utils.xqm";

declare namespace tei = "http://www.tei-c.org/ns/1.0";

declare variable $fcs:explain as xs:string := "explain";
declare variable $fcs:scan  as xs:string := "scan";
declare variable $fcs:searchRetrieve as xs:string := "searchRetrieve";

declare variable $fcs:scanSortText as xs:string := "text";
declare variable $fcs:scanSortSize as xs:string := "size";
declare variable $fcs:indexXsl := doc('index.xsl');

(: meanwhile accept both MD-PID or Res-PID (MdSelfLink or ResourceRef/text
:)
declare function fcs:explain($x-context as xs:string*) as item()* {
    let $context := if ($x-context) then $x-context
                    else repo-utils:config-value('explain')
   let $explain := $repo-utils:md-collection//CMD[Header/MdSelfLink/text() eq $context or .//ResourceRef/text() eq $context]//explain (: //ResourceRef/text() :)

    return $explain
};

(:
TODO?: only read explicit indexes + create index on demand.
:)
(:
declare function fcs:scan($scanClause as xs:string, $x-context as xs:string*) {

    let $clause-tokens := tokenize($scanClause,'='),
        $index := $clause-tokens[1],
        $term := $clause-tokens[2],
        (\:$map-index := $repo-utils:mappings/map/index[@key=$index], :\)
        $index-file := concat(repo-utils:config-value('index.prefix'),$index,'.xml'),
        h$result := doc($index-file)

    return $result
};
:)

(:
  (derived from cmd:scanIndex function)
two phases:
    1. one create full index for given path/element within given collection (for now the collection is stored in the name - not perfect) (and cache)
	2. select wished subsequence (on second call, only the second step is performed)
:)
declare function fcs:scan($scan-clause  as xs:string, $x-context as xs:string+, $start-item as xs:integer, $max-items as xs:integer, $p-sort as xs:string?) as item()? {

  let $scx := tokenize($scan-clause,'='),
	 $index-name := $scx[1],
	 $index := fcs:get-mapping($index-name, $x-context ),
	 (: if no index-mapping found, dare to use the index-name as xpath :)
	 $index-xpath := if ($index/text()) then $index/text() else $index-name,
 	 $filter := ($scx[2],'')[1],
	 $sort := if ($p-sort eq $fcs:scanSortText or $p-sort eq $fcs:scanSortSize) then $p-sort else $fcs:scanSortText,
	 $data-collection := repo-utils:context-to-collection($x-context)

	 (: WATCHME: this is quite unreliable, once the id become PIDs :)
	 let $short-xcontext := substring-after($x-context, concat(repo-utils:config-value('explain'),':'))
    let $index-doc-name := repo-utils:gen-cache-id("index", ($short-xcontext, $index-name, $sort),""),

  (: get the base-index from cache, or create and cache :)
    $index-scan := if (repo-utils:is-in-cache($index-doc-name )) then
      repo-utils:get-from-cache($index-doc-name )
    else
        let $getnodes := util:eval(fn:concat("$data-collection/descendant-or-self::", $index-xpath)),
            (: to overcome problems with attributes
            this is not really reliable, but the self::text() test produced bad error,
            so it is reversed, hoping that we will select only elements or text :)
            $prenodes := if ($getnodes[1][self::element()]) then $getnodes
                            else for $t in $getnodes return <v>{$t}</v>
        let $nodes := <nodes path="{fn:concat('//', $index-xpath)}"  >{$prenodes}</nodes>,
        	(: use XSLT-2.0 for-each-group functionality to aggregate the values of a node - much, much faster, than XQuery :)
   	    $data := transform:transform($nodes,$fcs:indexXsl, <parameters><param name="scan-clause" value="{$scan-clause}"/></parameters>)

return repo-utils:store-in-cache($index-doc-name , $data)

	(: extract the required subsequence (according to given sort) :)
	let $res-nodeset := transform:transform($index-scan,$fcs:indexXsl,
			<parameters><param name="scan-clause" value="{$scan-clause}"/>
			            <param name="mode" value="subsequence"/>
						<param name="sort" value="{$sort}"/>
						<param name="filter" value="{$filter}"/>
						<param name="start-item" value="{$start-item}"/>
						<param name="max-items" value="{$max-items}"/>
			</parameters>),
		$count-items := count($res-nodeset/sru:term),
		(: $colls := if (fn:empty($collection)) then '' else fn:string-join($collection, ","), :)
        $colls := string-join( $x-context, ', ') ,
		$created := fn:current-dateTime()
		(: $scan-clause := concat($xpath, '=', $filter) :)
		(: $res := <Terms colls="{$colls}" created="{$created}" count_items="{$count-items}"
					start-item="{$start-item}" max-items="{$max-items}" sort="{$sort}" scanClause="{$scan-clause}"  >{$res-term}</Terms>
					  count_text="{$count-text}" count_distinct_text="{$distinct-text-count}" :)
        (: $res := <sru:scanResponse>
                    <sru:version>1.2</sru:version>
                    {$res-nodeset}
                    <sru:echoedScanRequest>
                        <sru:scanClause>{$scan-clause}</sru:scanClause>
                        <sru:maximumTerms>{ $count-items }</sru:maximumTerms>

                    </sru:echoedScanRequest>
    			</sru:scanResponse>
           :)
(:	let	$result-count := $doc/Term/@count,
    $result-seq := fn:subsequence($doc/Term/v, $start-item, $end-item),
	$result-frag := ($doc/Term, $result-seq),
    $seq-count := fn:count($result-seq) :)

  return $res-nodeset
   (:  repo-utils:serialise-as($res, $format)	 :)
};

declare function fcs:search-retrieve($query as xs:string, $x-context as xs:string*, $startRecord as xs:integer, $maximumRecords as xs:integer) as item()* {
    let $start-time := util:system-dateTime()
    let $data-collection := repo-utils:context-to-collection($x-context)
    (:if ($x-context) then collection($repo-utils:mappings//map[xs:string(@key) eq $x-context]/@path)
                            else $repo-utils:data-collection:)
    let $xpath-query := concat("$data-collection", fcs:transform-query ($query, $x-context))

    let $results := util:eval($xpath-query)

    let	$result-count := fn:count($results),
    $result-seq := fn:subsequence($results, $startRecord, $maximumRecords),
    $seq-count := fn:count($result-seq),
    $end-time := util:system-dateTime(),

    (:<sru:recordSchema>mods</sru:recordSchema>:)
          (:<xQuery><searchClause xmlns="http://www.loc.gov/zing/cql/xcql/">
          <index>dc.title</index>
          <relation>
          <value>=</value>
          </relation>
          <term>dinosaur</term>
          </searchClause>
          </xQuery>:)
    $result :=
    <sru:searchRetrieveResponse>
      <sru:numberOfRecords>{$result-count}</sru:numberOfRecords>
      <sru:echoedSearchRetrieveRequest>
          <sru:version>1.2</sru:version>
          <sru:query>{$query}</sru:query>
          <fcs:x-context>{$x-context}</fcs:x-context>
          <sru:startRecord>{$startRecord}</sru:startRecord>
          <sru:maximumRecords>{$maximumRecords}</sru:maximumRecords>
          <sru:query>{$query}</sru:query>
          <sru:baseUrl>{repo-utils:config-value("base.url")}</sru:baseUrl>
      </sru:echoedSearchRetrieveRequest>
      <sru:extraResponseData>
      	<fcs:returnedRecords>{$seq-count}</fcs:returnedRecords>
		<fcs:duration>{$end-time - $start-time}</fcs:duration>
		<fcs:transformedQuery>{ $xpath-query }</fcs:transformedQuery>
      </sru:extraResponseData>
      <sru:records>
	       {for $rec at $pos in $result-seq
	           let $exp-rec := util:expand($rec, "expand-xincludes=no") (: kwic:summarize($rec,<config width="40"/>) :)
	           return
	               <sru:record>
	                   <sru:recordSchema>http://clarin.eu/fcs/1.0/Resource.xsd</sru:recordSchema>
	                   <sru:recordPacking>xml</sru:recordPacking>
	                   <sru:recordData>
	                       <fcs:Resource>
	                           <fcs:ResourceFragment>
    	                         <fcs:DataView type="full">{$exp-rec}</fcs:DataView>
    	                       </fcs:ResourceFragment>
	                       </fcs:Resource>
	                   </sru:recordData>
	                   <sru:recordPosition>{$pos}</sru:recordPosition>
	                   <sru:recordIdentifier>{$rec/@xml:id}</sru:recordIdentifier>
	                </sru:record>
	       }
      </sru:records>
    </sru:searchRetrieveResponse>

    return $result

};

(: This expects a CQL-query that it (will be able to) translates to XPath
returns: XPath version of the CQL-query :)
declare function fcs:transform-query($cql-query as xs:string, $x-context as xs:string) as xs:string {
    let $query-constituents := tokenize($cql-query, " ")
	let $index := if (count($query-constituents)=1) then
				  "cql.serverChoice"
				 else
					$query-constituents[1]
	let $searchTerm := if (count($query-constituents)=1) then
							$cql-query
						else
							$query-constituents[3]
            (: try to get a mapping specific to given context, else take the default :)
    let $context-map := fcs:get-mapping("",$x-context),

            (: try  to get a) a mapping for given index within the context-map,
                    b) in any of the mapping (if not found in the context-map) , - potentially dangerous!!
                    c) or else take the index itself :)

        $index-map := $context-map/index[xs:string(@key) eq $index],
        $resolved-index := if (exists($index-map)) then $index-map/text()
                           else if (exists($repo-utils:mappings//index[xs:string(@key) eq $index])) then
                                $repo-utils:mappings//index[xs:string(@key) eq $index]
                            else $index
            ,
            (: get either a) the specific base-element for the index,
                  b) the default for given map,
                  c) the index itself :)
        $base-elem := if (exists($index-map/@base_elem)) then xs:string($index-map/@base_elem)
                        else if (exists($context-map/@base_elem)) then xs:string($context-map/@base_elem)
                        else $index,
            (: <index status="indexed"> - flag to know if ft-indexes can be used.
            TODO?: should be checked against the actual index-configuration :)
        $indexed := (xs:string($index-map/@status) eq 'indexed'),
        $match-on := if (exists($index-map/@use) ) then xs:string($index-map/@use) else "."

	let $res := concat("//", $resolved-index, "[", if ($indexed) then "ft:query" else "contains", "(", $match-on, ",'", $searchTerm, "')]",
								"/ancestor-or-self::", $base-elem)

	return $res

};

(: if $index-param = "" return the map-element,
else - if found return the index-element
:)
declare function fcs:get-mapping($index as xs:string, $x-context as xs:string+) as node()* {
    let $context-map := if (exists($repo-utils:mappings//map[xs:string(@key) eq $x-context])) then
                                $repo-utils:mappings//map[xs:string(@key) eq $x-context]
                            else $repo-utils:mappings//map[xs:string(@key) eq 'default']

    return  if ($index eq '') then
                $context-map
             else $context-map/index[xs:string(@key) eq $index]

};


Fix atom feed title

Fix atom feed title

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

(: Generate Index :)

let $summaries := {
  "85623075060": "Charles Hoffman posted a great article on secxbrl.info.",
  "85528073805": "Did you ever wonder how secxbrl.info is able to handle the huge amount of highly-dimensional data? Here is why.",
  "85127528110": "In this blog entry, we are addressing the following characteristics: Consistency, accuracy, and comparability. Specifically, we show how the custom report feature of secxbrl.info can be used as a framework for building functionality to verify those characteristics.",
  "81678006917": "We are excited to announce a new way you to explore financial and business information: secxbrl.info."
}

let $channel := doc("http://28-io.tumblr.com/rss")/rss/channel
let $index :=  {
  "title": "secxbrl - US Public Company Financial Information Repository",
  "tags": {|
    for $tag in distinct-values($channel/item/category/string())
    return { $tag: count($channel/category/[string() eq $tag]) }
  |},
  "entries": [
    for $entry in $channel/item
    let $title := $entry/title/string()
    let $title-id := replace($title, "[^\w ]", "") ! lower-case(.) ! replace(., "\s", "-")
    let $id := tokenize($entry/guid/string(), "/")[last()]
    where $id = jn:keys($summaries)
    return {
      "title": $title,
      "guid": $id,
      "id": "/" || $entry/guid/string() ! tokenize(., '/')[last()] || "/" || $title-id,
      "updated": $entry/pubDate/text(),
      "summary": $summaries($entry/guid/string() ! tokenize(., '/')[last()]),
      "content": $entry/description/string(),
      "tags": [
        for $cat in $entry/category
        return $cat/string()
      ]
    }
  ]
}
(:
let $rss := http:send-request(<http:request href="http://28-io.tumblr.com/rss" method="GET" />)[2]
:)
let $feed := <feed xmlns="http://www.w3.org/2005/Atom">
  <title>secxbrl.info - US Public Company Financial Information Repository</title>
  <link href="https://app.secxbrl.info/blog/atom.xml"/>
  <updated>{current-dateTime()}</updated>
  <author>
    <name>28msec</name>
  </author>
  {
    for $entry in $index("entries") ! jn:members(.)
    let $id := $entry("guid")
    where $id = jn:keys($summaries)
    return <entry>
      <title>{$entry("title")}</title>
      <id>{$entry("id")}</id>
      <summary>{$entry("summary")}</summary>
      <updated>{$entry("updated")}</updated>
      <content type="html">
      {$entry("content")}
      </content>
      {
        for $cat in $entry("tags") ! jn:members(.)
        return <category label="{$cat}" />
      }
    </entry>
  }
</feed>
return {
  fs:write-text("index.json", serialize($index, ()), "utf-8");
  fs:write-text("atom.xml", serialize($feed, ()), "utf-8");
}

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

(: Generate Index :)

let $summaries := {
  "85623075060": "Charles Hoffman posted a great article on secxbrl.info.",
  "85528073805": "Did you ever wonder how secxbrl.info is able to handle the huge amount of highly-dimensional data? Here is why.",
  "85127528110": "In this blog entry, we are addressing the following characteristics: Consistency, accuracy, and comparability. Specifically, we show how the custom report feature of secxbrl.info can be used as a framework for building functionality to verify those characteristics.",
  "81678006917": "We are excited to announce a new way you to explore financial and business information: secxbrl.info."
}

let $channel := doc("http://28-io.tumblr.com/rss")/rss/channel
let $index :=  {
  "title": $channel/title/text(),
  "tags": {|
    for $tag in distinct-values($channel/item/category/string())
    return { $tag: count($channel/category/[string() eq $tag]) }
  |},
  "entries": [
    for $entry in $channel/item
    let $title := $entry/title/string()
    let $title-id := replace($title, "[^\w ]", "") ! lower-case(.) ! replace(., "\s", "-")
    let $id := tokenize($entry/guid/string(), "/")[last()]
    where $id = jn:keys($summaries)
    return {
      "title": $title,
      "guid": $id,
      "id": "/" || $entry/guid/string() ! tokenize(., '/')[last()] || "/" || $title-id,
      "updated": $entry/pubDate/text(),
      "summary": $summaries($entry/guid/string() ! tokenize(., '/')[last()]),
      "content": $entry/description/string(),
      "tags": [
        for $cat in $entry/category
        return $cat/string()
      ]
    }
  ]
}
(:
let $rss := http:send-request(<http:request href="http://28-io.tumblr.com/rss" method="GET" />)[2]
:)
let $feed := <feed xmlns="http://www.w3.org/2005/Atom">
  <title>28.io - Blog</title>
  <link href="https://app.secxbrl.info/blog/atom.xml"/>
  <updated>{current-dateTime()}</updated>
  <author>
    <name>28msec</name>
  </author>
  {
    for $entry in $index("entries") ! jn:members(.)
    let $id := $entry("guid")
    where $id = jn:keys($summaries)
    return <entry>
      <title>{$entry("title")}</title>
      <id>{$entry("id")}</id>
      <summary>{$entry("summary")}</summary>
      <updated>{$entry("updated")}</updated>
      <content type="html">
      {$entry("content")}
      </content>
      {
        for $cat in $entry("tags") ! jn:members(.)
        return <category label="{$cat}" />
      }
    </entry>
  }
</feed>
return {
  fs:write-text("index.json", serialize($index, ()), "utf-8");
  fs:write-text("atom.xml", serialize($feed, ()), "utf-8");
}