Removed too-condensed summary of errors

Removed too-condensed summary of errors

xquery version "3.0";

module namespace app="http://exist-db.org/extension/jms/templates";

import module namespace templates="http://exist-db.org/xquery/templates" ;
import module namespace config="http://exist-db.org/extension/jms/config" at "config.xqm";
import module namespace jms="http://exist-db.org/xquery/messaging" at "java:org.exist.messaging.xquery.MessagingModule";

(:~
 : This is a sample templating function. It will be called by the templating module if
 : it encounters an HTML element with an attribute: data-template="app:test" or class="app:test" (deprecated).
 : The function has to take 2 default parameters. Additional parameters are automatically mapped to
 : any matching request or function parameter.
 :
 : @param $node the HTML node with the attribute which triggered this call
 : @param $model a map containing arbitrary data - used to pass information between template calls
 :)
declare function app:test($node as node(), $model as map(*)) {

Dummy template output generated by function app:test at {current-dateTime()}. The templating
        function was triggered by the class attribute class="app:test".

};

declare function app:executeAction($node as node(), $model as map(*), $action as xs:string, $receiver as xs:int) {

{

        try {
            switch ($action)
               case "start" return jms:start($receiver)
               case "stop"  return jms:stop($receiver)
               case "close" return jms:close($receiver)
               default return "unknown action"
        } catch * {

            {$err:description}

        }

        }

};

declare function app:showReport($node as node(), $model as map(*), $show as xs:string, $receiver as xs:int) {

{
        try {
        let $report := jms:report($receiver)
        return

JMS configuration

                    Item	Value

id	{data($report/@id)}

state	{data($report/state)}

java.naming.factory.initial	{data($report/java.naming.factory.initial)}

java.naming.provider.url	{data($report/java.naming.provider.url)}

connection-factory	{data($report/connection-factory)}

connection.username	{data($report/connection.username)}

destination	{data($report/destination)}

connection.client-id	{data($report/connection.client-id)}

consumer.message-selector	{data($report/consumer.message-selector)}

usage	{data($report/usage)}

Statistics

                        Item	Value

Number of messages	{data($report/statistics/nrProcessedMessages)}

Nr of failed messages	{data($report/statistics/nrFailedMessages)}

Cumulative processing time	{data($report/statistics/cumulativeProcessingTime)}

Errors

                        Source	Message

                    {
                        for $error in $report/errorMessages/error
                        return

{data($error/@src)}	{data($error)}

                    }

        } catch * {

            {$err:description}

        }
        }

};

declare function app:showReceivers($node as node(), $model as map(*)) {

    try {

                Id	State	Action	URL	Destination	Client-id	#	F	E

        {
            for $id in jms:list()
            let $report := jms:report($id)
            let $nrErrors := count($report/errorMessages/error)
            return

                {data($report/@id)}
                {data($report/state)}

                {data($report/java.naming.provider.url)}
                {data($report/destination)}
                {data($report/connection.client-id)}
                {data($report/statistics/nrProcessedMessages)}
                {data($report/statistics/nrFailedMessages)}

                { $nrErrors }

        }

    } catch * {

            {$err:description}

    }

};

xquery version "3.0";

module namespace app="http://exist-db.org/extension/jms/templates";

import module namespace templates="http://exist-db.org/xquery/templates" ;
import module namespace config="http://exist-db.org/extension/jms/config" at "config.xqm";
import module namespace jms="http://exist-db.org/xquery/messaging" at "java:org.exist.messaging.xquery.MessagingModule";

(:~
 : This is a sample templating function. It will be called by the templating module if
 : it encounters an HTML element with an attribute: data-template="app:test" or class="app:test" (deprecated).
 : The function has to take 2 default parameters. Additional parameters are automatically mapped to
 : any matching request or function parameter.
 :
 : @param $node the HTML node with the attribute which triggered this call
 : @param $model a map containing arbitrary data - used to pass information between template calls
 :)
declare function app:test($node as node(), $model as map(*)) {

Dummy template output generated by function app:test at {current-dateTime()}. The templating
        function was triggered by the class attribute class="app:test".

};

declare function app:executeAction($node as node(), $model as map(*), $action as xs:string, $receiver as xs:int) {

{

        try {
            switch ($action)
               case "start" return jms:start($receiver)
               case "stop"  return jms:stop($receiver)
               case "close" return jms:close($receiver)
               default return "unknown action"
        } catch * {

            {$err:description}

        }

        }

};

declare function app:showReport($node as node(), $model as map(*), $show as xs:string, $receiver as xs:int) {

{
        try {
        let $report := jms:report($receiver)
        return

JMS configuration

                    Item	Value

id	{data($report/@id)}

state	{data($report/state)}

java.naming.factory.initial	{data($report/java.naming.factory.initial)}

java.naming.provider.url	{data($report/java.naming.provider.url)}

connection-factory	{data($report/connection-factory)}

connection.username	{data($report/connection.username)}

destination	{data($report/destination)}

connection.client-id	{data($report/connection.client-id)}

consumer.message-selector	{data($report/consumer.message-selector)}

usage	{data($report/usage)}

Statistics

                        Item	Value

Number of messages	{data($report/statistics/nrProcessedMessages)}

Nr of failed messages	{data($report/statistics/nrFailedMessages)}

Cumulative processing time	{data($report/statistics/cumulativeProcessingTime)}

Errors

                        Source	Message

                    {
                        for $error in $report/errorMessages/error
                        return

{data($error/@src)}	{data($error)}

                    }

        } catch * {

            {$err:description}

        }
        }

};

declare function app:showReceivers($node as node(), $model as map(*)) {

    try {

                Id	State	Action	URL	Destination	Client-id	#	F	E

        {
            for $id in jms:list()
            let $report := jms:report($id)
            let $nrErrors := count($report/errorMessages/error)
            return

                {data($report/@id)}
                {data($report/state)}

                {data($report/java.naming.provider.url)}
                {data($report/destination)}
                {data($report/connection.client-id)}
                {data($report/statistics/nrProcessedMessages)}
                {data($report/statistics/nrFailedMessages)}

                {

                    if($nrErrors eq 0)
                    then
                       $nrErrors
                    else
                        {$nrErrors}
                }

        }

    } catch * {

            {$err:description}

    }

};


added 422's and 404 for invlaid xquery when not using the urn of the stored function in the URL

module namespace page = 'http://basex.org/modules/web-page';

import module namespace csr_proc = "https://github.com/openhie/openinfoman/csr_proc";
import module namespace csd_dm = "https://github.com/openhie/openinfoman/csd_dm";
import module namespace csd_webconf =  "https://github.com/openhie/openinfoman/csd_webconf";
import module namespace csd_webui =  "https://github.com/openhie/openinfoman/csd_webui";

declare   namespace   csd = "urn:ihe:iti:csd:2013";
declare default element  namespace   "urn:ihe:iti:csd:2013";

declare variable $page:csd_docs := csd_dm:registered_documents($csd_webconf:db);

declare
  %rest:path("/CSD/csr/{$name}/careServicesRequest")
  %rest:POST("{$careServicesRequest}")
  function page:csr($name,$careServicesRequest)
{
  if (csd_dm:document_source_exists($csd_webconf:db,$name)) then
    try {
       csr_proc:process_CSR($csd_webconf:db,$careServicesRequest/careServicesRequest,$name,csd_webui:generateURL())
    } catch * {
       <rest:response>
         <http:response status="422" message="Error executing xquery.">
           <http:header name="Content-Language" value="en"/>
           <http:header name="Content-Type" value="text/html; charset=utf-8"/>
         </http:response>
       </rest:response>
    }
  else
       <rest:response>
         <http:response status="404" message="No document named {$name} exists">
           <http:header name="Content-Language" value="en"/>
           <http:header name="Content-Type" value="text/html; charset=utf-8"/>
         </http:response>
       </rest:response>

};

declare updating
  %rest:path("/CSD/csr/{$name}/careServicesRequest/update")
  %rest:consumes("application/xml", "text/xml", "multipart/form-data")
  %rest:POST("{$careServicesRequest}")
  function page:csr_updating($name,$careServicesRequest)
{
  if (csd_dm:document_source_exists($csd_webconf:db,$name)) then
    try {
       csr_proc:process_updating_CSR($csd_webconf:db,$careServicesRequest/csd:careServicesRequest,$name,csd_webui:generateURL())
    } catch * {
      db:output(
       <rest:response>
         <http:response status="422" message="Error executing xquery.">
           <http:header name="Content-Language" value="en"/>
           <http:header name="Content-Type" value="text/html; charset=utf-8"/>
         </http:response>
       </rest:response>
       )
    }
  else
    db:output(
       <rest:response>
         <http:response status="404" message="No document named {$name} exists">
           <http:header name="Content-Language" value="en"/>
           <http:header name="Content-Type" value="text/html; charset=utf-8"/>
         </http:response>
       </rest:response>
     )
};

declare
  %rest:path("/CSD/csr/{$name}/adhoc")
  %rest:consumes("application/xml", "text/xml", "multipart/form-data")
  %rest:POST
  %rest:form-param("adhoc","{$adhoc}")
  %rest:form-param("content", "{$content}","application/xml")
function page:adhoc($name,$adhoc,$content) {
  if (csd_dm:document_source_exists($csd_webconf:db,$name)) then
    try {
      let  $adhoc_doc := csr_proc:create_adhoc_doc(string($adhoc),$content)
      return  csr_proc:process_CSR($csd_webconf:db, $adhoc_doc,$name,csd_webui:generateURL())
    } catch * {
       <rest:response>
         <http:response status="422" message="Error executing xquery.">
           <http:header name="Content-Language" value="en"/>
           <http:header name="Content-Type" value="text/html; charset=utf-8"/>
         </http:response>
       </rest:response>
    }
  else
       <rest:response>
         <http:response status="404" message="No document named {$name} exists">
           <http:header name="Content-Language" value="en"/>
           <http:header name="Content-Type" value="text/html; charset=utf-8"/>
         </http:response>
       </rest:response>

};

declare
  %rest:path("/CSD/csr")
  %rest:GET
  %output:method("xhtml")
  function page:csr_list()
{
let $response := page:endpoints()
return csd_webui:wrapper($response)
};

