Add xf:wrap, xf:unwrap

Add xf:wrap, xf:unwrap

xquery version "3.0";

(:~
 : Origami templating.
 :
 : @version 0.3
 : @author Marc van Grootel
 : @see https://github.com/xokomola/origami
 :)

module namespace xf = 'http://xokomola.com/xquery/origami';

(:~
 : Transforms input, using the specified templates.
 :)
declare function xf:transform($templates as map(*)*, $input as node()*)
    as node()* {
    xf:transform($templates)($input)
};

(:~
 : Returns a node transformation function.
 :)
declare function xf:transform($templates as map(*)*)
    as function(*) {
    function ($nodes as node()*) as node()* {
        xf:apply($nodes, $templates)
    }
};

(:~
 : Identity transformer.
 :)
declare function xf:transform() { xf:transform(()) };

(:~
 : Extracts nodes from input, using the specified selectors.
 :)
declare function xf:extract($input as node()*, $selectors as function(*)*)
    as node()* {
    xf:extract($selectors)($input)
};

(:~
 : Returns an extractor function that only returns selected nodes
 : only outermost in document order and duplicates eleminated.
 :
 : TODO: when running on 8.0 20141116.135016 or higher then
 :       xf:distinct-nodes() can be removed due to bugfix
 :       remove it after 8.0 is released.
 :)
declare function xf:extract($selectors as function(*)*)
    as function(*) {
    function ($nodes as node()*) as node()* {
        xf:distinct-nodes(outermost(xf:select-nodes($nodes, $selectors)))
    }
};

(:~
 : Defines a template.
 :
 : A template takes a selector string or function and
 : a node transformation function or the items to return as
 : the template body.
 : Providing invalid matcher returns empty sequence.
 :)
declare function xf:template($selector, $body)
    as map(*)? {
    let $selector :=
        typeswitch ($selector)
        case xs:string return xf:matches($selector)
        case function(*) return $selector
        default return ()
    let $body :=
        typeswitch ($body)
        case empty-sequence() return function($node) { () }
        case function(*) return $body
        default return function($node) { $body }
    where $selector instance of function(*) and $body instance of function(*)
    return
        map {
            'selector': $selector,
            'fn': $body
        }
};

(:~
 : Compose a selector function from a sequence of selectors.
 : TODO: Suffers from the inlining bug $nodes gets fixed/inlined at all descendant nodes
 :       @see http://www.mail-archive.com/basex-talk%40mailman.uni-konstanz.de/msg05107.html
 :)
declare function xf:select($selectors as item()*)
    as function(node()*) as node()* {
    let $fns :=
        for $selector in $selectors
        return
            if ($selector instance of xs:string) then
                xf:xpath-matches($selector)
            else
                $selector
    return
        function($nodes as node()*) as node()* {
            fold-left($fns, $nodes,
                  function($nodes, $fn) {
                        $fn($nodes)
                  }
            )
        }
};

(:~
 : Wrap nodes in an element.
 :)
declare function xf:wrap($node as element())
    as function(*) {
    function($nodes as node()*) as element() {
        element { $node/name() } {
            $node/@*,
            $nodes
        }
    }
};

declare function xf:wrap($node as element(), $nodes as node()*)
    as node()* {
    xf:wrap($node)($nodes)
};

(:~
 : Removes the outer elements from nodes.
 :)
declare function xf:unwrap()
    as function(*) {
    function($nodes as node()*) {
        $nodes/node()
    }
};

declare function xf:unwrap($nodes as node()*)
    as node()* {
    xf:unwrap()($nodes)
};

(:~
 : Copies nodes to output, and calls apply for
 : nodes that are wrapped inside <xf:apply>.
 :)
declare %private function xf:copy($nodes as node()*, $xform as map(*)*)
    as node()* {
    for $node in $nodes
    return
        if ($node/self::xf:apply) then
            xf:apply(($node/@*,$node/node()), $xform)
        else if ($node instance of element()) then
            element { node-name($node) } {
                $node/@*,
                xf:copy($node/node(), $xform)
            }
        else if ($node instance of document-node()) then
            document {
                xf:copy($node/node(), $xform)
            }
        else
            $node
};

(:~
 : Applies node transformations to nodes.
 :)
declare %private function xf:apply($nodes as node()*, $xform as map(*)*)
    as node()* {
    for $node in $nodes
    let $match := xf:match-node($node, $xform)
    return
        if ($match instance of function(node()) as item()*) then
            xf:copy($match($node), $xform)
        else if ($node instance of element()) then
            element { node-name($node) } {
                xf:apply($node/@*, $xform),
                xf:apply($node/node(), $xform)
            }
        else if ($node instance of document-node()) then
            document {
                xf:apply($node/node(), $xform)
            }
        else
            $node
};

(:~
 : Apply to be used from within templates.
 :)
declare function xf:apply($nodes as node()*)
    as element(xf:apply) {
    <xf:apply>{ $nodes }</xf:apply>
};

(:~
 : Return matching nodes.
 :)
declare %private function xf:select-nodes($nodes as node()*, $selectors as function(*)*)
    as node()* {
    for $selector in $selectors
    return
        for $node in $nodes/descendant-or-self::node()
        return
            $selector($node)
};

