teacup/download.xqm

452 lines
21 KiB
Plaintext
Raw Normal View History

2021-12-15 11:29:23 +00:00
(:~
: Download content from the DB
:
: @author Rave Technologies, https://www.rave-tech.com/, 2017
:)
module namespace download = 'http://www.rave-tech.com/bloomsbury/download';
import module namespace config = 'http://www.rave-tech.com/bloomsbury/config' at './module/config.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';
(:~
: To download complete bunch of content from the database into the file system within zip
: <download><content><coid></coid><version>v1</version><uri>../dummy/fileurl</uri></content>...</content>
: @param $cid Content ID to download its component
: @param $format Content format to download (word,xml)
: @param $type A flat to download all content (all,none)
: @header $authorization Authorization key
: @return element(result)
:)
declare
%updating
%rest:path("/download")
%rest:POST("{$body}")
%rest:query-param("format", "{$format}", "NONE")
%rest:query-param("type", "{$type}", "NONE")
%rest:header-param("Authorization", "{$authorization}", "none")
%rest:consumes("application/xml", "text/xml")
function download:download(
$body as document-node(),
$format as xs:string,
$type as xs:string,
$authorization as xs:string
)
{
config:session-check($authorization),
try
{
if(fn:doc-available(fn:concat($config:CoreDatabase,$config:DownloadConfig)))
then
if($format='NONE' or $type="NONE")
then update:output(<result><status>Failure</status><message>Please supply correct parameters</message></result>)
else
if($format='xml' or $format='word')
then download:start-process($body,$format,$type,config:session-value($authorization))
else update:output(<result><status>Failure</status><message>Format other than XML/Word not supported</message></result>)
else update:output(<result><status>Failure</status><message>{fn:concat('Configuration file is not available :', $config:DownloadConfig)}</message></result>)
}
catch *
{
admin:write-log("[Download][Error: " || $err:description || "]"),
admin:write-log("[Download][Error: " || $err:additional || "]"),
update:output(<result><status>Error</status><message>Error generated. Please check system log</message></result>)
}
};
(:~
: Download content as XML from the database.
: @param $inputXml Download parameter chunk of the request
: @param $format Required download format (xml,word)
: @param $type A flat to download all content (all,none)
: @param $sessionValue Session Value
: @return element(result)
:)
(:declare %private %updating function download:start-process(
$inputXml as document-node(),
$format as xs:string,
$type as xs:string,
$sessionValue as xs:string
)
{
let $zipName := fn:format-dateTime(fn:current-dateTime(), "[Y1,4][M01][D01][H01][m01][s01][f01]")
let $zipUri := fn:concat($config:OutDir, $zipName,'.zip')
let $countDownload := fn:count($inputXml/download/content)
let $Uri := for $inputContent in $inputXml/download/content
return
if($type='all' and fn:not(matches(string-join($inputXml/download/content/uri/text(),'|'),'version')))
then
for $db in db:list()[not(contains(.,'bloomsbury'))]
return
fn:uri-collection(fn:concat($db,$config:ContentDir,$inputContent/cid))[fn:not(fn:contains(.,$config:AuditFileName)
or fn:contains(.,$config:VersionControlFileName)
or fn:contains(.,$config:InfoXml)
or fn:contains(.,$config:MetaXml)
or fn:contains(.,$config:WordDir)
or fn:contains(.,$config:VersionDir)
or fn:contains(.,$config:ClassifyXml)
)]
else if($type='all' and matches(string-join($inputXml/download/content/uri/text(),'|'),'version'))
then
for $db in db:list()[not(contains(.,'bloomsbury'))]
return
fn:uri-collection(fn:concat($db,$config:ContentDir,$inputContent/cid))[fn:not(fn:contains(.,$config:AuditFileName)
or fn:contains(.,$config:VersionControlFileName)
or fn:contains(.,$config:InfoXml)
or fn:contains(.,$config:MetaXml)
or fn:contains(.,$config:WordDir)
or fn:contains(.,$config:ClassifyXml)
)]
[fn:contains(.,fn:concat('v',$inputContent/version/text()))]
else $inputContent/uri/text()
let $zip := archive:create
(
for $dbUri in $Uri
let $cid := fn:tokenize($dbUri,'/')[4]
let $coid := fn:tokenize($dbUri,'/')[5]
let $contentType := fn:tokenize($dbUri,'/')[2]
let $supportedFormat := db:open($config:CoreDatabase,$config:DownloadConfig)/*:controlledList/*:name[@ctype-idref=$contentType]/@cformat-idref/string()
let $outputFormat := if(fn:contains($supportedFormat,fn:replace($format,'word','docx')))
then $format
else 'xml'
let $isDeleted := db:open(blcommon:get-db-name($contentType),fn:concat($config:ContentDir,$cid,'/',$coid,'/',$config:InfoXml))/info/delete/text()
return
if($isDeleted='yes')
then ()
else
(:if(fn:contains($dbUri,$config:HeaderXml) or $outputFormat='xml')
then if($type='all') then element archive:entry { fn:concat($cid,'/',fn:tokenize($dbUri,'/')[fn:last()]) } else()
else element archive:entry { fn:concat($cid,'/',fn:replace(fn:tokenize($dbUri,'/')[fn:last()],'.xml','.docx')) }:)
if(fn:contains($dbUri,$config:HeaderXml) or $outputFormat='xml')
then element archive:entry { fn:concat($cid,'/',fn:tokenize($dbUri,'/')[fn:last()]) }
else element archive:entry { fn:concat($cid,'/',fn:replace(fn:tokenize($dbUri,'/')[fn:last()],'.xml','.docx')) }
,
for $dbUri in $Uri
let $cid := fn:tokenize($dbUri,'/')[4]
let $coid := fn:tokenize($dbUri,'/')[5]
let $contentType := fn:tokenize($dbUri,'/')[2]
let $supportedFormat := db:open($config:CoreDatabase,$config:DownloadConfig)/*:controlledList/*:name[@ctype-idref=$contentType]/@cformat-idref/string()
let $outputFormat := if(fn:contains($supportedFormat,fn:replace($format,'word','docx')))
then $format
else 'xml'
let $isDeleted := db:open(blcommon:get-db-name($contentType),fn:concat($config:ContentDir,$cid,'/',$coid,'/',$config:InfoXml))/info/delete/text()
let $isPrintReady := db:open(blcommon:get-db-name($contentType),fn:concat($config:ContentDir,$cid,'/',$coid,'/',$config:InfoXml))/info/content-format/text()
return
if($isDeleted='yes')
then ()
else
if(fn:contains($dbUri,$config:HeaderXml) or $outputFormat='xml')
then bin:encode-string(fn:serialize((fn:doc($dbUri))))
(:bin:encode-string(fn:serialize( fn:doc($dbUri) ,map {'indent': 'no'})):)
else
(
let $inputFileName := fn:tokenize($dbUri,'/')[fn:last()]
let $inputUri := fn:replace(fn:concat(fn:substring-before($dbUri,$inputFileName),$config:WordDir,fn:replace($inputFileName,'.xml','.docx')),'//','/')
let $WordUri := fn:concat($config:OutDir, fn:replace(fn:tokenize($dbUri,'/')[fn:last()],'.xml','.docx'))
let $archive := db:retrieve(blcommon:get-db-name($contentType),fn:substring-after($inputUri,blcommon:get-db-name($contentType)))
let $worlRelation := fn:parse-xml(archive:extract-text($archive, $config:DocRelXml))
let $wordStyle := fn:parse-xml(archive:extract-text($archive, $config:StyleXml))
let $writeRelation := file:write(fn:concat($config:TempDir,$inputFileName), $worlRelation)
let $updateWord := if($isPrintReady='PRINT-READY')
then $archive
else archive:update($archive, $config:DocXml, fn:serialize(xslt:transform(fn:doc($dbUri), db:open($config:CoreDatabase,$config:DocBook2WordML),map { 'relFilePath':fn:concat($config:TempDir,$inputFileName)})))
let $updateStyle := if($isPrintReady='PRINT-READY')
then $updateWord
else archive:update($updateWord, $config:StyleXml, fn:serialize(xslt:transform($wordStyle, db:open($config:CoreDatabase,$config:WordStyle))))
return $updateStyle
)
)
return
(
if(file:is-dir($config:OutDir))
then ()
else file:create-dir($config:OutDir)
,
file:write-binary($zipUri, $zip)
,
for $dbUri in $Uri
let $contentType := fn:tokenize($dbUri,'/')[2]
return audit:update($dbUri,$contentType,$sessionValue,'Download')
,
update:output(<result><status>Success</status><message>Zip generated. Pls. check the output</message><path>{$zipUri}</path></result>)
,
config:update-message('[Content Download][Zip generated ' || $zipUri || ']')
)
};
:)
declare %private %updating function download:start-process(
$inputXml as document-node(),
$format as xs:string,
$type as xs:string,
$sessionValue as xs:string
)
{
let $zipName := fn:format-dateTime(fn:current-dateTime(), "[Y1,4][M01][D01][H01][m01][s01][f01]")
let $zipUri := fn:concat($config:OutDir, $zipName,'.zip')
let $countDownload := fn:count($inputXml/download/content)
let $Uri := for $inputContent in $inputXml/download/content
return
if($type='all' and fn:not(matches(string-join($inputXml/download/content/uri/text(),'|'),'version')))
then
for $db in db:list()[not(contains(.,'bloomsbury') or contains(.,$config:ContentManagementDatabase) or contains(.,$config:MetadataOnlyContentDatabase) or contains(.,$config:OnixDB ))]
return
fn:uri-collection(fn:concat($db,$config:ContentDir,$inputContent/cid))[fn:not(fn:contains(.,$config:AuditFileName)
or fn:contains(.,$config:VersionControlFileName)
or fn:contains(.,$config:InfoXml)
or fn:contains(.,$config:MetaXml)
or fn:contains(.,$config:WordDir)
or fn:contains(.,$config:VersionDir)
or fn:contains(.,$config:ClassifyXml)
)]
else if($type='all' and matches(string-join($inputXml/download/content/uri/text(),'|'),'version'))
then
for $db in db:list()[not(contains(.,'bloomsbury') or contains(.,$config:ContentManagementDatabase) or contains(.,$config:MetadataOnlyContentDatabase) or contains(.,$config:OnixDB ))]
return
fn:uri-collection(fn:concat($db,$config:ContentDir,$inputContent/cid))[fn:not(fn:contains(.,$config:AuditFileName)
or fn:contains(.,$config:VersionControlFileName)
or fn:contains(.,$config:InfoXml)
or fn:contains(.,$config:MetaXml)
or fn:contains(.,$config:WordDir)
or fn:contains(.,$config:ClassifyXml)
)]
[fn:contains(.,fn:concat('v',$inputContent/version/text()))]
else $inputContent/uri/text()
let $zip := archive:create
(
for $dbUri in $Uri
let $cid := fn:tokenize($dbUri,'/')[4]
let $coid := fn:tokenize($dbUri,'/')[5]
let $contentType := fn:tokenize($dbUri,'/')[2]
let $supportedFormat := db:open($config:CoreDatabase,$config:DownloadConfig)/*:controlledList/*:name[@ctype-idref=$contentType]/@cformat-idref/string()
(:let $outputFormat := if(fn:contains($supportedFormat,fn:replace($format,'word','docx')))
then $format
else 'xml':)
let $outputFormat := if(($contentType='monograph') or ($contentType='play'))
then $supportedFormat
else if ($contentType='looseleaf')
then
if($format='word') then 'docx'
else '.xml'
let $isDeleted := db:open(blcommon:get-db-name($contentType),fn:concat($config:ContentDir,$cid,'/',$coid,'/',$config:InfoXml))/info/delete/text()
return
if($isDeleted='yes')
then ()
else
if(fn:contains($dbUri,$config:HeaderXml) or $outputFormat='xml')
then if($type='all') then element archive:entry { fn:concat($cid,'/',fn:tokenize($dbUri,'/')[fn:last()]) } else()
else element archive:entry { fn:concat($cid,'/',fn:replace(fn:tokenize($dbUri,'/')[fn:last()],'.xml','.docx')) }
,
for $dbUri in $Uri
let $cid := fn:tokenize($dbUri,'/')[4]
let $coid := fn:tokenize($dbUri,'/')[5]
let $contentType := fn:tokenize($dbUri,'/')[2]
let $supportedFormat := db:open($config:CoreDatabase,$config:DownloadConfig)/*:controlledList/*:name[@ctype-idref=$contentType]/@cformat-idref/string()
(:let $outputFormat := if(fn:contains($supportedFormat,fn:replace($format,'word','docx')))
then $format
else 'xml':)
let $outputFormat := if(($contentType='monograph') or ($contentType='play'))
then $supportedFormat
else if ($contentType='looseleaf')
then
if($format='word') then 'docx'
else '.xml'
let $isDeleted := db:open(blcommon:get-db-name($contentType),fn:concat($config:ContentDir,$cid,'/',$coid,'/',$config:InfoXml))/info/delete/text()
let $isPrintReady := db:open(blcommon:get-db-name($contentType),fn:concat($config:ContentDir,$cid,'/',$coid,'/',$config:InfoXml))/info/content-format/text()
return
if($isDeleted='yes')
then ()
else
if(fn:contains($dbUri,$config:HeaderXml) or $outputFormat='xml')
then if($type='all') then bin:encode-string(fn:serialize((fn:doc($dbUri)))) else ()
else
(
let $inputFileName := fn:tokenize($dbUri,'/')[fn:last()]
let $inputUri := fn:replace(fn:concat(fn:substring-before($dbUri,$inputFileName),$config:WordDir,fn:replace($inputFileName,'.xml','.docx')),'//','/')
let $WordUri := fn:concat($config:OutDir, fn:replace(fn:tokenize($dbUri,'/')[fn:last()],'.xml','.docx'))
let $archive := db:retrieve(blcommon:get-db-name($contentType),fn:substring-after($inputUri,blcommon:get-db-name($contentType)))
let $worlRelation := fn:parse-xml(archive:extract-text($archive, $config:DocRelXml))
let $wordStyle := fn:parse-xml(archive:extract-text($archive, $config:StyleXml))
let $writeRelation := file:write(fn:concat($config:TempDir,$inputFileName), $worlRelation)
let $updateWord := if($isPrintReady='PRINT-READY')
then $archive
else archive:update($archive, $config:DocXml, fn:serialize(xslt:transform(fn:doc($dbUri), db:open($config:CoreDatabase,$config:DocBook2WordML),map { 'relFilePath':fn:concat($config:TempDir,$inputFileName)})))
let $updateStyle := if($isPrintReady='PRINT-READY')
then $updateWord
else archive:update($updateWord, $config:StyleXml, fn:serialize(xslt:transform($wordStyle, db:open($config:CoreDatabase,$config:WordStyle))))
return $updateStyle
)
)
let $xmlarchive := zip:zip-file(
<file xmlns="http://expath.org/ns/zip" href="{$config:Xmlziplocation}">
{
for $dbUri in $Uri
let $cid := fn:tokenize($dbUri,'/')[4]
let $coid := fn:tokenize($dbUri,'/')[5]
let $filename := fn:tokenize($dbUri,'/')[fn:last()]
let $contentType := fn:tokenize($dbUri,'/')[2]
let $supportedFormat := db:open($config:CoreDatabase,$config:DownloadConfig)/*:controlledList/*:name[@ctype-idref=$contentType]/@cformat-idref/string()
let $outputFormat := if(fn:contains($supportedFormat,fn:replace($format,'word','docx')))
then $format
else 'xml'
let $isDeleted := db:open(blcommon:get-db-name($contentType),fn:concat($config:ContentDir,$cid,'/',$coid,'/',$config:InfoXml))/info/delete/text()
let $isPrintReady := db:open(blcommon:get-db-name($contentType),fn:concat($config:ContentDir,$cid,'/',$coid,'/',$config:InfoXml))/info/content-format/text()
return
if($isDeleted='yes')
then ()
else
<entry name="{$filename}" indent="no">{fn:doc($dbUri)}</entry>
}
</file>
)
return
(
if(file:is-dir($config:OutDir))
then ()
else file:create-dir($config:OutDir)
,
if($format!='xml')
then
file:write-binary($zipUri, $zip)
else
(
let $xmlzip := file:read-binary($config:Xmlziplocation)
return
(
file:write-binary($zipUri, $xmlzip)
,
file:delete($config:Xmlziplocation)
)
)
,
for $dbUri in $Uri
let $contentType := fn:tokenize($dbUri,'/')[2]
return audit:update($dbUri,$contentType,$sessionValue,'Download')
,
update:output(<result><status>Success</status><message>Zip generated. Pls. check the output</message><path>{$zipUri}</path></result>)
,
config:update-message('[Content Download][Zip generated ' || $zipUri || ']')
)
};
(:~
: get content format information.
: @param $body parameter chunk of the request
: @param $format Required format (xml,word)
: @param $sessionValue Session Value
: @return element(result)
:)
declare
%rest:path("/downloadinfo")
%rest:POST("{$body}")
%rest:query-param("format", "{$format}", "NONE")
%rest:header-param("Authorization", "{$authorization}", "none")
%rest:consumes("application/xml", "text/xml")
function download:get-format(
$body as document-node(),
$format as xs:string,
$authorization as xs:string
)
{
let $countDownload := fn:count($body/content-format/content)
let $result :=
for $inputContent in $body/content-format/content
for $dbUri in
if((($countDownload eq 1) or (fn:contains($inputContent/uri, '/content/latest/'))))
then $inputContent/uri/text()
else
for $db in db:list()[not(contains(.,'bloomsbury') or contains(.,$config:ContentManagementDatabase) or contains(.,$config:MetadataOnlyContentDatabase) or contains(.,$config:OnixDB ))] return
fn:uri-collection(
fn:concat($db,$config:ContentDir,fn:substring-before(fn:substring-after($inputContent/uri,fn:concat($db,$config:ContentDir)),$config:ContentDir))
)[fn:not(fn:contains(.,$config:AuditFileName)
or fn:contains(.,$config:VersionControlFileName)
or fn:contains(.,$config:InfoXml)
or fn:contains(.,$config:MetaXml)
or fn:contains(.,$config:WordDir))]
let $cid := fn:tokenize($dbUri,'/')[4]
let $coid := fn:tokenize($dbUri,'/')[5]
let $contentType := distinct-values(fn:tokenize($dbUri,'/')[2])
let $supportedFormat := db:open($config:CoreDatabase,$config:DownloadConfig)/*:controlledList/*:name[@ctype-idref=$contentType]/@cformat-idref/string()
let $outputFormat := if(fn:contains($supportedFormat,fn:replace($format,'word','docx')))
then fn:replace($format,'docx','word')
else 'xml'
let $isDeleted := for $db in db:list()[not(contains(.,'bloomsbury') or contains(.,$config:ContentManagementDatabase) or contains(.,$config:MetadataOnlyContentDatabase) or contains(.,$config:OnixDB ))] return
db:open($db,fn:concat($config:ContentDir,$cid,'/',$coid,'/',$config:InfoXml))/info/delete/text()
return
if($contentType ='looseleaf')
then
if($isDeleted='yes')
then <message>content is deleted</message>
else if(fn:contains($dbUri,$config:HeaderXml))
then <entities>false</entities>
else if($outputFormat='word')
then <entities>true</entities>
else <entities>false</entities>
else(
if($isDeleted='yes')
then <message>content is deleted</message>
else if(fn:contains($dbUri,$config:HeaderXml))
then <entities>false</entities>
else if($outputFormat='word')
then <entities>true</entities>
else <entities>false</entities>
)
return
if($result!='')
then
<result>
{
<status>Success</status>,
$result
}</result>
else <result>
{
<status>Success</status>,
<message>records not available.</message>
}</result>
};