declare
  %rest:path("/CSD/csr/{$name}/careServicesRequest")
  %rest:GET
  %output:method("xhtml")
  function page:csr($name)
{
  let $contents :=
    (

      Example Usage:

curl -X POST -H 'content-type: text/xml'  --data-binary @request.xml $URL

      where $URL is one of the below and request.xml is an XML file containing a <csd:requestParams/> element

    ,

{
    (
      for $function in csr_proc:stored_functions($csd_webconf:db)
      let $url := csd_webui:generateURL(("CSD/csr", $name , "careServicesRequest", string($function/@urn)))
      return

Name: {string($function/@urn)}

URL: {$url}

Full Description

      ,
      for $function in csr_proc:stored_updating_functions($csd_webconf:db)
      let $url := csd_webui:generateURL(("CSD/csr", $name , "careServicesRequest/update", string($function/@urn)))
      return

Name: {string($function/@urn)} (updating)

URL: {$url}

Full Description

    )
    }

    )
  return csd_webui:wrapper($contents)
};

declare
  %rest:path("/CSD/csr/{$name}/storedfunctions")
  %rest:GET
  %output:method("xhtml")
  function page:show_type($name)
{
  let $funcs := (csr_proc:stored_functions($csd_webconf:db), csr_proc:stored_updating_functions($csd_webconf:db))
  let $options :=
    for $func in $funcs
    let $urn := string($func/@urn)
    let $val := csd_webui:generateURL(('/CSD/csr',$name,'careServicesRequest',$urn))
    return <option value="{$val}">{$urn}</option>

   let $content :=

Submit stored function:

       <form id='storedfunc' method='post' action=""  enctype="multipart/form-data">

Stored Function

	 <select name="func">{$options}</select>

Request Paramaters

	 <textarea  rows="10" cols="80" name="requestParams" ><![CDATA[<csd:requestParams xmlns:csd='urn:ihe:iti:csd:2013'/>]]></textarea>

	 <input type="submit" value="submit"/>

Response

         <textarea id='response' rows="50"  style='width:100%'/>
       </form>

  return csd_webui:wrapper($content)

};

declare function page:endpoints() {

Care Services Request - Endpoints

      {
	for $name in $page:csd_docs
	return

{$name} Document

	     Individual Stored functions

	    Submit Care Services Request for {$name} at:

{csd_webui:generateURL(('CSD/csr/',$name,'/careServicesRequest'))}

	    Submit ad-hoc query:
	    <form method='post' action="{csd_webui:generateURL(('/CSD/csr',$name,'adhoc'))}"  enctype="multipart/form-data">
	      Ad-Hoc Query<textarea  rows="10" cols="80" name="adhoc" >{$page:sample}</textarea>

	      Content Type<input    cols="80" name="content" value="text/html"/>

	      <input type="submit" value="submit"/>
	    </form>

      }

};

declare variable $page:sample :=
"declare namespace csd = 'urn:ihe:iti:csd:2013';