(:~
 : Find the first matching template for a node and return
 : it's node transformation function.
 :)
declare %private function xf:match-node($node as node(), $xform as map(*)*)
    as function(*)? {
    hof:until(
        function($templates as map(*)*) {
            let $is-match := head($templates)
            return
                empty($is-match) or
                not($is-match instance of map(*))
        },
        function($templates as map(*)*) {
            let $template := head($templates)
            return
                (
                    if ($template('selector')($node)) then
                        $template('fn')
                    else
                        ()
                    ,
                    tail($templates)
                )
        },
        $xform
    )[1]
};

(:~
 : Returns a function that returns true if the passed in node matches
 : the selector string.
 :)
declare function xf:matches($selector as xs:string)
    as function(*) {
    function($node as node()) as xs:boolean {
        typeswitch ($node)
        case element() return not($node/self::xf:*) and $selector = (name($node), '*')
        case attribute() return substring-after($selector, '@') = (name($node), '*')
        default return false()
    }
};

(:~
 : Match using XPath (only works in xf:select)
 :)
declare function xf:xpath-matches($selector as xs:string)
    as function(node()*) as node()* {
    function($nodes as node()*) as node()* {
        xquery:eval($selector, map { '': $nodes })
    }
};

(:~
 : Returns only distinct nodes.
 : @see http://www.xqueryfunctions.com/xq/functx_distinct-nodes.html
 :)
declare %private function xf:distinct-nodes($nodes as node()*)
    as node()* {
    for $seq in (1 to count($nodes))
    return $nodes[$seq][
        not(xf:is-node-in-sequence(
            .,$nodes[position() < $seq]))]
};

(:~
 : Is node defined in seq?
 : @see http://www.xqueryfunctions.com/xq/functx_is-node-in-sequence.html
 :)
declare %private function xf:is-node-in-sequence ($node as node()?, $seq as node()*)
    as xs:boolean {
    some $nodeInSeq in $seq satisfies $nodeInSeq is $node
 };

xquery version "3.0";

(:~
 : Origami templating.
 :
 : @version 0.3
 : @author Marc van Grootel
 : @see https://github.com/xokomola/origami
 :)

module namespace xf = 'http://xokomola.com/xquery/origami';

(:~
 : Transforms input, using the specified templates.
 :)
declare function xf:transform($templates as map(*)*, $input as node()*)
    as node()* {
    xf:transform($templates)($input)
};

(:~
 : Returns a node transformation function.
 :)
declare function xf:transform($templates as map(*)*)
    as function(*) {
    function ($nodes as node()*) as node()* {
        xf:apply($nodes, $templates)
    }
};

(:~
 : Identity transformer.
 :)
declare function xf:transform() { xf:transform(()) };

(:~
 : Extracts nodes from input, using the specified selectors.
 :)
declare function xf:extract($input as node()*, $selectors as function(*)*)
    as node()* {
    xf:extract($selectors)($input)
};

(:~
 : Returns an extractor function that only returns selected nodes
 : only outermost in document order and duplicates eleminated.
 :
 : TODO: when running on 8.0 20141116.135016 or higher then
 :       xf:distinct-nodes() can be removed due to bugfix
 :       remove it after 8.0 is released.
 :)
declare function xf:extract($selectors as function(*)*)
    as function(*) {
    function ($nodes as node()*) as node()* {
        xf:distinct-nodes(outermost(xf:select-nodes($nodes, $selectors)))
    }
};

(:~
 : Defines a template.
 :
 : A template takes a selector string or function and
 : a node transformation function or the items to return as
 : the template body.
 : Providing invalid matcher returns empty sequence.
 :)
declare function xf:template($selector, $body)
    as map(*)? {
    let $selector :=
        typeswitch ($selector)
        case xs:string return xf:matches($selector)
        case function(*) return $selector
        default return ()
    let $body :=
        typeswitch ($body)
        case empty-sequence() return function($node) { () }
        case function(*) return $body
        default return function($node) { $body }
    where $selector instance of function(*) and $body instance of function(*)
    return
        map {
            'selector': $selector,
            'fn': $body
        }
};

declare function xf:select($selectors as item()*)
    as function(node()*) as node()* {
    let $fns :=
        for $selector in $selectors
        return
            if ($selector instance of xs:string) then
                xf:xpath-matches($selector)
            else
                $selector
    return
        function($nodes) {
            fold-left($fns, $nodes,
                  function($nodes, $fn) {
                        $fn($nodes)
                  }
            )
        }
};

(:~
 : Copies nodes to output, and calls apply for
 : nodes that are wrapped inside <xf:apply>.
 :)
declare %private function xf:copy($nodes as node()*, $xform as map(*)*)
    as node()* {
    for $node in $nodes
    return
        if ($node/self::xf:apply) then
            xf:apply(($node/@*,$node/node()), $xform)
        else if ($node instance of element()) then
            element { node-name($node) } {
                $node/@*,
                xf:copy($node/node(), $xform)
            }
        else if ($node instance of document-node()) then
            document {
                xf:copy($node/node(), $xform)
            }
        else
            $node
};

(:~
 : Applies node transformations to nodes.
 :)
