(:~
: 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 (ACH-exportD:\2017\BLOOMSBURRY\taxnomy\T003.xml)
: @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(FailureAttribute id not required)
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(FailureTaxonomy is already available),
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(FailureTaxonomy XML is unrechable on this location),
config:update-message("[Taxonomy Add][Taxonomy XML is unrechable on this location]")
)
else update:output(FailurePlease ingest the correct XML)
}
catch *
{
admin:write-log("[Taxonomy Add][Error: " || $err:description || "]"),
admin:write-log("[Taxonomy Add][Error: " || $err:additional || "]"),
update:output(ErrorError generated. Please check system log)
}
};
(:~
: Update Taxonomy.
: @param $body Taxonomy XML as document node (ACH-exportD:\2017\BLOOMSBURRY\taxnomy\T003.xml)
: @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(FailureTaxonomy ID is invalid),
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(FailureTaxonomy is not available to update),
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(FailureTaxonomy is not available to update),
config:update-message("[Taxonomy Update][Taxonomy is not available to update : " || $taxonomyID || "]")
)
else
(
update:output(FailureTaxonomy XML is unrechable on this location),
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(ErrorError generated. Please check system log)
}
};
(:~
: 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
(
SuccessTaxonomy is available{$taxonomyXml},
config:non-update-message("[Taxonomy Info][Taxonomy information has been sent successfully : " || $taxonomyID || "]")
)
else
(
FailureTaxonomy is unavailable,
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 || "]"),
ErrorError generated. Please check system log
}
};
(:~
: 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 := {
for $eachTaxonomy in db:open($config:CoreDatabase,$config:TaxonomyDir)/taxonomy[if($query) then (matches(@name,$query,'i')) else .]
let $id := {$eachTaxonomy/@id/string()}
let $name := {$eachTaxonomy/@name/string()}
order by $name
return {$id,$name}
}
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
(
Success{$countRecord}{$taxonomyRecords/taxonomy[position() = $start to $end]},
config:non-update-message("[Taxonomy List][Taxonomy list has been sent successfully]")
)
else
(
SuccessTaxonomy is unavailable,
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 || "]"),
ErrorError generated. Please check system log
}
};
(:~
: 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(Failuretaxonomy {$taxonomyID} is in used)
else
if(fn:doc-available(fn:concat($config:CoreDatabase,$targetUri)))
then
(
db:delete($config:CoreDatabase,fn:concat($config:TaxonomyDir,$taxonomyID,'.xml')),
update:output(SuccessTaxonomy {$taxonomyID} deleted successfully),
config:update-message("[Taxonomy Delete][TaxonomyID deleted successfully : " || $taxonomyID || "]")
)
else update:output(SuccessTaxonomy {$taxonomyID} not available to delete)
}
catch *
{
admin:write-log("[Taxonomy Delete][Error: " || $err:description || "]"),
admin:write-log("[Taxonomy Delete][Error: " || $err:additional || "]"),
update:output(ErrorError generated. Please check system log)
}
};
(:~
: 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 :=
{$taxonomyID}
{$title}
{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}
{fn:substring-before($sessionValue,'$$$$')}
{fn:substring-after($sessionValue,'$$$$')}
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 :=
RELAX NG Validation
{$startTime}
{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}
Pass
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 :=
Schematron Validation
{$startTime}
{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}
Pass
return
copy $target := $appendReport
modify
(
insert node $updateReport as last into $target/ingestion-report/steps,
insert node {fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))} 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(Success{$messageFlag})
)
else
(
let $appendReport := let $updateReport :=
Schematron Validation
{$startTime}
{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}
Fail
{$validate}
return
copy $target := $appendReport
modify
(
insert node $updateReport as last into $target/ingestion-report/steps,
insert node {fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))} 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(Failure{if($taxonomyID!='') then $taxonomyID else fn:replace(fn:tokenize($reportUri,'/')[fn:last()],'.xml','')}Taxonomy is invalid as per schematron validation. Error report generated
),
config:update-message("["|| $messageFlag || "][Taxonomy is invalid as per schematron : " || $taxonomyID || "]")
)
)
)
else
(
let $appendReport := let $updateReport :=
RELAX NG Validation
{$startTime}
{fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))}
Fail
{$validate}
return
copy $target := $reportChunk
modify
(
insert node $updateReport as last into $target/ingestion-report/steps,
insert node {fn:adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()))} 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(Failure{if($taxonomyID!='') then $taxonomyID else fn:replace(fn:tokenize($reportUri,'/')[fn:last()],'_report.xml','')}Taxonomy is invalid as per Relax NG. Error report generated)
)
)
};
(:~
: 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),
Success
{$ziplocation}
)
)
else FailureJob information is not available
}
catch *
{
admin:write-log("[Job Details][Error: " || $err:description || "]"),
admin:write-log("[Job Details][Error: " || $err:additional || "]"),
ErrorError generated. Please check system log
}
};
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
{$tyaxonomydoc/taxonomy/*[(descendant-or-self::*:facet[@role='contentType'])] }
else
return
if($records[fn:local-name()='error'])
then SuccessRelated taxonomies is not available.
else Success{$records}
else FailurePlease supply the content-id and component-id
}
catch *
{
admin:write-log("[Content Search][Error: " || $err:description || "]"),
admin:write-log("[Content Search][Error: " || $err:additional || "]"),
ErrorError generated. Please check system log
}
};