xquery version "3.0";
(:
    ART-DECOR® STANDARD COPYRIGHT AND LICENSE NOTE
    Copyright © ART-DECOR Expert Group and ART-DECOR Open Tools GmbH
    see https://docs.art-decor.org/copyright and https://docs.art-decor.org/licenses

    This file is part of the ART-DECOR® tools suite.
:)

(: 
Function to create 'Registration' transaction for a dataset.
Meant to be run manually from eXist (eXide / Oxygen)
Set $doc and $datasetId manually before running.

Makes 'registration' transaction taking lowest min and highest maximumMultiplicity for all concepts in dataset, 
looking in all transactions fot that dataset.

Insert scenario 'Registration' if none exists, else updates the existing one.

Works (and is intended) for peri20
:)
import module namespace get             = "http://art-decor.org/ns/art-decor-settings" at "art-decor-settings.xqm";
import module namespace art             = "http://art-decor.org/ns/art" at "art-decor.xqm";
import module namespace decor           = "http://art-decor.org/ns/decor" at "../api/api-decor.xqm";

let $projectPrefix              := if (request:exists()) then request:get-parameter('prefix', ())[string-length() gt 0 ] else ('peri20-')
let $datasetId                  := if (request:exists()) then request:get-parameter('datasetId', ()) else ('2.16.840.1.113883.2.4.3.11.60.90.77.1.6')
let $datasetEff                 := if (request:exists()) then request:get-parameter('datasetEffectiveDate', ()) else ()

let $decor                      := if (empty($projectPrefix)) then () else art:getDecorByPrefix($projectPrefix)

let $defaultBaseIdSC            := decor:getDefaultBaseIdsP($decor, $decor:OBJECTTYPE-SCENARIO)/@id
let $defaultBaseIdTR            := decor:getDefaultBaseIdsP($decor, $decor:OBJECTTYPE-TRANSACTION)/@id

let $lastScenario               := decor:getNextAvailableIdP($decor, $decor:OBJECTTYPE-SCENARIO, $defaultBaseIdSC)
let $lastTransaction            := decor:getNextAvailableIdP($decor, $decor:OBJECTTYPE-TRANSACTION, $defaultBaseIdTR)

let $dataset                    := art:getDataset($datasetId, $datasetEff)
let $existingTransactions       := art:getTransactionsByDataset($dataset/@id, $dataset/@effectiveDate)
let $registrationTransaction    := $existingTransactions[ancestor::scenario/name = 'Registratie']
let $otherTransactions          := $existingTransactions[not(ancestor::scenario/name = 'Registratie')]

let $now                        := substring(string(current-dateTime()), 1, 19)
let $registratie :=
    <transaction>
    {
        if ($registrationTransaction) then (
            $registrationTransaction/@id,
            $registrationTransaction/@effectiveDate,
            $registrationTransaction/@statusCode,
            $registrationTransaction/@type
        ) else (
            (: transaction group will get the first next id compared to the current project, so stationary transaction should be one higher than that :)
            attribute id {concat($lastTransaction/@base, '.', $lastTransaction/@next + 1)},
            attribute effectiveDate {substring(xs:string(fn:current-dateTime()), 1, 19)},
            attribute statusCode {$dataset/@statusCode},
            attribute type {'stationary'}
        ),
        $registrationTransaction/(@* except (@id | @effectiveDate | @type | @statusCode | @lastModifiedDate)),
        attribute lastModifiedDate {$now}
    }
        <name language="nl-NL">Registratie</name>
        <name language="en-US">Registration</name>
        <actors>{$registrationTransaction/actors/actor}</actors>
        <representingTemplate sourceDataset="{$dataset/@id}" sourceDatasetFlexibility="{$dataset/@effectiveDate}">
        {
            $registrationTransaction/@ref, $registrationTransaction/@flexibility
            $registrationTransaction/@representingQuestionnaire, $registrationTransaction/@representingQuestionnaireFlexibility
        }
        {
            for $concept in $dataset//concept[not(ancestor::conceptList)][not(ancestor::history)][@statusCode=('new', 'draft', 'final', 'pending')]
            let $matches       := $otherTransactions//concept[@ref = $concept/@id]
            let $minmin         := 
                if ($matches//@minimumMultiplicity = '0') then '0' else 
                if ($matches//@minimumMultiplicity = '1') then '1' else '?'
            let $maxmax         := 
                if ($matches//@maximumMultiplicity = '*') then '*' else 
                if ($matches//@maximumMultiplicity) then max($matches//xs:integer(@maximumMultiplicity)) else '?'
            return (
                comment {$concept/name[1]}
                ,
                <concept ref="{$concept/@id}" flexibility="{$concept/@effectiveDate}" minimumMultiplicity="{$minmin}" maximumMultiplicity="{$maxmax}"/>
            )
        }
        </representingTemplate>
    </transaction>
let $scenario := 
    <scenario id="{$lastScenario/@id}" effectiveDate="{substring(string(current-dateTime()), 1, 19)}" statusCode="{$dataset/@statusCode}">
    {
        $registrationTransaction/ancestor::scenario/(@* except (@id | @effectiveDate | @statusCode | @lastModifiedDate)),
        attribute lastModifiedDate {$now}
    }
        <name language="nl-NL">Registratie</name>
        <name language="en-US">Registration</name>
        <transaction id="{$lastTransaction/@id}" effectiveDate="{substring(xs:string(fn:current-dateTime()), 1, 19)}" statusCode="{$dataset/@statusCode}" type="group" lastModifiedDate="{$now}">
            <name language="nl-NL">Registratie</name>
            <name language="en-US">Registration</name>
            {$registratie}
        </transaction>
    </scenario>

let $update := 
    if ($registrationTransaction)
    then update replace $registrationTransaction with $registratie
    else update insert $scenario into $decor//scenarios
    
return $scenario