declare %private function xf:apply($nodes as node()*, $xform as map(*)*)
    as node()* {
    for $node in $nodes
    let $match := xf:match-node($node, $xform)
    return
        if ($match instance of function(node()) as item()*) then
            xf:copy($match($node), $xform)
        else if ($node instance of element()) then
            element { node-name($node) } {
                xf:apply($node/@*, $xform),
                xf:apply($node/node(), $xform)
            }
        else if ($node instance of document-node()) then
            document {
                xf:apply($node/node(), $xform)
            }
        else
            $node
};

(:~
 : Apply to be used from within templates.
 :)
declare function xf:apply($nodes as node()*)
    as element(xf:apply) {
    <xf:apply>{ $nodes }</xf:apply>
};

(:~
 : Return matching nodes.
 :)
declare %private function xf:select-nodes($nodes as node()*, $selectors as function(*)*)
    as node()* {
    for $selector in $selectors
    return
        for $node in $nodes/descendant-or-self::node()
        return
            $selector($node)
};

(:~
 : Find the first matching template for a node and return
 : it's node transformation function.
 :)
declare %private function xf:match-node($node as node(), $xform as map(*)*)
    as function(*)? {
    hof:until(
        function($templates as map(*)*) {
            let $is-match := head($templates)
            return
                empty($is-match) or
                not($is-match instance of map(*))
        },
        function($templates as map(*)*) {
            let $template := head($templates)
            return
                (
                    if ($template('selector')($node)) then
                        $template('fn')
                    else
                        ()
                    ,
                    tail($templates)
                )
        },
        $xform
    )[1]
};

(:~
 : Returns a function that returns true if the passed in node matches
 : the selector string.
 :)
declare function xf:matches($selector as xs:string)
    as function(*) {
    function($node as node()) as xs:boolean {
        typeswitch ($node)
        case element() return not($node/self::xf:*) and $selector = (name($node), '*')
        case attribute() return substring-after($selector, '@') = (name($node), '*')
        default return false()
    }
};

(:~
 : Match using XPath (only works in xf:select)
 :)
declare function xf:xpath-matches($selector as xs:string)
    as function(node()*) as node()* {
    function($node as node()*) as node()* {
        xquery:eval($selector, map { '': $node })
    }
};

(:~
 : Returns only distinct nodes.
 : @see http://www.xqueryfunctions.com/xq/functx_distinct-nodes.html
 :)
declare %private function xf:distinct-nodes($nodes as node()*)
    as node()* {
    for $seq in (1 to count($nodes))
    return $nodes[$seq][
        not(xf:is-node-in-sequence(
            .,$nodes[position() < $seq]))]
};

(:~
 : Is node defined in seq?
 : @see http://www.xqueryfunctions.com/xq/functx_is-node-in-sequence.html
 :)
declare %private function xf:is-node-in-sequence ($node as node()?, $seq as node()*)
    as xs:boolean {
    some $nodeInSeq in $seq satisfies $nodeInSeq is $node
 };


Comment fixes

Comment fixes

xquery version "1.0";

(:
 : Copyright 2006-2009 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.
:)

(:~
 : The module provides functions to compute an immutable and opaque reference
 : for any node, either temporary or stored in a collection and for retrieving
 : nodes given their identifier. The identifiers are immutable, i.e. a node
 : identifier does not change during the node lifetime. Identifiers are also
 : unique, in that, two nodes with different identities will never have identical
 : identifiers.
 : A node, at any time during its lifetime, can be retrieved by its identifier.
 :
 :
Please see the data lifecycle
 : documentation about details on management and manipulation of collections.

 :
 : @see Data Lifecycle
 :
 : @author Federico Cavalieri
 :
 : @project XDM/node
 :
 :)
module namespace ref = "http://www.zorba-xquery.com/modules/node-reference";

declare namespace zerr = "http://www.zorba-xquery.com/errors";

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

(:~
 : Computes an immutable and opaque node reference (with type xs:anyURI) for
 : a given node, either temporary or stored in a collection.
 :
 :
The generated identifier is immutable, i.e. a node
 : identifier does not change during the node lifetime.

 :
 :
Identifiers are also unique, in that, two nodes with different identities
 : will never have identical identifiers.

 :
 : A node, at any time during its lifetime, can be retrieved by its
 : identifier.
 :
 : @param $arg the node for which the URI should be computed
 :
 : @return the opaque URI of the node.
 :)
declare function ref:node-reference(
  $arg as node()
) as xs:anyURI external;

(:~
 : Returns the node identified by the given node reference.
 :
 :
The function returns the empty sequence if the node
 : that is referenced was deleted.

 :
 : @param $arg the URI of the node to retrieve.
 :
 : @return the node identified by the URI passed as parameter
 :         or the empty-sequence if no node with that URI is found.
 :
 : @error zerr::ZAPI0028 if the given URI is not a valid node reference
 :        computed by the <tt>ref:node-reference</tt> function.
 :)
declare function ref:node-by-reference(
  $arg as xs:anyURI
) as node()? external;

xquery version "1.0";

(:
 : Copyright 2006-2009 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.
:)

