/tapas-xq/{$filedir}/tei
) return ( (: Only store TEI if there were no errors. :) if ( tap:is-expected-response($response, $successCode) ) then db:put($tap:db-name, $fileXML, $filepath) else () , update:output($response) ) }; (:~ Construct a MODS metadata record using the TEI header and any additional information provided in the request. Store the MODS in the database alongside its core file TEI. The TEI core file must be stored before any of its derivatives. @param project-id The unique identifier of the project which owns the work. @param doc-id A unique identifier for the document record attached to the original TEI document and its derivatives. @param title Optional. The work’s title as it should appear in TAPAS metadata. @param authors Optional. A list of authors’ names as they should appear in TAPAS metadata, separated by vertical bars. @param contributors Optional. A list of contributors’ names as they should appear in TAPAS metadata, separated by vertical bars. @return the MODS record derived from the TEI file, with status code 201. If no TEI document is associated with the givendoc-id, the response will have a status code
of 500.
:)
(: Originally ../legacy/store-mods.xq :)
declare
%updating
%rest:POST
%rest:path("/tapas-xq/{$project-id}/{$doc-id}/mods")
%rest:form-param('title', '{$title}')
%rest:form-param('authors', '{$authors}')
%rest:form-param('contributors', '{$contributors}')
%output:method("xml")
%output:media-type("application/xml")
function tap:store-core-file-object-description($project-id as xs:string, $doc-id as xs:string,
$title as xs:string?, $authors as xs:string?, $contributors as xs:string?) {
let $successCode := 201
let $teiDoc := tap:get-stored-xml($project-id, $doc-id)
let $mods := tap:generate-mods($teiDoc, $title, $authors, $contributors)
let $filepath := concat($project-id,'/',$doc-id,'/mods.xml')
let $possiblyErroneous := ( $teiDoc, $mods )
let $response := tap:plan-response($successCode, $possiblyErroneous, $mods)
return (
(: Only store MODS if there were no errors. :)
if ( tap:is-expected-response($response, $successCode) ) then
db:put($tap:db-name, $mods, $filepath)
else ()
,
update:output($response)
)
};
(:~
Store “TAPAS-friendly environment” (TFE) metadata. Triggers the generation of a small XML file
containing useful information about the context of the TEI document, such as its parent project.
The TEI core file must be stored before any of its derivatives.
@param project-id The unique identifier of the project which owns the work.
@param doc-id A unique identifier for the document record attached to the original TEI document and
its derivatives.
@param collections Comma-separated list of collection identifiers with which the work should be
associated.
@param is-public Optional. Value of “true” or “false”. Indicates if the XML document should be
queryable by the public. By default, the document is considered private. (Note that if the
document belongs to even one public collection, it should be queryable.)
@return a URL path for reading the new TFE file through the TAPAS-xq API, with status code 201. If
no TEI document is associated with the given doc-id, the response will
have a status code of 500.
:)
(: Originally ../legacy/store-tfe.xq :)
declare
%updating
%rest:POST
%rest:path("/tapas-xq/{$project-id}/{$doc-id}/tfe")
%rest:form-param('collections', '{$collections}')
%rest:form-param('is-public', '{$is-public}', "false")
%output:method("xml")
%output:media-type("application/xml")
function tap:store-core-file-contextual-metadata($project-id as xs:string, $doc-id as xs:string,
$collections as xs:string+, $is-public as xs:boolean) {
let $successCode := 201
let $tfe := tap:generate-tfe($project-id, $doc-id, $collections, $is-public)
let $filedir := concat($project-id,'/',$doc-id)
let $filepath := concat($filedir,'/tfe.xml')
let $response :=
let $teiDoc := tap:get-stored-xml($project-id, $doc-id)
return
tap:plan-response($successCode, ($teiDoc), /tapas-xq/{$filedir}/tfe
) return ( (: Only store the TFE if there were no errors. :) if ( tap:is-expected-response($response, $successCode) ) then db:put($tap:db-name, $tfe, $filepath) else () , update:output($response) ) }; (:~ Given the name of a TAPAS view package, generate an XHTML file from the provided TEI document. The generated XHTML is not a full webpage but a<div> snippet, suitable for inclusion
in the TAPAS reading interface.
The XML database does not store any files as a result of this request.
Note that additional form parameters may be available, depending on the view package selected. Check
the view package’s configuration file for additional parameters.
@param type A keyword representing the type of reader view to generate. Valid keywords can be found
by making a request to the “List registered view packages” endpoint.
@param file A TEI-encoded XML document. If, in the future, a view package makes use of a different
input source (such as a TAPAS collection or a project), the file parameter may become optional.
@return generated XHTML with status code 200.
:)
(: Originally ../legacy/derive-reader.xq :)
declare
%rest:POST
%rest:path("/tapas-xq/derive-reader/{$type}")
%rest:form-param('file', '{$file}')
%output:method("xhtml")
%output:media-type("text/html")
function tap:derive-reader($type as xs:string, $file as item()) {
let $successCode := 200
let $isKnownType :=
if ( not(dpkg:can-read-registry()) ) then
tgen:set-error(500, "This user does not have read access to the view package database.")
else if ( dpkg:is-known-view-package($type) ) then ()
else tgen:set-error(400, "There is no view package named '"||$type||"'")
let $fileXML := tap:get-file-content($file)
let $xmlFileIsTEI :=
if ( $fileXML instance of element(tap:err) ) then () else
tap:validate-tei-minimally($fileXML)
let $possiblyErroneous := ( $isKnownType, $fileXML, $xmlFileIsTEI )
let $requestedHtml :=
if ( exists(tap:compile-errors($possiblyErroneous)) ) then () else
let $viewPkgRunStmt := dpkg:get-run-stmt($type)
let $runType := $viewPkgRunStmt/@type/data(.)
return
switch ( $runType )
case 'xslt' return
let $xslPath :=
dpkg:get-path-from-package($type, $viewPkgRunStmt/@pgm/data(.))
let $viewPkgParams := dpkg:set-view-package-parameter-values($type)
return try {
xslt:transform($fileXML, doc($xslPath), $viewPkgParams)
} catch * {
tgen:set-error(500, 'XSLT transformation failed with error "'||$err:description||'" '
||$err:value)
}
(: TODO: XProc :)
(: Any other program type is politely declined. :)
default return
let $error :=
if ( empty($runType) ) then
"View package configuration must include a method of transformation"
else "Programs of type '"||$runType||"' cannot be run."
return tgen:set-error(501, $error)
return
tap:plan-response($successCode, ($possiblyErroneous, $requestedHtml), $requestedHtml)
};
(:~
Retrieve a TEI file stored in the XML database.
@param project-id The identifier of the project which owns the core file.
@param doc-id The identifier of the TEI core file.
@return a copy of the TEI file, with status code 200. If the file does not exist, the response will
have a status code of 404.
If the file is marked as private in the contextual metadata (TFE file), only users with write
access to the database will be able to access the file. An attempt at unauthorized access will
yield a 403 status code and error.
:)
declare
%rest:GET
%rest:path("/tapas-xq/{$project-id}/{$doc-id}/tei")
%output:indent("no")
%output:method("xml")
%output:media-type("application/xml")
function tap:read-core-file($project-id as xs:string, $doc-id as xs:string) {
let $successCode := 200
let $file := tap:get-stored-xml($project-id, $doc-id)
return tap:plan-response($successCode, $file, $file)
};
(:~
Retrieve a MODS file associated with a given core file identifier.
@param project-id The identifier of the project which owns the core file.
@param doc-id The identifier of the TEI core file.
@return a copy of the MODS metadata, with status code 200. If the file does not exist, the response
will have a status code of 404.
If the file is marked as private in the contextual metadata (TFE file), only users with write
access to the database will be able to access the file. An attempt at unauthorized access will
yield a 403 status code and error.
:)
declare
%rest:GET
%rest:path("/tapas-xq/{$project-id}/{$doc-id}/mods")
%output:indent("yes")
%output:method("xml")
%output:media-type("application/xml")
function tap:read-core-file-object-description($project-id as xs:string, $doc-id as xs:string) {
let $successCode := 200
let $file := tap:get-stored-xml($project-id, $doc-id, 'mods.xml')
return tap:plan-response($successCode, $file, $file)
};
(:~
Retrieve a TAPAS-friendly environment (TFE) file associated with a given core file identifier.
@param project-id The identifier of the project which owns the core file.
@param doc-id The identifier of the TEI core file.
@return a copy of the TFE metadata, with status code 200. If the file does not exist, the response
will have a status code of 404.
If the file is marked as private in the contextual metadata (TFE file), only users with write
access to the database will be able to access the file. An attempt at unauthorized access will
yield a 403 status code and error.
:)
declare
%rest:GET
%rest:path("/tapas-xq/{$project-id}/{$doc-id}/tfe")
%output:indent("yes")
%output:method("xml")
%output:media-type("application/xml")
function tap:read-core-file-contextual-metadata($project-id as xs:string, $doc-id as xs:string) {
let $successCode := 200
let $file := tap:get-stored-xml($project-id, $doc-id, 'tfe.xml')
return tap:plan-response($successCode, $file, $file)
};
(:~
Completely remove all database records associated with a given TEI core file identifier: TEI file,
MODS metadata, and TAPAS-friendly environment record.
@param project-id The identifier of the project which owns the core file.
@param doc-id The identifier of the TEI core file.
@return a short confirmation in XML that the resources will be deleted, with status code 202. If no
TEI document is associated with the given identifier, the response will have a status code of 500.
:)
(: Originally ../legacy/delete-by-docid.xq :)
declare
%updating
%rest:DELETE
%rest:path("/tapas-xq/{$project-id}/{$doc-id}")
%output:method("xml")
%output:media-type("application/xml")
function tap:delete-core-file($project-id as xs:string, $doc-id as xs:string) {
(: Originally, this endpoint returned a 200 response, since it could check to make sure that the
file was gone after deletion. The "202 Accepted" response is more appropriate now, since we can only
promise that we *will* delete the item, we can't say that we *have done* it. :)
let $successCode := 202
let $response :=
let $teiDoc := tap:get-stored-xml($project-id, $doc-id)
return
tap:plan-response($successCode, ($teiDoc),
Deleting core file {$doc-id} and associated files in project {$project-id}.
) return ( (: Delete the core file only if the response anticipates success. (Note that, unlike in eXist, the deletion must occur at the end of execution. This function can't be *certain* that deletion will occur, but it can check for odds of success (authenticated user, available documents). :) if ( tap:is-expected-response($response, $successCode) ) then db:delete($tap:db-name, concat($project-id,'/',$doc-id)) else () , update:output($response) ) }; (:~ Completely remove all database records associated with the given TAPAS project. @param project-id The unique identifier of the project to be deleted. @return a short confirmation in XML that the resources will be deleted, with status code 202. If no TEI document is associated with the given identifier, the response will have a status code of 500. :) (: Originally ../legacy/delete-by-projid.xq :) declare %updating %rest:DELETE %rest:path("/tapas-xq/{$project-id}") %output:method("xml") %output:media-type("application/xml") function tap:delete-project-documents($project-id as xs:string) { (: See comments in tap:delete-core-file() above for info on this HTTP status code. :) let $successCode := 202 let $response := let $numDocs := tap:count-project-docs($project-id) return tap:plan-response($successCode, ($numDocs),Deleting {$numDocs} resources in project {$project-id}.
) return ( (: Delete the core file only if the response anticipates success. :) if ( tap:is-expected-response($response, $successCode) ) then db:delete($tap:db-name, $project-id) else () , update:output($response) ) }; (:~ Retrieve the XML registry of all view packages currently available in TAPAS-xq. @return the XML registry of view packages, with status code 200. :) declare %rest:GET %rest:path("/tapas-xq/view-packages") %output:method("xml") %output:media-type("application/xml") function tap:list-registered-view-packages() { let $successCode := 200 let $registry := if ( not(dpkg:can-read-registry()) ) then tgen:set-error(401, "This user does not have read access to the view package database.") else dpkg:get-registry() return tap:plan-response($successCode, $registry, $registry) }; (:~ Update the view packages database using the latest commits from the GitHub repository. Then, update the view package registry. Important: This endpoint can only be accessed by BaseX accounts with administrator permissions. @return a short confirmation in XML that the view package repository and database has been updated, with status code 201. The view package registry will be re-generated after 500 milliseconds. :) declare %updating %rest:POST %rest:path("/tapas-xq/view-packages") %output:method("xml") %output:media-type("application/xml") function tap:update-registered-view-packages() { let $successCode := 201 return (: Attempt to update the view package database. If the current user does not have permission to run `job:eval()`, or some other error occurs, return the error. :) try { ( dpkg:update-database-to-latest(), update:output(tap:plan-response(201, ())) ) } catch Q{http://basex.org}permission { let $err := tgen:set-error(401, "This endpoint is limited to administrator accounts only.") return update:output(tap:plan-response(201, $err)) } catch * { let $err := tgen:set-error(500, $err:code||' '||$err:value) return update:output(tap:plan-response(201, $err)) } }; (:~ Retrieve the configuration file for a given view package. @param package-id The identifier of the view package. @return the XML configuration file of the view package with status code 200. If the requested identifier does not match a view package registered with TAPAS-xq, the response will have a status code of 400. :) declare %rest:GET %rest:path("/tapas-xq/view-packages/{$package-id}") %output:method("xml") %output:media-type("application/xml") function tap:get-view-package-configuration($package-id as xs:string) { let $successCode := 200 let $configFile := if ( not(dpkg:can-read-registry()) ) then tgen:set-error(401, "This user does not have read access to the view package database.") else if ( not(dpkg:is-known-view-package($package-id)) ) then tgen:set-error(400, "A view package named '"||$package-id||"' is not available") else dpkg:get-configuration($package-id) return tap:plan-response($successCode, $configFile, $configFile) }; (: SUPPORT FUNCTIONS :) (:~ Build an HTTP response from only a status code. :) declare function tap:build-response($status-code as xs:integer) as item()+ { tap:build-response($status-code, (), ()) }; (:~ Build an HTTP response with some content in the response body. :) declare function tap:build-response($status-code as xs:integer, $content as item()*) as item()+ { tap:build-response($status-code, $content, ()) }; (:~ Build an HTTP response with a response body and response headers. :) declare function tap:build-response($status-code as xs:integer, $content as item()*, $headers as item()*) as item()+ { (: If $content appears to be an integer, then this function treats that integer as an error code. :) let $noContentProvided := empty($content) return (Problem found: { $useMessage($errors) }
else