fixed small typo in node-position.xq

fixed small typo in node-position.xq

xquery version "1.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 a function (np:node-position) that, given a node,
 : returns positional information about the node in the form of an xs:anyURI
 : item. The module also defines functions that use such positional information
 : to determine: (1) structural relationships between two nodes (e.g. if one
 : is the ancestor of another) and (2) properties of a node (e.g. its level in
 : the tree).
 :
 : Within this module, the term "node position" will be used to refer to an
 : xs:anyURI item that is returned by the np:node-position function.
 :
 : @author Federico Cavalieri
 :)
module namespace np = "http://www.zorba-xquery.com/modules/node-position";

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

(:~
 : Compute a stable and opaque structural information representation
 : (with type xs:anyURI) for a given node.
 :
 :
The returned URI is stable, i.e. it does not change when other
 : nodes are inserted, deleted or modified.

 :
 :
Each node in a snapshot has a different URI. Note however that
 : different nodes in different snapshots might have the same URI.

 :
 : @param $arg the node for which the structural information URI
 :  should be computed
 :
 : @return the opaque structural information URI of the node.
 :)
declare function np:node-position(
  $arg as node()
) as xs:anyURI external;

(:~
 : Determines whether the node whose structural information is
 : given as second argument is an ancestor of the node whose
 : structural information is given as first argument.
 :
 : @param $s-info1 the potential descendant structural information
 : @param $s-info2 the potential ancestor structural information
 :
 : @return true if the node whose structural information is $s-info2
 : is an ancestor of the node whose structural information is $s-info1;
 : false otherwise.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:ancestor-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether the node whose structural information is
 : given as second argument is a descendant of the node whose
 : structural information is given as first argument.
 :
 : @param $s-info1 the potential ancestor structural information
 : @param $s-info2 the potential descendant structural information
 :
 : @return true if the node whose structural information is $s-info2
 : is a descendant of the node whose structural information is $s-info1;
 : false otherwise.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:descendant-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether the node whose structural information is
 : given as second argument is the parent of the node whose
 : structural information is given as first argument.
 :
 : @param $s-info1 the potential child structural information
 : @param $s-info2 the potential parent structural information
 :
 : @return true if the node whose structural information is $s-info2
 : is the parent of the node whose structural information is $s-info1;
 : false otherwise.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:parent-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether the node whose structural information is
 : given as second argument is a child of the node whose
 : structural information is given as first argument.
 :
 : @param $s-info1 the potential parent structural information
 : @param $s-info2 the potential child structural information
 :
 : @return true if the node whose structural information is $s-info2
 : is a child of the node whose structural information is $s-info1;
 : false otherwise.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:child-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether the node whose structural information is
 : given as second argument is an attribute of the node whose
 : structural information is given as first argument.
 :
 : @param $s-info1 the potential parent structural information
 : @param $s-info2 the potential attribute structural information
 :
 : @return true if the node whose structural information is $s-info2
 : is an attribute of the node whose structural information is $s-info1;
 : false otherwise.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:attribute-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether the node whose structural information is
 : given as second argument is a following-sibling of the node
 : whose structural information is given as first argument.
 :
 : @param $s-info1 the potential preceding-sibling structural information
 : @param $s-info2 the potential following-sibling structural information
 :
 : @return true if the node whose structural information is $s-info2
 : is a following-sibling of the node whose structural information is $s-info1;
 : false otherwise.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:following-sibling-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether the node whose structural information is
 : given as second argument is a preceding-sibling of the node
 : whose structural information is given as first argument.
 :
 : @param $s-info1 the potential following-sibling structural information
 : @param $s-info2 the potential preceding-sibling structural information
 :
 : @return true if the node whose structural information is $s-info2
 : is a preceding-sibling of the node whose structural information is $s-info1;
 : false otherwise.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:preceding-sibling-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether the node whose structural information is
 : given as second argument is following the node whose
 : structural information is given as first argument.
 :
 : @param $s-info1 the potential preceding node structural information
 : @param $s-info2 the potential following node structural information
 :
 : @return true if the node whose structural information is $s-info2
 : is following the node whose structural information is $s-info1;
 : false otherwise.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:following-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether the node whose structural information is
 : given as second argument is following in document order the node whose
 : structural information is given as first argument.
 :
 : @param $s-info1 the potential preceding node structural information
 : @param $s-info2 the potential following node structural information
 :
 : @return true if the node whose structural information is $s-info2
 : is following in document order the node whose structural information
 : is $s-info1; false otherwise.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:following-in-document-order-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether the node whose structural information is
 : given as second argument is preceding the node whose
 : structural information is given as first argument.
 :
 : @param $s-info1 the potential following node structural information
 : @param $s-info2 the potential preceding node structural information
 :
 : @return true if the node whose structural information is $s-info2
 : is preceding the node whose structural information is $s-info1;
 : false otherwise.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:preceding-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether the node whose structural information is
 : given as second argument is preceding the node whose
 : structural information is given as first argument.
 :
 : @param $s-info1 the potential following node structural information
 : @param $s-info2 the potential preceding node structural information
 :
 : @return true if the node whose structural information is $s-info2
 : is preceding in document order the node whose structural information
 : is $s-info1; false otherwise.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:preceding-in-document-order-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Computes the level of a node in the tree given its structural
 : information.
 :
 : Note: The first level has the number one.
 :
 : @param $s-info the structural information of the node which
 :  level should be computed
 :
 : @return The level in the tree as xs:integer of the node whose
 : structural information is $s-info.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:level(
  $s-info as xs:anyURI) as xs:integer external;

(:~
 : Determines whether two nodes are siblings given their structural information.
 :
 : @param $s-info1 a node structural information
 : @param $s-info2 a node structural information
 :
 : @return true if the two nodes whose structural information are $s-info1
 : and $s-info2 are siblings; false otherwise.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:sibling-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether a node is an attribute given its structural information.
 :
 : @param $s-info the potential attribute structural information
 :
 : @return true if the node whose structural information is $s-info
 : is an attribute; false otherwise.
 :
 : @error zerr:ZAPI0028 if the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:is-attribute(
  $s-info1 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether a node is a comment given its structural information.
 :
 : @param $s-info the potential comment structural information
 :
 : @return true if the node whose structural information is $s-info
 : is a comment; false otherwise.
 :
 : @error zerr:ZAPI0028 if the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:is-comment(
  $s-info1 as xs:anyURI) as xs:boolean external;

  (:~
 : Determines whether a node is a document given its structural information.
 :
 : @param $s-info the potential document structural information
 :
 : @return true if the node whose structural information is $s-info
 : is a document; false otherwise.
 :
 : @error zerr:ZAPI0028 if the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:is-document(
  $s-info1 as xs:anyURI) as xs:boolean external;

  (:~
 : Determines whether a node is an element given its structural information.
 :
 : @param $s-info the potential element structural information
 :
 : @return true if the node whose structural information is $s-info
 : is an element; false otherwise.
 :
 : @error zerr:ZAPI0028 if the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:is-element(
  $s-info1 as xs:anyURI) as xs:boolean external;

  (:~
 : Determines whether a node is a processing-instruction given its structural information.
 :
 : @param $s-info the potential processing-instruction structural information
 :
 : @return true if the node whose structural information is $s-info
 : is a processing-instruction; false otherwise.
 :
 : @error zerr:ZAPI0028 if the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:is-processing-instruction(
  $s-info1 as xs:anyURI) as xs:boolean external;

  (:~
 : Determines whether a node is a text given its structural information.
 :
 : @param $s-info the potential text node structural information
 :
 : @return true if the node whose structural information is $s-info
 : is a text node; false otherwise.
 :
 : @error zerr:ZAPI0028 if the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:is-text(
  $s-info1 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether two nodes belong to the same tree given their
 : structural information.
 :
 : @param $s-info1 a node structural information
 : @param $s-info2 a node structural information
 :
 : @return true if the two node whose structural information are $s-info1
 : and $s-info2 belong to the same tree.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:in-same-tree-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether a node belongs to a collection given its structural
 : information.
 :
 : @param $s-info the node structural information
 :
 : @return true if the node whose structural information is $s-info
 : is in a collection; false otherwise.
 :
 : @error zerr:ZAPI0028 if the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:in-collection(
  $s-info as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether two nodes belong to the same collection given their
 : structural information.
 :
 : @param $s-info1 a node structural information
 : @param $s-info2 a node structural information
 :
 : @return true if the two node whose structural information are $s-info1
 : and $s-info2 belong to the same collection.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:in-same-collection-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

xquery version "1.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 a function (np:node-position) that, given a node,
 : returns positional information about the node in the form of an xs:anyURI
 : item. The module also defines functions that use such positional information
 : to determine: (1) structural relationships between two nodes (e.g. if one
 : is the ancestor of another) and (2) properties of a node (e.g. its level in
 : the tree).
 :
 : Within this module, the temp "node position" will be used to refer to an
 : xs:anyURI item that is returned by the np:node-position function.
 :
 : @author Federico Cavalieri
 :)
module namespace np = "http://www.zorba-xquery.com/modules/node-position";

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

(:~
 : Compute a stable and opaque structural information representation
 : (with type xs:anyURI) for a given node.
 :
 :
The returned URI is stable, i.e. it does not change when other
 : nodes are inserted, deleted or modified.

 :
 :
Each node in a snapshot has a different URI. Note however that
 : different nodes in different snapshots might have the same URI.

 :
 : @param $arg the node for which the structural information URI
 :  should be computed
 :
 : @return the opaque structural information URI of the node.
 :)
declare function np:node-position(
  $arg as node()
) as xs:anyURI external;

(:~
 : Determines whether the node whose structural information is
 : given as second argument is an ancestor of the node whose
 : structural information is given as first argument.
 :
 : @param $s-info1 the potential descendant structural information
 : @param $s-info2 the potential ancestor structural information
 :
 : @return true if the node whose structural information is $s-info2
 : is an ancestor of the node whose structural information is $s-info1;
 : false otherwise.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:ancestor-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether the node whose structural information is
 : given as second argument is a descendant of the node whose
 : structural information is given as first argument.
 :
 : @param $s-info1 the potential ancestor structural information
 : @param $s-info2 the potential descendant structural information
 :
 : @return true if the node whose structural information is $s-info2
 : is a descendant of the node whose structural information is $s-info1;
 : false otherwise.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:descendant-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether the node whose structural information is
 : given as second argument is the parent of the node whose
 : structural information is given as first argument.
 :
 : @param $s-info1 the potential child structural information
 : @param $s-info2 the potential parent structural information
 :
 : @return true if the node whose structural information is $s-info2
 : is the parent of the node whose structural information is $s-info1;
 : false otherwise.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:parent-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether the node whose structural information is
 : given as second argument is a child of the node whose
 : structural information is given as first argument.
 :
 : @param $s-info1 the potential parent structural information
 : @param $s-info2 the potential child structural information
 :
 : @return true if the node whose structural information is $s-info2
 : is a child of the node whose structural information is $s-info1;
 : false otherwise.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:child-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether the node whose structural information is
 : given as second argument is an attribute of the node whose
 : structural information is given as first argument.
 :
 : @param $s-info1 the potential parent structural information
 : @param $s-info2 the potential attribute structural information
 :
 : @return true if the node whose structural information is $s-info2
 : is an attribute of the node whose structural information is $s-info1;
 : false otherwise.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:attribute-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether the node whose structural information is
 : given as second argument is a following-sibling of the node
 : whose structural information is given as first argument.
 :
 : @param $s-info1 the potential preceding-sibling structural information
 : @param $s-info2 the potential following-sibling structural information
 :
 : @return true if the node whose structural information is $s-info2
 : is a following-sibling of the node whose structural information is $s-info1;
 : false otherwise.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:following-sibling-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether the node whose structural information is
 : given as second argument is a preceding-sibling of the node
 : whose structural information is given as first argument.
 :
 : @param $s-info1 the potential following-sibling structural information
 : @param $s-info2 the potential preceding-sibling structural information
 :
 : @return true if the node whose structural information is $s-info2
 : is a preceding-sibling of the node whose structural information is $s-info1;
 : false otherwise.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:preceding-sibling-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether the node whose structural information is
 : given as second argument is following the node whose
 : structural information is given as first argument.
 :
 : @param $s-info1 the potential preceding node structural information
 : @param $s-info2 the potential following node structural information
 :
 : @return true if the node whose structural information is $s-info2
 : is following the node whose structural information is $s-info1;
 : false otherwise.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:following-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether the node whose structural information is
 : given as second argument is following in document order the node whose
 : structural information is given as first argument.
 :
 : @param $s-info1 the potential preceding node structural information
 : @param $s-info2 the potential following node structural information
 :
 : @return true if the node whose structural information is $s-info2
 : is following in document order the node whose structural information
 : is $s-info1; false otherwise.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:following-in-document-order-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether the node whose structural information is
 : given as second argument is preceding the node whose
 : structural information is given as first argument.
 :
 : @param $s-info1 the potential following node structural information
 : @param $s-info2 the potential preceding node structural information
 :
 : @return true if the node whose structural information is $s-info2
 : is preceding the node whose structural information is $s-info1;
 : false otherwise.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:preceding-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether the node whose structural information is
 : given as second argument is preceding the node whose
 : structural information is given as first argument.
 :
 : @param $s-info1 the potential following node structural information
 : @param $s-info2 the potential preceding node structural information
 :
 : @return true if the node whose structural information is $s-info2
 : is preceding in document order the node whose structural information
 : is $s-info1; false otherwise.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:preceding-in-document-order-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Computes the level of a node in the tree given its structural
 : information.
 :
 : Note: The first level has the number one.
 :
 : @param $s-info the structural information of the node which
 :  level should be computed
 :
 : @return The level in the tree as xs:integer of the node whose
 : structural information is $s-info.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:level(
  $s-info as xs:anyURI) as xs:integer external;

(:~
 : Determines whether two nodes are siblings given their structural information.
 :
 : @param $s-info1 a node structural information
 : @param $s-info2 a node structural information
 :
 : @return true if the two nodes whose structural information are $s-info1
 : and $s-info2 are siblings; false otherwise.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:sibling-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether a node is an attribute given its structural information.
 :
 : @param $s-info the potential attribute structural information
 :
 : @return true if the node whose structural information is $s-info
 : is an attribute; false otherwise.
 :
 : @error zerr:ZAPI0028 if the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:is-attribute(
  $s-info1 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether a node is a comment given its structural information.
 :
 : @param $s-info the potential comment structural information
 :
 : @return true if the node whose structural information is $s-info
 : is a comment; false otherwise.
 :
 : @error zerr:ZAPI0028 if the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:is-comment(
  $s-info1 as xs:anyURI) as xs:boolean external;

  (:~
 : Determines whether a node is a document given its structural information.
 :
 : @param $s-info the potential document structural information
 :
 : @return true if the node whose structural information is $s-info
 : is a document; false otherwise.
 :
 : @error zerr:ZAPI0028 if the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:is-document(
  $s-info1 as xs:anyURI) as xs:boolean external;

  (:~
 : Determines whether a node is an element given its structural information.
 :
 : @param $s-info the potential element structural information
 :
 : @return true if the node whose structural information is $s-info
 : is an element; false otherwise.
 :
 : @error zerr:ZAPI0028 if the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:is-element(
  $s-info1 as xs:anyURI) as xs:boolean external;

  (:~
 : Determines whether a node is a processing-instruction given its structural information.
 :
 : @param $s-info the potential processing-instruction structural information
 :
 : @return true if the node whose structural information is $s-info
 : is a processing-instruction; false otherwise.
 :
 : @error zerr:ZAPI0028 if the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:is-processing-instruction(
  $s-info1 as xs:anyURI) as xs:boolean external;

  (:~
 : Determines whether a node is a text given its structural information.
 :
 : @param $s-info the potential text node structural information
 :
 : @return true if the node whose structural information is $s-info
 : is a text node; false otherwise.
 :
 : @error zerr:ZAPI0028 if the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:is-text(
  $s-info1 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether two nodes belong to the same tree given their
 : structural information.
 :
 : @param $s-info1 a node structural information
 : @param $s-info2 a node structural information
 :
 : @return true if the two node whose structural information are $s-info1
 : and $s-info2 belong to the same tree.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:in-same-tree-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether a node belongs to a collection given its structural
 : information.
 :
 : @param $s-info the node structural information
 :
 : @return true if the node whose structural information is $s-info
 : is in a collection; false otherwise.
 :
 : @error zerr:ZAPI0028 if the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:in-collection(
  $s-info as xs:anyURI) as xs:boolean external;

(:~
 : Determines whether two nodes belong to the same collection given their
 : structural information.
 :
 : @param $s-info1 a node structural information
 : @param $s-info2 a node structural information
 :
 : @return true if the two node whose structural information are $s-info1
 : and $s-info2 belong to the same collection.
 :
 : @error zerr:ZAPI0028 if one of the given URI is not a valid node structural
 : information computed by the <tt>np:node-position</tt> function.
 :)
declare function np:in-same-collection-of(
  $s-info1 as xs:anyURI,
  $s-info2 as xs:anyURI) as xs:boolean external;


[ignore] redirect requests to index.xml to the main start page

svn path=/trunk/eXist/; revision=10475

xquery version "1.0";

import module namespace request="http://exist-db.org/xquery/request";
import module namespace xdb = "http://exist-db.org/xquery/xmldb";

if ($exist:path = "/") then
    <dispatch xmlns="http://exist.sourceforge.net/NS/exist">
		<redirect url="../examples.xml"/>
	</dispatch>
else if ($exist:resource = 'index.xml') then
    <dispatch xmlns="http://exist.sourceforge.net/NS/exist">
		<redirect url="{$exist:context}/index.xml"/>
	</dispatch>
else if (ends-with($exist:path, '.xql/source')) then
    let $resource := substring-before($exist:path, '/source')
    return
        <dispatch xmlns="http://exist.sourceforge.net/NS/exist">
    		<forward url="{$exist:controller}{$resource}?source"/>
    		<view>
    			<forward url="/xquery/source.xql">
                    <set-attribute name="resource" value="{$resource}"/>
                </forward>
    		</view>
    	</dispatch>
else if ($exist:resource = ('search.xql', 'functions.xql', 'svnlog.xql')) then
	<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
		<!-- query results are passed to XSLT servlet via request attribute -->
		<set-attribute name="xquery.attribute"
			value="model"/>
		<view>
			<forward servlet="XSLTServlet">
				<set-attribute name="xslt.input"
					value="model"/>
				<set-attribute name="xslt.stylesheet"
					value="{$exist:root}/stylesheets/db2xhtml.xsl"/>
				<set-attribute name="xslt.output.media-type"
				        value="text/html"/>
				<set-attribute name="xslt.output.doctype-public"
				    value="-//W3C//DTD XHTML 1.0 Transitional//EN"/>
				<set-attribute name="xslt.output.doctype-system"
				    value="resources/xhtml1-transitional.dtd"/>
			</forward>
		</view>
		<cache-control cache="no"/>
	</dispatch>
else if ($exist:resource eq 'acronyms.xql') then
	<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
		<!-- query results are passed to XSLT servlet via request attribute -->
		<set-attribute name="xquery.attribute"
			value="model"/>
		<view>
			<forward servlet="XSLTServlet">
				<set-attribute name="xslt.input"
					value="model"/>
				<set-attribute name="xslt.stylesheet"
					value="stylesheets/acronyms.xsl"/>
			</forward>
			<forward servlet="XSLTServlet">
				<set-attribute name="xslt.input"
					value=""/>
				<set-attribute name="xslt.stylesheet"
					value="{$exist:root}/stylesheets/db2xhtml.xsl"/>
				<set-attribute name="xslt.output.media-type"
				        value="text/html"/>
				<set-attribute name="xslt.output.doctype-public"
				    value="-//W3C//DTD XHTML 1.0 Transitional//EN"/>
				<set-attribute name="xslt.output.doctype-system"
				    value="resources/xhtml1-transitional.dtd"/>
			</forward>
		</view>
	</dispatch>
else if ($exist:resource = 'biblio.xml') then
	<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
		<view>
			<forward servlet="XSLTServlet">
				<set-attribute name="xslt.stylesheet"
					value="stylesheets/doc2html-2.xsl"/>
			</forward>
		</view>
		<cache-control cache="yes"/>
	</dispatch>
else if ($exist:resource eq 'biblio.xql') then
	let $display := request:get-parameter("display", "overview")
	let $xsl :=
		if ($display eq "details") then "detailed.xsl" else "overview.xsl"
	return
		<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
			<set-attribute name="xquery.attribute" value="model"/>
			<view>
			<forward servlet="XSLTServlet">
				<set-attribute name="xslt.input"
					value="model"/>
				<set-attribute name="xslt.stylesheet"
					value="xquery/stylesheets/{$xsl}"/>
			</forward>
			<forward servlet="XSLTServlet">
				<set-attribute name="xslt.input"
					value=""/>
				<set-attribute name="xslt.stylesheet"
					value="stylesheets/doc2html-2.xsl"/>
			</forward>

			</view>
		</dispatch>
else if ($exist:resource eq 'twitter.xql') then
    <dispatch xmlns="http://exist.sourceforge.net/NS/exist">
       <forward url="twitter.xql"/>
        <view>
            <forward url="twitter-view.xql"/>
        </view>
    </dispatch>
else if (matches($exist:path, '(styles/syntax|scripts/syntax/|logo.jpg|default-style2.css|curvycorners.js)')) then
    let $newPath := replace($exist:path, '^.*((styles/|scripts/|logo).*)$', '/$1')
    return
        <dispatch xmlns="http://exist.sourceforge.net/NS/exist">
    		<forward url="{$newPath}"/>
    		<cache-control cache="yes"/>
    	</dispatch>
else if (ends-with($exist:path, '/dump')) then
	let $newPath := substring-before($exist:path, '/dump')
	return
        <dispatch xmlns="http://exist.sourceforge.net/NS/exist">
			<forward url="{$exist:controller}{$newPath}"/>
			<view>
				<forward url="/xquery/dump.xql">
				   <set-attribute name="controller" value="{$exist:controller}"/>
				   <set-attribute name="path" value="{$exist:path}"/>
				   <set-attribute name="resource" value="{$exist:resource}"/>
			    </forward>
			</view>
		</dispatch>
else
    <ignore xmlns="http://exist.sourceforge.net/NS/exist">
        <cache-control cache="yes"/>
	</ignore>

xquery version "1.0";

import module namespace request="http://exist-db.org/xquery/request";
import module namespace xdb = "http://exist-db.org/xquery/xmldb";

if ($exist:path = "/") then
    <dispatch xmlns="http://exist.sourceforge.net/NS/exist">
		<redirect url="../examples.xml"/>
	</dispatch>
else if (ends-with($exist:path, '.xql/source')) then
    let $resource := substring-before($exist:path, '/source')
    return
        <dispatch xmlns="http://exist.sourceforge.net/NS/exist">
    		<forward url="{$exist:controller}{$resource}?source"/>
    		<view>
    			<forward url="/xquery/source.xql">
                    <set-attribute name="resource" value="{$resource}"/>
                </forward>
    		</view>
    	</dispatch>
else if ($exist:resource = ('search.xql', 'functions.xql', 'svnlog.xql')) then
	<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
		<!-- query results are passed to XSLT servlet via request attribute -->
		<set-attribute name="xquery.attribute"
			value="model"/>
		<view>
			<forward servlet="XSLTServlet">
				<set-attribute name="xslt.input"
					value="model"/>
				<set-attribute name="xslt.stylesheet"
					value="{$exist:root}/stylesheets/db2xhtml.xsl"/>
				<set-attribute name="xslt.output.media-type"
				        value="text/html"/>
				<set-attribute name="xslt.output.doctype-public"
				    value="-//W3C//DTD XHTML 1.0 Transitional//EN"/>
				<set-attribute name="xslt.output.doctype-system"
				    value="resources/xhtml1-transitional.dtd"/>
			</forward>
		</view>
		<cache-control cache="no"/>
	</dispatch>
else if ($exist:resource eq 'acronyms.xql') then
	<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
		<!-- query results are passed to XSLT servlet via request attribute -->
		<set-attribute name="xquery.attribute"
			value="model"/>
		<view>
			<forward servlet="XSLTServlet">
				<set-attribute name="xslt.input"
					value="model"/>
				<set-attribute name="xslt.stylesheet"
					value="stylesheets/acronyms.xsl"/>
			</forward>
			<forward servlet="XSLTServlet">
				<set-attribute name="xslt.input"
					value=""/>
				<set-attribute name="xslt.stylesheet"
					value="{$exist:root}/stylesheets/db2xhtml.xsl"/>
				<set-attribute name="xslt.output.media-type"
				        value="text/html"/>
				<set-attribute name="xslt.output.doctype-public"
				    value="-//W3C//DTD XHTML 1.0 Transitional//EN"/>
				<set-attribute name="xslt.output.doctype-system"
				    value="resources/xhtml1-transitional.dtd"/>
			</forward>
		</view>
	</dispatch>
else if ($exist:resource = 'biblio.xml') then
	<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
		<view>
			<forward servlet="XSLTServlet">
				<set-attribute name="xslt.stylesheet"
					value="stylesheets/doc2html-2.xsl"/>
			</forward>
		</view>
		<cache-control cache="yes"/>
	</dispatch>
else if ($exist:resource eq 'biblio.xql') then
	let $display := request:get-parameter("display", "overview")
	let $xsl :=
		if ($display eq "details") then "detailed.xsl" else "overview.xsl"
	return
		<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
			<set-attribute name="xquery.attribute" value="model"/>
			<view>
			<forward servlet="XSLTServlet">
				<set-attribute name="xslt.input"
					value="model"/>
				<set-attribute name="xslt.stylesheet"
					value="xquery/stylesheets/{$xsl}"/>
			</forward>
			<forward servlet="XSLTServlet">
				<set-attribute name="xslt.input"
					value=""/>
				<set-attribute name="xslt.stylesheet"
					value="stylesheets/doc2html-2.xsl"/>
			</forward>

			</view>
		</dispatch>
else if ($exist:resource eq 'twitter.xql') then
    <dispatch xmlns="http://exist.sourceforge.net/NS/exist">
       <forward url="twitter.xql"/>
        <view>
            <forward url="twitter-view.xql"/>
        </view>
    </dispatch>
else if (matches($exist:path, '(styles/syntax|scripts/syntax/|logo.jpg|default-style2.css|curvycorners.js)')) then
    let $newPath := replace($exist:path, '^.*((styles/|scripts/|logo).*)$', '/$1')
    return
        <dispatch xmlns="http://exist.sourceforge.net/NS/exist">
    		<forward url="{$newPath}"/>
    		<cache-control cache="yes"/>
    	</dispatch>
else if (ends-with($exist:path, '/dump')) then
	let $newPath := substring-before($exist:path, '/dump')
	return
        <dispatch xmlns="http://exist.sourceforge.net/NS/exist">
			<forward url="{$exist:controller}{$newPath}"/>
			<view>
				<forward url="/xquery/dump.xql">
				   <set-attribute name="controller" value="{$exist:controller}"/>
				   <set-attribute name="path" value="{$exist:path}"/>
				   <set-attribute name="resource" value="{$exist:resource}"/>
			    </forward>
			</view>
		</dispatch>
else
    <ignore xmlns="http://exist.sourceforge.net/NS/exist">
        <cache-control cache="yes"/>
	</ignore>


[ignore] Reformatted code

[ignore] Reformatted code

xquery version "3.0";

module namespace excepttest="http://exist-db.org/xquery/test/except";
import module namespace test="http://exist-db.org/xquery/xqsuite" at "resource:org/exist/xquery/lib/xqsuite/xqsuite.xql";
declare namespace tei="http://www.tei-c.org/ns/1.0";

declare variable $excepttest:DATA :=
    <TEI xmlns="http://www.tei-c.org/ns/1.0" xml:id="sha-mac">
        <text>

                    Act 1

        </text>
    </TEI>;

declare variable $excepttest:DATA2 :=
    <TEI xmlns="http://www.tei-c.org/ns/1.0" xml:id="sha-mac">
        <text>

                    Act 12

        </text>
    </TEI>;

declare variable $excepttest:COLLECTION_NAME := "/exceptTest";
declare variable $excepttest:SUBCOL1_NAME := $excepttest:COLLECTION_NAME||"/col1";
declare variable $excepttest:SUBCOL2_NAME := $excepttest:COLLECTION_NAME||"/col2";

declare variable $excepttest:COLLECTION := collection("/db"||$excepttest:COLLECTION_NAME);
declare variable $excepttest:SUBCOL1 := collection("/db"||$excepttest:SUBCOL1_NAME);
declare variable $excepttest:SUBCOL2 := collection("/db"||$excepttest:SUBCOL2_NAME);

declare
%test:setUp
function excepttest:setup() {

    xmldb:create-collection("/db", $excepttest:COLLECTION_NAME),
    xmldb:create-collection("/db", $excepttest:SUBCOL1_NAME),
    xmldb:create-collection("/db", $excepttest:SUBCOL2_NAME),
    xmldb:store("/db"||$excepttest:SUBCOL1_NAME, "test.xml", $excepttest:DATA),
    xmldb:store("/db"||$excepttest:SUBCOL2_NAME, "test2.xml", $excepttest:DATA2)
};

declare
    %test:tearDown
function excepttest:cleanup() {
    xmldb:remove($excepttest:COLLECTION_NAME)
};

declare
    %test:pending("https://github.com/eXist-db/exist/issues/1348")
    %test:assertEquals("Act 1")
function excepttest:except-wildcard() {
    ($excepttest:COLLECTION/* except $excepttest:SUBCOL2/*)//tei:head/text()
};

declare
    %test:assertEquals("Act 1")
function excepttest:except-node-name() {
    ($excepttest:COLLECTION/tei:TEI except $excepttest:SUBCOL2/tei:TEI)//tei:head/text()
};


corrected the exist db url

corrected the exist db url

xquery version "1.0";

(: ~
 : Module Name:             edit context webpage and XQuery
 :
 : Module Version           2.0
 :
 : Date                     31st July 2009
 :
 : Copyright                The cagrid consortium
 :
 : Module overview          edit context information
 :
 :)

(:~
 :    @author Rakesh Dhaval
      @author Puneet Mathur
 :    @version 0.2
 :
 :    User Management Page
~ :)

  import module namespace
  lib-forms="http://www.cagrid.org/xquery/library/forms"
  at "../edit/m-lib-forms.xquery";

  import module namespace
  lib-util="http://www.cagrid.org/xquery/library/util"
  at "../library/m-lib-util.xquery";

  import module namespace
  lib-rendering="http://www.cagrid.org/xquery/library/rendering"
  at "../web/m-lib-rendering.xquery";

  import module namespace
  lib-make-admin-item="http://www.cagrid.org/xquery/library/make-admin-item"
  at "../edit/m-lib-make-admin-item.xquery";

declare namespace openMDR = "http://www.cagrid.org/schema/openMDR";
declare namespace ISO11179= "http://www.cagrid.org/schema/ISO11179";
declare namespace session="http://exist-db.org/xquery/session";
declare namespace request="http://exist-db.org/xquery/request";
declare namespace response="http://exist-db.org/xquery/response";
declare namespace exist = "http://exist.sourceforge.net/NS/exist";
declare namespace util="http://exist-db.org/xquery/util";
declare namespace xmldb="http://exist-db.org/xquery/xmldb";

declare function local:success-page()
{
   let $calling-page := request:get-parameter("calling-page","")
   return

        if(local:validateUser()=true()) then
        (
        	local:process()
        )
        else(

            Access Denied !! Only users of "dba" group have access

            Return to maintenance menu

        )

};

declare function local:new-user() as element()*
{

    let $name := request:get-parameter("name", ()),
    $grp := request:get-parameter("groups", ()),
    $groups := if ($grp) then
        (
            if(contains($grp, ",")) then
            (
                tokenize($grp, "\s*,\s*")
            )
            else
            (
                $grp
            )
        )else(),
    $pass1 := request:get-parameter("pass1", ""),
    $pass2 := request:get-parameter("pass2", "")
    return

    if($name eq "") then
    (

	Error : UserName is missing !!!!

 {local:correct-user(-1, $name, $grp)}

    )
   (:
   else if($name != "") then
   (
                for $user in doc("/db/system/users.xml")//users/user
                    let $stored_username := xs:string($user/@name)
 	 return(
 	 	if($name eq $stored_username) then
 	 	(

			Error : UserName Already Exists !! Chooose a different Username!!!!

 {local:correct-user(-1, $name, $grp)}

		)
		else()
	   )

   ) :)

    else if($grp eq "") then
    (

	Error : GroupName is missing !! Please specify atleast one group!!!!!

 {local:correct-user(-1, $name, $grp)}

    )

    else if($pass1 != $pass2 or $pass1 eq "") then
        (

	Error : Either Password is missing or Passwords are not identical !!!!

 {local:correct-user(-1, $name, $grp)}

        )
        else(

            xmldb:create-user($name, $pass1, $groups, ""),

            User "{$name}" Created !!!

{local:display()}

          )
};

 declare function local:do-display() as node()?
{
    let $uid := request:get-parameter("uid", ())
    return
        if (empty($uid)) then
            local:display()
        else ()
};

declare function local:display() as node()?
{

      <form  method="get" action="{session:encode-url(request:get-uri())}">

                Name
                Groups

            {
                for $user in doc("/db/system/users.xml")//users/user
                    let $name := xs:string($user/@name),
                    $groups := string-join($user/group, ", ")
                order by $name return

                        <input type="radio" name="uid" value="{$user/@uid}"/>
                        {$name}
                        {$groups}

            }

                    <input type="submit" name="action" value="Edit"/>
                    <input type="submit" name="action" value="New User"/>
                    <input type="submit" name="action" value="Remove"/>

        {
                let $action := request:get-parameter("action", ""),
                $uid := request:get-parameter("uid", ()) return
                if($action eq "Edit") then
                    (
                            if(empty($uid) or xs:integer($uid) le 0)then
 	             (

Error : Select a User to Update !!!!

	            )
      	          else
	            (
                         		let $user := doc("/db/system/users.xml")//users/user[@uid = $uid] return
        			if( ($user/@name) eq "admin" and xmldb:get-current-user() != "admin" ) then
	      	              (

 Error : You do not have permission to Edit the Admin User !!!!

	       	             )
       	             	          else(
                         		local:edit-user(xs:integer($uid), $user/@name, string-join($user/group, ", "))
                         	          )
                           )
                    )
                    else if($action eq "New User") then
                    (
                        local:edit-user(-1, "", "")
                    )else()

        }

Return to maintenance menu
     </form>

} ;

declare function local:correct-user($uid as xs:integer, $name as xs:string, $groups as xs:string)  as element()
{

    <form action="{session:encode-url(request:get-uri())}" method="get">
        {local:edit-user($uid, $name, $groups)}
        <input type="hidden" name="panel" value="users"/>
    </form>

};

declare function local:edit-user($uid as xs:integer, $name as xs:string, $groups as xs:string) as element()
{

            User:
            {
                if($name eq "") then
                (
                    <input type="text" name="name"/>
                )
                else
                (
                    <input type="hidden" name="name" value="{$name}"/>{$name}
                )
            }

            Groups:
            <input type="text" name="groups" value="{$groups}"/>
            A comma-separated list of groups.
            Note: non-existing groups will be created automatically.

            Password:
            <input type="password" name="pass1"/>

            Repeat:
            <input type="password" name="pass2"/>

         {
            if($uid ge 0) then
            (
                <input type="checkbox" name="nopass"/> Leave password unchanged.
            )else()
        }

        {
            if($uid lt 0) then
            (

                <input type="submit" name="action" value="Create"/>
	<input type="submit" name="action" value="Cancel"/>
            )
            else
            (

                <input type="submit" name="action" value="Change"/>
	 <input type="submit" name="action" value="Cancel"/>
            )

        }

        <input type="hidden" name="uid" value="{$uid}"/>

 };

declare function local:process()  as element()*
{
    let $action := request:get-parameter("action", "") ,
    $session_user  := session:get-attribute("username"),
    $current_user := xmldb:get-current-user()
    return
        if($action eq "Create") then
        (
            local:new-user()
        )
       else if($action eq "Change") then
        (
            local:update-user()
        )

         else if($action eq "Remove") then
        (
            local:remove-user()
        )
        else if($action eq "Cancel") then
        (

	       {local:display()}

        )
        else(

	       {local:display()}

        )

};

declare function local:validateUser() as xs:boolean
{
   let $hostname :=  request:get-hostname()

   let $resource_location := concat("xmldb:exist://", "localhost", ":8080/exist/xmlrpc/db")
   let $user := session:get-attribute("username")
   let $password := session:get-attribute("password")
   let $is-ssl :=  lib-util:checkSSL()
   return
           if(xmldb:is-admin-user($user)) then
           (
            	if (xmldb:login($resource_location, $user, $password))
              then (
		true()
	)
	else(
		false()
	)
          )
          else(
	          false()
          )

};

declare function local:update-user() as element()*
{

    let $name := request:get-parameter("name", ()),
    $grp := request:get-parameter("groups", ()),
    $groups := if ($grp) then
        (
            if(contains($grp, ",")) then
            (
                tokenize($grp, "\s*,\s*")
            )
            else
            (
                $grp
            )
        )else(),
    $pass1 := request:get-parameter("pass1", ""),
    $pass2 := request:get-parameter("pass2", ""),
    $nopass := request:get-parameter("nopass", ()),
    $pass := if($nopass) then () else $pass1,
    $uid := request:get-parameter("uid", "") return

        if(not($nopass) and $pass1 ne $pass2)then
        (

Passwords are not identical.
,
            local:correct-user($uid, $name, $grp)
        )
        else if(empty($groups)) then
        (

Please specify one group at least.
,
            local:correct-user($uid, $name, $grp)
        )
        else
        (
            xmldb:change-user($name, $pass, $groups, ""),

            if(xmldb:get-current-user() eq $name) then
            (
                session:set-attribute("password", $pass)
            )else(),

            User "{$name}" Updated !!!

{local:display()}

        )

};

declare function local:remove-user()
{
    if(empty(request:get-parameter("uid", ())) or xs:integer(request:get-parameter("uid", ())) le 0 )then
    (

            Error : Select a User to Remove !!!!

Return to User Management

    )
   else
   (
    let $uid := request:get-parameter("uid", ()),
    $name := doc("/db/system/users.xml")//user[@uid = $uid]/@name cast as xs:string return

        if($name eq xmldb:get-current-user() or $name eq "admin") then
        (

            You cannot remove the Admin User or Current User!!!!

Return to User Management

        )
        else if (xmldb:is-admin-user($name) and xmldb:get-current-user() != "admin") then
        (

            You do not have the permission to remove the user of "dba" group!!!!

Return to User Management

      )
      else
      (

            User "{$name}" Removed !!!

{local:display()}

        )
     )
};

declare option exist:serialize "media-type=text/html method=xhtml doctype-public=-//W3C//DTD XHTML 1.0 Transitional//EN doctype-system=http://www.w3.org/TR/2002/REC-xhtml1-20020801/DTD/xhtml1-transitional.dtd";

   session:create(),
   let $id := request:get-parameter('id','')
   let $title as xs:string := concat(" User Management", $id)

   return
      lib-rendering:txfrm-webpage(
      $title,
            local:success-page()
         )

xquery version "1.0";

(: ~
 : Module Name:             edit context webpage and XQuery
 :
 : Module Version           2.0
 :
 : Date                     31st July 2009
 :
 : Copyright                The cagrid consortium
 :
 : Module overview          edit context information
 :
 :)

(:~
 :    @author Rakesh Dhaval
      @author Puneet Mathur
 :    @version 0.2
 :
 :    User Management Page
~ :)

  import module namespace
  lib-forms="http://www.cagrid.org/xquery/library/forms"
  at "../edit/m-lib-forms.xquery";

  import module namespace
  lib-util="http://www.cagrid.org/xquery/library/util"
  at "../library/m-lib-util.xquery";

  import module namespace
  lib-rendering="http://www.cagrid.org/xquery/library/rendering"
  at "../web/m-lib-rendering.xquery";

  import module namespace
  lib-make-admin-item="http://www.cagrid.org/xquery/library/make-admin-item"
  at "../edit/m-lib-make-admin-item.xquery";

declare namespace openMDR = "http://www.cagrid.org/schema/openMDR";
declare namespace ISO11179= "http://www.cagrid.org/schema/ISO11179";
declare namespace session="http://exist-db.org/xquery/session";
declare namespace request="http://exist-db.org/xquery/request";
declare namespace response="http://exist-db.org/xquery/response";
declare namespace exist = "http://exist.sourceforge.net/NS/exist";
declare namespace util="http://exist-db.org/xquery/util";
declare namespace xmldb="http://exist-db.org/xquery/xmldb";

declare function local:success-page()
{
   let $calling-page := request:get-parameter("calling-page","")
   return

        if(local:validateUser()=true()) then
        (
        	local:process()
        )
        else(

            Access Denied !! Only users of "dba" group have access

            Return to maintenance menu

        )

};

declare function local:new-user() as element()*
{

    let $name := request:get-parameter("name", ()),
    $grp := request:get-parameter("groups", ()),
    $groups := if ($grp) then
        (
            if(contains($grp, ",")) then
            (
                tokenize($grp, "\s*,\s*")
            )
            else
            (
                $grp
            )
        )else(),
    $pass1 := request:get-parameter("pass1", ""),
    $pass2 := request:get-parameter("pass2", "")
    return

    if($name eq "") then
    (

	Error : UserName is missing !!!!

 {local:correct-user(-1, $name, $grp)}

    )
   (:
   else if($name != "") then
   (
                for $user in doc("/db/system/users.xml")//users/user
                    let $stored_username := xs:string($user/@name)
 	 return(
 	 	if($name eq $stored_username) then
 	 	(

			Error : UserName Already Exists !! Chooose a different Username!!!!

 {local:correct-user(-1, $name, $grp)}

		)
		else()
	   )

   ) :)

    else if($grp eq "") then
    (

	Error : GroupName is missing !! Please specify atleast one group!!!!!

 {local:correct-user(-1, $name, $grp)}

    )

    else if($pass1 != $pass2 or $pass1 eq "") then
        (

	Error : Either Password is missing or Passwords are not identical !!!!

 {local:correct-user(-1, $name, $grp)}

        )
        else(

            xmldb:create-user($name, $pass1, $groups, ""),

            User "{$name}" Created !!!

{local:display()}

          )
};

declare function local:display()
{

      <form  method="get" action="{session:encode-url(request:get-uri())}">

                Name
                Groups

            {
                for $user in doc("/db/system/users.xml")//users/user
                    let $name := xs:string($user/@name),
                    $groups := string-join($user/group, ", ")
                order by $name return

                        <input type="radio" name="uid" value="{$user/@uid}"/>
                        {$name}
                        {$groups}

            }

                    <input type="submit" name="action" value="Edit"/>
                    <input type="submit" name="action" value="New User"/>
                    <input type="submit" name="action" value="Remove"/>

        {
                let $action := request:get-parameter("action", ""),
                $uid := request:get-parameter("uid", ()) return
                if($action eq "Edit") then
                    (
                            if(empty($uid) )then
 	             (

		            <be/>
Error : Select a User to Update !!!!

	            )
      	          else
	            (
                         		let $user := doc("/db/system/users.xml")//users/user[@uid = $uid] return
        			if( ($user/@name) eq "admin" and xmldb:get-current-user() != "admin" ) then
	      	              (

 Error : You do not have permission to Edit the Admin User !!!!

	       	             )
       	             	          else(
                         		local:edit-user(xs:integer($uid), $user/@name, string-join($user/group, ", "))
                         	          )
                           )
                    )
                    else if($action eq "New User") then
                    (
                        local:edit-user(-1, "", "")
                    )else()

        }

Return to maintenance menu
     </form>

} ;

declare function local:correct-user($uid as xs:integer, $name as xs:string, $groups as xs:string)  as element()
{

    <form action="{session:encode-url(request:get-uri())}" method="get">
        {local:edit-user($uid, $name, $groups)}
        <input type="hidden" name="panel" value="users"/>
    </form>

};

declare function local:edit-user($uid as xs:integer, $name as xs:string, $groups as xs:string) as element()
{

            User:
            {
                if($name eq "") then
                (
                    <input type="text" name="name"/>
                )
                else
                (
                    <input type="hidden" name="name" value="{$name}"/>{$name}
                )
            }

            Groups:
            <input type="text" name="groups" value="{$groups}"/>
            A comma-separated list of groups.
            Note: non-existing groups will be created automatically.

            Password:
            <input type="password" name="pass1"/>

            Repeat:
            <input type="password" name="pass2"/>

         {
            if($uid ge 0) then
            (
                <input type="checkbox" name="nopass"/> Leave password unchanged.
            )else()
        }

        {
            if($uid lt 0) then
            (

                <input type="submit" name="action" value="Create"/>
	<input type="submit" name="action" value="Cancel"/>
            )
            else
            (

                <input type="submit" name="action" value="Change"/>
	 <input type="submit" name="action" value="Cancel"/>
            )

        }

        <input type="hidden" name="uid" value="{$uid}"/>

 };

declare function local:process()  as element()*
{
    let $action := request:get-parameter("action", "") ,
    $session_user  := session:get-attribute("username"),
    $current_user := xmldb:get-current-user()
    return
        if($action eq "Create") then
        (
            local:new-user()
        )
       else if($action eq "Change") then
        (
            local:update-user()
        )

         else if($action eq "Remove") then
        (
            local:remove-user()
        )
        else if($action eq "Cancel") then
        (

	       {local:display()}

        )
        else(

	       {local:display()}

        )

};

declare function local:validateUser() as xs:boolean
{
   let $hostname :=  request:get-hostname()

   let $resource_location := concat("xmldb:exist://", $hostname, ":8080/exist/xmlrpc/db")
   let $user := session:get-attribute("username")
   let $password := session:get-attribute("password")
   let $is-ssl :=  lib-util:checkSSL()
   return
           if(xmldb:is-admin-user($user)) then
           (
            	if (xmldb:login($resource_location, $user, $password))
              then (
		true()
	)
	else(
		false()
	)
          )
          else(
	          false()
          )

};

declare function local:update-user() as element()*
{

    let $name := request:get-parameter("name", ()),
    $grp := request:get-parameter("groups", ()),
    $groups := if ($grp) then
        (
            if(contains($grp, ",")) then
            (
                tokenize($grp, "\s*,\s*")
            )
            else
            (
                $grp
            )
        )else(),
    $pass1 := request:get-parameter("pass1", ""),
    $pass2 := request:get-parameter("pass2", ""),
    $nopass := request:get-parameter("nopass", ()),
    $pass := if($nopass) then () else $pass1,
    $uid := request:get-parameter("uid", "") return

        if(not($nopass) and $pass1 ne $pass2)then
        (

Passwords are not identical.
,
            local:correct-user($uid, $name, $grp)
        )
        else if(empty($groups)) then
        (

Please specify one group at least.
,
            local:correct-user($uid, $name, $grp)
        )
        else
        (
            xmldb:change-user($name, $pass, $groups, ""),

            if(xmldb:get-current-user() eq $name) then
            (
                session:set-attribute("password", $pass)
            )else(),

            User "{$name}" Updated !!!

{local:display()}

        )

};

declare function local:remove-user()
{
    if(empty(request:get-parameter("uid", ())) )then
    (

            Error : Select a User to Remove !!!!

Return to User Management

    )
   else
   (
    let $uid := request:get-parameter("uid", ()),
    $name := doc("/db/system/users.xml")//user[@uid = $uid]/@name cast as xs:string return

        if($name eq xmldb:get-current-user() or $name eq "admin") then
        (

            You cannot remove the Admin User or Current User!!!!

Return to User Management

        )
        else if (xmldb:is-admin-user($name) and xmldb:get-current-user() != "admin") then
        (

            You do not have the permission to remove the user of "dba" group!!!!

Return to User Management

      )
      else
      (

            User "{$name}" Removed !!!

{local:display()}

        )
     )
};

declare option exist:serialize "media-type=text/html method=xhtml doctype-public=-//W3C//DTD XHTML 1.0 Transitional//EN doctype-system=http://www.w3.org/TR/2002/REC-xhtml1-20020801/DTD/xhtml1-transitional.dtd";

   session:create(),
   let $id := request:get-parameter('id','')
   let $title as xs:string := concat(" User Management", $id)

   return
      lib-rendering:txfrm-webpage(
      $title,
            local:success-page()
         )


[ignore] added title for New Group table

svn path=/trunk/eXist/; revision=13969

xquery version "1.0";
(: $Id$ :)
(:
    Module: display and edit users.
:)

module namespace users="http://exist-db.org/xquery/admin-interface/users";

declare namespace util="http://exist-db.org/xquery/util";
declare namespace xdb="http://exist-db.org/xquery/xmldb";
declare namespace request="http://exist-db.org/xquery/request";
declare namespace session="http://exist-db.org/xquery/session";
declare namespace config="http://exist-db.org/Configuration";

declare function users:main() as element() {

User Management

Note: This is work in progress.  Don't use this page to manage
        users in a production environment.  Use the Java admin client instead.

        {
        (: We do not need to check if the current user is an admin user, since admin.xql does this. :)
        (: if (not(xdb:is-admin-user(xdb:get-current-user()))) then

                Only users of the "dba" group can change user settings.

        else :)
            users:process()
        }

};

declare function users:process() as element()* {
    let $action := request:get-parameter("action", "")
    return
        if ($action eq "Create User") then
            users:new-user()
        else if ($action eq "Change User") then
            users:update-user()
        else if ($action eq "Remove User" and exists(request:get-parameter("uid", ()))) then
            users:remove-user()
        else if ($action eq "Create Group") then
            users:new-group()
        else
            users:display()
};

declare variable $users:all-users {
    collection("/db/system/security/exist/accounts")/config:account
};

declare variable $users:current-users {
    $users:all-users[util:collection-name(.) ne '/db/system/security/exist/accounts/removed']
};

declare variable $users:all-groups {
    collection("/db/system/security/exist/groups")/config:group
};

declare variable $users:current-groups {
    $users:all-groups[util:collection-name(.) ne '/db/system/security/exist/groups/removed']
};

declare function users:remove-user() as element()* {
    let $uid := request:get-parameter("uid", ())
    let $name := $users:all-users[@id = $uid]/config:name/text()
    return
        if ($name eq xdb:get-current-user()) then

You cannot remove the current user!

        else if ($name eq 'guest') then

You cannot remove guest!

        else
            (
            xdb:delete-user($name),

User {$name} removed.

            )
        ,
        users:display()
};

declare function users:new-user() as element()* {
    let $name := request:get-parameter("name", ())
    let $grp := string-join(request:get-parameter("groups", ()), ',')
    let $groups :=
        if ($grp) then
            if (contains($grp, ",")) then
                tokenize($grp, "\s*,\s*")
            else
                $grp
         else ()
    let $pass1 := request:get-parameter("pass1", "")
    let $pass2 := request:get-parameter("pass2", "")
    let $home := request:get-parameter("home", ())
    return
        if ($pass1 != $pass2) then
            (

Passwords are not identical.
,
            users:correct-user(-1, $name, $grp, $home)
            )
        else if (empty($groups)) then
            (

Please specify one group at least.
,
            users:correct-user(-1, $name, $grp, $home)
            )
        else
            (
            xdb:create-user($name, $pass1, $groups, $home),
            users:display()
            )
};

declare function users:update-user() as element()* {
    let $name := request:get-parameter("name", ())
    let $grp := string-join(request:get-parameter("groups", ()), ',')
    let $groups :=
        if ($grp) then
            if (contains($grp, ",")) then
                tokenize($grp, "\s*,\s*")
            else
                $grp
        else ()
    let $pass1 := request:get-parameter("pass1", "")
    let $pass2 := request:get-parameter("pass2", "")
    let $nopass := request:get-parameter("nopass", ())
    let $pass := if ($nopass) then () else $pass1
    let $home := request:get-parameter("home", ())
    let $uid := request:get-parameter("uid", "")
    return
        if (not($nopass) and $pass1 ne $pass2) then
            (

Passwords are not identical.
,
            users:correct-user($uid, $name, $grp, $home)
            )
        else if (empty($groups)) then
            (

Please specify one group at least.
,
            users:correct-user($uid, $name, $grp, $home)
            )
        else
            (
            xdb:change-user($name, $pass, $groups, $home),
            if (xdb:get-current-user() eq $name) then
                session:set-attribute("password", $pass)
            else (),
            users:display()
            )
};

declare function users:new-group() as element()* {
    let $group := request:get-parameter("group", ())
    let $manager := request:get-parameter("manager", ())
    return
        if (empty($manager)) then
            (

Please specify a manager.
,
            users:correct-group(-1, $group, $manager)
            )
        else
            (
            xdb:create-group($group, $manager),
            users:display()
            )
};

declare function users:display() as element() {
    let $action := request:get-parameter("action", "")
    return
    <form action="{session:encode-url(request:get-uri())}" method="GET">
        {
        if ($action = ("New User", "Edit User", "New Group")) then ()
        else
            (

                    {$action}

                    Name
                    Groups
                    Home

                {
                for $user in $users:current-users
                let $name := $user/config:name/text()
                let $groups := string-join($user/config:group/@name, ", ") (: alternatively, use xmldb:get-user-groups() :)
                let $home := if ($user/config:home ne "") then $user/config:home/text() else not set
                order by $name
                return

                        <input type="radio" name="uid" value="{$user/@id}"/>
                        {$name}
                        {$groups}
                        {$home}

                }

            ,

                        <input type="submit" name="action" value="Edit User"/>
                        <input type="submit" name="action" value="Remove User"/>
                        <input type="submit" name="action" value="New User"/>

            ,

                    Group
                    Manager

                {
                for $group in $users:current-groups
                let $name := $group/config:name/text()
                let $manager := $group/config:manager/@name/string()
                order by $name
                return

                        {(:{if ($name = ('dba', 'guest')) then () else <input type="radio" name="gid" value="{$group/@id}"/>}:)''}
                        {$name}
                        {if ($name = 'dba') then 'admin' else if ($name = 'guest') then 'guest' else $manager}

                }

            ,

                        <input type="submit" name="action" value="New Group"/>

            )
        ,

        let $uid := request:get-parameter("uid", "")
        let $gid := request:get-parameter("gid", "")
        return
            (
            if ($action eq "Edit User" and (: prevent error if no user selected :) $uid ne "") then
                let $user := $users:all-users[@id = $uid]
                return
                    users:edit-user(xs:integer($uid), xs:string($user/config:name), string-join($user/config:group/@name, ", "), xs:string($user/config:home))
            else if ($action eq "New User") then
                users:edit-user(-1, "", "", ())
            else if ($action eq "New Group") then
                users:edit-group(-1, "", "")
            else if ($action = ("", "Remove User")) then
                ()
            else
                response:redirect-to(xs:anyURI('admin.xql?panel=users'))
            )
        }
        <input type="hidden" name="panel" value="users"/>
    </form>
};

declare function users:correct-user($uid as xs:integer, $name as xs:string, $groups as xs:string, $home as xs:string?) as element() {
    <form action="{session:encode-url(request:get-uri())}" method="GET">
        { users:edit-user($uid, $name, $groups, $home) }
        <input type="hidden" name="panel" value="users"/>
    </form>
};

declare function users:correct-group($uid as xs:integer, $group as xs:string, $manager) as element() {
    <form action="{session:encode-url(request:get-uri())}" method="GET">
        { users:edit-group($uid, $group, $manager) }
        <input type="hidden" name="panel" value="users"/>
    </form>
};

declare function users:edit-user($uid as xs:integer, $name as xs:string, $groups as xs:string, $home as xs:string?) as element() {

            {request:get-parameter('action', '')}

            User:
            {
            if ($name eq "") then
                <input type="text" name="name"/>
            else
                <input type="hidden" name="name" value="{$name}"/>{$name}
            }

            Groups:

{
                for $group in $users:current-groups/config:name
                let $selected := $group = tokenize($groups, '\s?,\s?')
                return

                        <input type="checkbox" name="groups" value="{$group}" id="{$group}"/> {if ($selected) then attribute checked {'checked'} else ()}
                        {$group/text()}

            }

            Warning: Do not modify admin or guest group settings.

            Password:
            <input type="password" name="pass1"/>

            Password (again):
            <input type="password" name="pass2"/>

        {
        if ($uid ge 0) then
            <input type="checkbox" name="nopass"/> Leave password unchanged.
        else ()
        }

            Home Collection:
            <input type="text" name="home" value="{$home}"/>
            Optional: assign a home collection, e.g. /db/home/me.
                The user will be the owner of this collection.
                Note: non-existing collections will be created automatically.

        {
        if ($uid lt 0) then
            <input type="submit" name="action" value="Create User"/>
        else
            <input type="submit" name="action" value="Change User"/>
        }

                <input type="button" value="Cancel" onClick="parent.location='admin.xql?panel=users'"/>
                <input type="hidden" name="uid" value="{$uid}"/>

};

declare function users:edit-group($uid as xs:integer, $group as xs:string, $manager as xs:string?) as element() {

            {request:get-parameter('action', '')}

            Group:
            <input type="text" name="group"/>

            Manager:

{
                for $name in $users:current-users/config:name
                let $selected := $name = $manager
                return

                        <input type="radio" name="manager" value="{$name}" id="{$name}"/> {if ($selected) then attribute checked {'checked'} else ()}
                        {$name/text()}

            }

            Every group needs a manager.

            <input type="submit" name="action" value="Create Group"/>

            <input type="button" value="Cancel" onClick="parent.location='admin.xql?panel=users'"/>

};

xquery version "1.0";
(: $Id$ :)
(:
    Module: display and edit users.
:)

module namespace users="http://exist-db.org/xquery/admin-interface/users";

declare namespace util="http://exist-db.org/xquery/util";
declare namespace xdb="http://exist-db.org/xquery/xmldb";
declare namespace request="http://exist-db.org/xquery/request";
declare namespace session="http://exist-db.org/xquery/session";
declare namespace config="http://exist-db.org/Configuration";

declare function users:main() as element() {

User Management

Note: This is work in progress.  Don't use this page to manage
        users in a production environment.  Use the Java admin client instead.

        {
        (: We do not need to check if the current user is an admin user, since admin.xql does this. :)
        (: if (not(xdb:is-admin-user(xdb:get-current-user()))) then

                Only users of the "dba" group can change user settings.

        else :)
            users:process()
        }

};

declare function users:process() as element()* {
    let $action := request:get-parameter("action", "")
    return
        if ($action eq "Create User") then
            users:new-user()
        else if ($action eq "Change User") then
            users:update-user()
        else if ($action eq "Remove User" and exists(request:get-parameter("uid", ()))) then
            users:remove-user()
        else if ($action eq "Create Group") then
            users:new-group()
        else
            users:display()
};

declare variable $users:all-users {
    collection("/db/system/security/exist/accounts")/config:account
};

declare variable $users:current-users {
    $users:all-users[util:collection-name(.) ne '/db/system/security/exist/accounts/removed']
};

declare variable $users:all-groups {
    collection("/db/system/security/exist/groups")/config:group
};

declare variable $users:current-groups {
    $users:all-groups[util:collection-name(.) ne '/db/system/security/exist/groups/removed']
};

declare function users:remove-user() as element()* {
    let $uid := request:get-parameter("uid", ())
    let $name := $users:all-users[@id = $uid]/config:name/text()
    return
        if ($name eq xdb:get-current-user()) then

You cannot remove the current user!

        else if ($name eq 'guest') then

You cannot remove guest!

        else
            (
            xdb:delete-user($name),

User {$name} removed.

            )
        ,
        users:display()
};

declare function users:new-user() as element()* {
    let $name := request:get-parameter("name", ())
    let $grp := string-join(request:get-parameter("groups", ()), ',')
    let $groups :=
        if ($grp) then
            if (contains($grp, ",")) then
                tokenize($grp, "\s*,\s*")
            else
                $grp
         else ()
    let $pass1 := request:get-parameter("pass1", "")
    let $pass2 := request:get-parameter("pass2", "")
    let $home := request:get-parameter("home", ())
    return
        if ($pass1 != $pass2) then
            (

Passwords are not identical.
,
            users:correct-user(-1, $name, $grp, $home)
            )
        else if (empty($groups)) then
            (

Please specify one group at least.
,
            users:correct-user(-1, $name, $grp, $home)
            )
        else
            (
            xdb:create-user($name, $pass1, $groups, $home),
            users:display()
            )
};

declare function users:update-user() as element()* {
    let $name := request:get-parameter("name", ())
    let $grp := string-join(request:get-parameter("groups", ()), ',')
    let $groups :=
        if ($grp) then
            if (contains($grp, ",")) then
                tokenize($grp, "\s*,\s*")
            else
                $grp
        else ()
    let $pass1 := request:get-parameter("pass1", "")
    let $pass2 := request:get-parameter("pass2", "")
    let $nopass := request:get-parameter("nopass", ())
    let $pass := if ($nopass) then () else $pass1
    let $home := request:get-parameter("home", ())
    let $uid := request:get-parameter("uid", "")
    return
        if (not($nopass) and $pass1 ne $pass2) then
            (

Passwords are not identical.
,
            users:correct-user($uid, $name, $grp, $home)
            )
        else if (empty($groups)) then
            (

Please specify one group at least.
,
            users:correct-user($uid, $name, $grp, $home)
            )
        else
            (
            xdb:change-user($name, $pass, $groups, $home),
            if (xdb:get-current-user() eq $name) then
                session:set-attribute("password", $pass)
            else (),
            users:display()
            )
};

declare function users:new-group() as element()* {
    let $group := request:get-parameter("group", ())
    let $manager := request:get-parameter("manager", ())
    return
        if (empty($manager)) then
            (

Please specify a manager.
,
            users:correct-group(-1, $group, $manager)
            )
        else
            (
            xdb:create-group($group, $manager),
            users:display()
            )
};

declare function users:display() as element() {
    let $action := request:get-parameter("action", "")
    return
    <form action="{session:encode-url(request:get-uri())}" method="GET">
        {
        if ($action = ("New User", "Edit User", "New Group")) then ()
        else
            (

                    {$action}

                    Name
                    Groups
                    Home

                {
                for $user in $users:current-users
                let $name := $user/config:name/text()
                let $groups := string-join($user/config:group/@name, ", ") (: alternatively, use xmldb:get-user-groups() :)
                let $home := if ($user/config:home ne "") then $user/config:home/text() else not set
                order by $name
                return

                        <input type="radio" name="uid" value="{$user/@id}"/>
                        {$name}
                        {$groups}
                        {$home}

                }

            ,

                        <input type="submit" name="action" value="Edit User"/>
                        <input type="submit" name="action" value="Remove User"/>
                        <input type="submit" name="action" value="New User"/>

            ,

                    Group
                    Manager

                {
                for $group in $users:current-groups
                let $name := $group/config:name/text()
                let $manager := $group/config:manager/@name/string()
                order by $name
                return

                        {(:{if ($name = ('dba', 'guest')) then () else <input type="radio" name="gid" value="{$group/@id}"/>}:)''}
                        {$name}
                        {if ($name = 'dba') then 'admin' else if ($name = 'guest') then 'guest' else $manager}

                }

            ,

                        <input type="submit" name="action" value="New Group"/>

            )
        ,

        let $uid := request:get-parameter("uid", "")
        let $gid := request:get-parameter("gid", "")
        return
            (
            if ($action eq "Edit User" and (: prevent error if no user selected :) $uid ne "") then
                let $user := $users:all-users[@id = $uid]
                return
                    users:edit-user(xs:integer($uid), xs:string($user/config:name), string-join($user/config:group/@name, ", "), xs:string($user/config:home))
            else if ($action eq "New User") then
                users:edit-user(-1, "", "", ())
            else if ($action eq "New Group") then
                users:edit-group(-1, "", "")
            else if ($action = ("", "Remove User")) then
                ()
            else
                response:redirect-to(xs:anyURI('admin.xql?panel=users'))
            )
        }
        <input type="hidden" name="panel" value="users"/>
    </form>
};

declare function users:correct-user($uid as xs:integer, $name as xs:string, $groups as xs:string, $home as xs:string?) as element() {
    <form action="{session:encode-url(request:get-uri())}" method="GET">
        { users:edit-user($uid, $name, $groups, $home) }
        <input type="hidden" name="panel" value="users"/>
    </form>
};

declare function users:correct-group($uid as xs:integer, $group as xs:string, $manager) as element() {
    <form action="{session:encode-url(request:get-uri())}" method="GET">
        { users:edit-group($uid, $group, $manager) }
        <input type="hidden" name="panel" value="users"/>
    </form>
};

declare function users:edit-user($uid as xs:integer, $name as xs:string, $groups as xs:string, $home as xs:string?) as element() {

            {request:get-parameter('action', '')}

            User:
            {
            if ($name eq "") then
                <input type="text" name="name"/>
            else
                <input type="hidden" name="name" value="{$name}"/>{$name}
            }

            Groups:

{
                for $group in $users:current-groups/config:name
                let $selected := $group = tokenize($groups, '\s?,\s?')
                return

                        <input type="checkbox" name="groups" value="{$group}" id="{$group}"/> {if ($selected) then attribute checked {'checked'} else ()}
                        {$group/text()}

            }

            Warning: Do not modify admin or guest group settings.

            Password:
            <input type="password" name="pass1"/>

            Password (again):
            <input type="password" name="pass2"/>

        {
        if ($uid ge 0) then
            <input type="checkbox" name="nopass"/> Leave password unchanged.
        else ()
        }

            Home Collection:
            <input type="text" name="home" value="{$home}"/>
            Optional: assign a home collection, e.g. /db/home/me.
                The user will be the owner of this collection.
                Note: non-existing collections will be created automatically.

        {
        if ($uid lt 0) then
            <input type="submit" name="action" value="Create User"/>
        else
            <input type="submit" name="action" value="Change User"/>
        }

                <input type="button" value="Cancel" onClick="parent.location='admin.xql?panel=users'"/>
                <input type="hidden" name="uid" value="{$uid}"/>

};

declare function users:edit-group($uid as xs:integer, $group as xs:string, $manager as xs:string?) as element() {

            Group:
            <input type="text" name="group"/>

            Manager:

{
                for $name in $users:current-users/config:name
                let $selected := $name = $manager
                return

                        <input type="radio" name="manager" value="{$name}" id="{$name}"/> {if ($selected) then attribute checked {'checked'} else ()}
                        {$name/text()}

            }

            Every group needs a manager.

            <input type="submit" name="action" value="Create Group"/>

            <input type="button" value="Cancel" onClick="parent.location='admin.xql?panel=users'"/>

};