(:~
 : The module provides functions to compute an immutable and opaque reference
 : for any node, either temporary or stored in a collection and for retrieving
 : nodes given their identifier. The identifiers are immutable, i.e. a node
 : identifier does not change during the node lifetime. Identifiers are also
 : unique, in that, two different nodes will never have identical identifiers.
 : A node, at any time during its lifetime, can be retrieved by its identifier.
 :
 :
Please see the data lifecycle
 : documentation about details on management and manipulation of collections.

 :
 : @see Data Lifecycle
 :
 : @author Federico Cavalieri
 :
 : @project XDM/node
 :
 :)
module namespace ref = "http://www.zorba-xquery.com/modules/node-reference";

declare namespace zerr = "http://www.zorba-xquery.com/errors";

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

(:~
 : Computes an immutable and opaque node reference (with type xs:anyURI) for
 : a given node, either temporary or stored in a collection.
 :
 :
The generated identifier is immutable, i.e. a node
 : identifier does not change during the node lifetime.

 :
 :
Identifiers are also unique, in that, two different nodes
 : will never have identical identifiers.

 :
 : A node, at any time during its lifetime, can be retrieved by its
 : identifier.
 :
 : @param $arg the node for which the URI should be computed
 :
 : @return the opaque URI of the node.
 :)
declare function ref:node-reference(
  $arg as node()
) as xs:anyURI external;

(:~
 : Returns the node identified by the given node reference.
 :
 :
The function returns the empty sequence if the node
 : that is referenced was deleted.

 :
 : @param $arg the URI of the node to retrieve.
 :
 : @return the node identified by the URI passed as parameter
 :         or the empty-sequence if no node with that URI is found.
 :
 : @error zerr::ZAPI0028 if the given URI is not a valid node reference
 :        computed by the <tt>ref:node-reference</tt> function.
 :)
declare function ref:node-by-reference(
  $arg as xs:anyURI
) as node()? external;


[repo]  tweaking repo ui

[repo]  tweaking repo ui

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

xquery version "1.0";

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

declare namespace package="http://expath.org/ns/pkg";
declare namespace request="http://exist-db.org/xquery/request";
declare namespace xdb="http://exist-db.org/xquery/xmldb";
declare namespace util="http://exist-db.org/xquery/util";
import module namespace repo="http://exist-db.org/xquery/repo";

declare variable $repomanager:coll := "/db/system/repo";
declare variable $repomanager:repo-uri := if (request:get-parameter("repository-url", ())) then
              request:get-parameter("repository-url", ())
            else
              "http://demo.exist-db.org/exist/repo/public/all/";

declare function local:entry-data($path as xs:anyURI, $type as xs:string, $data as item()?, $param as item()*) as item()?
{

	<entry>
		<path>{$path}</path>
		<type>{$type}</type>
		<data>{$data}</data>
	</entry>
};

declare function local:entry-filter($path as xs:anyURI, $type as xs:string, $param as item()*) as xs:boolean
{
	true()
};

declare function repomanager:publicrepo() as element()
{
let $package-url := request:get-parameter("package-url", ())
return

Actions:

                {
                if (ends-with($package-url,'.xar')) then
                    (
uploaded package: {$package-url}
,

                    let $http-response := httpclient:get(xs:anyURI($package-url), false(), ())
                    let $name := tokenize($package-url, "/")[last()]
                    return
                    let $package-mimetype := "application/xar",
                    $package-data := xs:base64Binary($http-response/httpclient:body/text())
                    return
                    xmldb:store($repomanager:coll, $name, $package-data, $package-mimetype)
                    )
                else

Error uploading - Must be a valid Package archive (.xar file extension)

                }

};

declare function repomanager:upload() as element()
{
    let $name := request:get-parameter("name", ()),
    $repocol :=  if (collection($repomanager:coll)) then () else xmldb:create-collection('/db/system','repo'),
    $docName := if($name) then $name else request:get-uploaded-file-name("upload"),
    $file := request:get-uploaded-file-data("upload") return

Actions:

                {
                if (contains($docName,'.xar')) then
                    (
uploaded package: {$docName}
,

                    xdb:decode-uri(xs:anyURI(xdb:store($repomanager:coll, xdb:encode-uri($docName), $file)))
                    )
                else

Error uploading - Must be a valid Package archive (.xar file extension)

                }

};

declare function repomanager:activate() as element()
{
    let $name := request:get-parameter("name", ()),
    $hostname := request:get-hostname(),            (:  pkg-repo.jar needs http or file scheme :)
    $port := request:get-server-port()
     return

Actions:

activated package: {$name}

                {
                    repo:install(concat('http://',$hostname,':',$port,'/exist/rest',$repomanager:coll,'/',$name,'.xar'))
                }

};

declare function repomanager:deactivate() as element()
{
    let $name := request:get-parameter("name", ())
     return

Actions:

deactivated package: {$name}

                {
                    repo:remove($name)
                }

};

declare function repomanager:remove() as element()
{
    let $name := request:get-parameter("name", ())
     return

Actions:

removed package: {$name}

                {xmldb:remove($repomanager:coll,concat($name,'.xar'))}

};

declare function repomanager:process-action() as element()*
{
    let $action := request:get-parameter("action", ()) return
        util:catch("java.lang.Exception",
            if($action eq "remove") then
            (
                repomanager:remove()
            )
            else if($action eq "activate") then
            (
                repomanager:activate()
            )
            else if($action eq "deactivate") then
            (
                repomanager:deactivate()
            )
            else if($action eq "Upload Package") then
            (
                repomanager:upload()
            )
            else if($action eq "Download from Public Repository") then
            (
                repomanager:publicrepo()
            )else(),

                An error occurred while processing the action:

                {$util:exception-message}

        )
};