You have {count(/csd:CSD/csd:providerDirectory/*)} providers.

You have {count(/csd:CSD/csd:facilityDirectory/*)} facilities.

You have {count(/csd:CSD/csd:organizationDirectory/*)} organizations.

You have {count(/csd:CSD/csd:serviceDirectory/*)} services.

";

module namespace page = 'http://basex.org/modules/web-page';

import module namespace csr_proc = "https://github.com/openhie/openinfoman/csr_proc";
import module namespace csd_dm = "https://github.com/openhie/openinfoman/csd_dm";
import module namespace csd_webconf =  "https://github.com/openhie/openinfoman/csd_webconf";
import module namespace csd_webui =  "https://github.com/openhie/openinfoman/csd_webui";

declare   namespace   csd = "urn:ihe:iti:csd:2013";
declare default element  namespace   "urn:ihe:iti:csd:2013";

declare variable $page:csd_docs := csd_dm:registered_documents($csd_webconf:db);

declare
  %rest:path("/CSD/csr/{$name}/careServicesRequest")
  %rest:POST("{$careServicesRequest}")
  function page:csr($name,$careServicesRequest)
{
if (csd_dm:document_source_exists($csd_webconf:db,$name)) then
 csr_proc:process_CSR($csd_webconf:db,$careServicesRequest/careServicesRequest,$name,csd_webui:generateURL())
else
  (:need appropriate error handling:)
  ()

};

declare updating
  %rest:path("/CSD/csr/{$name}/careServicesRequest/update")
  %rest:consumes("application/xml", "text/xml", "multipart/form-data")
  %rest:POST("{$careServicesRequest}")
  function page:csr_updating($name,$careServicesRequest)
{
  if (csd_dm:document_source_exists($csd_webconf:db,$name)) then
    csr_proc:process_updating_CSR($csd_webconf:db,$careServicesRequest/csd:careServicesRequest,$name,csd_webui:generateURL())
  else
    (:need appropriate error handling:)
    ()
};

declare
  %rest:path("/CSD/csr/{$name}/adhoc")
  %rest:consumes("application/xml", "text/xml", "multipart/form-data")
  %rest:POST
  %rest:form-param("adhoc","{$adhoc}")
  %rest:form-param("content", "{$content}","application/xml")
function page:adhoc($name,$adhoc,$content) {
if (csd_dm:document_source_exists($csd_webconf:db,$name)) then
let  $adhoc_doc := csr_proc:create_adhoc_doc(string($adhoc),$content)
  return  csr_proc:process_CSR($csd_webconf:db, $adhoc_doc,$name,csd_webui:generateURL())
else
  (:need appropriate error handling:)
  ()

};

declare
  %rest:path("/CSD/csr")
  %rest:GET
  %output:method("xhtml")
  function page:csr_list()
{
let $response := page:endpoints()
return csd_webui:wrapper($response)
};

declare
  %rest:path("/CSD/csr/{$name}/careServicesRequest")
  %rest:GET
  %output:method("xhtml")
  function page:csr($name)
{
  let $contents :=
    (

      Example Usage:

curl -X POST -H 'content-type: text/xml'  --data-binary @request.xml $URL

      where $URL is one of the below and request.xml is an XML file containing a <csd:requestParams/> element

    ,

{
    (
      for $function in csr_proc:stored_functions($csd_webconf:db)
      let $url := csd_webui:generateURL(("CSD/csr", $name , "careServicesRequest", string($function/@urn)))
      return

Name: {string($function/@urn)}

URL: {$url}

Full Description

      ,
      for $function in csr_proc:stored_updating_functions($csd_webconf:db)
      let $url := csd_webui:generateURL(("CSD/csr", $name , "careServicesRequest/update", string($function/@urn)))
      return

Name: {string($function/@urn)} (updating)

URL: {$url}

Full Description

    )
    }

    )
  return csd_webui:wrapper($contents)
};

declare
  %rest:path("/CSD/csr/{$name}/storedfunctions")
  %rest:GET
  %output:method("xhtml")
  function page:show_type($name)
{
  let $funcs := (csr_proc:stored_functions($csd_webconf:db), csr_proc:stored_updating_functions($csd_webconf:db))
  let $options :=
    for $func in $funcs
    let $urn := string($func/@urn)
    let $val := csd_webui:generateURL(('/CSD/csr',$name,'careServicesRequest',$urn))
    return <option value="{$val}">{$urn}</option>

   let $content :=

Submit stored function:

       <form id='storedfunc' method='post' action=""  enctype="multipart/form-data">

Stored Function

	 <select name="func">{$options}</select>

Request Paramaters

	 <textarea  rows="10" cols="80" name="requestParams" ><![CDATA[<csd:requestParams xmlns:csd='urn:ihe:iti:csd:2013'/>]]></textarea>

	 <input type="submit" value="submit"/>

Response

         <textarea id='response' rows="50"  style='width:100%'/>
       </form>

  return csd_webui:wrapper($content)

};

declare function page:endpoints() {

Care Services Request - Endpoints

      {
	for $name in $page:csd_docs
	return

{$name} Document

	     Individual Stored functions

	    Submit Care Services Request for {$name} at:

{csd_webui:generateURL(('CSD/csr/',$name,'/careServicesRequest'))}

	    Submit ad-hoc query:
	    <form method='post' action="{csd_webui:generateURL(('/CSD/csr',$name,'adhoc'))}"  enctype="multipart/form-data">
	      Ad-Hoc Query<textarea  rows="10" cols="80" name="adhoc" >{$page:sample}</textarea>

	      Content Type<input    cols="80" name="content" value="text/html"/>

	      <input type="submit" value="submit"/>
	    </form>

      }

};

declare variable $page:sample :=
"declare namespace csd = 'urn:ihe:iti:csd:2013';

You have {count(/csd:CSD/csd:providerDirectory/*)} providers.

You have {count(/csd:CSD/csd:facilityDirectory/*)} facilities.

You have {count(/csd:CSD/csd:organizationDirectory/*)} organizations.

You have {count(/csd:CSD/csd:serviceDirectory/*)} services.

";


Updated keys per fix for #170

Updated keys per fix for #170

xquery version "1.0-ml";

(:
 This module was generated by MarkLogic Entity Services.
 The source entity type document was et-required-0.0.1
 To use this module, examine how you wish to extract data from sources,
 and modify the various extract-instance-{X} functions to
 create the instances you wish.

 You may wish to/need to alter
 1.  values.  For example, creating duration values from decimal months.
 2.  references.  This conversion module assumes you want to denormalize
     instances when storing them in documents.  You may choose to remove
     code that denormalizes, and just include reference values in your
     instances instead.
 3.  Source XPath expressions.  The data coming into the extract-instance-{X}
     functions will probably not be exactly what this module predicts.

 After modifying this file, put it in your project for deployment to the modules
 database of your application, and check it into your source control system.

 Modification History:
 Generated at timestamp: 2016-10-19T00:00:33.783666-07:00
 Persisted by AUTHOR
 Date: DATE
 :)

module namespace et-required
    = "http://baloo/et-required-0.0.1";

import module namespace es = "http://marklogic.com/entity-services"
    at "/MarkLogic/entity-services/entity-services.xqy";

declare option xdmp:mapping "false";

(:
  extract-instance-{entity-type} functions

  These functions together take a source document and create a nested
  map structure from it.
  The resulting map is used by instance-to-canonical-xml to create documents
  in the database.

  It is expected that an implementer will edit at least XPath expressions in
  the extraction functions.  It is less likely that you will want to edit
  the instance-to-canonical-xml or envelope functions.
 :)

(:~
 : Creates a map:map instance from some source document.
 : @param $source-node  A document or node that contains
 :   data for populating a ETOne
 : @return A map:map instance with extracted data and
 :   metadata about the instance.
 :)
declare function et-required:extract-instance-ETOne(
    $source as node()?
) as map:map
{
    let $source-node :=
        if ( ($source instance of document-node())
            or (exists($source/ETOne)))
        then $source/node()
        else $source
    let $instance := json:object()
    (: Add the original source document as an attachment. (optional, for lineage) :)
        =>map:with('$attachments',
            typeswitch($source-node)
            case object-node() return xdmp:quote($source)
            case array-node() return xdmp:quote($source)
            default return $source)
    (: Add type information to the entity instance (required, do not change) :)
        =>map:with('$type', 'ETOne')
    return

    (: The following logic may not be required for every extraction       :)
    (: if this $source-node has no child elements, it has a reference key :)
    if (empty($source-node/*))
    then $instance=>map:with('$ref', $source-node/text())
    (: Otherwise, this source node contains instance data. Populate it. :)
    else

    (:
    The following code populates the properties of the 'ETOne'
    entity type. Ensure that all of the property paths are correct for your
    source data.  The general pattern is
    =>map:with('keyName', casting-function($source-node/path/to/data))
    but you may also wish to convert values
    =>map:with('dateKeyName',
          xdmp:parse-dateTime("[Y0001]-[M01]-[D01]T[h01]:[m01]:[s01].[f1][Z]",
          $source-node/path/to/data/in/the/source))
    You can also implement lookup functions,
    =>map:with('lookupKey',
          cts:search( collection('customers'),
              string($source-node/path/to/lookup/key))/id
    or populate the instance with constants.
    =>map:with('constantValue', 10)
    The output of this function should structurally match the output of
    es:model-get-test-instances($model)
    :)

    $instance
    =>   map:with('a',                      xs:integer($source-node/a))
    =>   map:with('b',                      xs:string($source-node/b))
    =>es:optional('c',                      xs:date($source-node/c))
};

(:~
 : Turns an entity instance into an XML structure.
 : This out-of-the box implementation traverses a map structure
 : and turns it deterministically into an XML tree.
 : Using this function as-is should be sufficient for most use
 : cases, and will play well with other generated artifacts.
 : @param $entity-instance A map:map instance returned from one of the extract-instance
 :    functions.
 : @return An XML element that encodes the instance.
 :)
declare function et-required:instance-to-canonical-xml(
    $entity-instance as map:map
) as element()
{
    (: Construct an element that is named the same as the Entity Type :)
    element { map:get($entity-instance, "$type") }  {
        if ( map:contains($entity-instance, "$ref") )
        then map:get($entity-instance, "$ref")
        else
            for $key in map:keys($entity-instance)
            let $instance-property := map:get($entity-instance, $key)
            where ($key castable as xs:NCName and $key ne "$type")
            return
                typeswitch ($instance-property)
                (: This branch handles embedded objects.  You can choose to prune
                   an entity's representation of extend it with lookups here. :)
                case json:object+
                    return
                        for $prop in $instance-property
                        return element { $key } { et-required:instance-to-canonical-xml($prop) }
                (: An array can also treated as multiple elements :)
                case json:array
                    return
                        for $val in json:array-values($instance-property)
                        return
                            if ($val instance of json:object)
                            then element { $key } {
                                attribute datatype { "array" },
                                et-required:instance-to-canonical-xml($val) }
                            else element { $key } {
                                attribute datatype { "array" },
                                $val }
                (: A sequence of values should be simply treated as multiple elements :)
                case item()+
                    return
                        for $val in $instance-property
                        return element { $key } { $val }
                default return element { $key } { $instance-property }
    }
};

(:
 : Wraps a canonical instance (returned by instance-to-canonical-xml())
 : within an envelope patterned document, along with the source
 : document, which is stored in an attachments section.
 : @param $entity-instance an instance, as returned by an extract-instance
 : function
 : @return A document which wraps both the canonical instance and source docs.
 :)
declare function et-required:instance-to-envelope(
    $entity-instance as map:map
) as document-node()
{
    document {
        element es:envelope {
            element es:instance {
                element es:info {
                    element es:title { map:get($entity-instance,'$type') },
                    element es:version { "0.0.1" }
                },
                et-required:instance-to-canonical-xml($entity-instance)
            },
            element es:attachments {
                map:get($entity-instance, "$attachments")
            }
        }
    }
};

xquery version "1.0-ml";

(: This module was generated by MarkLogic Entity Services.                          :)
(: The source entity type document was et-required-0.0.1                            :)
(:                                                                                :)
(: To use this module, examine how you wish to extract data from sources,           :)
(: and modify the various extract-instance-{X} functions to                         :)
(: create the instances you wish.                                                   :)
(:                                                                                :)
(: You may wish to/need to alter                                                    :)
(: 1.  values.  For example, creating duration values from decimal months.          :)
(: 2.  references.  This conversion module assumes you want to denormalize          :)
(:     instances when storing them in documents.  You may choose to remove          :)
(:     code that denormalizes, and just include reference values in your instances  :)
(:     instead.                                                                     :)
(: 3.  Source XPath expressions.  The data coming into the extract-instance-{X}     :)
(:     functions will probably not be exactly what this module predicts.            :)
(:                                                                                :)
(: After modifying this file, put it in your project for deployment to the modules  :)
(: database of your application, and check it into your source control system.      :)
(:                                                                                :)
(: Modification History:                                                            :)
(: Generated at timestamp: 2016-10-05T12:28:46.957409-07:00                         :)
(:   Persisted by AUTHOR                                                            :)
(:   Date: DATE                                                                     :)
module namespace et-required
    = "http://baloo/et-required-0.0.1";

import module namespace es = "http://marklogic.com/entity-services"
    at "/MarkLogic/entity-services/entity-services.xqy";

declare option xdmp:mapping "false";

(:  extract-instance-{entity-type} functions                                        :)
(:                                                                                :)
(:  These functions take together take a source document and create a nested        :)
(:  map structure from it.                                                          :)
(:  The resulting map is used by instance-to-canonical-xml to create documents      :)
(:  in the database.                                                                :)
(:                                                                                :)
(:  It is expected that an implementer will edit at least XPath expressions in      :)
(:  the extraction functions.  It is less likely that you will want to edit         :)
(:  the instance-to-canonical-xml or envelope functions.                            :)

(:~
 : Creates a map:map instance from some source document.
 : @param $source-node  A document or node that contains
 :   data for populating a ETOne
 : @return A map:map instance with extracted data and
 :   metadata about the instance.
 :)
declare function et-required:extract-instance-ETOne(
    $source as node()?
) as map:map
{
    let $source-node :=
        if ( ($source instance of document-node())
            or (exists($source/ETOne)))
        then $source/node()
        else $source
    let $instance := json:object()
(: Add the original source document as an attachment.                               :)
        =>map:with('$attachments',
            typeswitch($source-node)
            case object-node() return xdmp:quote($source)
            case array-node() return xdmp:quote($source)
            default return $source)
        =>map:with('$type', 'ETOne')
    return
(: if this $source-node is a reference to another instance, then extract its key    :)
    if (empty($source-node/*))
    then $instance=>map:with('$ref', $source-node/text())
(: Otherwise, this source node contains instance data, so populate it.              :)
    else
        $instance
(: The following line identifies the type of this instance.  Do not change it.      :)
(: because this implementation uses an XML envelope.                                :)
(:                                                                                :)
(: The following code populates the properties of the                               :)
(: 'ETOne' entity type                                                              :)
(: Ensure that all of the property paths are correct for your source data.          :)
(: The general pattern is                                                           :)
(: =>map:with('keyName', casting-function($source-node/path/to/data))               :)
(: but you may also wish to convert values                                          :)
(: =>map:with('dateKeyName',                                                        :)
(:       xdmp:parse-dateTime("[Y0001]-[M01]-[D01]T[h01]:[m01]:[s01].[f1][Z]",       :)
(:       $source-node/path/to/data/in/the/source))                                  :)
(: You can also implement lookup functions,                                         :)
(: =>map:with('lookupKey',                                                          :)
(:       cts:search( collection('customers'),                                       :)
(:           string($source-node/path/to/lookup/key))/id                            :)
(: or populate the instance with constants.                                         :)
(: =>map:with('constantValue', 10)                                                  :)
(: The output of this function should structurally match the output of              :)
(: es:model-get-test-instances($model)                                              :)
(:                                                                                :)
 =>   map:with('a',                      xs:integer($source-node/a))
 =>   map:with('b',                      xs:string($source-node/b))
 =>es:optional('c',                      xs:date($source-node/c))

};

(:~
 : Turns an entity instance into an XML structure.
 : This out-of-the box implementation traverses a map structure
 : and turns it deterministically into an XML tree.
 : Using this function as-is should be sufficient for most use
 : cases, and will play well with other generated artifacts.
 : @param $entity-instance A map:map instance returned from one of the extract-instance
 :    functions.
 : @return An XML element that encodes the instance.
 :)
declare function et-required:instance-to-canonical-xml(
    $entity-instance as map:map
) as element()
{
    (: Construct an element that is named the same as the Entity Type :)
    element { map:get($entity-instance, "$type") }  {
        if ( map:contains($entity-instance, "$ref") )
        then map:get($entity-instance, "$ref")
        else
            for $key in map:keys($entity-instance)
            let $instance-property := map:get($entity-instance, $key)
            where ($key castable as xs:NCName and $key ne "$type")
            return
                typeswitch ($instance-property)
                (: This branch handles embedded objects.  You can choose to prune
                   an entity's representation of extend it with lookups here. :)
                case json:object+
                    return
                        for $prop in $instance-property
                        return element { $key } { et-required:instance-to-canonical-xml($prop) }
                (: An array can also treated as multiple elements :)
                case json:array
                    return
                        for $val in json:array-values($instance-property)
                        return
                            if ($val instance of json:object)
                            then element { $key } {
                                attribute datatype { "array" },
                                et-required:instance-to-canonical-xml($val) }
                            else element { $key } {
                                attribute datatype { "array" },
                                $val }
                (: A sequence of values should be simply treated as multiple elements :)
                case item()+
                    return
                        for $val in $instance-property
                        return element { $key } { $val }
                default return element { $key } { $instance-property }
    }
};

(:
 : Wraps a canonical instance (returned by instance-to-canonical-xml())
 : within an envelope patterned document, along with the source
 : document, which is stored in an attachments section.
 : @param $entity-instance an instance, as returned by an extract-instance
 : function
 : @return A document which wraps both the canonical instance and source docs.
 :)
declare function et-required:instance-to-envelope(
    $entity-instance as map:map
) as document-node()
{
    document {
        element es:envelope {
            element es:instance {
                element es:info {
                    element es:title { map:get($entity-instance,'$type') },
                    element es:version { "0.0.1" }
                },
                et-required:instance-to-canonical-xml($entity-instance)
            },
            element es:attachments {
                map:get($entity-instance, "$attachments")
            }
        }
    }
};


the cancel button should go to the previous 'edit' page in same window

xquery version "1.0";

(: ~
 : Module Name:             edit value domain webpage and XQuery
 :
 : Module Version           3.0
 :
 : Date                     26th Aug 2009
 :
 : Copyright                The cagrid consortium
 :
 : Module overview          Edit Value Domain
 :
 :)

(:~
 :    @author Rakesh Dhaval
 :    @author Puneet Mathur
 :    @version 3.0
 :    allows editing the DataElementConcept
~ :)

  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";

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

  import module namespace
    lib-uri-resolution="http://www.cagrid.org/xquery/library/resolver"
    at "../resolver/m-lib-uri-resolution.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 function local:value_domain(
   $id as xs:string,
   $reg-auth as xs:string,
   $administrative-note as xs:string,
   $administrative-status as xs:string,
   $administered-by as xs:string,
   $submitted-by as xs:string,
   $registered-by as xs:string,
   $context-ids as xs:string*,
   $country-identifiers as xs:string*,
   $language-identifiers as xs:string*,
   $names as xs:string*,
   $definitions as xs:string*,
   $sources as xs:string*,
   $preferred as xs:string?,
   $conceptual_domain_id as xs:string?,
   $enum_datatype as xs:string?,
   $enum_uom as xs:string?,
   $char_quantity as xs:string?,
   $value_domain_format as xs:string?,
   $values as xs:string*
   ) as xs:boolean
{
   let $version := lib-forms:substring-after-last($id,'_')
   let $data-identifier := substring-after(lib-forms:substring-before-last($id,'_'),'_')
   let $doc-name := concat($id,'.xml')
   let $concept_domain := lib-util:mdrElement("conceptual_domain",$conceptual_domain_id)
   let $permissible-identifier := substring-after(lib-forms:substring-before-last($id,'_'),'_')
   let $value_meaning_identifier := $concept_domain//openMDR:value_meaning_identifier/text()
   let $content := (
            lib-make-admin-item:administration-record($administrative-note,$administrative-status,'Recorded'),
            lib-make-admin-item:custodians($administered-by,$registered-by,$submitted-by),
            lib-make-admin-item:havings(
                    $context-ids,
                    $country-identifiers,
                    $language-identifiers,
                    $names,
                    $definitions,
                    $preferred,
                    $sources),

             for $meaning at $pos in $concept_domain//openMDR:value_meaning_description
                    return (
                       element openMDR:containing {
                         attribute permissible_value_identifier {$permissible-identifier},
                         element openMDR:permissible_value_begin_date {current-date()},
                         element openMDR:value_item {$values[$pos]},
                         element openMDR:contained_in {$value_meaning_identifier[$pos]}
                       }
             ),
            element openMDR:representing {$conceptual_domain_id},
            element openMDR:value_domain_datatype {$enum_datatype},
            element openMDR:value_domain_unit_of_measure {$enum_uom},
            element openMDR:value_domain_maximum_character_quantity{$char_quantity},
            element openMDR:value_domain_format{$value_domain_format}

    )

   (: compose the document :)
    let $document := (
     if($values > '' ) then (
      element openMDR:Enumerated_Value_Domain {
            attribute item_registration_authority_identifier {$reg-auth},
            attribute data_identifier {$data-identifier},
            attribute version {$version},
            $content
           }
      ) else (
       element openMDR:Non_Enumerated_Value_Domain {
            attribute item_registration_authority_identifier {$reg-auth},
            attribute data_identifier {$data-identifier},
            attribute version {$version},
            $content
           }
      )
   )

   let $collection := 'value_domain'
   let $message := lib-forms:store-document($document)
   return
      if ($message='stored')
      then true()
      else response:redirect-to(xs:anyURI(concat("../web/login.xquery?calling_page=editValueDomain.xquery&",$message)))
};

declare function local:input-page(
   $message as xs:string?,
   $id as xs:string?,
   $reg-auth as xs:string?,
   $administrative-note  as xs:string?,
   $administrative-status  as xs:string?,
   $administered-by  as xs:string?,
   $submitted-by  as xs:string?,
   $registered-by  as xs:string?,
   $context-ids  as xs:string*,
   $country-identifiers as xs:string*,
   $language-identifiers as xs:string*,
   $names as xs:string*,
   $definitions as xs:string*,
   $sources as xs:string*,
   $action as xs:string?,
   $preferred as xs:string?,
   $conceptual_domain_id as xs:string?,
   $enum_datatype as xs:string?,
   $enum_uom as xs:string?,
   $char_quantity as xs:string?,
   $value_domain_format as xs:string?,
   $values as xs:string*
   ) {
   let $skip-name := substring-after($action,'delete naming entry')
   let $skip-name-index := if ($skip-name>'') then xs:int($skip-name) else 0
   return

                This form will allow you to edit a Value Domain in the metadata repository

                <form name="edit_value_domain" action="editValueDomain.xquery" method="post" class="cagridForm" enctype="multipart/form-data">

                {lib-forms:hidden-element('id',$id)}
                {lib-forms:hidden-element('updating','updating')}

                {lib-forms:edit-admin-item($reg-auth,
                     $administrative-note,
                     $administrative-status,
                     $administered-by,
                     $submitted-by,
                     $registered-by,
                     $context-ids,
                     $country-identifiers,
                     $language-identifiers,
                     $names,
                     $definitions,
                     $sources,
                     $preferred,
                     $action)}

                            Conceptual Domain

                        {
                        let $concept_domain := lib-util:mdrElement("conceptual_domain",$conceptual_domain_id)

                        return
                        if ($conceptual_domain_id > '' or $conceptual_domain_id eq "Cancel")
                        then (

                                Conceptual Domain ID
                                {$conceptual_domain_id}
                                {session:set-attribute("old_cd_id", $conceptual_domain_id)}
                                {lib-forms:popup-form-search('conceptual_domain','conceptual_domain_id','edit_value_domain', 'Change Relationship')}
                                {lib-forms:hidden-element('conceptual_domain_id',$conceptual_domain_id)}

,

                                Conceptual Domain Name
                                {administered-item:preferred-name('conceptual_domain',$conceptual_domain_id)}

,

Value Domain
,

                               Value Domain Data Type
                               {lib-forms:make-select-datatype('enum_datatype', $enum_datatype)}

,

                               Value Domain Unit of Measure
                               {lib-forms:make-select-uom('enum_uom',$enum_uom)}

,

                               Value Domain Format (E.g. MM-DD-YYYY)
                               <input type="text" name="value_domain_format" value='{$value_domain_format}'></input>

,

                               Value Domain Maximum Character Count
                               <input type="text" name="char_quantity" value='{$char_quantity}'></input>

,
                           if ($concept_domain//openMDR:value_meaning_description > '')
                           then
                           (

                                   Possible Values
                                   meaning
                                   value

,
                                        for $meaning at $pos in $concept_domain//openMDR:value_meaning_description
                                        return (

                                              Permissable Value {$pos}
                                              {$meaning}
                                              {lib-forms:input-element('values', 20, $values[$pos])}

                                        )
                           )
                           else ()
                    )
                    else (

                                    Choose Conceptual Domain
                                    {lib-forms:make-select-form-admin-item('conceptual_domain','conceptual_domain_id',$conceptual_domain_id,'edit_value_domain', 'Select Relationship')}

                   )
               }

Store

	<input type="submit" name="update" value="Store Changes"/>
                          <input type="button"  name="update" value="Cancel"
                              onClick= "{concat("location.href='../web/value_domain.xquery?compound_id=", $id, "';")}" />

          </form>

{$message}

   };

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

                    Value Domain modified.

                Return to maintenance menu

                Create another Value Domain

};

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 $updating := request:get-parameter('updating','')
   let $title as xs:string := concat("Editing ValueDomain ", $id)
   let $element := lib-util:mdrElement("value_domain",$id)
   let $action := request:get-parameter('update','')

   let $ireg-auth := string($element/@item_registration_authority_identifier)
   let $iadministrative-note := string($element//openMDR:administrative_note)
   let $iadministrative-status := string($element//openMDR:administrative_status)
   let $iadministered-by := string($element//openMDR:administered_by)
   let $isubmitted-by := string($element//openMDR:submitted_by)
   let $iregistered-by := string($element//openMDR:registered_by)
   let $icontext-ids := $element//openMDR:context_identifier
   let $icountry-identifiers := $element//openMDR:country_identifier
   let $ilanguage-identifiers := $element//openMDR:language_identifier
   let $inames := $element//openMDR:name
   let $idefinitions := $element//openMDR:definition_text
   let $isources := $element//openMDR:definition_source_reference
   let $ipreferred := string(fn:index-of($element//openMDR:preferred_designation,'true'))

    let $iconceptual_domain_id := if($element//openMDR:representing/text() > '')
                                    then ($element//openMDR:representing/text()) else ("")
    let $iconceptual_domain := lib-util:mdrElement("conceptual_domain",$iconceptual_domain_id)
    let $ivalues := $element//openMDR:value_item
    let $ienum_datatype := $element//openMDR:value_domain_datatype
    let $ienum_uom := $element//openMDR:value_domain_unit_of_measure
    let $ichar_quantity := $element//openMDR:value_domain_maximum_character_quantity
    let $ivalue_domain_format := $element//openMDR:value_domain_format

    (:
    let $icontained_in_identifier := $element//openMDR:contained_in
    let $log := util:log-system-err($iconceptual_domain)
    let $log := util:log-system-err($ivalues)
    let $log := util:log-system-err($element//openMDR:contained_in)
    let $log := util:log-system-err($iconceptual_domain_id)
    let $log := util:log-system-err(value-meaning:value-meaning($element/openMDR:contained_in/text()/openMDR:value_meaning_description))
    let $log := util:log-system-err($element//openMDR:contained_in/text()/openMDR:value_meaning_description)
    let test := element//openMDR:contained_in/text())/openMDR:value_meaning_description
    for $meaning at $pos in $iconceptual_domain//openMDR:value_meaning_description
       let $log := util:log-system-err($meaning)
    :)

   let $reg-auth := request:get-parameter('registration-authority','')
   let $administrative-note := request:get-parameter('administrative-note','')
   let $administrative-status := request:get-parameter('administrative-status','')
   let $administered-by := request:get-parameter('administered-by','')
   let $submitted-by := request:get-parameter('submitted-by','')
   let $registered-by := request:get-parameter('registered-by','')
   let $context-ids := request:get-parameter('context-ids',())
   let $country-identifiers := request:get-parameter('country-identifiers',())
   let $language-identifiers := request:get-parameter('language-identifiers',())
   let $names := request:get-parameter('names',())
   let $definitions := request:get-parameter('definitions',())
   let $sources := request:get-parameter('sources',())
   let $preferred := request:get-parameter('preferred','')
   let $conceptual_domain_id := request:get-parameter('conceptual_domain_id','')
   let $values := request:get-parameter('values',())
   let $enum_datatype := request:get-parameter('enum_datatype','')
   let $enum_uom := request:get-parameter('enum_uom','')
   let $char_quantity := request:get-parameter('char_quantity','')
   let $value_domain_format := request:get-parameter('value_domain_format','')

   return
      lib-rendering:txfrm-webpage(
      $title,
      if ($action='Store Changes')
      then
         (
         if (
               local:value_domain
                  (
                     $id,
                     $reg-auth,
                     $administrative-note,
                     $administrative-status,
                     $administered-by,
                     $submitted-by,
                     $registered-by,
                     $context-ids,
                     $country-identifiers,
                     $language-identifiers,
                     $names,
                     $definitions,
                     $sources,
                     $preferred,
                     $conceptual_domain_id,
                     $enum_datatype,
                     $enum_uom,
                     $char_quantity,
                     $value_domain_format,
                     $values
                  )
            )
         then (local:success-page()  )
         else (local:input-page(
            'could not store document',
                     $id,
                     $reg-auth,
                     $administrative-note,
                     $administrative-status,
                     $administered-by,
                     $submitted-by,
                     $registered-by,
                     $context-ids,
                     $country-identifiers,
                     $language-identifiers,
                     $names,
                     $definitions,
                     $sources,
                     $action,
                     $preferred,
                     $conceptual_domain_id,
                     $enum_datatype,
                     $enum_uom,
                     $char_quantity,
                     $value_domain_format,
                     $values
                     )
               )
         )
       else if ($action='Change Relationship')
         then(
               let $conceptual_domain_id as xs:string? := ""

               return
               local:input-page
               (
               '',
               $id,
               $reg-auth,
               $administrative-note,
               $administrative-status,
               $administered-by,
               $submitted-by,
               $registered-by,
               $context-ids,
               $country-identifiers,
               $language-identifiers,
               $names,
               $definitions,
               $sources,
               $action,
               $preferred,
               $conceptual_domain_id,
               $enum_datatype,
               $enum_uom,
               $char_quantity,
               $value_domain_format,
               $values
               )
         )
         else if($conceptual_domain_id eq "Cancel")
         then(
               local:input-page
               (
               '',
               $id,
               $reg-auth,
               $administrative-note,
               $administrative-status,
               $administered-by,
               $submitted-by,
               $registered-by,
               $context-ids,
               $country-identifiers,
               $language-identifiers,
               $names,
               $definitions,
               $sources,
               $action,
               $preferred,
               session:get-attribute("old_cd_id"),
               $enum_datatype,
               $enum_uom,
               $char_quantity,
               $value_domain_format,
               $values
               ),
               session:set-attribute("old_cd_id", $iconceptual_domain_id)
        )
        else (
         if ($updating ='updating')
         then (

         local:input-page
               (
               '',
               $id,
               $reg-auth,
               $administrative-note,
               $administrative-status,
               $administered-by,
               $submitted-by,
               $registered-by,
               $context-ids,
               $country-identifiers,
               $language-identifiers,
               $names,
               $definitions,
               $sources,
               $action,
               $preferred,
               $conceptual_domain_id,
               $enum_datatype,
               $enum_uom,
               $char_quantity,
               $value_domain_format,
               $values
               )
         ) else (
               local:input-page
               (
               '',
               $id,
               $ireg-auth,
               $iadministrative-note,
               $iadministrative-status,
               $iadministered-by,
               $isubmitted-by,
               $iregistered-by,
               $icontext-ids,
               $icountry-identifiers,
               $ilanguage-identifiers,
               $inames,
               $idefinitions,
               $isources,
               $action,
               $ipreferred,
               $iconceptual_domain_id,
               $ienum_datatype,
               $ienum_uom,
               $ichar_quantity,
               $ivalue_domain_format,
               $ivalues
               )
         )
       )
    )

xquery version "1.0";

(: ~
 : Module Name:             edit value domain webpage and XQuery
 :
 : Module Version           3.0
 :
 : Date                     26th Aug 2009
 :
 : Copyright                The cagrid consortium
 :
 : Module overview          Edit Value Domain
 :
 :)

(:~
 :    @author Rakesh Dhaval
 :    @author Puneet Mathur
 :    @version 3.0
 :    allows editing the DataElementConcept
~ :)

  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";

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

  import module namespace
    lib-uri-resolution="http://www.cagrid.org/xquery/library/resolver"
    at "../resolver/m-lib-uri-resolution.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 function local:value_domain(
   $id as xs:string,
   $reg-auth as xs:string,
   $administrative-note as xs:string,
   $administrative-status as xs:string,
   $administered-by as xs:string,
   $submitted-by as xs:string,
   $registered-by as xs:string,
   $context-ids as xs:string*,
   $country-identifiers as xs:string*,
   $language-identifiers as xs:string*,
   $names as xs:string*,
   $definitions as xs:string*,
   $sources as xs:string*,
   $preferred as xs:string?,
   $conceptual_domain_id as xs:string?,
   $enum_datatype as xs:string?,
   $enum_uom as xs:string?,
   $char_quantity as xs:string?,
   $value_domain_format as xs:string?,
   $values as xs:string*
   ) as xs:boolean
{
   let $version := lib-forms:substring-after-last($id,'_')
   let $data-identifier := substring-after(lib-forms:substring-before-last($id,'_'),'_')
   let $doc-name := concat($id,'.xml')
   let $concept_domain := lib-util:mdrElement("conceptual_domain",$conceptual_domain_id)
   let $permissible-identifier := substring-after(lib-forms:substring-before-last($id,'_'),'_')
   let $value_meaning_identifier := $concept_domain//openMDR:value_meaning_identifier/text()
   let $content := (
            lib-make-admin-item:administration-record($administrative-note,$administrative-status,'Recorded'),
            lib-make-admin-item:custodians($administered-by,$registered-by,$submitted-by),
            lib-make-admin-item:havings(
                    $context-ids,
                    $country-identifiers,
                    $language-identifiers,
                    $names,
                    $definitions,
                    $preferred,
                    $sources),

             for $meaning at $pos in $concept_domain//openMDR:value_meaning_description
                    return (
                       element openMDR:containing {
                         attribute permissible_value_identifier {$permissible-identifier},
                         element openMDR:permissible_value_begin_date {current-date()},
                         element openMDR:value_item {$values[$pos]},
                         element openMDR:contained_in {$value_meaning_identifier[$pos]}
                       }
             ),
            element openMDR:representing {$conceptual_domain_id},
            element openMDR:value_domain_datatype {$enum_datatype},
            element openMDR:value_domain_unit_of_measure {$enum_uom},
            element openMDR:value_domain_maximum_character_quantity{$char_quantity},
            element openMDR:value_domain_format{$value_domain_format}

    )

   (: compose the document :)
    let $document := (
     if($values > '' ) then (
      element openMDR:Enumerated_Value_Domain {
            attribute item_registration_authority_identifier {$reg-auth},
            attribute data_identifier {$data-identifier},
            attribute version {$version},
            $content
           }
      ) else (
       element openMDR:Non_Enumerated_Value_Domain {
            attribute item_registration_authority_identifier {$reg-auth},
            attribute data_identifier {$data-identifier},
            attribute version {$version},
            $content
           }
      )
   )

   let $collection := 'value_domain'
   let $message := lib-forms:store-document($document)
   return
      if ($message='stored')
      then true()
      else response:redirect-to(xs:anyURI(concat("../web/login.xquery?calling_page=editValueDomain.xquery&",$message)))
};

declare function local:input-page(
   $message as xs:string?,
   $id as xs:string?,
   $reg-auth as xs:string?,
   $administrative-note  as xs:string?,
   $administrative-status  as xs:string?,
   $administered-by  as xs:string?,
   $submitted-by  as xs:string?,
   $registered-by  as xs:string?,
   $context-ids  as xs:string*,
   $country-identifiers as xs:string*,
   $language-identifiers as xs:string*,
   $names as xs:string*,
   $definitions as xs:string*,
   $sources as xs:string*,
   $action as xs:string?,
   $preferred as xs:string?,
   $conceptual_domain_id as xs:string?,
   $enum_datatype as xs:string?,
   $enum_uom as xs:string?,
   $char_quantity as xs:string?,
   $value_domain_format as xs:string?,
   $values as xs:string*
   ) {
   let $skip-name := substring-after($action,'delete naming entry')
   let $skip-name-index := if ($skip-name>'') then xs:int($skip-name) else 0
   return

                This form will allow you to edit a Value Domain in the metadata repository

                <form name="edit_value_domain" action="editValueDomain.xquery" method="post" class="cagridForm" enctype="multipart/form-data">

                {lib-forms:hidden-element('id',$id)}
                {lib-forms:hidden-element('updating','updating')}

                {lib-forms:edit-admin-item($reg-auth,
                     $administrative-note,
                     $administrative-status,
                     $administered-by,
                     $submitted-by,
                     $registered-by,
                     $context-ids,
                     $country-identifiers,
                     $language-identifiers,
                     $names,
                     $definitions,
                     $sources,
                     $preferred,
                     $action)}

                            Conceptual Domain

                        {
                        let $concept_domain := lib-util:mdrElement("conceptual_domain",$conceptual_domain_id)

                        return
                        if ($conceptual_domain_id > '' or $conceptual_domain_id eq "Cancel")
                        then (

                                Conceptual Domain ID
                                {$conceptual_domain_id}
                                {session:set-attribute("old_cd_id", $conceptual_domain_id)}
                                {lib-forms:popup-form-search('conceptual_domain','conceptual_domain_id','edit_value_domain', 'Change Relationship')}
                                {lib-forms:hidden-element('conceptual_domain_id',$conceptual_domain_id)}

,

                                Conceptual Domain Name
                                {administered-item:preferred-name('conceptual_domain',$conceptual_domain_id)}

,

Value Domain
,

                               Value Domain Data Type
                               {lib-forms:make-select-datatype('enum_datatype', $enum_datatype)}

,

                               Value Domain Unit of Measure
                               {lib-forms:make-select-uom('enum_uom',$enum_uom)}

,

                               Value Domain Format (E.g. MM-DD-YYYY)
                               <input type="text" name="value_domain_format" value='{$value_domain_format}'></input>

,

                               Value Domain Maximum Character Count
                               <input type="text" name="char_quantity" value='{$char_quantity}'></input>

,
                           if ($concept_domain//openMDR:value_meaning_description > '')
                           then
                           (

                                   Possible Values
                                   meaning
                                   value

,
                                        for $meaning at $pos in $concept_domain//openMDR:value_meaning_description
                                        return (

                                              Permissable Value {$pos}
                                              {$meaning}
                                              {lib-forms:input-element('values', 20, $values[$pos])}

                                        )
                           )
                           else ()
                    )
                    else (

                                    Choose Conceptual Domain
                                    {lib-forms:make-select-form-admin-item('conceptual_domain','conceptual_domain_id',$conceptual_domain_id,'edit_value_domain', 'Select Relationship')}

                   )
               }

Store

	<input type="submit" name="update" value="Store Changes"/>
                          <input type="submit"  name="update" value="Cancel"
                              onClick= "{concat("window.open('../web/value_domain.xquery?compound_id=", $id, "');")}" />

          </form>

{$message}

   };

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

                    Value Domain modified.

                Return to maintenance menu

                Create another Value Domain

};

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 $updating := request:get-parameter('updating','')
   let $title as xs:string := concat("Editing ValueDomain ", $id)
   let $element := lib-util:mdrElement("value_domain",$id)
   let $action := request:get-parameter('update','')

   let $ireg-auth := string($element/@item_registration_authority_identifier)
   let $iadministrative-note := string($element//openMDR:administrative_note)
   let $iadministrative-status := string($element//openMDR:administrative_status)
   let $iadministered-by := string($element//openMDR:administered_by)
   let $isubmitted-by := string($element//openMDR:submitted_by)
   let $iregistered-by := string($element//openMDR:registered_by)
   let $icontext-ids := $element//openMDR:context_identifier
   let $icountry-identifiers := $element//openMDR:country_identifier
   let $ilanguage-identifiers := $element//openMDR:language_identifier
   let $inames := $element//openMDR:name
   let $idefinitions := $element//openMDR:definition_text
   let $isources := $element//openMDR:definition_source_reference
   let $ipreferred := string(fn:index-of($element//openMDR:preferred_designation,'true'))

    let $iconceptual_domain_id := if($element//openMDR:representing/text() > '')
                                    then ($element//openMDR:representing/text()) else ("")
    let $iconceptual_domain := lib-util:mdrElement("conceptual_domain",$iconceptual_domain_id)
    let $ivalues := $element//openMDR:value_item
    let $ienum_datatype := $element//openMDR:value_domain_datatype
    let $ienum_uom := $element//openMDR:value_domain_unit_of_measure
    let $ichar_quantity := $element//openMDR:value_domain_maximum_character_quantity
    let $ivalue_domain_format := $element//openMDR:value_domain_format

    (:
    let $icontained_in_identifier := $element//openMDR:contained_in
    let $log := util:log-system-err($iconceptual_domain)
    let $log := util:log-system-err($ivalues)
    let $log := util:log-system-err($element//openMDR:contained_in)
    let $log := util:log-system-err($iconceptual_domain_id)
    let $log := util:log-system-err(value-meaning:value-meaning($element/openMDR:contained_in/text()/openMDR:value_meaning_description))
    let $log := util:log-system-err($element//openMDR:contained_in/text()/openMDR:value_meaning_description)
    let test := element//openMDR:contained_in/text())/openMDR:value_meaning_description
    for $meaning at $pos in $iconceptual_domain//openMDR:value_meaning_description
       let $log := util:log-system-err($meaning)
    :)

   let $reg-auth := request:get-parameter('registration-authority','')
   let $administrative-note := request:get-parameter('administrative-note','')
   let $administrative-status := request:get-parameter('administrative-status','')
   let $administered-by := request:get-parameter('administered-by','')
   let $submitted-by := request:get-parameter('submitted-by','')
   let $registered-by := request:get-parameter('registered-by','')
   let $context-ids := request:get-parameter('context-ids',())
   let $country-identifiers := request:get-parameter('country-identifiers',())
   let $language-identifiers := request:get-parameter('language-identifiers',())
   let $names := request:get-parameter('names',())
   let $definitions := request:get-parameter('definitions',())
   let $sources := request:get-parameter('sources',())
   let $preferred := request:get-parameter('preferred','')
   let $conceptual_domain_id := request:get-parameter('conceptual_domain_id','')
   let $values := request:get-parameter('values',())
   let $enum_datatype := request:get-parameter('enum_datatype','')
   let $enum_uom := request:get-parameter('enum_uom','')
   let $char_quantity := request:get-parameter('char_quantity','')
   let $value_domain_format := request:get-parameter('value_domain_format','')

   return
      lib-rendering:txfrm-webpage(
      $title,
      if ($action='Store Changes')
      then
         (
         if (
               local:value_domain
                  (
                     $id,
                     $reg-auth,
                     $administrative-note,
                     $administrative-status,
                     $administered-by,
                     $submitted-by,
                     $registered-by,
                     $context-ids,
                     $country-identifiers,
                     $language-identifiers,
                     $names,
                     $definitions,
                     $sources,
                     $preferred,
                     $conceptual_domain_id,
                     $enum_datatype,
                     $enum_uom,
                     $char_quantity,
                     $value_domain_format,
                     $values
                  )
            )
         then (local:success-page()  )
         else (local:input-page(
            'could not store document',
                     $id,
                     $reg-auth,
                     $administrative-note,
                     $administrative-status,
                     $administered-by,
                     $submitted-by,
                     $registered-by,
                     $context-ids,
                     $country-identifiers,
                     $language-identifiers,
                     $names,
                     $definitions,
                     $sources,
                     $action,
                     $preferred,
                     $conceptual_domain_id,
                     $enum_datatype,
                     $enum_uom,
                     $char_quantity,
                     $value_domain_format,
                     $values
                     )
               )
         )
       else if ($action='Change Relationship')
         then(
               let $conceptual_domain_id as xs:string? := ""

               return
               local:input-page
               (
               '',
               $id,
               $reg-auth,
               $administrative-note,
               $administrative-status,
               $administered-by,
               $submitted-by,
               $registered-by,
               $context-ids,
               $country-identifiers,
               $language-identifiers,
               $names,
               $definitions,
               $sources,
               $action,
               $preferred,
               $conceptual_domain_id,
               $enum_datatype,
               $enum_uom,
               $char_quantity,
               $value_domain_format,
               $values
               )
         )
         else if($conceptual_domain_id eq "Cancel")
         then(
               local:input-page
               (
               '',
               $id,
               $reg-auth,
               $administrative-note,
               $administrative-status,
               $administered-by,
               $submitted-by,
               $registered-by,
               $context-ids,
               $country-identifiers,
               $language-identifiers,
               $names,
               $definitions,
               $sources,
               $action,
               $preferred,
               session:get-attribute("old_cd_id"),
               $enum_datatype,
               $enum_uom,
               $char_quantity,
               $value_domain_format,
               $values
               ),
               session:set-attribute("old_cd_id", $iconceptual_domain_id)
        )
        else (
         if ($updating ='updating')
         then (

         local:input-page
               (
               '',
               $id,
               $reg-auth,
               $administrative-note,
               $administrative-status,
               $administered-by,
               $submitted-by,
               $registered-by,
               $context-ids,
               $country-identifiers,
               $language-identifiers,
               $names,
               $definitions,
               $sources,
               $action,
               $preferred,
               $conceptual_domain_id,
               $enum_datatype,
               $enum_uom,
               $char_quantity,
               $value_domain_format,
               $values
               )
         ) else (
               local:input-page
               (
               '',
               $id,
               $ireg-auth,
               $iadministrative-note,
               $iadministrative-status,
               $iadministered-by,
               $isubmitted-by,
               $iregistered-by,
               $icontext-ids,
               $icountry-identifiers,
               $ilanguage-identifiers,
               $inames,
               $idefinitions,
               $isources,
               $action,
               $ipreferred,
               $iconceptual_domain_id,
               $ienum_datatype,
               $ienum_uom,
               $ichar_quantity,
               $ivalue_domain_format,
               $ivalues
               )
         )
       )
    )


Handle a null "range-path-index" value

Handle a null "range-path-index" value

This is breaking the Harmonize Orders step in the tutorial.

xquery version "1.0-ml";

module namespace hent = "http://marklogic.com/data-hub/hub-entities";

import module namespace es-wrapper = "http://marklogic.com/data-hub/es-wrapper"
  at "/com.marklogic.hub/lib/entity-services-wrapper.xqy";

import module namespace search = "http://marklogic.com/appservices/search"
  at "/MarkLogic/appservices/search/search.xqy";

declare variable $ENTITY-MODEL-COLLECTION := "http://marklogic.com/entity-services/models";

declare option xdmp:mapping "false";

declare function hent:get-model($entity-name as xs:string)
{
  hent:get-model($entity-name, ())
};

declare function hent:get-model($entity-name as xs:string, $used-models as xs:string*)
{
  let $model := fn:collection($ENTITY-MODEL-COLLECTION)[info/title = $entity-name]
  where fn:exists($model)
  return
    let $model-map as map:map? := $model
    let $refs := $model//*[fn:local-name(.) = '$ref'][fn:starts-with(., "#/definitions")] ! fn:replace(., "#/definitions/", "")
    let $_ :=
      let $definitions := map:get($model-map, "definitions")
      for $ref in $refs[fn:not(. = $used-models)]
      let $other-model as map:map? := hent:get-model($ref, ($used-models, $entity-name))
      let $other-defs := map:get($other-model, "definitions")
      for $key in map:keys($other-defs)
      return
        map:put($definitions, $key, map:get($other-defs, $key))
    return
      $model-map
};

declare function hent:uber-model() as map:map
{
  hent:uber-model(fn:collection($ENTITY-MODEL-COLLECTION)/object-node())
};

declare function hent:uber-model($models as object-node()*) as map:map
{
  let $uber-model := map:map()
  let $definitions :=
    let $m := map:map()
    let $_ :=
      for $model as map:map in $models
      let $defs := map:get($model, "definitions")
      for $key in map:keys($defs)
      return
        map:put($m, $key, map:get($defs, $key))
    return
      map:put($uber-model, "definitions", $m)
  return
    $uber-model
};

declare function hent:wrap-duplicates(
    $duplicate-map as map:map,
    $property-name as xs:string,
    $item as element()
) as item()
{
    if (map:contains($duplicate-map, $property-name))
    then
        comment { "This item is a duplicate and is commented out so as to create a valid artifact.
",
            xdmp:quote($item),
            "
"
        }
    else (
        map:put($duplicate-map, $property-name, true()),
        $item)
};

(:
  this method doctors the output from ES
  because of https://github.com/marklogic/entity-services/issues/359
:)
declare %private function hent:fix-options($nodes as node()*)
{
  for $n in $nodes
  return
    typeswitch($n)
      case element() return
        element { fn:node-name($n) } { hent:fix-options(($n/@*, $n/node())) }
      case text() return
        fn:replace($n, "es:", "*:")
      default return $n
};

declare function hent:dump-search-options($entities as json:array)
{
  let $uber-model := hent:uber-model(json:array-values($entities) ! xdmp:to-json(.)/object-node())
  return
    (: call fix-options because of https://github.com/marklogic/entity-services/issues/359 :)
    hent:fix-options(es-wrapper:search-options-generate($uber-model))
};

declare function hent:dump-indexes($entities as json:array)
{
  let $uber-model := hent:uber-model(json:array-values($entities) ! xdmp:to-json(.)/object-node())
  let $o := xdmp:from-json(es-wrapper:database-properties-generate($uber-model))
  let $_ :=
    for $x in ("database-name", "schema-database", "triple-index", "collection-lexicon")
    return
      map:delete($o, $x)
  let $_ :=
    for $idx in map:get($o, "range-path-index") ! json:array-values(.)
    return
      map:put($idx, "path-expression", fn:replace(map:get($idx, "path-expression"), "es:", "*:"))
  return
    xdmp:to-json($o)
};

xquery version "1.0-ml";

module namespace hent = "http://marklogic.com/data-hub/hub-entities";

import module namespace es-wrapper = "http://marklogic.com/data-hub/es-wrapper"
  at "/com.marklogic.hub/lib/entity-services-wrapper.xqy";

import module namespace search = "http://marklogic.com/appservices/search"
  at "/MarkLogic/appservices/search/search.xqy";

declare variable $ENTITY-MODEL-COLLECTION := "http://marklogic.com/entity-services/models";

declare option xdmp:mapping "false";

declare function hent:get-model($entity-name as xs:string)
{
  hent:get-model($entity-name, ())
};

declare function hent:get-model($entity-name as xs:string, $used-models as xs:string*)
{
  let $model := fn:collection($ENTITY-MODEL-COLLECTION)[info/title = $entity-name]
  where fn:exists($model)
  return
    let $model-map as map:map? := $model
    let $refs := $model//*[fn:local-name(.) = '$ref'][fn:starts-with(., "#/definitions")] ! fn:replace(., "#/definitions/", "")
    let $_ :=
      let $definitions := map:get($model-map, "definitions")
      for $ref in $refs[fn:not(. = $used-models)]
      let $other-model as map:map? := hent:get-model($ref, ($used-models, $entity-name))
      let $other-defs := map:get($other-model, "definitions")
      for $key in map:keys($other-defs)
      return
        map:put($definitions, $key, map:get($other-defs, $key))
    return
      $model-map
};

declare function hent:uber-model() as map:map
{
  hent:uber-model(fn:collection($ENTITY-MODEL-COLLECTION)/object-node())
};

declare function hent:uber-model($models as object-node()*) as map:map
{
  let $uber-model := map:map()
  let $definitions :=
    let $m := map:map()
    let $_ :=
      for $model as map:map in $models
      let $defs := map:get($model, "definitions")
      for $key in map:keys($defs)
      return
        map:put($m, $key, map:get($defs, $key))
    return
      map:put($uber-model, "definitions", $m)
  return
    $uber-model
};

declare function hent:wrap-duplicates(
    $duplicate-map as map:map,
    $property-name as xs:string,
    $item as element()
) as item()
{
    if (map:contains($duplicate-map, $property-name))
    then
        comment { "This item is a duplicate and is commented out so as to create a valid artifact.
",
            xdmp:quote($item),
            "
"
        }
    else (
        map:put($duplicate-map, $property-name, true()),
        $item)
};

(:
  this method doctors the output from ES
  because of https://github.com/marklogic/entity-services/issues/359
:)
declare %private function hent:fix-options($nodes as node()*)
{
  for $n in $nodes
  return
    typeswitch($n)
      case element() return
        element { fn:node-name($n) } { hent:fix-options(($n/@*, $n/node())) }
      case text() return
        fn:replace($n, "es:", "*:")
      default return $n
};

declare function hent:dump-search-options($entities as json:array)
{
  let $uber-model := hent:uber-model(json:array-values($entities) ! xdmp:to-json(.)/object-node())
  return
    (: call fix-options because of https://github.com/marklogic/entity-services/issues/359 :)
    hent:fix-options(es-wrapper:search-options-generate($uber-model))
};

declare function hent:dump-indexes($entities as json:array)
{
  let $uber-model := hent:uber-model(json:array-values($entities) ! xdmp:to-json(.)/object-node())
  let $o := xdmp:from-json(es-wrapper:database-properties-generate($uber-model))
  let $_ :=
    for $x in ("database-name", "schema-database", "triple-index", "collection-lexicon")
    return
      map:delete($o, $x)
  let $_ :=
    for $idx in json:array-values(map:get($o, "range-path-index"))
    return
      map:put($idx, "path-expression", fn:replace(map:get($idx, "path-expression"), "es:", "*:"))
  return
    xdmp:to-json($o)
};


DHFPROD-3719: Improve performance checking for blocked merges

xquery version "1.0-ml";

(:
 : This is an implementation library, not an interface to the Smart Mastering functionality.
 :
 : Match blocks prevent automatic merges from happening. They can be created
 : manually and are automatically created when a merge gets rolled back.
 : Blocks are implemented here as managed RDF triples of the form:
 :   <uri1> $const:PRED-MATCH-BLOCK <uri2>
 : The reverse triple also gets stored:
 :   <uri2> $const:PRED-MATCH-BLOCK <uri1>
 :)

module namespace blocks-impl = "http://marklogic.com/smart-mastering/blocks-impl";

import module namespace const = "http://marklogic.com/smart-mastering/constants"
  at "/com.marklogic.smart-mastering/constants.xqy";
import module namespace sem = "http://marklogic.com/semantics"
  at "/MarkLogic/semantics.xqy";

declare option xdmp:mapping "false";

(:
 : Return a JSON array of any URIs the that input URI is blocked from matching.
 : @param $uri  input URI
 : @return JSON array of URIs
 :)
declare function blocks-impl:get-blocks($uri as xs:string?)
  as array-node()
{
  array-node {
    if (fn:exists($uri)) then
      if (map:contains($cached-blocks-by-uri, $uri)) then
        map:get($cached-blocks-by-uri, $uri)[. ne ""]
      else
        blocks-impl:get-blocks-of-uris($uri)
    else ()
  }
};

declare variable $cached-blocks-by-uri as map:map := map:map();

declare function blocks-impl:get-values(
  $map as map:map,
  $key as xs:string
)
{
  let $values := map:get($map, $key)
  return
    if (fn:exists($values))
    then $values
    else let $n :=  map:map()
    return (map:put($map, $key, $n), $n)
};

declare function blocks-impl:get-blocks-of-uris($uris as xs:string*)
as xs:string*{
  if (fn:exists($uris)) then (
    let $iris := $uris ! sem:iri(.)
    let $elapsed := xdmp:elapsed-time()
    let $solution :=
      sem:sparql(
        "select distinct ?targetURI (?uri as ?blocked) where {
            {
              ?uri ?isBlocked ?target.
              ?target ?isBlocked ?targetURI.
            } UNION {
              ?target ?isBlocked ?uri.
              ?uri ?isBlocked ?targetURI.
            }
            FILTER (?uri != ?targetURI)
          }",
        map:new((
          map:entry("target", $iris),
          map:entry("isBlocked", $const:PRED-MATCH-BLOCK)
        )),
        ("map","optimize=0"),
        cts:triple-range-query((),(), $iris, "=")
      )

    let $elapsed := xs:integer((xdmp:elapsed-time() - $elapsed) div xs:dayTimeDuration("PT0.001S"))
    let $_ := if (xdmp:trace-enabled($const:TRACE-MATCH-RESULTS)) then
                xdmp:trace($const:TRACE-MATCH-RESULTS, "get-blocks-of-uris," || xdmp:request() || ",sparql," || $elapsed ||  ",uris," || fn:string-join($uris, ";"))
              else ()
    let $elapsed := xdmp:elapsed-time()
    let $tmp := map:map()
    let $values :=
      for $triple in $solution
      let $value := fn:string(map:get($triple, "blocked"))
      let $target := fn:string(map:get($triple, "targetURI"))
      let $current-for-target := blocks-impl:get-values ($tmp, $target)
      let $current-for-value := blocks-impl:get-values($tmp, $value)
      return
        (
          map:put($current-for-target,$value, fn:true()),
          map:put($current-for-value,$target, fn:true()),
          $value
        )
    let $_ := for $k in map:keys($tmp)
    return map:put($cached-blocks-by-uri, $k,
      fn:distinct-values((map:get($cached-blocks-by-uri, $k), map:keys(map:get($tmp, $k))))  )
    let $_populate-empty :=
      for $uri in $uris
      where fn:not(map:contains($cached-blocks-by-uri, $uri))
      return
        map:put($cached-blocks-by-uri, $uri, "")
    let $elapsed := xs:integer((xdmp:elapsed-time() - $elapsed) div xs:dayTimeDuration("PT0.001S"))
    let $_ := if (xdmp:trace-enabled($const:TRACE-MATCH-RESULTS)) then
                xdmp:trace($const:TRACE-MATCH-RESULTS, "get-blocks-of-uris," || xdmp:request() || ",map," || $elapsed)
              else ()
    return fn:distinct-values($values)
  ) else ()
};

(:
 : Block all pairs of URIs from matching. This function will start with URI #1
 : and call matcher:block-match with it each of the remaining URIs. It then
 : recurses on the tail, repeating the process of blocking URI #2 from matching
 : with the remaining URIs (3, 4). This stops when there are zero or one URIs
 : remaining.
 : No return type specified to allow tail call optimization.
 :
 : @param uris the sequence of URIs
 : @return empty sequence
 :)
declare function blocks-impl:block-matches($uris as xs:string*)
{
  if (fn:empty($uris) or fn:count($uris) = 1) then
  (: We're done :)
    ()
  else
    let $tail := fn:tail($uris)
    let $_ := $tail ! blocks-impl:block-match(fn:head($uris), .)
    return blocks-impl:block-matches($tail)
};

(:
 : Prevent the two input URIs from being allowed to match. Helper function for block-matches.
 :
 : @param $uri1  First input URI
 : @param $uri2  Second input URI
 : @error will throw xs:QName("SM-CANT-BLOCK") if unable to record the block.
 : @return empty sequence
 :)
declare function blocks-impl:block-match($uri1 as xs:string, $uri2 as xs:string)
as empty-sequence()
{
  let $_ :=
    (: Suppress sem:rdf-insert's return value :)
    sem:rdf-insert(
      (
        sem:triple(sem:iri($uri1), $const:PRED-MATCH-BLOCK, sem:iri($uri2)),
        sem:triple(sem:iri($uri2), $const:PRED-MATCH-BLOCK, sem:iri($uri1))
      )
    )
  return ()
};

(:
 : Clear a match block between the two input URIs.
 :
 : @param $uri1  First input URI
 : @param $uri2  Second input URI
 :
 : @error will throw xs:QName("SM-CANT-UNBLOCK") if a block is present, but it cannot be cleared
 : @return  fn:true if a block was found and cleared; fn:false if no block was found
 :)
declare function blocks-impl:allow-match($uri1 as xs:string, $uri2 as xs:string)
{
  let $nodes := sem:database-nodes((
    cts:triples(sem:iri($uri1), $const:PRED-MATCH-BLOCK, sem:iri($uri2)),
    cts:triples(sem:iri($uri2), $const:PRED-MATCH-BLOCK, sem:iri($uri1))
  ))
  return (
    $nodes ! xdmp:node-delete(.),
    fn:exists($nodes)
  )
};

xquery version "1.0-ml";

(:
 : This is an implementation library, not an interface to the Smart Mastering functionality.
 :
 : Match blocks prevent automatic merges from happening. They can be created
 : manually and are automatically created when a merge gets rolled back.
 : Blocks are implemented here as managed RDF triples of the form:
 :   <uri1> $const:PRED-MATCH-BLOCK <uri2>
 : The reverse triple also gets stored:
 :   <uri2> $const:PRED-MATCH-BLOCK <uri1>
 :)

module namespace blocks-impl = "http://marklogic.com/smart-mastering/blocks-impl";

import module namespace const = "http://marklogic.com/smart-mastering/constants"
  at "/com.marklogic.smart-mastering/constants.xqy";
import module namespace sem = "http://marklogic.com/semantics"
  at "/MarkLogic/semantics.xqy";

declare option xdmp:mapping "false";

(:
 : Return a JSON array of any URIs the that input URI is blocked from matching.
 : @param $uri  input URI
 : @return JSON array of URIs
 :)
declare function blocks-impl:get-blocks($uri as xs:string?)
  as array-node()
{
  array-node {
    if (fn:exists($uri)) then
      if (map:contains($cached-blocks-by-uri, $uri)) then
        map:get($cached-blocks-by-uri, $uri)[. ne ""]
      else
        blocks-impl:get-blocks-of-uris($uri)
    else ()
  }
};

declare variable $cached-blocks-by-uri as map:map := map:map();

declare function blocks-impl:get-blocks-of-uris($uris as xs:string*)
  as xs:string*
{
    if (fn:exists($uris)) then (
      let $iris := $uris ! sem:iri(.)
      let $solution :=
        sem:sparql(
          "select distinct ?targetURI (?uri as ?blocked) where {
            {
              ?uri ?isBlocked ?target.
              ?target ?isBlocked ?targetURI.
            } UNION {
              ?target ?isBlocked ?uri.
              ?uri ?isBlocked ?targetURI.
            }
            FILTER (?uri != ?targetURI)
          }",
          map:new((
            map:entry("target", $iris),
            map:entry("isBlocked", $const:PRED-MATCH-BLOCK)
          )),
          ("map","optimize=0"),
          cts:triple-range-query((),(), $iris, "=")
        )
      let $values :=
        fn:distinct-values(
          for $triple in $solution
          let $value := fn:string(map:get($triple, "blocked"))
          let $target := fn:string(map:get($triple, "targetURI"))
          let $current-for-target := map:get($cached-blocks-by-uri, $target)
          let $current-for-value := map:get($cached-blocks-by-uri, $value)
          return
            (
              map:put($cached-blocks-by-uri, $target, fn:distinct-values(($current-for-target,$value))),
              map:put($cached-blocks-by-uri, $value, fn:distinct-values(($current-for-value,$target))),
              $value
            )
        )
      let $_populate-empty :=
        for $uri in $uris
        where fn:not(map:contains($cached-blocks-by-uri, $uri))
        return
          map:put($cached-blocks-by-uri, $uri, "")
      return $values
    ) else ()
};

(:
 : Block all pairs of URIs from matching. This function will start with URI #1
 : and call matcher:block-match with it each of the remaining URIs. It then
 : recurses on the tail, repeating the process of blocking URI #2 from matching
 : with the remaining URIs (3, 4). This stops when there are zero or one URIs
 : remaining.
 : No return type specified to allow tail call optimization.
 :
 : @param uris the sequence of URIs
 : @return empty sequence
 :)
declare function blocks-impl:block-matches($uris as xs:string*)
{
  if (fn:empty($uris) or fn:count($uris) = 1) then
  (: We're done :)
    ()
  else
    let $tail := fn:tail($uris)
    let $_ := $tail ! blocks-impl:block-match(fn:head($uris), .)
    return blocks-impl:block-matches($tail)
};

(:
 : Prevent the two input URIs from being allowed to match. Helper function for block-matches.
 :
 : @param $uri1  First input URI
 : @param $uri2  Second input URI
 : @error will throw xs:QName("SM-CANT-BLOCK") if unable to record the block.
 : @return empty sequence
 :)
declare function blocks-impl:block-match($uri1 as xs:string, $uri2 as xs:string)
as empty-sequence()
{
  let $_ :=
    (: Suppress sem:rdf-insert's return value :)
    sem:rdf-insert(
      (
        sem:triple(sem:iri($uri1), $const:PRED-MATCH-BLOCK, sem:iri($uri2)),
        sem:triple(sem:iri($uri2), $const:PRED-MATCH-BLOCK, sem:iri($uri1))
      )
    )
  return ()
};

(:
 : Clear a match block between the two input URIs.
 :
 : @param $uri1  First input URI
 : @param $uri2  Second input URI
 :
 : @error will throw xs:QName("SM-CANT-UNBLOCK") if a block is present, but it cannot be cleared
 : @return  fn:true if a block was found and cleared; fn:false if no block was found
 :)
declare function blocks-impl:allow-match($uri1 as xs:string, $uri2 as xs:string)
{
  let $nodes := sem:database-nodes((
    cts:triples(sem:iri($uri1), $const:PRED-MATCH-BLOCK, sem:iri($uri2)),
    cts:triples(sem:iri($uri2), $const:PRED-MATCH-BLOCK, sem:iri($uri1))
  ))
  return (
    $nodes ! xdmp:node-delete(.),
    fn:exists($nodes)
  )
};


removed more old data

removed more old data

<?xml version="1.0" encoding="UTF-8"?>
<docs>
    <doc>
        <id>berlin-ms-germ-qrt-1666</id>
        <title>Vorlesungsmitschrift 1775 (Berlin)</title>
        <titleShort>V 1775 (Berlin)</titleShort>
        <preview>http://134.76.21.92:8080/images/berlin-ms-germ-qrt-1666/500/00000001.jpeg</preview>
        <tei>/db/archaeo18/data/tei/berlin-ms-germ-qrt-1666.xml</tei>
        <teiEnriched>/db/archaeo18/data/tei-enriched/berlin-ms-germ-qrt-1666-enriched.xml</teiEnriched>
        <mets>/db/archaeo18/data/mets/berlin-ms-germ-qrt-1666.mets.xml</mets>
        <pageCount>311</pageCount>
    </doc>
    <doc>
        <id>bern-mss-muel-507</id>
        <title>Vorlesungsmitschrift 1780 (Bern)</title>
        <titleShort>Vorlesung 1780</titleShort>
        <preview>http://134.76.21.92:8080/images/bern-mss-muel-507/500/00000001.jpeg</preview>
        <tei>/db/archaeo18/data/tei/bern-mss-muel-507.xml</tei>
        <teiEnriched>/db/archaeo18/data/tei-enriched/bern-mss-muel-507-enriched.xml</teiEnriched>
        <mets>/db/archaeo18/data/mets/bern-mss-muel-507.mets.xml</mets>
        <pageCount>631</pageCount>
    </doc>
    <doc>
        <id>rom-heyne1798</id>
        <title>Vorlesungsmitschrift 1798 (Rom)</title>
        <titleShort>V 1798 (Rom)</titleShort>
        <preview>http://134.76.21.92:8080/images/rom-heyne1798/500/00000001.jpeg</preview>
        <tei>/db/archaeo18/data/tei/rom-heyne1798.xml</tei>
        <teiEnriched>/db/archaeo18/data/tei-enriched/rom-heyne1798-enriched.xml</teiEnriched>
        <mets>/db/archaeo18/data/mets/rom-heyne1798.mets.xml</mets>
        <pageCount>269</pageCount>
    </doc>
    <doc>
        <id>weimar-hs-2056</id>
        <title>Vorlesungsmitschrift 1772 (Weimar)</title>
        <titleShort>Vorlesung 1772</titleShort>
        <preview>http://134.76.21.92:8080/images/weimar-hs-2056/500/00000001.jpeg</preview>
        <tei>/db/archaeo18/data/tei/weimar-hs-2056.xml</tei>
        <teiEnriched>/db/archaeo18/data/tei-enriched/weimar-hs-2056-enriched.xml</teiEnriched>
        <mets>/db/archaeo18/data/mets/weimar-hs-2056.mets.xml</mets>
        <pageCount>492</pageCount>
    </doc>
</docs>