teacup/taxonomies.xqm

567 lines
23 KiB
Plaintext

(:~
: Taxonomies functions.
:
: @author Rave Technologies, https://www.rave-tech.com/, 2017
:)
(:~
: Update History :
: Modified on 16/03/21: Resolve ticket CMS-236
:)
module namespace bltaxonomy = 'http://www.rave-tech.com/bloomsbury/taxonomy';
import module namespace config = 'http://www.rave-tech.com/bloomsbury/config' at './module/config.xqm';
import module namespace audit = 'http://www.rave-tech.com/bloomsbury/audit' at './module/manage-audit.xqm';
import module namespace schematron = "http://github.com/Schematron/schematron-basex";
(:~
: Add Taxonomy into the system.
: @param $body Taxonomy XML as document node (<taxonomy><name>ACH-export</name><file-path>D:\2017\BLOOMSBURRY\taxnomy\T003.xml</file-path></taxonomy>)
: @header $authorization Authorization key
: @return element(result)
:)
declare
%updating
%rest:path("/taxonomies")
%rest:POST("{$body}")
%rest:header-param("Authorization", "{$authorization}", "none")
%rest:consumes("application/xml", "text/xml")
function bltaxonomy:add($body as document-node(), $authorization as xs:string)
{
config:session-check($authorization),
try
{
if(fetch:xml($body/taxonomy/file-path/string(),map { 'xinclude': false() })/*[fn:local-name()='taxonomy'])
then
if(fetch:xml($body/taxonomy/file-path/string())/*:taxonomy/@id)
then
update:output(<result><status>Failure</status><message>Attribute id not required</message></result>)
else
if(fn:doc-available($body/taxonomy/file-path/string()))
then
let $taxonomyXml := fn:doc($body/taxonomy/file-path/string())
let $taxonomyID := if($taxonomyXml/taxonomy/@id/string())
then $taxonomyXml/taxonomy/@id/string()
else fn:concat($config:TaxonomyIDPrefix,fn:string(convert:dateTime-to-integer(fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms())))))
let $taxonomyName := $taxonomyXml/taxonomy/@name/string()
let $updatedName := $body/taxonomy/name/string()
let $targetUri := fn:concat($config:TaxonomyDir,$taxonomyID,'.xml')
let $taxonomyXml := if($taxonomyXml/taxonomy/@id/string())
then ()
else
copy $tax := $taxonomyXml
modify insert node (attribute { 'id' } { $taxonomyID }) into $tax/taxonomy
return $tax
return
(:Step 1: Check if taxonomy is already exist :)
if(fn:doc-available(fn:concat($config:CoreDatabase,$targetUri)))
then
(
update:output(<result><status>Failure</status><message>Taxonomy is already available</message></result>),
config:update-message("[Taxonomy Add][Taxonomy is already available : " || $taxonomyID || "]")
)
else
bltaxonomy:validate-and-add-taxonomy($taxonomyXml, $taxonomyID, $taxonomyName, $targetUri, 'Taxonomy Add', config:session-value($authorization), $updatedName)
else
(
update:output(<result><status>Failure</status><message>Taxonomy XML is unrechable on this location</message></result>),
config:update-message("[Taxonomy Add][Taxonomy XML is unrechable on this location]")
)
else update:output(<result><status>Failure</status><message>Please ingest the correct XML</message></result>)
}
catch *
{
admin:write-log("[Taxonomy Add][Error: " || $err:description || "]"),
admin:write-log("[Taxonomy Add][Error: " || $err:additional || "]"),
update:output(<result><status>Error</status><message>Error generated. Please check system log</message></result>)
}
};
(:~
: Update Taxonomy.
: @param $body Taxonomy XML as document node (<taxonomy><name>ACH-export</name><file-path>D:\2017\BLOOMSBURRY\taxnomy\T003.xml</file-path></taxonomy>)
: @header $authorization Authorization key
: @return element(result)
:)
declare
%updating
%rest:path("/taxonomies/{$taxonomyID=.+}")
%rest:PUT("{$body}")
%rest:header-param("Authorization", "{$authorization}", "none")
%rest:consumes("application/xml", "text/xml")
function bltaxonomy:update(
$body as document-node(),
$taxonomyID as xs:string,
$authorization as xs:string
)
{
config:session-check($authorization),
try
{
if(fn:doc-available($body/taxonomy/file-path/string()))
then
let $fileLocation := $body/taxonomy/file-path/string()
let $taxonomyXml := fn:doc($fileLocation)
let $taxonomyXml := if($taxonomyXml/taxonomy/@id/string())
then ()
else
copy $tax := $taxonomyXml
modify insert node (attribute { 'id' } { $taxonomyID }) into $tax/taxonomy
return $tax
return
if($taxonomyXml/taxonomy/@id/string() != $taxonomyID)
then
(
update:output(<result><status>Failure</status><message>Taxonomy ID is invalid</message></result>),
config:update-message("[Taxonomy Update][Taxonomy ID is invalid]")
)
else
let $taxonomyName := $taxonomyXml/taxonomy/@name/string()
let $updatedName := $body/taxonomy/name/string()
let $targetUri := fn:concat($config:TaxonomyDir,$taxonomyID,'.xml')
return
if(fn:doc-available(fn:concat($config:CoreDatabase,$targetUri)))
then bltaxonomy:validate-and-add-taxonomy($taxonomyXml,$taxonomyID,$taxonomyName,$targetUri,'Taxonomy Update',config:session-value($authorization),$updatedName)
else
(
update:output(<result><status>Failure</status><message>Taxonomy is not available to update</message></result>),
config:update-message("[Taxonomy Update][Taxonomy is not available to update : " || $taxonomyID || "]")
)
else
if($body/taxonomy/file-path='')
then
let $taxonomyXml := db:open($config:CoreDatabase,$config:TaxonomyDir)/taxonomy[@id=$taxonomyID]
return
if($taxonomyXml)
then
let $taxonomyName := $taxonomyXml/@name/string()
let $updatedName := $body/taxonomy/name/string()
let $targetUri := fn:concat($config:TaxonomyDir,$taxonomyID,'.xml')
return
bltaxonomy:validate-and-add-taxonomy(document{$taxonomyXml},$taxonomyID,$taxonomyName,$targetUri,'Taxonomy Update',config:session-value($authorization),$updatedName)
else
(
update:output(<result><status>Failure</status><message>Taxonomy is not available to update</message></result>),
config:update-message("[Taxonomy Update][Taxonomy is not available to update : " || $taxonomyID || "]")
)
else
(
update:output(<result><status>Failure</status><message>Taxonomy XML is unrechable on this location</message></result>),
config:update-message("[Taxonomy Update][Taxonomy XML is unrechable on this location]")
)
}
catch *
{
admin:write-log("[Taxonomy Update][Error: " || $err:description || "]"),
admin:write-log("[Taxonomy Update][Error: " || $err:additional || "]"),
update:output(<result><status>Error</status><message>Error generated. Please check system log</message></result>)
}
};
(:~
: Display Taxonomy specific detail.
: @param $taxonomyID ID of the taxonomy
: @header $authorization Authorization key
: @return element(result)
:)
declare
%rest:path("/taxonomies/{$taxonomyID=.+}")
%rest:GET
%rest:header-param("Authorization", "{$authorization}", "none")
function bltaxonomy:info(
$taxonomyID as xs:string,
$authorization as xs:string
)
{
config:session-check($authorization),
try
{
let $targetUri := fn:concat($config:TaxonomyDir,$taxonomyID,'.xml')
let $taxonomyXml := db:open($config:CoreDatabase,$targetUri)
return
if($taxonomyXml)
then
(
<result><status>Success</status><message>Taxonomy is available</message>{$taxonomyXml}</result>,
config:non-update-message("[Taxonomy Info][Taxonomy information has been sent successfully : " || $taxonomyID || "]")
)
else
(
<result><status>Failure</status><message>Taxonomy is unavailable</message></result>,
config:non-update-message("[Taxonomy Info][Taxonomy is unavailable : " || $taxonomyID || "]")
)
}
catch *
{
admin:write-log("[Taxonomy Info][Error: " || $err:description || "]"),
admin:write-log("[Taxonomy Info][Error: " || $err:additional || "]"),
<result><status>Error</status><message>Error generated. Please check system log</message></result>
}
};
(:~
: To get specific or list of available taxonomies.
: @param $query Name of the taxonomy to filter
: @param $page Page number of the list optional
: @param $size Total number of records to display in a page optional
: @header $authorization Authorization key
: @return element(result)
:)
declare
%rest:path("/taxonomies")
%rest:GET
%rest:query-param("q", "{$query}")
%rest:query-param("page", "{$page}")
%rest:query-param("size", "{$size}")
%rest:header-param("Authorization", "{$authorization}", "none")
function bltaxonomy:list(
$query 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 $taxonomyRecords := <taxonomies>{
for $eachTaxonomy in db:open($config:CoreDatabase,$config:TaxonomyDir)/taxonomy[if($query) then (matches(@name,$query,'i')) else .]
let $id := <id>{$eachTaxonomy/@id/string()}</id>
let $name := <name>{$eachTaxonomy/@name/string()}</name>
order by $name
return <taxonomy>{$id,$name}</taxonomy>
}</taxonomies>
let $countRecord := count($taxonomyRecords/taxonomy)
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($taxonomyRecords/taxonomy)
then
(
<result><status>Success</status><total>{$countRecord}</total><entities>{$taxonomyRecords/taxonomy[position() = $start to $end]}</entities></result>,
config:non-update-message("[Taxonomy List][Taxonomy list has been sent successfully]")
)
else
(
<result><status>Success</status><message>Taxonomy is unavailable</message></result>,
config:non-update-message("[Taxonomy List][Taxonomy is unavailable]")
)
}
catch *
{
admin:write-log("[Taxonomy List][Error: " || $err:description || "]"),
admin:write-log("[Taxonomy List][Error: " || $err:additional || "]"),
<result><status>Error</status><message>Error generated. Please check system log</message></result>
}
};
(:~
: Delete specific taxonomy.
: @param $taxonomyID ID of the taxonomy to delete
: @header $authorization Authorization key
: @return element(result)
:)
declare
%updating
%rest:path("/taxonomies/{$taxonomyID=.+}")
%rest:DELETE
%rest:header-param("Authorization", "{$authorization}")
function bltaxonomy:delete(
$taxonomyID as xs:string,
$authorization as xs:string
)
{
config:session-check($authorization),
try
{
let $targetUri := fn:concat($config:TaxonomyDir,$taxonomyID,'.xml')
let $producttaxonomy := db:open($config:CoreDatabase,$config:ProductDir)/*:product/@taxonomyRef/string()
return
if($taxonomyID=$producttaxonomy)
then
update:output(<result><status>Failure</status><message>taxonomy {$taxonomyID} is in used</message></result>)
else
if(fn:doc-available(fn:concat($config:CoreDatabase,$targetUri)))
then
(
db:delete($config:CoreDatabase,fn:concat($config:TaxonomyDir,$taxonomyID,'.xml')),
update:output(<result><status>Success</status><message>Taxonomy {$taxonomyID} deleted successfully</message></result>),
config:update-message("[Taxonomy Delete][TaxonomyID deleted successfully : " || $taxonomyID || "]")
)
else update:output(<result><status>Success</status><message>Taxonomy {$taxonomyID} not available to delete</message></result>)
}
catch *
{
admin:write-log("[Taxonomy Delete][Error: " || $err:description || "]"),
admin:write-log("[Taxonomy Delete][Error: " || $err:additional || "]"),
update:output(<result><status>Error</status><message>Error generated. Please check system log</message></result>)
}
};
(:~
: Add or update taxonomies.
: @param $taxonomyXml Taxonomy XML content
: @param $taxonomyID ID of the taxonomy
: @param $name Name of the taxonomy
: @param $targetUri The saving path of the taxonomy
: @param $messageFlag The action of taxonomy (add or update)
: @param $sessionValue Session Value
: @param $title Updated title of the taxonomy
: @return element(result)
:)
declare %private %updating function bltaxonomy:validate-and-add-taxonomy(
$taxonomyXml as document-node(),
$taxonomyID as xs:string?,
$taxonomyName as xs:string,
$targetUri as xs:string,
$messageFlag as xs:string,
$sessionValue as xs:string,
$title as xs:string?
)
{
(:Step 1: Validate as per Relax NG :)
let $taxonomyXml := if($title)
then
(
copy $c := $taxonomyXml
modify ( replace value of node $c/taxonomy/@name with $title )
return $c
)
else $taxonomyXml
let $reportChunk := <report>
<info>
<id>{$taxonomyID}</id>
<name>{$title}</name>
<submitted-on>{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}</submitted-on>
<requester-id>{fn:substring-before($sessionValue,'$$$$')}</requester-id>
<requester-email>{fn:substring-after($sessionValue,'$$$$')}</requester-email>
</info>
<ingestion-report>
<steps/>
</ingestion-report>
</report>
let $startTime := fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))
let $validate := validate:rng-report($taxonomyXml, bin:decode-string(db:retrieve($config:CoreDatabase, fn:concat($config:ValidationDir,$config:TaxonomyRelaxNG)),'UTF-8'), fn:true())
return
if($validate/status='valid')
then
(
config:update-message("[" || $messageFlag || "][Taxonomy is valid as per Relax NG : " || $taxonomyID || "]")
,
let $appendReport := let $updateReport := <step>
<type>RELAX NG Validation</type>
<started-on>{$startTime}</started-on>
<completed-on>{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}</completed-on>
<status>Pass</status>
<error></error>
</step>
return
copy $target := $reportChunk
modify insert node $updateReport as last into $target/ingestion-report/steps
return $target
return
(:Step 2: Validate as per Schematron :)
let $startTime := fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))
let $schematron := schematron:compile(db:open($config:CoreDatabase, fn:concat($config:ValidationDir,$config:TaxonomySchematron)))
let $validate := schematron:validate($taxonomyXml, $schematron)
return
if(schematron:is-valid($validate))
then
(
db:replace($config:CoreDatabase,$targetUri,$taxonomyXml),
audit:taxonomy($taxonomyID,$messageFlag,$sessionValue)
,
let $appendReport := let $updateReport := <step>
<type>Schematron Validation</type>
<started-on>{$startTime}</started-on>
<completed-on>{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}</completed-on>
<status>Pass</status>
<error></error>
</step>
return
copy $target := $appendReport
modify
(
insert node $updateReport as last into $target/ingestion-report/steps,
insert node <finished-on>{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}</finished-on> as last into $target/ingestion-report
)
return $target
let $reportUri := fn:concat($config:TaxonomyDir,$config:ReportDir,$taxonomyID,'_report.xml')
return db:replace($config:CoreDatabase,$reportUri,$appendReport)
,
config:update-message("[" || $messageFlag || "][Taxonomy is valid as per schematron : " || $taxonomyID || "]"),
config:update-message("[" || $messageFlag || "][A new Taxonomy added into the system : " || $taxonomyID || "]"),
update:output(<result><status>Success</status><message>{$messageFlag}</message></result>)
)
else
(
let $appendReport := let $updateReport := <step>
<type>Schematron Validation</type>
<started-on>{$startTime}</started-on>
<completed-on>{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}</completed-on>
<status>Fail</status>
<error>{$validate}</error>
</step>
return
copy $target := $appendReport
modify
(
insert node $updateReport as last into $target/ingestion-report/steps,
insert node <finished-on>{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}</finished-on> as last into $target/ingestion-report
)
return $target
let $reportUri := fn:concat($config:TaxonomyDir,$config:ReportDir,if($taxonomyID!='') then $taxonomyID else fn:format-dateTime(fn:current-dateTime(), "[Y1,4][M01][D01][H01][m01][s01][f01]"),'_report.xml')
return
(
db:replace($config:CoreDatabase,$reportUri,$appendReport),
update:output(<result><status>Failure</status><taxonomyId>{if($taxonomyID!='') then $taxonomyID else fn:replace(fn:tokenize($reportUri,'/')[fn:last()],'.xml','')}</taxonomyId><message>Taxonomy is invalid as per schematron validation. Error report generated</message>
</result>),
config:update-message("["|| $messageFlag || "][Taxonomy is invalid as per schematron : " || $taxonomyID || "]")
)
)
)
else
(
let $appendReport := let $updateReport := <step>
<type>RELAX NG Validation</type>
<started-on>{$startTime}</started-on>
<completed-on>{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}</completed-on>
<status>Fail</status>
<error>{$validate}</error>
</step>
return
copy $target := $reportChunk
modify
(
insert node $updateReport as last into $target/ingestion-report/steps,
insert node <finished-on>{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}</finished-on> as last into $target/ingestion-report
)
return $target
(:let $reportUri := fn:concat($config:TaxonomyDir,$config:ReportDir,$taxonomyID,'_report.xml'):)
let $reportUri := fn:concat($config:TaxonomyDir,$config:ReportDir,if($taxonomyID!='') then $taxonomyID else fn:format-dateTime(fn:current-dateTime(), "[Y1,4][M01][D01][H01][m01][s01][f01]"),'_report.xml')
return
(
db:replace($config:CoreDatabase,$reportUri,$appendReport)
,
config:update-message("[" || $messageFlag || "][Taxonomy is invalid as per Relax NG : " || $taxonomyID || "]"),
update:output(<result><status>Failure</status><taxonomyId>{if($taxonomyID!='') then $taxonomyID else fn:replace(fn:tokenize($reportUri,'/')[fn:last()],'_report.xml','')}</taxonomyId><message>Taxonomy is invalid as per Relax NG. Error report generated</message></result>)
)
)
};
(:~
: To Download Taxonomy error report
: @param $taxonomyID ID of the taxonomy
: @header $authorization Authorization key
: @return element(result)
:)
declare
%rest:path("/taxonomyreport/{$taxonomyID=.+}")
%rest:GET
%rest:header-param("Authorization", "{$authorization}", "none")
function bltaxonomy:taxonomyreport(
$taxonomyID as xs:string?,
$authorization as xs:string
)
{
config:session-check($authorization),
try
{
let $taxonomyErrordoc := db:open($config:CoreDatabase, fn:concat($config:TaxonomyDir,$config:ReportDir,$taxonomyID,'_report','.xml'))
return
if($taxonomyErrordoc)
then
let $uri := base-uri($taxonomyErrordoc)
let $filename := fn:tokenize($uri,'/')[fn:last()]
return
(
if(file:is-dir($config:PublishReportDir))
then
file:write(fn:concat($config:PublishReportDir,$filename),$taxonomyErrordoc)
else
(
file:create-dir($config:PublishReportDir),
file:write(fn:concat($config:PublishReportDir,$filename),$taxonomyErrordoc))
,
let $zipName := fn:concat($taxonomyID,'_',fn:format-dateTime(fn:current-dateTime(), "[Y1,4][M01][D01][H01][m01][s01][f01]"))
let $filelist := file:list($config:PublishReportDir, true(),fn:concat($taxonomyID,'_report','.xml'))
let $archive := archive:create($filelist ! element archive:entry { . }, $filelist ! file:read-binary($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>
}
};
declare
%rest:path("/contenttypefacet/{$taxonomyid=.+}")
%rest:GET
%rest:header-param("Authorization", "{$authorization}", "none")
function bltaxonomy:get-taxonomies-contenttypefacet(
$taxonomyid as xs:string,
$authorization as xs:string
)
{
config:session-check($authorization),
try
{ if($taxonomyid!='')
then
let $records := for $tyaxonomydoc in fn:doc(fn:concat($config:CoreDatabase,$config:TaxonomyDir,$taxonomyid,'.xml'))
return
if($tyaxonomydoc)
then
<taxonomy id= "{$tyaxonomydoc/taxonomy/@id/string()}" name="{$tyaxonomydoc/taxonomy/@name/string()}" releaseDate="{$tyaxonomydoc/taxonomy/@releaseDate/string()}">{$tyaxonomydoc/taxonomy/*[(descendant-or-self::*:facet[@role='contentType'])] }</taxonomy>
else <error/>
return
if($records[fn:local-name()='error'])
then <result><status>Success</status><message>Related taxonomies is not available.</message></result>
else <result><status>Success</status><entities>{$records}</entities></result>
else <result><status>Failure</status><message>Please supply the content-id and component-id</message></result>
}
catch *
{
admin:write-log("[Content Search][Error: " || $err:description || "]"),
admin:write-log("[Content Search][Error: " || $err:additional || "]"),
<result><status>Error</status><message>Error generated. Please check system log</message></result>
}
};