declare function repomanager:main() as element() {
    let $action := lower-case(request:get-parameter("action", "set repository"))
    let $repocol :=  if (collection($repomanager:coll)) then () else xmldb:create-collection('/db/system','repo')

    return

Package Repository

        <form method="POST" enctype="multipart/form-data">
        { repomanager:process-action() }

                Name
                Description
                Date Installed
                Status
                Action

         {
         let $files := if (collection($repomanager:coll)) then collection($repomanager:coll)/util:document-name(.) else ()
         let $repos := repo:list()
         return

            for $file in $files[contains(.,'.xar')]
            let $package-name := substring-before($file,'.xar')
            let $xar := util:binary-doc(concat($repomanager:coll,'/',$file))

            let $meta := compression:unzip($xar, util:function(xs:QName("local:entry-filter"), 3), (),  util:function(xs:QName("local:entry-data"), 4), ())
            let $package := $meta//package:package
            let $repo := $meta//repo:meta

            let $installed := exists($repos[. eq $package-name])
            return

                {$package-name}

                {$repo//repo:type}
                {$repo//repo:description}

                {xmldb:last-modified($repomanager:coll, concat($package-name,'.xar'))}

                {if ($installed) then
                    Active
                else
                    Inactive
                }

                {
                if($installed) then

                    ( deactivate,
                      if ($repo//repo:type eq 'application') then
                        ( ' | ',deploy )
                     else
                        ()
                     )
                 else
                 ( activate,' | ',
                 remove
                 )
                }

            }

                Important: You must restart eXistdb to pick up any changes in repository.

                        <input type="submit" name="action" value="Download from Public Repository"/>

                        <select size="5" width="200" style="width:340px" name="package-url">
                           {
                            let $packages := httpclient:get(xs:anyURI($repomanager:repo-uri),false(),())//httpclient:body/node()
                             return
                             for $package in $packages//package[contains(url/.,'.xar')]
                             return
                                <option value="{$package/url}">{tokenize($package/url, "/")[last()]}</option>
                           }
                        </select>

                         Public Repository URL :

                        <input name="repository-url" size="40" value="{$repomanager:repo-uri}"/>
                        <input type="submit" name="action" value="set repository"/>

                        <input type="submit" name="action" value="Upload Package"/>
                        <input type="file" size="30" name="upload"/>

                Note: You can upload example .xar packages located under webapp/repo/packages
          </form>

};

xquery version "1.0";

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

declare namespace package="http://expath.org/ns/pkg";
declare namespace request="http://exist-db.org/xquery/request";
declare namespace xdb="http://exist-db.org/xquery/xmldb";
declare namespace util="http://exist-db.org/xquery/util";
import module namespace repo="http://exist-db.org/xquery/repo";

declare variable $repomanager:coll := "/db/system/repo";
declare variable $repomanager:repo-uri := if (request:get-parameter("repository-url", ())) then
              request:get-parameter("repository-url", ())
            else
              "http://demo.exist-db.org/exist/repo/public/all/";

declare function local:entry-data($path as xs:anyURI, $type as xs:string, $data as item()?, $param as item()*) as item()?
{

	<entry>
		<path>{$path}</path>
		<type>{$type}</type>
		<data>{$data}</data>
	</entry>
};

declare function local:entry-filter($path as xs:anyURI, $type as xs:string, $param as item()*) as xs:boolean
{
	true()
};

declare function repomanager:publicrepo() as element()
{
let $package-url := request:get-parameter("package-url", ())
return

Actions:

                {
                if (ends-with($package-url,'.xar')) then
                    (
uploaded package: {$package-url}
,

                    let $http-response := httpclient:get(xs:anyURI($package-url), false(), ())
                    let $name := tokenize($package-url, "/")[last()]
                    return
                    let $package-mimetype := "application/xar",
                    $package-data := xs:base64Binary($http-response/httpclient:body/text())
                    return
                    xmldb:store($repomanager:coll, $name, $package-data, $package-mimetype)
                    )
                else

Error uploading - Must be a valid Package archive (.xar file extension)

                }

};

declare function repomanager:upload() as element()
{
    let $name := request:get-parameter("name", ()),
    $repocol :=  if (collection($repomanager:coll)) then () else xmldb:create-collection('/db/system','repo'),
    $docName := if($name) then $name else request:get-uploaded-file-name("upload"),
    $file := request:get-uploaded-file-data("upload") return

Actions:

                {
                if (contains($docName,'.xar')) then
                    (
uploaded package: {$docName}
,

                    xdb:decode-uri(xs:anyURI(xdb:store($repomanager:coll, xdb:encode-uri($docName), $file)))
                    )
                else

Error uploading - Must be a valid Package archive (.xar file extension)

                }

};

declare function repomanager:activate() as element()
{
    let $name := request:get-parameter("name", ()),
    $hostname := request:get-hostname(),            (:  pkg-repo.jar needs http or file scheme :)
    $port := request:get-server-port()
     return

Actions:

activated package: {$name}

                {
                    repo:install(concat('http://',$hostname,':',$port,'/exist/rest',$repomanager:coll,'/',$name,'.xar'))
                }

};

declare function repomanager:deactivate() as element()
{
    let $name := request:get-parameter("name", ())
     return

Actions:

deactivated package: {$name}

                {
                    repo:remove($name)
                }

};

declare function repomanager:remove() as element()
{
    let $name := request:get-parameter("name", ())
     return

Actions:

removed package: {$name}

                {xmldb:remove($repomanager:coll,concat($name,'.xar'))}

};

declare function repomanager:process-action() as element()*
{
    let $action := request:get-parameter("action", ()) return
        util:catch("java.lang.Exception",
            if($action eq "remove") then
            (
                repomanager:remove()
            )
            else if($action eq "activate") then
            (
                repomanager:activate()
            )
            else if($action eq "deactivate") then
            (
                repomanager:deactivate()
            )
            else if($action eq "Upload Package") then
            (
                repomanager:upload()
            )
            else if($action eq "Download from Public Repository") then
            (
                repomanager:publicrepo()
            )else(),

                An error occurred while processing the action:

                {$util:exception-message}

        )
};

declare function repomanager:main() as element() {
    let $action := lower-case(request:get-parameter("action", "set repository"))
    let $repocol :=  if (collection($repomanager:coll)) then () else xmldb:create-collection('/db/system','repo')

    return

Package Repository

        <form method="POST" enctype="multipart/form-data">
        { repomanager:process-action() }

                Name
                Description
                Date Installed
                Status
                Action

         {
         let $files := if (collection($repomanager:coll)) then collection($repomanager:coll)/util:document-name(.) else ()
         let $repos := repo:list()
         return

            for $file in $files[contains(.,'.xar')]
            let $package-name := substring-before($file,'.xar')
            let $xar := util:binary-doc(concat($repomanager:coll,'/',$file))

            let $meta := compression:unzip($xar, util:function(xs:QName("local:entry-filter"), 3), (),  util:function(xs:QName("local:entry-data"), 4), ())
            let $package := $meta//package:package
            let $repo := $meta//repo:meta

            let $installed := exists($repos[. eq $package-name])
            return

                {$package-name}

                {$repo//repo:type}
                {$repo//repo:description}

                {xmldb:last-modified($repomanager:coll, concat($package-name,'.xar'))}

                {if ($installed) then
                    Active
                else
                    Inactive
                }

                {
                if($installed) then

                    ( deactivate,
                      if ($repo//repo:deploy) then
                        ( ' | ',deploy )
                     else
                        ()
                     )
                 else
                 ( activate,' | ',
                 remove
                 )
                }

            }

                Important: You must restart eXistdb to pick up any changes in repository.

                        <input type="submit" name="action" value="Download from Public Repository"/>

                        <select size="5" width="200" style="width:340px" name="package-url">
                           {
                            let $packages := httpclient:get(xs:anyURI($repomanager:repo-uri),false(),())//httpclient:body/node()
                             return
                             for $package in $packages//package[contains(url/.,'.xar')]
                             return
                                <option value="{$package/url}">{tokenize($package/url, "/")[last()]}</option>
                           }
                        </select>

                         Public Repository URL :

                        <input name="repository-url" size="40" value="{$repomanager:repo-uri}"/>
                        <input type="submit" name="action" value="set repository"/>

                        <input type="submit" name="action" value="Upload Package"/>
                        <input type="file" size="30" name="upload"/>

                Note: You can upload example .xar packages located under webapp/repo/packages
          </form>

};


Minor comment fix

Minor comment fix

xquery version "1.0";

(:
 : Copyright 2006-2009 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.
:)

(:~
 : The module provides functions to compute an immutable and opaque reference
 : for any node, either temporary or stored in a collection and for retrieving
 : nodes given their identifier. The identifiers are immutable, i.e. a node
 : identifier do not change during the node lifetime. Identifiers are also
 : unique, in that, a generated identifier has never been generated before.
 : A node, at any time during its lifetime, can be retrieved by its identifier.
 :
 :
Please see the data lifecycle
 : documentation about details on management and manipulation of collections.

 :
 : @see Data Lifecycle
 :
 : @author Federico Cavalieri
 :
 : @project XDM/node
 :
 :)
module namespace ref = "http://www.zorba-xquery.com/modules/node-reference";

declare namespace zerr = "http://www.zorba-xquery.com/errors";

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

(:~
 : Computes an immutable and opaque node reference (with type xs:anyURI) for
 : a given node, either temporary or stored in a collection.
 :
 :
The generated identifier is immutable, i.e. a node
 : identifier do not change during the node lifetime.

 :
 :
Identifiers are also unique, in that, a generated identifier has never
 : been generated before.

 :
 : A node, at any time during its lifetime, can be retrieved by its
 : identifier.
 :
 : @param $arg the node for which the URI should be computed
 :
 : @return the opaque URI of the node.
 :)
declare function ref:node-reference(
  $arg as node()
) as xs:anyURI external;

(:~
 : Returns the node identified by the given node reference.
 :
 :
The function returns the empty sequence if the node
 : that is referenced was deleted.

 :
 : @param $arg the URI of the node to retrieve.
 :
 : @return the node identified by the URI passed as parameter
 :         or the empty-sequence if no node with that URI is found.
 :
 : @error zerr::ZAPI0028 if the given URI is not a valid node reference
 :  computed by the <tt>ref:node-reference</tt> function.
 :)
declare function ref:node-by-reference(
  $arg as xs:anyURI
) as node()? external;

xquery version "1.0";

(:
 : Copyright 2006-2009 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.
:)

(:~
 : The module provides functions to compute an immutable and opaque reference
 : for any node, either temporary or stored in a collection and for retrieving
 : nodes given their identifier. The identifiers are immutable, i.e. a node
 : identifier do not change during the node lifetime. Identifiers are also
 : unique, in that, a generated identifier has been generated before.
 : A node, at any time during its lifetime, can be retrieved by its identifier.
 :
 :
Please see the data lifecycle
 : documentation about details on management and manipulation of collections.

 :
 : @see Data Lifecycle
 :
 : @author Federico Cavalieri
 :
 : @project XDM/node
 :
 :)
module namespace ref = "http://www.zorba-xquery.com/modules/node-reference";

declare namespace zerr = "http://www.zorba-xquery.com/errors";

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

(:~
 : Computes an immutable and opaque node reference (with type xs:anyURI) for
 : a given node, either temporary or stored in a collection.
 :
 :
The generated identifier is immutable, i.e. a node
 : identifier do not change during the node lifetime.

 :
 :
Identifiers are also unique, in that, a generated identifier has an
 : extremely high probability to never have been generated before.

 :
 : A node, at any time during its lifetime, can be retrieved by its
 : identifier.
 :
 : @param $arg the node for which the URI should be computed
 :
 : @return the opaque URI of the node.
 :)
declare function ref:node-reference(
  $arg as node()
) as xs:anyURI external;

(:~
 : Returns the node identified by the given node reference.
 :
 :
The function returns the empty sequence if the node
 : that is referenced was deleted.

 :
 : @param $arg the URI of the node to retrieve.
 :
 : @return the node identified by the URI passed as parameter
 :         or the empty-sequence if no node with that URI is found.
 :
 : @error zerr::ZAPI0028 if the given URI is not a valid node reference
 :  computed by the <tt>ref:node-reference</tt> function.
 :)
declare function ref:node-by-reference(
  $arg as xs:anyURI
) as node()? external;


updating date arithmetic example

updating date arithmetic example

xquery version "3.1";
declare namespace ebb="http://newtfire.org";
declare variable $rocketColl := collection('/db/rocket/');
(: ebb: This script introduces you to user-defined functions in XQuery.
These can be useful for taking values from your XQuery variables and performing a conversion, as we're doing here.
Since the Rocket Launches project has multiple attributes encoding launch dates and landing dates in the same xs:dateTime format,
and since they work with the xs:duration datatype too, for coding how long a mission lasted,
we can work with these data to do "date arithmetic" to make simple graphs and charts if we can convert it to a simple decimal notation.
Let's start reading this by skipping past the section I've marked off with asterisks as USER-DEFINED FUNCTIONS, and come back to it :)

(: **************** USER-DEFINED FUNCTIONS **************************:)
(: CONVERT DATETIME to DECIMAL :)
(: ebb :This user-defined function will unpack the date components from an input xs:dateTime datatype.
We will first extract the year from the datatype with year-from-dateTime(),
and then use format-dateTime() to return a 'picture string' that will give us the date's numerical position in the year.
We then divide that date number by 365 (since most years have 365 days).
This will give us a decimal format we can use in making charts and graphs. :)
declare function ebb:dateDecimalConverter($dT as xs:dateTime)
as xs:decimal?
{
let $year := year-from-dateTime($dT) ! xs:integer(.)
let $dayInYear := format-dateTime($dT, '[d]') ! xs:integer(.)
let $decimalDay := $dayInYear div 365
return $year + $decimalDay
};
(: CONVERT DURATION TO DECIMAL :)
(: ebb: The next user-defined function will convert the xs:duration datatype into a decimal value based on number of days.
 : So if we input a duration indicating 1 day, 6 hours, and 0 minutes, we should return 1.25 from this function.
 : Here's what we're calculating: There are 24 hours in a day. (Divide the H portion by 24) and add it to the days.
 : There are 60 minutes in an hour, and 60 * 24 gives the total number of minutes in a day.
 : (So we divide the M portion by 60 * 24) and add it to hours.
 : There are 60 seconds in a minute. and 60 * 60 * 24 gives us the total number of seconds in a day.
 : (We then divide the S portion by 60 * 60 * 24) and add it to minutes and hours
 : :)
declare function ebb:durationConverter($d as xs:integer, $h as xs:integer, $m as xs:integer, $s as xs:integer?)
as xs:decimal?
{
let $TDec := $h div 24 + $m div (60 * 24) + $s div (60 * 60 * 24)
return $d + $TDec
};
(: *******************END USER-DEFINED FUNCTIONS ********************** :)

let $launchDateTimes := $rocketColl//launch/@sDateTime
for $l in $launchDateTimes
(: To do date arithmetic, take a look at these functions: https://www.w3.org/TR/xpath-functions-31/#dates-times
 : We'll write a user-defined function to convert this datatype into a decimal notation. :)
let $lDec := ebb:dateDecimalConverter($l)
let $m := $rocketColl//launch[@sDateTime = $l]/preceding-sibling::sts
let $mID := $m  ! tokenize(., ':')[1]

let $duration := $m/following-sibling::duration/@time
(: ebb: To do duration arithmetic, start by looking at the functions here:
: https://www.w3.org/TR/xpath-functions-31/#durations
 : Let's try representing durations in terms of days with a decimal.
 : We'll write a user-defined function to convert hours, minutes, and seconds into a fraction of the day. :)
let $durDays := days-from-duration($duration)
let $durHours := hours-from-duration($duration)
let $durMins := minutes-from-duration($duration)
let $durSecs := seconds-from-duration($duration)
(: Now in line 43, we send our variables to our user-defined function for turning date datatypes into decimal values. :)
let $durDayDec := ebb:durationConverter($durDays, $durHours, $durMins, $durSecs)

order by $lDec
return concat('Launch Date: ', $l, ', mission: ', $mID, ': This Launch Decimal Date: ', $lDec,
': Duration: ', $duration, ': Decimal Notation:', $durDayDec)

xquery version "3.1";
declare namespace ebb="http://newtfire.org";
declare variable $rocketColl := collection('/db/rocket/');
(: ebb: This script introduces you to user-defined functions in XQuery.
These can be useful for taking values from your XQuery variables and performing a conversion, as we're doing here.
Since the Rocket Launches project has multiple attributes encoding launch dates and landing dates in the same xs:dateTime format,
and since they work with the xs:duration datatype too, for coding how long a mission lasted,
we can work with these data to do "date arithmetic" to make simple graphs and charts if we can convert it to a simple decimal notation.
Let's start reading this by skipping past the section I've marked off with asterisks as USER-DEFINED FUNCTIONS, and come back to it :)

(: **************** USER-DEFINED FUNCTIONS **************************:)
(: CONVERT DATETIME to DECIMAL :)
(: ebb :This user-defined function will unpack the date components from an input xs:dateTime datatype.
We will first extract the year from the datatype with year-from-dateTime(),
and then use format-dateTime() to return a 'picture string' that will give us the date's numerical position in the year.
We then divide that date number by 365 (since most years have 365 days).
This will give us a decimal format we can use in making charts and graphs. :)
declare function ebb:dateDecimalConverter($dT as xs:dateTime)
as xs:decimal?
{
let $year := year-from-dateTime($dT) ! xs:integer(.)
let $dayInYear := format-dateTime($dT, '[d]') ! xs:integer(.)
let $decimalDay := $dayInYear div 365
return $year + $decimalDay
};
(: CONVERT DURATION TO DECIMAL :)
(: ebb: The next user-defined function will convert the xs:duration datatype into a decimal value based on number of days.
 : So if we input a duration indicating 1 day, 6 hours, and 0 minutes, we should return 1.25 from this function.
 : Here's what we're calculating: There are 24 hours in a day. (Divide the H portion by 24) and add it to the days.
 : There are 60 minutes in an hour, and 60 * 24 gives the total number of minutes in a day.
 : (So we divide the M portion by 60 * 24) and add it to hours.
 : There are 60 seconds in a minute. and 60 * 60 * 24 gives us the total number of seconds in a day.
 : (We then divide the S portion by 60 * 60 * 24) and add it to minutes and hours
 : :)
declare function ebb:durationConverter($d as xs:integer, $h as xs:integer, $m as xs:integer, $s as xs:integer?)
as xs:decimal?
{
let $TDec := $h div 24 + $m div (60 * 24) + $s div (60 * 60 * 24)
return $d + $TDec
};
(: *******************END USER-DEFINED FUNCTIONS ********************** :)

let $launchDateTimes := $rocketColl//launch/@sDateTime
for $l in $launchDateTimes
(: To do date arithmetic, take a look at these functions: https://www.w3.org/TR/xpath-functions-31/#dates-times
 : We'll write a user-defined function to convert this datatype into a decimal notation. :)
let $lDec := ebb:dateDecimalConverter($l)
let $m := $rocketColl//launch[@sDateTime = $l]/preceding-sibling::sts
let $mID := $m  ! tokenize(., ':')[1]

let $duration := $m/following-sibling::duration/@time
(: ebb: To do duration arithmetic, start by looking at the functions here: https://www.w3.org/TR/xpath-functions-31/#durations
 : Let's try representing durations in terms of days with a decimal.
 : We'll write a user-defined function to convert hours, minutes, and seconds into a fraction of the day. :)
let $durDays := days-from-duration($duration)
let $durHours := hours-from-duration($duration)
let $durMins := minutes-from-duration($duration)
let $durSecs := seconds-from-duration($duration)
(: Now in line 43, we send our variables to our user-defined function for turning date datatypes into decimal values. :)
let $durDayDec := ebb:durationConverter($durDays, $durHours, $durMins, $durSecs)

order by $lDec
return concat('Launch Date: ', $l, ', mission: ', $mID, ': This Launch Decimal Date: ', $lDec,
': Duration: ', $duration, ': Decimal Notation:', $durDayDec)