teacup/jobs.xqm

2022 lines
94 KiB
Plaintext

(:~
: Job Library.
:
: @author Rave Technologies, https://www.rave-tech.com/, 2017
:)
module namespace JOBS = 'http://www.rave-tech.com/bloomsbury/jobs';
import module namespace config = 'http://www.rave-tech.com/bloomsbury/config' at './module/config.xqm';
import module namespace contents = 'http://www.rave-tech.com/bloomsbury/contents' at 'content.xqm';
import module namespace report = 'http://www.rave-tech.com/bloomsbury/report' at 'report.xqm';
import module namespace blcommon = 'http://www.rave-tech.com/bloomsbury/common' at 'common.xqm';
import module namespace audit = 'http://www.rave-tech.com/bloomsbury/audit' at './module/manage-audit.xqm';
declare namespace product = 'http://cms.bloomsbury.com/product-manifest';
declare namespace pipeline = 'http://cms.bloomsbury.com/pipeline';
(:~
: Add Job into the system.
: Ingest job
:----------------------------------
: @param $body Parameters to ingest content into the system <job><ingest><area>Professional</area><ctype>looseleaf</ctype><ignore-validation>true</ignore-validation><mail>true</mail><path>D:\Backup\Projects\bloomsbury\SharedData\Steve\word2xml\small66.zip</path></ingest></job>
: <job><publish><product>vat-construction-land-property</product><ignore-validation>true</ignore-validation><mail>true</mail></publish></job>
: @header $authorization Authorization key
: @return element(result)
:
: Checkin job
:----------------------------------
: @param $body Parameters to lock content into the system <job><checkin><role>Admin</role><uri></uri><uri></uri><upload-path></upload-path><ignore-validation>true</ignore-validation><mail>true</mail><comment></comment></checkin></job>
: <role> = Role of the user. Admin user can check-in another user check out files.
: <uri> = The uri of the files which has been selected to check-in (db uri), separated by '|', no space should present while joining by '|'
: <upload-path> = Selected content to upload (zip,word,xml)
: <ignore-validation> = program will ignore validation or not
: <mail> = mail indicator to send mail after check-in
: <comment> = check-in comment of the user
:
: Publish job
:----------------------------------
: @param $body Parameters to lock content into the system <job><publish>id of the product</publish></job>
:)
declare
%updating
%rest:path("/jobs")
%rest:POST("{$body}")
%rest:header-param("Authorization", "{$authorization}", "none")
%rest:consumes("application/xml", "text/xml")
function JOBS:create(
$body as document-node(),
$authorization as xs:string
)
{
config:session-check($authorization),
try{
if(file:exists(fn:replace($body/job/*/path/text(),'\\','/')))
then
(: Ingest Job :)
if($body/job/ingest/type='bulk' and $body/job/ingest)
then
(:let $contentPath := fn:replace($body/job/ingest/path/text(),'\\','/')
let $archive := file:read-binary($contentPath)
for $entry in archive:entries($archive)[fn:ends-with(., '.xml')]
let $rootNode := fn:name(fn:parse-xml(archive:extract-text($archive, $entry))/*)
(:let $files := fn:parse-xml(archive:extract-text($archive, $entry))/*/@xml:id/string():)
let $files := fn:parse-xml(archive:extract-text($archive, $entry))/*/@xml:id/string()[$rootNode='TEI']
return:)
JOBS:ingest-job($body,$authorization)
else
if($body/job/ingest and not($body/type))
then JOBS:ingest-job($body,$authorization)
else
(: Check-in Job :)
if($body/job/checkin)
then JOBS:checkin-job($body,$authorization)
else
(: Publish Job :)
if($body/job/publish)
then JOBS:publish-job($body,$authorization)
else update:output(<result><status>Failure</status><message>Currently system supports job type 'ingest', 'check-in' only.</message></result>)
else update:output(<result><status>Failure</status><message>Uploaded file is unavailable.</message></result>)
}
catch *
{
admin:write-log("[Job Create][Error: " || $err:description || "]"),
admin:write-log("[Job Create][Error: " || $err:additional || "]"),
update:output(<result><status>Error</status><message>Error generated. Please check system log</message></result>)
}
};
(:~
: To get information of a specific job
: @param $jobID ID of the job
: @header $authorization Authorization key
: @return element(result)
:)
declare
%rest:path("/job")
%rest:GET
%rest:query-param("jobid", "{$jobID}")
%rest:query-param("supress", "{$supress}")
%rest:header-param("Authorization", "{$authorization}", "none")
function JOBS:info(
$jobID as xs:string?,
$supress as xs:string?,
$authorization as xs:string
)
{
config:session-check($authorization),
try
{
let $jobDoc := db:open($config:CoreDatabase,fn:concat($config:JobDir,$jobID,'.xml'))
return
if($jobDoc)
then
if($jobDoc/job/job-info/job-type='Publish')
then
let $id := $jobDoc/job/job-info/id
let $productid := $jobDoc/job/job-info/product-id
let $producname := $jobDoc/job/job-info/product-name
let $pipelineid := $jobDoc/job/job-info/pipeline-id
let $pipelinename := $jobDoc/job/job-info/pipeline-name
let $taxonomyid := $jobDoc/job/job-info/taxonomy-id
let $taxonomyname := $jobDoc/job/job-info/taxonomy-name
let $jobtype := $jobDoc/job/job-info/job-type
let $submittedon := $jobDoc/job/job-info/submitted-on
let $ignorevalidation := $jobDoc/job/job-info/ignore-validation
let $mailrequired := $jobDoc/job/job-info/mail-required
let $requesterid := $jobDoc/job/job-info/requester-id
let $requesteremail := $jobDoc/job/job-info/requester-email
let $location := $jobDoc/job/job-info/location
let $status := $jobDoc/job/ingestion-report/status
let $finished-on := $jobDoc/job/ingestion-report/finished-on
return <result>
<status>Success</status>
<job><job-info>
{
$id,
$productid,
$producname,
$pipelineid,
$pipelinename,
$taxonomyid,
$taxonomyname,
$jobtype,
$submittedon,
$ignorevalidation,
$mailrequired,
$requesterid,
$requesteremail,
$location
}
</job-info>
<ingestion-report><steps></steps>{$status,$finished-on}</ingestion-report>
</job>
</result>
else
(:<result><status>Success</status>{$jobDoc}</result>:)
if($supress='yes')
then
let $SkipErrorStep := <job>{$jobDoc/job/job-info}
<ingestion-report>
<steps>
{
for $steps in $jobDoc/job/ingestion-report/steps/step[*:errors!='']
return
<step>
{
$steps/type,
$steps[contains(type,'schema-validation :')]/*:errors,
if($steps[contains(type,'schematron-validation :')]) then
<error>
{
<report>{
$steps/*:errors[.!='']/message[not(
contains(.,'warn:')
or contains(.,'info:')
)
]
}
</report>
}</error>
else()
}
</step>
}
</steps>
</ingestion-report>
</job>
return
<result><status>Success</status>{$SkipErrorStep}</result>
else
<result><status>Success</status>{$jobDoc}</result>
else
<result><status>Failure</status><message>Job information is not available</message></result>
}
catch *
{
admin:write-log("[Job Details][Error: " || $err:description || "]"),
admin:write-log("[Job Details][Error: " || $err:additional || "]"),
<result><status>Error</status><message>Error generated. Please check system log</message></result>
}
};
(:~
: To Download publish report
: @param $jobID ID of the job
: @header $authorization Authorization key
: @return element(result)
:)
declare
%rest:path("/publishreport/{$jobID=.+}")
%rest:GET
%rest:header-param("Authorization", "{$authorization}", "none")
function JOBS:publishjobreport(
$jobID as xs:string?,
$authorization as xs:string
)
{
config:session-check($authorization),
try
{
let $jobDoc := db:open($config:CoreDatabase,fn:concat($config:JobDir,$jobID,'.xml'))
return
if($jobDoc)
then
let $joburi := base-uri($jobDoc)
let $filename := fn:tokenize($joburi,'/')[fn:last()]
return
(
if(file:is-dir($config:PublishReportDir))
then
file:write(fn:concat($config:PublishReportDir,$filename),$jobDoc)
else
(
file:create-dir($config:PublishReportDir),
file:write(fn:concat($config:PublishReportDir,$filename),$jobDoc))
,
let $zipName := fn:concat($jobID,'_',fn:format-dateTime(fn:current-dateTime(), "[Y1,4][M01][D01][H01][m01][s01][f01]"))
let $filelist := file:list($config:PublishReportDir, true(),fn:concat($jobID,'.xml'))
let $archive := archive:create($filelist ! element archive:entry { . }, $filelist ! file:read-binary($config:PublishReportDir || .))
(:let $archive := archive:create-from($config:PublishReportDir):)
let $ziplocation := fn:concat($config:OutDir,$zipName,'.zip')
return
(
file:write-binary(fn:concat($config:OutDir,$zipName,'.zip'),$archive),
<result>
<status>Success</status>
<path>{$ziplocation}</path>
</result>
)
)
else <result><status>Failure</status><message>Job information is not available</message></result>
}
catch *
{
admin:write-log("[Job Details][Error: " || $err:description || "]"),
admin:write-log("[Job Details][Error: " || $err:additional || "]"),
<result><status>Error</status><message>Error generated. Please check system log</message></result>
}
};
(:~
: To get all available user or search users by user name.
: @param $user Email of the user to get user specific jobs
: @param $type Job type (Ingest/Publish)
: @param $status Job status (Success/Failure/In Progress)
: @param $page integer Page number of the list optional
: @param $size integer Total number of records to diplay in a page optional
: @header $authorization Authorization key
: @return element(result)
:)
declare
%rest:path("/jobs")
%rest:GET
%rest:query-param("query", "{$query}","")
%rest:query-param("user", "{$user}","")
%rest:query-param("allrecords", "{$allrecords}","")
%rest:query-param("type", "{$type}","")
%rest:query-param("status", "{$status}","")
%rest:query-param("orderby", "{$orderby}","")
%rest:query-param("page", "{$page}")
%rest:query-param("size", "{$size}")
%rest:header-param("Authorization", "{$authorization}", "none")
function JOBS:list(
$query as xs:string?,
$user as xs:string?,
$allrecords as xs:string?,
$type as xs:string,
$status as xs:string,
$orderby as xs:string,
$page as xs:integer?,
$size as xs:integer?,
$authorization as xs:string
)
{
config:session-check($authorization),
try
{
let $page := if($page) then $page else $config:page
let $size := if($size) then $size else $config:size
let $jobRecords := <jobs>{
for $eachJob in db:open($config:CoreDatabase,$config:JobDir)/job[if($type='Publish') then job-info/job-type='Publish' else .]
[if($type!='Publish') then job-info/job-type!='Publish' else .]
(:[if($user) then job-info/requester-id=$user else .]:)
[if($user and $allrecords='true') then (db:open($config:CoreDatabase,$config:UserDir)/user[role='admin'][id=$user]) else job-info/requester-id=$user]
(:[if($query!='') then fn:matches(job-info/requester-name,$query,'i') else .]:)
[if($query!='') then let $requesterid := job-info/requester-id/string() return fn:matches((fn:collection(fn:concat('bloomsbury/user/',$requesterid,'.xml'))/user/name/string()),$query,'i' ) else .]
[if($status) then fn:starts-with(ingestion-report/status,$status) else .]
let $name := if($type!='Publish') then <upload-file>{fn:tokenize(data($eachJob/job-info/uploaded-file),'/')[fn:last()]}</upload-file> else <product-name>{$eachJob/job-info/product-name/string()}</product-name>
let $requester-email := $eachJob/job-info/requester-email
let $requester-id := $eachJob/job-info/requester-id
let $id := $eachJob/job-info/id
let $date := $eachJob/job-info/submitted-on
let $type := $eachJob/job-info/job-type
let $username := <user>{distinct-values(db:open($config:CoreDatabase,$config:UserDir)/user[id=$requester-id][fn:not(fn:matches(fn:base-uri(.),'(/version/|/audit/)'))]/name/string())}</user>
let $status := $eachJob/ingestion-report/status
let $filename := fn:tokenize($eachJob/job-info/uploaded-file,'/')[fn:last()]
order by
if ($orderby='dateasc') then xs:dateTime($date) else (),
if ($orderby='datedsc') then xs:dateTime($date) else () descending,
if ($orderby='userasc') then ($username) else (),
if ($orderby='userdsc') then ($username) else () descending,
if ($orderby='filenameasc') then ($filename) else (),
if ($orderby='filenamedsc') then ($filename) else () descending,
if ($orderby='productasc') then ($name) else (),
if ($orderby='productdsc') then ($name) else () descending
return <job>{$id,$name,$date,$type,$username,$status,$requester-email,$requester-id}</job>
}</jobs>
let $countRecord := count($jobRecords/job)
let $start := if($page eq 1)
then $page
else if($page gt 1)
then fn:sum(($page * $size)+1) - $size
else fn:sum(($page * $size)) - $size
let $end := if($page eq 1)
then $size
else if($page gt 1)
then fn:sum(($start + $size)-1)
else fn:sum($start + $size)
return
if($jobRecords/job)
then
(
<result><status>Success</status><total>{$countRecord}</total><entities>{$jobRecords/job[position() = $start to $end]}</entities></result>,
config:non-update-message("[Job List][Job list has been sent successfully]")
)
else
(
<result><status>Failure</status><message>Job information is unavailable</message></result>,
config:non-update-message("[Job List][Job list is unavailable]")
)
}
catch *
{
admin:write-log("[Job List][Error: " || $err:description || "]"),
admin:write-log("[Job List][Error: " || $err:additional || "]"),
<result><status>Error</status><message>Error generated. Please check system log</message></result>
}
};
(:~
: To ingest a content
: @param $body <job><ingest><area>Professional</area><ctype>looseleaf</ctype><ignore-validation>true</ignore-validation><mail>true</mail><path>D:\Backup\Projects\bloomsbury\SharedData\Steve\word2xml\small66.zip</path></ingest></job>
: @header $authorization Authorization key
: @return element(result)
:)
declare %private %updating function JOBS:ingest-job(
$body as document-node(),
$authorization as xs:string
)
{
let $area := $body/job/ingest/area/text()
let $ctype := $body/job/ingest/ctype/text()
let $ignoreValidation := $body/job/ingest/ignore-validation/text()
let $sendMail := $body/job/ingest/mail/text()
let $contentPath := fn:replace($body/job/ingest/path/text(),'\\','/')
let $sessionValue := config:session-value($authorization)
let $UploadFileName := fn:tokenize($contentPath,'\\')[fn:last()]
let $jobID := fn:concat($config:JobIDPrefix,fn:string(fn:format-dateTime(fn:current-dateTime(), '[Y0001][M01][D01][H01][m01][s01][f01]')))
return
<results>
{
if(fn:ends-with(fn:lower-case($UploadFileName),'.zip'))
then
if(file:exists($UploadFileName))
then
if($ctype='looseleaf')
then
(: Check header.xml existence. Raise error if not available.:)
if(archive:entries(file:read-binary($contentPath))[fn:contains(.,$config:HeaderXml)])
then
let $cid := try
{
let $archive := file:read-binary($contentPath)
let $entry := archive:entries($archive)[fn:ends-with(., $config:HeaderXml)]
return fn:parse-xml(archive:extract-text($archive, $entry))/*/@xml:id/string()
}
catch *
{
let $archive := file:read-binary($contentPath)
let $entry := archive:entries($archive)[fn:ends-with(.,$config:HeaderXml)]
let $xml:= archive:extract-text($archive, $entry)
return fn:substring-before(fn:substring-after($xml,'xml:id="'),'"')
}
return
if($cid)
then
if(db:open($config:CoreDatabase,$config:JobDir)/job[job-info/cid/text()=$cid][job-info/job-type='Ingest'][ingestion-report/status='InQueue'])
then <result><status>Failure</status><message>Job is already in queue.</message></result>
else
if(db:open($config:CoreDatabase,$config:JobDir)/job[job-info/cid/text()=$cid][job-info/job-type='Ingest'] and (db:list(blcommon:get-db-name($ctype),fn:concat($config:ContentDir,$cid,'/')))[1])
then <result><status>Failure</status><message>This is already ingested</message></result>
else
let $pid := contents:get-applied-ingest-pipeline($ctype,'zip')
return
if(
db:open($config:CoreDatabase,$config:JobDir)/job[job-info/cid/text()=$cid]
[job-info/job-type='Ingest']
[ingestion-report/status='InQueue']
or (db:list(blcommon:get-db-name($ctype),fn:concat($config:ContentDir,$cid,'/')))[1]
)
then
<result><status>Failure</status><message>The Content Id/s {$cid} is/are already ingested or in queue</message></result>
else
if($pid)
then
(
let $jobChunk := <job>
<job-info>
<id>{$jobID}</id>
<cid>{$cid}</cid>
<pipeline-id>{$pid}</pipeline-id>
<pipeline-name>{db:open($config:CoreDatabase,$config:PipelineDir)/pipeline:pipeline[@id=$pid]/@name/string()}</pipeline-name>
<area>{$area}</area>
<job-type>Ingest</job-type>
<submitted-on>{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}</submitted-on>
<uploaded-file>{$contentPath}</uploaded-file>
<content-type>{$ctype}</content-type>
<content-format>zip</content-format>
<ignore-validation>{$ignoreValidation}</ignore-validation>
<mail-required>{$sendMail}</mail-required>
<requester-id>{fn:substring-before(config:session-value($authorization),'$$$$')}</requester-id>
<requester-email>{fn:substring-after(config:session-value($authorization),'$$$$')}</requester-email>
<requester-name>{distinct-values(db:open($config:CoreDatabase,$config:UserDir)/user[fn:not(fn:matches(fn:base-uri(.),'(/version/|/audit/)'))][id=fn:substring-before(config:session-value($authorization),'$$$$')]/name)}</requester-name>
<location>{fn:concat($config:TempPipelineDir,$jobID)}</location>
</job-info>
<ingestion-report>
<steps/>
<status>InQueue</status>
<finished-on></finished-on>
</ingestion-report>
</job>
return db:add($config:CoreDatabase,$jobChunk,fn:concat($config:JobDir,$jobID,'.xml'))
,
<result><status>Success</status><message>Job created</message><jobid>{$jobID}</jobid></result>
)
else <result><status>Failure</status><message>Pipeline is not available.</message></result>
else <result><status>Failure</status><message>System error</message></result>
else <result><status>Failure</status><message>Content fails pre-ingestion check. header.xml file is not available</message></result>
else if($ctype='play')
then
( let $startedOn := fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))
let $archive := file:read-binary($contentPath)
for $entry in archive:entries($archive)[fn:ends-with(., '.xml')]
let $validate := validate:dtd-report(archive:extract-text($archive,$entry))
let $ContentId := fn:replace($entry/text(),'[^0-9]', '')
(:let $ContentId := fn:parse-xml(archive:extract-text($archive, $entry))/*/@xml:id/string():)
let $WellformedReport := <errors>
{
for $Message in $validate//message[@level='Fatal']
return $Message
}
</errors>
let $ModifiedReport := <report>
{
<status>{if($WellformedReport//message/@level/string()='Fatal') then 'invalid' else ()}</status>,
$WellformedReport
}
</report>
return
(:if(not(fn:empty($WellformedReport/*))):)
if($ModifiedReport//status='invalid')
then
let $jobID := fn:concat($config:JobIDPrefix,$ContentId,'-',fn:string(fn:format-dateTime(fn:current-dateTime(), '[Y0001][M01][D01][H01][m01][s01][f01]')))
let $jobChunk := <job>
<job-info>
<id>{$jobID}</id>
<cid>{$ContentId}</cid>
<pipeline-id></pipeline-id>
<pipeline-name></pipeline-name>
<area>{$area}</area>
<job-type>Ingest</job-type>
<submitted-on>{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}</submitted-on>
<uploaded-file>{$contentPath}</uploaded-file>
<content-type>{$ctype}</content-type>
<content-format>zip</content-format>
<ignore-validation>{$ignoreValidation}</ignore-validation>
<mail-required>{$sendMail}</mail-required>
<requester-id>{fn:substring-before(config:session-value($authorization),'$$$$')}</requester-id>
<requester-email>{fn:substring-after(config:session-value($authorization),'$$$$')}</requester-email>
<requester-name>{distinct-values(db:open($config:CoreDatabase,$config:UserDir)/user[fn:not(fn:matches(fn:base-uri(.),'(/version/|/audit/)'))][id=fn:substring-before(config:session-value($authorization),'$$$$')]/name)}</requester-name>
<location>{fn:concat($config:TempPipelineDir,$jobID)}</location>
</job-info>
<ingestion-report>
<steps>
<step>Wellformed:</step>
<started-on>{$startedOn}</started-on>
<location></location>
<completed-on>{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}</completed-on>
<errors>
{
$WellformedReport//message
}
</errors>
</steps>
<status>Failure</status>
</ingestion-report>
</job>
return
(
db:add($config:CoreDatabase,$jobChunk,fn:concat($config:JobDir,$jobID,'.xml'))
,
<result><status>Success</status><message>Job created</message><jobid>{$jobID}</jobid></result>
)
else
let $doc := fn:parse-xml(archive:extract-text($archive, $entry))
let $RootNode := fn:name($doc/*)
return
if($RootNode='TEI')
then
(
for $cid in try
{
let $docId := $doc/*/@xml:id/string()[$RootNode='TEI']
return $docId
}
catch *
{
let $docId := $doc/*/@xml:id/string()[$RootNode='TEI']
return $docId
}
let $jobID := fn:concat($config:JobIDPrefix,$cid,'-',fn:string(fn:format-dateTime(fn:current-dateTime(), '[Y0001][M01][D01][H01][m01][s01][f01]')))
return
if($cid)
then
if(db:open($config:CoreDatabase,$config:JobDir)/job[job-info/cid/text()=$cid][job-info/job-type='Ingest'][ingestion-report/status='InQueue'])
then <result><status>Failure</status><message>Job is already in queue.</message></result>
else
if(db:open($config:CoreDatabase,$config:JobDir)/job[job-info/cid/text()=$cid][job-info/job-type='Ingest'] and (db:list(blcommon:get-db-name($ctype),fn:concat($config:ContentDir,$cid,'/')))[1])
then <result><status>Failure</status><message>Content ID:{$cid} is/are already ingested</message></result>
else
let $pid := contents:get-applied-ingest-pipeline($ctype,'zip')
return
if(
db:open($config:CoreDatabase,$config:JobDir)/job[job-info/cid/text()=$cid]
[job-info/job-type='Ingest']
[ingestion-report/status='InQueue']
(:or (db:list(blcommon:get-db-name($ctype),fn:concat($config:ContentDir,$cid,'/')))[1]:)
)
then
<result><status>Failure</status><message>The Content Id/s {$cid} is/are already ingested or in queue</message></result>
else
if($pid)
then
(
let $jobChunk := <job>
<job-info>
<id>{$jobID}</id>
<cid>{$cid}</cid>
<pipeline-id>{$pid}</pipeline-id>
<pipeline-name>{db:open($config:CoreDatabase,$config:PipelineDir)/pipeline:pipeline[@id=$pid]/@name/string()}</pipeline-name>
<area>{$area}</area>
<job-type>Ingest</job-type>
<submitted-on>{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}</submitted-on>
<uploaded-file>{$contentPath}</uploaded-file>
<content-type>{$ctype}</content-type>
<content-format>zip</content-format>
<ignore-validation>{$ignoreValidation}</ignore-validation>
<mail-required>{$sendMail}</mail-required>
<requester-id>{fn:substring-before(config:session-value($authorization),'$$$$')}</requester-id>
<requester-email>{fn:substring-after(config:session-value($authorization),'$$$$')}</requester-email>
<requester-name>{distinct-values(db:open($config:CoreDatabase,$config:UserDir)/user[fn:not(fn:matches(fn:base-uri(.),'(/version/|/audit/)'))][id=fn:substring-before(config:session-value($authorization),'$$$$')]/name)}</requester-name>
<location>{fn:concat($config:TempPipelineDir,$jobID)}</location>
</job-info>
<ingestion-report>
<steps/>
<status>InQueue</status>
<finished-on></finished-on>
</ingestion-report>
</job>
return db:add($config:CoreDatabase,$jobChunk,fn:concat($config:JobDir,$jobID,'.xml'))
,
<result><status>Success</status><message>Job created</message><jobid>{$jobID}</jobid></result>
)
else <result><status>Failure</status><message>Pipeline is not available.</message></result>
else <result><status>Failure</status><message>System error</message></result>
)
else <result><status>Failure</status><message>Content fails pre-ingestion check. TEI format required only for content type play.</message></result>
)
else if($ctype='monograph')
then
let $startedOn := fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))
let $archive := file:read-binary($contentPath)
for $entry in archive:entries($archive)[fn:ends-with(., '.xml')]
let $validate := validate:dtd-report(archive:extract-text($archive,$entry))
let $ContentId := fn:replace($entry/text(),'[^0-9]', '')
let $WellformedReport := <errors>
{
for $Message in $validate//message[@level='Fatal']
return $Message
}
</errors>
let $ModifiedReport := <report>
{
<status>{if($WellformedReport//message/@level/string()='Fatal') then 'invalid' else ()}</status>,
$WellformedReport
}
</report>
return
if($ModifiedReport//status='invalid')
then
let $jobID := fn:concat($config:JobIDPrefix,$ContentId,'-',fn:string(fn:format-dateTime(fn:current-dateTime(), '[Y0001][M01][D01][H01][m01][s01][f01]')))
let $jobChunk := <job>
<job-info>
<id>{$jobID}</id>
<cid>{$ContentId}</cid>
<pipeline-id></pipeline-id>
<pipeline-name></pipeline-name>
<area>{$area}</area>
<job-type>Ingest</job-type>
<submitted-on>{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}</submitted-on>
<uploaded-file>{$contentPath}</uploaded-file>
<content-type>{$ctype}</content-type>
<content-format>zip</content-format>
<ignore-validation>{$ignoreValidation}</ignore-validation>
<mail-required>{$sendMail}</mail-required>
<requester-id>{fn:substring-before(config:session-value($authorization),'$$$$')}</requester-id>
<requester-email>{fn:substring-after(config:session-value($authorization),'$$$$')}</requester-email>
<requester-name>{distinct-values(db:open($config:CoreDatabase,$config:UserDir)/user[fn:not(fn:matches(fn:base-uri(.),'(/version/|/audit/)'))][id=fn:substring-before(config:session-value($authorization),'$$$$')]/name)}</requester-name>
<location>{fn:concat($config:TempPipelineDir,$jobID)}</location>
</job-info>
<ingestion-report>
<steps>
<step>Wellformed:</step>
<started-on>{$startedOn}</started-on>
<location></location>
<completed-on>{{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}}</completed-on>
<errors>
{
$WellformedReport//message
}
</errors>
</steps>
<status>Failure</status>
</ingestion-report>
</job>
return
(
db:add($config:CoreDatabase,$jobChunk,fn:concat($config:JobDir,$jobID,'.xml'))
,
<result><status>Success</status><message>Job created</message><jobid>{$jobID}</jobid></result>
)
else
let $doc := fn:parse-xml(archive:extract-text($archive, $entry))
let $RootNode := fn:name($doc/*)
return
if($RootNode='book')
then
(
for $cid in try
{
let $docId := $doc/*/@xml:id/string()
return $docId
}
catch *
{
let $docId := $doc/*/@xml:id/string()
return $docId
}
let $jobID := fn:concat($config:JobIDPrefix,$cid,'-',fn:string(fn:format-dateTime(fn:current-dateTime(), '[Y0001][M01][D01][H01][m01][s01][f01]')))
return
if($cid)
then
if(db:open($config:CoreDatabase,$config:JobDir)/job[job-info/cid/text()=$cid][job-info/job-type='Ingest'][ingestion-report/status='InQueue'])
then <result><status>Failure</status><message>Job is already in queue.</message></result>
else
if(db:open($config:CoreDatabase,$config:JobDir)/job[job-info/cid/text()=$cid][job-info/job-type='Ingest'] and (db:list(blcommon:get-db-name($ctype),fn:concat($config:ContentDir,$cid,'/')))[1])
then <result><status>Failure</status><message>Content ID:{$cid} is/are already ingested</message></result>
else
let $pid := contents:get-applied-ingest-pipeline($ctype,'zip')
return
if(
db:open($config:CoreDatabase,$config:JobDir)/job[job-info/cid/text()=$cid]
[job-info/job-type='Ingest']
[ingestion-report/status='InQueue']
(:or (db:list(blcommon:get-db-name($ctype),fn:concat($config:ContentDir,$cid,'/')))[1]:)
)
then
<result><status>Failure</status><message>The Content Id/s {$cid} is/are already ingested or in queue</message></result>
else
if($pid)
then
(
let $jobChunk := <job>
<job-info>
<id>{$jobID}</id>
<cid>{$cid}</cid>
<pipeline-id>{$pid}</pipeline-id>
<pipeline-name>{db:open($config:CoreDatabase,$config:PipelineDir)/pipeline:pipeline[@id=$pid]/@name/string()}</pipeline-name>
<area>{$area}</area>
<job-type>Ingest</job-type>
<submitted-on>{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}</submitted-on>
<uploaded-file>{$contentPath}</uploaded-file>
<content-type>{$ctype}</content-type>
<content-format>zip</content-format>
<ignore-validation>{$ignoreValidation}</ignore-validation>
<mail-required>{$sendMail}</mail-required>
<requester-id>{fn:substring-before(config:session-value($authorization),'$$$$')}</requester-id>
<requester-email>{fn:substring-after(config:session-value($authorization),'$$$$')}</requester-email>
<requester-name>{distinct-values(db:open($config:CoreDatabase,$config:UserDir)/user[fn:not(fn:matches(fn:base-uri(.),'(/version/|/audit/)'))][id=fn:substring-before(config:session-value($authorization),'$$$$')]/name)}</requester-name>
<location>{fn:concat($config:TempPipelineDir,$jobID)}</location>
</job-info>
<ingestion-report>
<steps/>
<status>InQueue</status>
<finished-on></finished-on>
</ingestion-report>
</job>
return db:add($config:CoreDatabase,$jobChunk,fn:concat($config:JobDir,$jobID,'.xml'))
,
<result><status>Success</status><message>Job created</message><jobid>{$jobID}</jobid></result>
)
else <result><status>Failure</status><message>Pipeline is not available.</message></result>
else <result><status>Failure</status><message>System error</message></result>
)
else <result><status>Failure</status><message>Content fails pre-ingestion check. Book format required only for content type play.</message></result>
else<result><status>Failure</status><message>Zip is not allowed for this content type {$ctype}.</message></result>
else <result><status>Failure</status><message>Content is not available or accessible from this location</message></result>
else
if(fn:ends-with(fn:lower-case($UploadFileName),'.xml') or fn:ends-with(fn:lower-case($UploadFileName),'.docx'))
then
if(file:exists($UploadFileName))
then
let $startedOn := fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))
let $CheckWelformed := let $ValidateDoc := validate:dtd-report($UploadFileName)
let $Report := <erros>
{
for $Message in $ValidateDoc/message[@level='Fatal']
return $Message
}
</erros>
return
<report>
{
<status>{if($Report//message/@level/string()='Fatal') then 'invalid' else ()}</status>,
$Report
}
</report>
return
if($CheckWelformed//status='invalid')
then
let $jobChunk := <job>
<job-info>
<id>{$jobID}</id>
<cid>{fn:replace(fn:tokenize(fn:replace($UploadFileName,'\\','/'),'/')[fn:last()],'[^0-9]', '')}</cid>
<pipeline-id></pipeline-id>
<pipeline-name></pipeline-name>
<area>{$area}</area>
<job-type>Ingest</job-type>
<submitted-on>{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}</submitted-on>
<uploaded-file>{$contentPath}</uploaded-file>
<content-type>{$ctype}</content-type>
<content-format>
{
if(fn:ends-with(fn:lower-case($UploadFileName),'.xml'))
then 'xml'
else 'docx'
}
</content-format>
<ignore-validation>{$ignoreValidation}</ignore-validation>
<mail-required>{$sendMail}</mail-required>
<requester-id>{fn:substring-before(config:session-value($authorization),'$$$$')}</requester-id>
<requester-email>{fn:substring-after(config:session-value($authorization),'$$$$')}</requester-email>
<requester-name>{distinct-values(db:open($config:CoreDatabase,$config:UserDir)/user[fn:not(fn:matches(fn:base-uri(.),'(/version/|/audit/)'))][id=fn:substring-before(config:session-value($authorization),'$$$$')]/name)}</requester-name>
<location>{fn:concat($config:TempPipelineDir,$jobID)}</location>
</job-info>
<ingestion-report>
<steps>
<step>Wellformed:</step>
<started-on>{$startedOn}</started-on>
<location></location>
<completed-on>{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}</completed-on>
<errors>
{
$CheckWelformed
}
</errors>
</steps>
<status>Failure</status>
</ingestion-report>
</job>
return
(
db:add($config:CoreDatabase,$jobChunk,fn:concat($config:JobDir,$jobID,'.xml'))
,
<result><status>Success</status><message>Job created</message><jobid>{$jobID}</jobid></result>
)
else
if($ctype='play')
then
let $doc := fetch:xml($contentPath,map { 'xinclude': false() })
let $rootNode := fn:name($doc/*)
return
if($rootNode!='TEI')
then <result><status>Failure</status><message>Content fails pre-ingestion check. TEI format required only for content type play.</message></result>
else
(:let $cid := if( fn:matches(fn:doc($contentPath)/*/@xml:id/string(),'[a-zA-z-]'))
then fn:replace(fn:doc($contentPath)/*/@xml:id/string(),'[a-zA-z-]','')
else fn:doc($contentPath)/*/@xml:id/string():)
let $cid := fn:doc($contentPath)/*/@xml:id/string()
return
if($cid)
then
if (
db:open($config:CoreDatabase,$config:JobDir)/job[job-info/cid/text()=$cid]
[job-info/job-type='Ingest']
[ingestion-report/status='InQueue']
or (db:list( blcommon:get-db-name($ctype),fn:concat($config:ContentDir,$cid,'/')))[1]
)
then
<result><status>Failure</status><message>The Content Id/s {$cid} is/are already ingested or in queue</message></result>
else
let $pid := contents:get-applied-ingest-pipeline($ctype,if(fn:ends-with(fn:lower-case($UploadFileName),'.xml')) then 'xml' else ())
return
if($pid)
then
(
let $jobChunk := <job>
<job-info>
<id>{$jobID}</id>
<cid>{$cid}</cid>
<pipeline-id>{$pid}</pipeline-id>
<pipeline-name>{db:open($config:CoreDatabase,$config:PipelineDir)/pipeline:pipeline[@id=$pid]/@name/string()}</pipeline-name>
<area>{$area}</area>
<job-type>Ingest</job-type>
<submitted-on>{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}</submitted-on>
<uploaded-file>{$contentPath}</uploaded-file>
<content-type>{$ctype}</content-type>
<content-format>
{
if(fn:ends-with(fn:lower-case($UploadFileName),'.xml'))
then 'xml'
else 'docx'
}
</content-format>
<ignore-validation>{$ignoreValidation}</ignore-validation>
<mail-required>{$sendMail}</mail-required>
<requester-id>{fn:substring-before(config:session-value($authorization),'$$$$')}</requester-id>
<requester-email>{fn:substring-after(config:session-value($authorization),'$$$$')}</requester-email>
<requester-name>{distinct-values(db:open($config:CoreDatabase,$config:UserDir)/user[fn:not(fn:matches(fn:base-uri(.),'(/version/|/audit/)'))][id=fn:substring-before(config:session-value($authorization),'$$$$')]/name)}</requester-name>
<location>{fn:concat($config:TempPipelineDir,$jobID)}</location>
</job-info>
<ingestion-report>
<steps/>
<status>InQueue</status>
<finished-on></finished-on>
</ingestion-report>
</job>
return db:add($config:CoreDatabase,$jobChunk,fn:concat($config:JobDir,$jobID,'.xml'))
,
<result><status>Success</status><message>Job created</message><jobid>{$jobID}</jobid></result>
)
else <result><status>Failure</status><message>Pipeline is not available.</message></result>
else <result><status>Failure</status><message>System error</message></result>
else if($ctype='monograph')
then
let $doc := fetch:xml($contentPath,map { 'xinclude': false() })
let $rootNode := fn:name($doc/*)
return
if($rootNode!='book')
then <result><status>Failure</status><message>Content fails pre-ingestion check. DocBook format required only for content type {$ctype}.</message></result>
else
(:let $cid := if( fn:matches(fetch:xml($contentPath,map { 'xinclude': false() })/*/@xml:id/string(),'[a-zA-z-]'))
then fn:replace(fetch:xml($contentPath,map { 'xinclude': false() })/*/@xml:id/string(),'[a-zA-z-]','')
else fn:doc($contentPath)/*/@xml:id/string():)
let $cid := fn:doc($contentPath)/*/@xml:id/string()
return
if($cid)
then
if (
db:open($config:CoreDatabase,$config:JobDir)/job[job-info/cid/text()=$cid]
[job-info/job-type='Ingest']
[ingestion-report/status='InQueue']
or (db:list( blcommon:get-db-name($ctype),fn:concat($config:ContentDir,$cid,'/')))[1]
)
then
<result><status>Failure</status><message>The Content Id/s {$cid} is/are already ingested or in queue</message></result>
else
let $pid := contents:get-applied-ingest-pipeline($ctype,if(fn:ends-with(fn:lower-case($UploadFileName),'.xml')) then 'xml' else ())
return
if($pid)
then
(
let $jobChunk := <job>
<job-info>
<id>{$jobID}</id>
<cid>{$cid}</cid>
<pipeline-id>{$pid}</pipeline-id>
<pipeline-name>{db:open($config:CoreDatabase,$config:PipelineDir)/pipeline:pipeline[@id=$pid]/@name/string()}</pipeline-name>
<area>{$area}</area>
<job-type>Ingest</job-type>
<submitted-on>{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}</submitted-on>
<uploaded-file>{$contentPath}</uploaded-file>
<content-type>{$ctype}</content-type>
<content-format>
{
if(fn:ends-with(fn:lower-case($UploadFileName),'.xml'))
then 'xml'
else 'docx'
}
</content-format>
<ignore-validation>{$ignoreValidation}</ignore-validation>
<mail-required>{$sendMail}</mail-required>
<requester-id>{fn:substring-before(config:session-value($authorization),'$$$$')}</requester-id>
<requester-email>{fn:substring-after(config:session-value($authorization),'$$$$')}</requester-email>
<requester-name>{distinct-values(db:open($config:CoreDatabase,$config:UserDir)/user[fn:not(fn:matches(fn:base-uri(.),'(/version/|/audit/)'))][id=fn:substring-before(config:session-value($authorization),'$$$$')]/name)}</requester-name>
<location>{fn:concat($config:TempPipelineDir,$jobID)}</location>
</job-info>
<ingestion-report>
<steps/>
<status>InQueue</status>
<finished-on></finished-on>
</ingestion-report>
</job>
return db:add($config:CoreDatabase,$jobChunk,fn:concat($config:JobDir,$jobID,'.xml'))
,
<result><status>Success</status><message>Job created</message><jobid>{$jobID}</jobid></result>
)
else <result><status>Failure</status><message>Pipeline is not available.</message></result>
else <result><status>Failure</status><message>System error</message></result>
else if($ctype='screenplay')
then
if(fn:not(fn:ends-with($contentPath, '.docx')))
then <result><status>Failure</status><message>Content fails pre-ingestion check. docx format allowed only.</message></result>
else
let $cid := if(fn:ends-with(fn:lower-case($UploadFileName),'.docx'))
then fn:substring-before(fn:tokenize($UploadFileName,'/')[fn:last()],'.docx')
else ()
return
if($cid)
then
if (
db:open($config:CoreDatabase,$config:JobDir)/job[job-info/cid/text()=$cid]
[job-info/job-type='Ingest']
[ingestion-report/status='InQueue']
or (db:list( blcommon:get-db-name($ctype),fn:concat($config:ContentDir,$cid,'/')))[1]
)
then
<result><status>Failure</status><message>The Content Id/s {$cid} is/are already ingested or in queue</message></result>
else
let $pid := contents:get-applied-ingest-pipeline($ctype,if(fn:ends-with(fn:lower-case($UploadFileName),'.docx')) then 'docx' else ())
return
if($pid)
then
(
let $jobChunk := <job>
<job-info>
<id>{$jobID}</id>
<cid>{$cid}</cid>
<pipeline-id>{$pid}</pipeline-id>
<pipeline-name>{db:open($config:CoreDatabase,$config:PipelineDir)/pipeline:pipeline[@id=$pid]/@name/string()}</pipeline-name>
<area>{$area}</area>
<job-type>Ingest</job-type>
<submitted-on>{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}</submitted-on>
<uploaded-file>{$contentPath}</uploaded-file>
<content-type>{$ctype}</content-type>
<content-format>
{
if(fn:ends-with(fn:lower-case($UploadFileName),'.xml'))
then 'xml'
else 'docx'
}
</content-format>
<ignore-validation>{$ignoreValidation}</ignore-validation>
<mail-required>{$sendMail}</mail-required>
<requester-id>{fn:substring-before(config:session-value($authorization),'$$$$')}</requester-id>
<requester-email>{fn:substring-after(config:session-value($authorization),'$$$$')}</requester-email>
<requester-name>{distinct-values(db:open($config:CoreDatabase,$config:UserDir)/user[fn:not(fn:matches(fn:base-uri(.),'(/version/|/audit/)'))][id=fn:substring-before(config:session-value($authorization),'$$$$')]/name)}</requester-name>
<location>{fn:concat($config:TempPipelineDir,$jobID)}</location>
</job-info>
<ingestion-report>
<steps/>
<status>InQueue</status>
<finished-on></finished-on>
</ingestion-report>
</job>
return db:add($config:CoreDatabase,$jobChunk,fn:concat($config:JobDir,$jobID,'.xml'))
,
<result><status>Success</status><message>Job created</message><jobid>{$jobID}</jobid></result>
)
else <result><status>Failure</status><message>Pipeline is not available.</message></result>
else <result><status>Failure</status><message>System error</message></result>
else if($ctype='looseleaf')
then <result><status>Failure</status><message>Zip format required only for content type {$ctype}.</message></result>
else()
else <result><status>Failure</status><message>Content is not available or accessible from this location</message></result>
else <result><status>Failure</status><message>Uploaded content format is not supported. Please supply ZIP, DOCX or XML only</message></result>
}
</results>
};
(:~
: To schedule check-in job
: @param $body Paremeters to lock content into the system <checkin><role>Admin</role><uri></uri><uri></uri><upload-path></upload-path><ignore-validation>true</ignore-validation><mail>true</mail><comment></comment></checkin>
: <role> = Role of the user. Admin user can check-in another user check out files.
: <uri> = The uri of the files which has been selected to check-in (db uri), separated by '|', no space should present while joining by '|'
: <upload-path> = Selected content to upload (zip,word,xml)
: <ignore-validation> = program will ignore validation or not
: <mail> = mail indicator to send mail after check-in
: <comment> = check-in comment of the user
: @header $authorization Authorization key
: @return boolean
:)
declare %private %updating function JOBS:checkin-job(
$body as document-node(),
$authorization as xs:string
)
{
let $uri := $body/job/checkin/uri/text()
let $countUri := fn:count($body/job/checkin/uri)
let $ctype := $body/job/checkin/ctype/text()
let $allUri := fn:string-join(for $uri in $body/job/checkin/uri/text() return $uri, '|')
let $contentPath := fn:replace($body/job/checkin/upload-path/text(),'\\','/')
let $sendMail := $body/job/checkin/mail/text()
let $comment := $body/job/checkin/comment/text()
let $requesterRole := $body/job/checkin/role/text()
let $ignoreValidation := $body/job/checkin/ignore-validation/text()
let $sessionValue := config:session-value($authorization)
let $userID := fn:substring-before($sessionValue,'$$$$')
let $userEmail := fn:substring-after($sessionValue,'$$$$')
let $jobID := fn:concat($config:JobIDPrefix,fn:string(fn:format-dateTime(fn:current-dateTime(), '[Y0001][M01][D01][H01][m01][s01][f01]')))
let $checkoutVerify := JOBS:is-any-checkout($allUri,$userID)
let $checkUpload := JOBS:selected-vs-uploaded($checkoutVerify,$contentPath,$userID,$allUri,$ctype)
let $allUri := if(fn:contains($allUri,'|')) then fn:concat('(',$allUri,')') else $allUri
let $verfyzip := if(fn:ends-with($contentPath,'.zip'))
then
let $archive := file:read-binary($contentPath)
for $entries in archive:entries($archive)
let $filename := substring-before($entries/text(),'.xml')
return (if(fn:not(fn:contains($allUri,$filename)))
then 'false'
else ()
)
else()
return
try
{ (: verify the empty parameter :)
if($body/job//*[.=''])
then update:output(<result><status>Failure</status><message>Some parameter is empty. Please supply all the parameters.</message></result>)
else (: if selected content is multiple, user must supply zip folder to check-in :)
if(($ctype='play' or $ctype='monograph' or $ctype='screenplay') and (fn:ends-with($contentPath,'.zip') or fn:ends-with($contentPath,'.ZIP')) )
then update:output(<result><status>Failure</status><message>Zip not allowed for single check-in.</message></result>)
else
if(($countUri gt 1) and fn:not(fn:ends-with($contentPath,'.zip') or fn:ends-with($contentPath,'.ZIP')))
then update:output(<result><status>Failure</status><message>For multiple check-in send ZIP format only</message></result>)
else (: to verify uploaded content existence :)
if(file:exists($contentPath))
then (: verify the selected content is checked out or not by requester user, Admin user can perform action :)
if(($checkoutVerify/file[locked='yes'][locked-by/requester-id=$userID]) or (($requesterRole='Admin') and ($checkoutVerify/file[locked='yes'])))
then (: verify, is uploaded content has already checked-out content, if checked-out by other and user is Admin :)
if(($checkUpload/file[exist='yes'][locked-by/requester-id=$userID]) or (($requesterRole='Admin') and ($checkUpload/file[exist='yes'][locked-by])))
then
if(fn:ends-with($contentPath,'.zip') or fn:ends-with($contentPath,'.ZIP'))
then
if($verfyzip='false') then update:output(<result><status>Failure</status><message>some files are not part of this content please check zip.</message></result>)
(: header.xml not locked and available in zip to check-in :)
else if(fn:not(fn:contains($allUri,$config:HeaderXml)) and archive:entries(file:read-binary($contentPath))[fn:contains(.,$config:HeaderXml)])
then update:output(<result><status>Failure</status><message>header.xml is not checked-out/selected to check-in, but available in zip to check-in.</message></result>)
else
if(
(: Check header.xml locked :)
fn:contains($allUri,$config:HeaderXml)
or
(: Check header.xml not locked and not available in zip :)
(fn:not(fn:contains($allUri,$config:HeaderXml)) and archive:entries(file:read-binary($contentPath))[fn:not(fn:contains(.,$config:HeaderXml))])
)
then
let $cid := (: header.xml exists in zip :)
if(fn:contains($allUri,$config:HeaderXml) and archive:entries(file:read-binary($contentPath))[fn:contains(.,$config:HeaderXml)])
then
try
{
let $archive := file:read-binary($contentPath)
let $entry := archive:entries($archive)[fn:ends-with(., $config:HeaderXml)]
return fn:parse-xml(archive:extract-text($archive, $entry))/*/@xml:id/string()
}
catch *
{
let $archive := file:read-binary($contentPath)
let $entry := archive:entries($archive)[fn:ends-with(.,$config:HeaderXml)]
let $xml:= archive:extract-text($archive, $entry)
return fn:substring-before(fn:substring-after($xml,'xml:id="'),'"')
}
else
let $cid := fn:distinct-values
(
for $x in $body/job/checkin/uri/text()
return fn:tokenize($x,'/')[fn:position()=4]
)
return
if(fn:count($cid) eq 1) then $cid else 'ERROR'
return
if($cid!='ERROR')
then
let $coid := fn:concat($cid,'_',$cid)
let $infoXml := fn:doc(fn:concat(blcommon:get-db-name($ctype),$config:ContentDir,$cid,'/',$coid,'/',$config:InfoXml))
let $area := $infoXml/info/area/text()
let $ctype := $infoXml/info/ctype/text()
let $sessionValue := config:session-value($authorization)
let $pid := contents:get-applied-ingest-pipeline($ctype,'zip')
return
if(db:list(blcommon:get-db-name($ctype),fn:concat($config:ContentDir,$cid))[1])
then
if($cid)
then
if(
db:open($config:CoreDatabase,$config:JobDir)/job[job-info/cid/text()=$cid]
[job-info/job-type='Checkin']
[ingestion-report/status='InQueue' or ingestion-report/status='InProgress']
[job-info/lock[some $uri in file/uri satisfies fn:matches(.,$allUri)]]
and (db:list(blcommon:get-db-name($ctype),fn:concat($config:ContentDir,$cid,'/')))[1]
)
then update:output(<result><status>Failure</status><message>This is already ingested or in queue</message></result>)
else
if($pid)
then
(
let $jobChunk := <job>
<job-info>
<id>{$jobID}</id>
<cid>{$cid}</cid>
<pipeline-id>{$pid}</pipeline-id>
<pipeline-name>{db:open($config:CoreDatabase,$config:PipelineDir)/pipeline:pipeline[@id=$pid]/@name/string()}</pipeline-name>
<area>{$area}</area>
<job-type>Checkin</job-type>
<comment>{$comment}</comment>
<submitted-on>{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}</submitted-on>
<uploaded-file>{$contentPath}</uploaded-file>
<content-type>{$ctype}</content-type>
<content-format>zip</content-format>
<ignore-validation>{$ignoreValidation}</ignore-validation>
<mail-required>{$sendMail}</mail-required>
<requester-id>{fn:substring-before(config:session-value($authorization),'$$$$')}</requester-id>
<requester-email>{distinct-values(db:open($config:CoreDatabase,$config:UserDir)/user[fn:not(fn:matches(fn:base-uri(.),'(/version/|/audit/)'))][id=fn:substring-before(config:session-value($authorization),'$$$$')]/email)}</requester-email>
<requester-name>{distinct-values(db:open($config:CoreDatabase,$config:UserDir)/user[fn:not(fn:matches(fn:base-uri(.),'(/version/|/audit/)'))][id=fn:substring-before(config:session-value($authorization),'$$$$')]/name)}</requester-name>
<location>{fn:concat($config:TempPipelineDir,$jobID)}</location>
{$checkUpload}
</job-info>
<ingestion-report>
<steps/>
<status>InQueue</status>
<finished-on></finished-on>
</ingestion-report>
</job>
return db:add($config:CoreDatabase,$jobChunk,fn:concat($config:JobDir,$jobID,'.xml'))
,
update:output(<result><status>Success</status><message>Job created</message><jobid>{$jobID}</jobid></result>)
)
else update:output(<result><status>Failure</status><message>Related pipeline is not available</message></result>)
else update:output(<result><status>Failure</status><message>System error</message></result>)
else update:output(<result><status>Failure</status><message>Please ingest this content before check-in</message></result>)
else update:output(<result><status>Failure</status><message>Multiple CID found to check-in.</message></result>)
else ()
else
if(fn:ends-with(fn:lower-case($contentPath),'.xml') or fn:ends-with(fn:lower-case($contentPath),'.docx'))
then
let $startedOn := fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))
let $CheckWelformed := let $ValidateDoc := validate:dtd-report($contentPath)
let $Report := <erros>
{
for $Message in $ValidateDoc/message[@level='Fatal']
return $Message
}
</erros>
return
<report>
{
<status>{if($Report//message/@level/string()='Fatal') then 'invalid' else ()}</status>,
$Report
}
</report>
return
if($CheckWelformed//status='invalid')
then
let $jobChunk := <job>
<job-info>
<id>{$jobID}</id>
<cid>{fn:replace(fn:tokenize(fn:replace($contentPath,'\\','/'),'/')[fn:last()],'[^0-9]', '')}</cid>
<pipeline-id></pipeline-id>
<pipeline-name></pipeline-name>
<area></area>
<job-type>Check-in</job-type>
<submitted-on>{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}</submitted-on>
<uploaded-file>{$contentPath}</uploaded-file>
<content-type>{$ctype}</content-type>
<content-format>
{
if(fn:ends-with(fn:lower-case($contentPath),'.xml'))
then 'xml'
else 'docx'
}
</content-format>
<ignore-validation>{$ignoreValidation}</ignore-validation>
<mail-required>{$sendMail}</mail-required>
<requester-id>{fn:substring-before(config:session-value($authorization),'$$$$')}</requester-id>
<requester-email>{fn:substring-after(config:session-value($authorization),'$$$$')}</requester-email>
<requester-name>{distinct-values(db:open($config:CoreDatabase,$config:UserDir)/user[fn:not(fn:matches(fn:base-uri(.),'(/version/|/audit/)'))][id=fn:substring-before(config:session-value($authorization),'$$$$')]/name)}</requester-name>
<location>{fn:concat($config:TempPipelineDir,$jobID)}</location>
</job-info>
<ingestion-report>
<steps>
<step>Wellformed:</step>
<started-on>{$startedOn}</started-on>
<location></location>
<completed-on>{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}</completed-on>
<errors>
{
$CheckWelformed//message
}
</errors>
</steps>
<status>Failure</status>
</ingestion-report>
</job>
return
(
db:add($config:CoreDatabase,$jobChunk,fn:concat($config:JobDir,$jobID,'.xml'))
,
<result><status>Success</status><message>Job created</message><jobid>{$jobID}</jobid></result>
)
else
let $coid := if(fn:ends-with(fn:lower-case($contentPath),$config:HeaderXml))
then
let $cid := try
{
fn:doc($contentPath)/*/@xml:id/string()
}
catch *
{
fetch:xml($contentPath,map { 'xinclude': false() })/*/@xml:id/string()
}
return fn:concat($cid,'_',$cid)
else
if(fn:ends-with(fn:lower-case($contentPath),'.docx'))
then
let $fileName := fn:replace(fn:tokenize($contentPath,'/')[fn:last()],'.docx','')
return fn:concat($fileName,'_',$fileName)
else
(:let $fileName := if (fn:contains(fn:substring-before(fn:tokenize($contentPath,'/')[fn:last()],'.xml'),'_txt_xml'))
then fn:replace( fn:substring-before(fn:tokenize($contentPath,'/')[fn:last()],'.xml') ,'_txt_xml','')
else fn:substring-before(fn:tokenize($contentPath,'/')[fn:last()],'.xml')
return fn:concat($fileName,'_',$fileName):)
if(($ctype='play') or ($ctype='monograph'))
then
let $cid := fn:doc($contentPath)/*/@xml:id/string()
return
fn:concat($cid,'_',$cid)
else
let $fileName := fn:replace(fn:tokenize($contentPath,'/')[fn:last()],'.xml','')
return fn:concat($fileName,'_',$fileName)
let $cid := if(fn:ends-with(fn:lower-case($contentPath),$config:HeaderXml))
then
try
{
fn:doc($contentPath)/*/@xml:id/string()
}
catch *
{
fetch:xml($contentPath,map { 'xinclude': false() })/*/@xml:id/string()
}
else if(fn:ends-with(fn:lower-case($contentPath),'.docx'))
then fn:tokenize((db:list( blcommon:get-db-name($ctype))[fn:contains(.,$coid)])[1],'/')[2]
else
try
{
fn:doc($contentPath)/*/@xml:id/string()
(:if( fn:matches(fn:doc($contentPath)/*/@xml:id/string(),'[a-zA-z-]'))
then fn:replace(fn:doc($contentPath)/*/@xml:id/string(),'[a-zA-z-]','')
else fn:doc($contentPath)/*/@xml:id/string():)
}
catch *
{
fetch:xml($contentPath,map { 'xinclude': false() })/*/@xml:id/string()
}
let $area := (db:open($config:CoreDatabase,$config:JobDir)/job/job-info[cid=$cid][job-type='Ingest']/area/text())[1]
let $ctype := (db:open($config:CoreDatabase,$config:JobDir)/job/job-info[cid=$cid][job-type='Ingest']/content-type/text())[1]
let $sessionValue := config:session-value($authorization)
let $pid := if(fn:ends-with(fn:lower-case($contentPath),'.docx'))
then contents:get-applied-ingest-pipeline($ctype,'docx')
else
if(fn:ends-with(fn:lower-case($contentPath),'.xml'))
then contents:get-applied-ingest-pipeline($ctype,'xml')
else ()
return
if(($cid and $coid) and (db:list(blcommon:get-db-name($ctype),fn:concat($config:ContentDir,$cid,'/',$coid))[1]))
then
if($pid)
then
if(
db:open($config:CoreDatabase,$config:JobDir)/job[job-info/cid/text()=$cid]
[job-info/job-type='Checkin']
[ingestion-report/status='InQueue' or ingestion-report/status='InProgress']
[job-info/lock[some $uri in file/uri satisfies fn:matches(.,$allUri)]]
and (db:list( blcommon:get-db-name($ctype),fn:concat($config:ContentDir,$cid,'/')))[1]
)
then update:output(<result><status>Failure</status><message>This is already ingested or in queue</message></result>)
else
if($cid)
then
(
let $jobChunk := <job>
<job-info>
<id>{$jobID}</id>
<cid>{$cid}</cid>
<pipeline-id>{$pid}</pipeline-id>
<pipeline-name>{db:open($config:CoreDatabase,$config:PipelineDir)/pipeline:pipeline[@id=$pid]/@name/string()}</pipeline-name>
<area>{$area}</area>
<job-type>Checkin</job-type>
<comment>{$comment}</comment>
<submitted-on>{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}</submitted-on>
<uploaded-file>{$contentPath}</uploaded-file>
<content-type>{$ctype}</content-type>
<content-format>
{
if(fn:ends-with(fn:lower-case($contentPath),'.xml'))
then 'xml'
else 'docx'
}
</content-format>
<ignore-validation>{$ignoreValidation}</ignore-validation>
<mail-required>{$sendMail}</mail-required>
<requester-id>{fn:substring-before(config:session-value($authorization),'$$$$')}</requester-id>
<requester-email>{distinct-values(db:open($config:CoreDatabase,$config:UserDir)/user[fn:not(fn:matches(fn:base-uri(.),'(/version/|/audit/)'))][id=fn:substring-before(config:session-value($authorization),'$$$$')]/email)}</requester-email>
<requester-name>{distinct-values(db:open($config:CoreDatabase,$config:UserDir)/user[fn:not(fn:matches(fn:base-uri(.),'(/version/|/audit/)'))][id=fn:substring-before(config:session-value($authorization),'$$$$')]/name)}</requester-name>
<location>{fn:concat($config:TempPipelineDir,$jobID)}</location>
{$checkUpload}
</job-info>
<ingestion-report>
<steps/>
<status>InQueue</status>
<finished-on></finished-on>
</ingestion-report>
</job>
return db:add($config:CoreDatabase,$jobChunk,fn:concat($config:JobDir,$jobID,'.xml'))
,
update:output(<result><status>Success</status><message>Job created</message><jobid>{$jobID}</jobid></result>)
)
else update:output(<result><status>Failure</status><message>System error</message></result>)
else update:output(<result><status>Failure</status><message>Related pipeline is not available</message></result>)
else
(
update:output(<result><status>Failure</status><message>Please ingest this content before checkin</message></result>)
)
else update:output(<result><status>Failure</status><message>Uploaded content format is not supported. Please supply ZIP, DOCX or XML only</message></result>)
else update:output(<result><status>Failure</status><message>Uploaded content do not have any checked-out content to check-in</message></result>)
else update:output(<result><status>Failure</status><message>Selected files are not checked-out or checked-out by others.</message></result>)
else update:output(<result><status>Failure</status><message>Content is not available or accessible from this location</message></result>)
}
catch *
{
admin:write-log("[Content Checkin][Error: " || $err:description || "]"),
admin:write-log("[Content Checkin][Error: " || $err:additional || "]"),
update:output(<result><status>Error</status><message>Error generated. Please check system log</message></result>)
}
};
(:~
: To publish a product
: @param $body <job><publish><product>$pid</product><ignore-validation>true</ignore-validation><mail>true</mail></publish></job>
: @header $authorization Authorization key
: @return element(result)
:)
declare %private %updating function JOBS:publish-job(
$body as document-node(),
$authorization as xs:string
)
{
let $productID := $body/job/publish/product/text()
let $ignoreValidation := $body/job/publish/ignore-validation/text()
let $sendMail := $body/job/publish/mail/text()
let $productXML := db:open($config:CoreDatabase,fn:concat($config:ProductDir,$productID,$config:LatestDir,$productID,'.xml'))
let $productTitle := $productXML/product:product/@name/string()
let $sessionValue := config:session-value($authorization)
let $userID := fn:substring-before($sessionValue,'$$$$')
let $userRole := db:open($config:CoreDatabase,fn:concat($config:UserDir,$userID,'.xml'))/user/role/text()
let $userEmail := fn:substring-after($sessionValue,'$$$$')
(:let $pipelineID := $productXML/product:product/@pipelineRef/string():)
let $taxonomyID := $productXML/product:product/@taxonomyRef/string()
let $assiginedManagers := let $managers := fn:string-join(
for $user in $productXML/product:product/product:managers/product:user/@id/string()
return $user
,'|')
return if(fn:contains($managers,'|')) then fn:concat('(',$managers,')') else $managers
(:let $jobID := fn:concat($config:JobIDPrefix,fn:string(fn:format-dateTime(fn:current-dateTime(), '[Y0001][M01][D01][H01][m01][s01][f01]'))):)
return
try
{ (: verify the empty parameter :)
if($body/job//*[.=''])
then update:output(<result><status>Failure</status><message>Some parameter is empty. Please supply all the parameters.</message></result>)
else (: verify the delete product :)
if($productXML/product:product[@delete])
then update:output(<result><status>Success</status><message>Product is deleted. You cannot publish it.</message></result>)
else (: check the requester has authority to publish :)
if(fn:not(fn:matches($userID,$assiginedManagers)) and $userRole!='admin')
then update:output(<result><status>Failure</status><message>You are not authorized to publish this product.</message></result>)
else
<results>
{
for $Content at $pos in $productXML/product:product/product:contents/product:content
let $PipelineID := $Content/@pipelineRef/string()
let $jobID := fn:concat($config:JobIDPrefix,fn:string(fn:format-dateTime(fn:current-dateTime(), '[Y0001][M01][D01][H01][m01][s01][f01]')),'-',$pos)
let $PipelineXML := db:open($config:CoreDatabase,$config:PipelineDir||$PipelineID||'.xml')
let $TaxonomyXML := fn:doc($config:CoreDatabase||$config:TaxonomyDir||$taxonomyID||'.xml')
let $TaxonomyName := $TaxonomyXML/*:taxonomy/@name/string()
let $CType := $Content/@sourceContentType/string()
let $CopyContent := (
let $steps := for $eachStep in $PipelineXML/*:pipeline/child::*/local-name()
return $eachStep
let $normalizedsteps := string-join($steps,'|')
return
if(fn:contains($normalizedsteps,'xquery'))
then
for $XquerySteps at $pos in $PipelineXML/*:pipeline/*:xquery
let $templocation := fn:concat($config:TempPipelineDir,$jobID,'/step-',$pos,'/')
return
if($pos eq 1)
then
(
file:create-dir($templocation)
,
file:create-dir(fn:concat($config:TempPipelineDir,$jobID,'/Publish/') )
,
JOBS:Copy-Content($Content,$templocation)
,
JOBS:Copy-Metadata($Content,$templocation)
,
JOBS:Copy-MetadataOnlyContent-metadata($Content,$templocation)
,
JOBS:Copy-MetaContent($PipelineXML,$templocation)
,
JOBS:Copy-Content-Management($Content,$templocation)
,
JOBS:Copy-Manifest($productID,$Content,$templocation)
,
JOBS:Copy-Taxonomy($TaxonomyXML,$templocation)
)
else if ($pos gt 1)
then
let $templocation := fn:concat($config:TempPipelineDir,$jobID,'/step-',$pos,'/input/')
return
file:create-dir($templocation)
else()
else
(
let $templocation := fn:concat($config:TempPipelineDir,$jobID,'/')
return
(
file:create-dir(fn:concat($config:TempPipelineDir,$jobID,'/Publish/') )
,
JOBS:Copy-Content($Content,$templocation)
,
JOBS:Copy-Metadata($Content,$templocation)
)
)
)
return
(
let $jobChunk := <job>
<job-info>
<id>{$jobID}</id>
<product-id>{$productID}</product-id>
<product-name>{$productTitle}</product-name>
<pipeline-id>{if($Content/@pipelineRef) then $Content/@pipelineRef/string() else 'Pipeline is not available'}</pipeline-id>
<pipeline-name>{db:open($config:CoreDatabase,$config:PipelineDir)/pipeline:pipeline[@id=$Content/@pipelineRef/string()]/@name/string()}</pipeline-name>
<taxonomy-id>{if($taxonomyID) then $taxonomyID else 'Taxonomy is not available'}</taxonomy-id>
<taxonomy-name>{db:open($config:CoreDatabase,$config:TaxonomyDir)/taxonomy[@id=$taxonomyID]/@name/string()}</taxonomy-name>
<job-type>Publish</job-type>
<submitted-on>{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}</submitted-on>
<ignore-validation>{$ignoreValidation}</ignore-validation>
<mail-required>{$sendMail}</mail-required>
<requester-id>{fn:substring-before($sessionValue,'$$$$')}</requester-id>
<requester-email>{fn:substring-after($sessionValue,'$$$$')}</requester-email>
<requester-name>{distinct-values(db:open($config:CoreDatabase,$config:UserDir)/user[fn:not(fn:matches(fn:base-uri(.),'(/version/|/audit/)'))][id=fn:substring-before(config:session-value($authorization),'$$$$')]/name)}</requester-name>
<location></location>
{JOBS:publish-info($Content)}
</job-info>
<ingestion-report>
<steps/>
<status>InQueue</status>
<finished-on></finished-on>
</ingestion-report>
</job>
return db:add($config:CoreDatabase,$jobChunk,fn:concat($config:JobDir,$jobID,'.xml'))
,
<result><status>Success</status><message>Job created</message><jobid>{$jobID}</jobid></result>
)
}</results>
}
catch *
{
admin:write-log("[Content Publish][Error: " || $err:description || "]"),
admin:write-log("[Content Publish][Error: " || $err:additional || "]"),
update:output(<result><status>Error</status><message>Error generated. Please check system log</message></result>)
}
};
(:~
: To collect publishable content information
: @param $productXML Product XML
: @return element(items)
:)
declare function JOBS:publish-info(
$ContentXML as node ()
) as element(items)
{
<items>
{
let $ContentTypeXML := fn:doc(fn:concat($config:CoreDatabase,$config:ContentType))
for $item in $ContentXML/*:item
let $itemTitle := $item/@title/string()
let $itemID := $item/@id/string()
let $ProductSourceCType := $ContentXML//@sourceContentType/string()
let $sourceCType := if($ContentTypeXML/*:controlledList/*:name[@xml:id/string()=$ProductSourceCType]/@referenceid)
then $ContentTypeXML/*:controlledList/*:name[@xml:id/string()=$ProductSourceCType]/@referenceid/string()
else $ContentTypeXML/*:controlledList/*:name[@xml:id/string()=$ProductSourceCType]/@xml:id/string()
let $itemInfo := for $uri in fn:uri-collection(fn:concat(blcommon:get-db-name($sourceCType),$config:ContentDir))[fn:contains(.,$itemID)]
[fn:contains(.,'/content/latest')]
[fn:not(fn:contains(.,$config:AuditFileName)
or fn:contains(.,$config:VersionControlFileName)
or fn:contains(.,$config:InfoXml)
or fn:contains(.,$config:VersionDir)
or fn:contains(.,$config:Metadata)
)]
let $isCheckedOut := db:open(blcommon:get-db-name($sourceCType),$config:LockDir)/locks/lock/files/file[uri=$uri]
let $cid := fn:substring-before(fn:substring-before(fn:substring-after($uri,$config:ContentDir),$config:ContentDir),'/')
let $coid := fn:substring-after(fn:substring-before(fn:substring-after($uri,$config:ContentDir),$config:ContentDir),'/')
let $auditUri := fn:concat(blcommon:get-db-name($sourceCType),$config:ContentDir,$cid,'/',$coid,'/',$config:AuditFileName)
let $version := let $versionUri := fn:replace($auditUri,$config:AuditFileName,$config:VersionControlFileName)
return
if(fn:doc-available($versionUri))
then
let $versionXml := fn:doc($versionUri)
let $version := $versionXml/versions/version[@uri=$uri]/@number/string()
return
if($version)
then $version
else fn:sum(fn:max($versionXml/versions/version/@number) + 1)
else 1
return
<item>
<source-type>{$sourceCType}</source-type>
<uri>{$uri}</uri>
<checkout>{if($isCheckedOut) then 'true' else 'false'}</checkout>
<version>{$version}</version>
</item>
return $itemInfo
}
</items>
};
(:~
: To check from supplied anything is checked-out
: @param $uri The uri of the files which has been selected to check-in (db uri)
: @param $userID Current User ID who wants to check-in
: @return element(lock)
:)
declare %private function JOBS:is-any-checkout(
$uri as xs:string,
$userID as xs:string
) as element(lock)
{
<lock>
{
let $lockDoc := db:open($config:CoreDatabase,fn:concat($config:LockDir,$userID,'.xml'))
for $eachUri in fn:tokenize($uri,'\|')
return
<file>
{ (: check in same user lock first :)
if($lockDoc/locks/lock/files[file/uri=$eachUri])
then
(
<locked>yes</locked>,
<uri>{$lockDoc/locks/lock/files/file[uri=$eachUri]/uri/text()}</uri>,
<previous-version>{$lockDoc/locks/lock/files/file[uri=$eachUri]/version/text()}</previous-version>,
<latest-version>{fn:sum($lockDoc/locks/lock/files/file[uri=$eachUri]/version/text()+1)}</latest-version>,
<locked-by>
<requester-id>{$userID}</requester-id>
<requester-email>{$lockDoc/locks/lock[files/file/uri=$eachUri]/requester-email/string()}</requester-email>
<locked-by>Self</locked-by>
</locked-by>
)
else (: if not available, check with other user lock :)
let $lockDoc := db:open($config:CoreDatabase,$config:LockDir)/locks[lock/files/file/uri=$eachUri]
return
if($lockDoc)
then
(
<locked>yes</locked>,
<uri>{$lockDoc/lock/files/file[uri=$eachUri]/uri/text()}</uri>,
<previous-version>{$lockDoc/lock/files/file[uri=$eachUri]/version/text()}</previous-version>,
<latest-version>{fn:sum($lockDoc/lock/files/file[uri=$eachUri]/version/text()+1)}</latest-version>,
<locked-by>
<requester-id>{$lockDoc/lock[files/file/uri=$eachUri]/requester-id/text()}</requester-id>
<requester-email>{$lockDoc/locks/lock[files/file/uri=$eachUri]/requester-email/string()}</requester-email>
<locked-by>Other</locked-by>
</locked-by>
)
else
(
<locked>no</locked>,
<uri>{$eachUri}</uri>
)
}
</file>
}
</lock>
};
(:~
: To check checked-out is in the attached (zip,word,xml) or not
: @param $checkOutInfo locking information chunk
: @param $contentPath Upload path (zip,word,xml)
: @param $userID Current User ID who wants to check-in
: @@param $allUri The uri of the files which has been selected to check-in
: @return element(lock)
:)
declare %private function JOBS:selected-vs-uploaded(
$checkOutInfo as element(lock),
$contentPath as xs:string,
$userID as xs:string,
$allUri as xs:string,
$ctype as xs:string
) as element(lock)
{
<lock>
{
if(fn:ends-with($contentPath,'.zip') or fn:ends-with($contentPath,'.ZIP'))
then
for $entry in archive:entries(file:read-binary($contentPath))
let $checkoutFiles := let $join := fn:string-join(for $chckoutFile in $checkOutInfo/file[locked='yes']/uri
return fn:tokenize($chckoutFile,'/')[fn:last()], '|')
return if(fn:contains($join,'|')) then fn:concat('(',$join,')') else if($join) then $join else 'NONE'
return
if(fn:matches(fn:replace($entry/text(),'.docx','.xml'),$checkoutFiles))
then
<file>
<exist>yes</exist>
<selected-to-checkin>yes</selected-to-checkin>
{
let $checkoutInfo := $checkOutInfo/file[locked='yes']
[fn:tokenize(uri,'/')[fn:last()]=fn:replace($entry/text(),'.docx','.xml')]
return
(
$checkoutInfo/locked-by,
$checkoutInfo/uri,
$checkoutInfo/previous-version,
$checkoutInfo/latest-version
)
}
</file>
else
(: to find out new content into the zip to upload into the system :)
let $cid := (: header.xml exists in zip :)
if(fn:contains($allUri,$config:HeaderXml) and archive:entries(file:read-binary($contentPath))[fn:contains(.,$config:HeaderXml)])
then
try
{
let $archive := file:read-binary($contentPath)
let $entry := archive:entries($archive)[fn:ends-with(., $config:HeaderXml)]
return fn:parse-xml(archive:extract-text($archive, $entry))/*/@xml:id/string()
}
catch *
{
let $archive := file:read-binary($contentPath)
let $entry := archive:entries($archive)[fn:ends-with(.,$config:HeaderXml)]
let $xml:= archive:extract-text($archive, $entry)
return fn:substring-before(fn:substring-after($xml,'xml:id="'),'"')
}
else
let $cid := fn:distinct-values
(
for $x in fn:tokenize($allUri,'\|')
return fn:tokenize($x,'/')[fn:position()=4]
)
return
if(fn:count($cid) eq 1) then $cid else 'ERROR'
return
(:if((fn:uri-collection($config:Database)[fn:contains(.,fn:replace($entry/text(),'.docx','.xml'))])[1]):)
if(
db:list(blcommon:get-db-name($ctype),fn:concat($config:ContentDir,$cid))[fn:contains(.,'/content/latest/')]
[fn:not(fn:contains(.,$config:WordDir))]
[fn:ends-with(.,fn:replace($entry/text(),'.docx','.xml'))]
)
then
<file>
<exist>yes</exist>
<selected-to-checkin>no</selected-to-checkin>
<uri>{$entry/text()}</uri>
</file>
else
<file>
<exist>yes</exist>
<selected-to-checkin>New Content</selected-to-checkin>
<locked-by><locked-by>None</locked-by></locked-by>
<uri>{$entry/text()}</uri>
<latest-version>1</latest-version>
</file>
else
if(fn:ends-with($contentPath,'.xml'))
then
let $uploadedFileName := fn:tokenize($contentPath,'/')[fn:last()]
return
if($checkOutInfo/file[locked='yes'][fn:contains(uri,$uploadedFileName)])
then
<file>
<exist>yes</exist>
<selected-to-checkin>yes</selected-to-checkin>
<uri>{$checkOutInfo/file[locked='yes'][fn:contains(uri,$uploadedFileName)]/uri/text()}</uri>
{
let $checkoutInfo := $checkOutInfo/file[locked='yes']
[fn:tokenize(uri,'/')[fn:last()]=$uploadedFileName]
return
(
$checkoutInfo/locked-by,
$checkoutInfo/previous-version,
$checkoutInfo/latest-version
)
}
</file>
else ()
else
if(fn:ends-with($contentPath,'.docx'))
then
let $uploadedFileName := fn:replace(fn:tokenize($contentPath,'/')[fn:last()],'.docx','.xml')
return
if($checkOutInfo/file[locked='yes'][fn:contains(uri,$uploadedFileName)])
then
<file>
<exist>yes</exist>
<selected-to-checkin>yes</selected-to-checkin>
<uri>{$checkOutInfo/file[locked='yes'][fn:contains(uri,$uploadedFileName)]/uri/text()}</uri>
{
let $checkoutInfo := $checkOutInfo/file[locked='yes']
[fn:tokenize(uri,'/')[fn:last()]=fn:replace($uploadedFileName,'.docx','.xml')]
return
(
$checkoutInfo/locked-by,
$checkoutInfo/previous-version,
$checkoutInfo/latest-version
)
}
</file>
else ()
else ()
}
</lock>
};
declare %updating function JOBS:Copy-MetaContent(
$PipelineXml as document-node(),
$XQuerySteptempLocation as xs:string
)
{
for $MetadataType in $PipelineXml/*:pipeline/*:xquery/*:requires/@metadataType/string()
return
(
if($MetadataType='onix')
then
let $templocation := fn:concat($XQuerySteptempLocation,$MetadataType)
for $Uri in fn:uri-collection(fn:concat($config:OnixDB,'/',$MetadataType))
let $filename := fn:tokenize($Uri,'/')[fn:last()]
let $modifiedFilename := if( fn:ends-with($filename,'.xml')) then $filename else fn:concat($filename,'.xml')
return
(
file:create-dir($templocation),
file:write(fn:concat($templocation,'/',$modifiedFilename),fn:doc($Uri))
)
else
let $templocation := fn:concat($XQuerySteptempLocation,$MetadataType)
for $Uri in fn:uri-collection(fn:concat($config:MetadataOnlyContentDatabase,'/',$MetadataType))
let $filename := fn:tokenize($Uri,'/')[fn:last()]
return
(
file:create-dir($templocation),
file:write(fn:concat($templocation,'/',$filename),fn:doc($Uri))
)
)
};
declare %updating function JOBS:Copy-Content(
$Content as node(),
$XQuerySteptempLocation as xs:string
)
{
let $ContentType := $Content/@sourceContentType/string()
let $DbCollection := if (
$ContentType = "person" or $ContentType = "audio" or
$ContentType = "video" or $ContentType = "organisation" or
$ContentType = "image" or $ContentType = "series" or
$ContentType = "publisher"
)
then ($config:MetadataOnlyContentDatabase||'/'||$ContentType)
else if($ContentType = "reference" or $ContentType = "monograph")
then ($config:MonographDatabase||'/content/')
else if($ContentType = "play")
then ($config:playDatabase||'/content/')
else $ContentType
for $cid in $Content/*:item/@id/string()
for $DocUri in fn:uri-collection($DbCollection)[fn:contains(.,$cid)][fn:not(contains(.,$config:InfoXml) or contains(.,'version.xml'))]
[if($ContentType = 'play' or $ContentType = 'monograph' or $ContentType = 'reference')
then fn:contains(.,'/latest/')
else .
]
let $filename := fn:tokenize($DocUri,'/')[fn:last()]
let $templocation := fn:concat($XQuerySteptempLocation,'content/',$ContentType,'/',$cid)
return
(
file:create-dir($templocation),
file:write(fn:concat($templocation,'/',$filename),fn:doc($DocUri))
(:,
file:create-dir(fn:concat($XQuerySteptempLocation,'Publish/') ):)
)
};
declare %updating function JOBS:Copy-Manifest(
$ProductID as xs:string,
$Content as node(),
$XQuerySteptempLocation as xs:string
)
{
let $templocation := fn:concat($XQuerySteptempLocation,'manifest/')
return
(
file:create-dir($templocation),
file:write(fn:concat($templocation,'/',$ProductID,'.xml'),$Content)
)
};
declare %updating function JOBS:Copy-Content-Management(
$Content as node(),
$XQuerySteptempLocation as xs:string
)
{
for $cid in $Content/*:item/@id/string()
for $ContentManagementUri in fn:uri-collection(fn:concat($config:ContentManagementDatabase,$config:ContentManagementCollection))[contains(.,$cid)]
let $DocId := fn:doc($ContentManagementUri)/*/@id/string()
let $filename := fn:tokenize($ContentManagementUri,'/')[fn:last()]
let $templocation := fn:concat($XQuerySteptempLocation,$config:ContentManagementDatabase,'/',$DocId)
return
(
file:create-dir($templocation),
file:write(fn:concat($templocation,'/',$filename),fn:doc($ContentManagementUri))
)
};
declare %updating function JOBS:Copy-Taxonomy(
$TaxonomyXML as document-node(),
$XQuerySteptempLocation as xs:string
)
{
let $TaxonomyName := $TaxonomyXML/*:taxonomy/@name/string()
let $templocation := fn:concat($XQuerySteptempLocation,'taxonomy/')
return
(
file:create-dir($templocation),
file:write($templocation||$TaxonomyName||'.xml',$TaxonomyXML)
)
};
declare %updating function JOBS:Copy-Metadata(
$Content as element(product:content),
$TempLocation as xs:string
)
{
let $ctype := $Content/@sourceContentType/string()
let $MetaDataCollection := if ($ctype = 'monograph' or $ctype = 'reference')
then
($config:ContentMetadataDatabse||'/'||$config:MonographDatabase||$config:ContentDir)
else if ($ctype = 'play')
then
($config:ContentMetadataDatabse||'/'||$config:playDatabase||$config:ContentDir)
else if (
$ctype = "person" or $ctype = "audio" or
$ctype = "video" or $ctype = "organisation" or
$ctype = "image" or $ctype = "series" or
$ctype = "publisher"
)
then
($config:ContentMetadataDatabse||'/'||$ctype)
let $PipelineId := $Content/@pipelineRef/string()
for $cid in $Content/*:item/@id/string()
for $MetaUri in fn:uri-collection($MetaDataCollection)[contains(.,$cid)][fn:contains(.,'latest')][if(
$ctype = "person" or $ctype = "audio" or
$ctype = "video" or $ctype = "organisation" or
$ctype = "image" or $ctype = "series" or
$ctype = "publisher"
) then fn:contains(.,'classify.xml') else .]
let $filename := fn:tokenize($MetaUri,'/')[fn:last()]
let $templocation := fn:concat($TempLocation,'metadata/')
return
if(file:is-dir($templocation))
then
(
file:write(fn:concat($templocation,'/',$filename),fn:doc($MetaUri))
)
else
(
file:create-dir($templocation),
file:write(fn:concat($templocation,'/',$filename),fn:doc($MetaUri))
)
};
declare %updating function JOBS:Copy-MetadataOnlyContent-metadata(
$Content as element(product:content),
$TempLocation as xs:string
)
{
let $PipelineId := $Content/@pipelineRef/string()
let $PipelineXml := db:open($config:CoreDatabase,$config:PipelineDir||'/'||$PipelineId||'.xml')
for $RequiresContentType in $PipelineXml/*:pipeline/*:xquery/*:requires/@metadataType/string()
return
if($RequiresContentType!='')
then
let $DbCollection := db:open($config:MetadataOnlyContentDatabase,$RequiresContentType)/*
for $Docid in $DbCollection/@id/string()
for $ClassifyUrl in db:open($config:ContentMetadataDatabse,$RequiresContentType)/*:taxonomies[@cid/string()=$Docid]/base-uri()[fn:contains(.,$config:ClassifyXml)]
[fn:contains(.,'/latest/')]
let $filename := fn:tokenize($ClassifyUrl,'/')[fn:last()]
let $templocation := fn:concat($TempLocation,'metadata/')
return
if(file:is-dir($templocation))
then
(
file:write(fn:concat($templocation,'/',$filename),fn:doc($ClassifyUrl))
)
else
(
file:create-dir($templocation),
file:write(fn:concat($templocation,'/',$filename),fn:doc($ClassifyUrl))
)
else()
};
(:~ Return error message to the UI if authentication fails :)
declare
%rest:error("JOBS:job-error")
%rest:error-param("description", "{$message}")
function JOBS:job-error($message)
{
fn:error()
};