import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'; import { RequestContract } from '@ioc:Adonis/Core/Request'; import { XMLBuilder } from 'xmlbuilder2/lib/interfaces'; import { create } from 'xmlbuilder2'; import dayjs, { Dayjs } from 'dayjs'; import utc from 'dayjs/plugin/utc'; import timezone from 'dayjs/plugin/timezone'; import { readFileSync } from 'fs'; import { StatusCodes } from 'http-status-codes'; import { transform } from 'saxon-js'; // import { Xslt, xmlParse } from 'xslt-processor' import { OaiErrorCodes, OaiModelError } from 'App/Exceptions/OaiErrorCodes'; import { OaiModelException } from 'App/Exceptions/OaiModelException'; interface XslTParameter { [key: string]: any; } interface Dictionary { [index: string]: string; } export default class OaiController { // private deliveringDocumentStates = ["published", "deleted"]; // private sampleRegEx = /^[A-Za-zäüÄÜß0-9\-_.!~]+$/; private xsltParameter: XslTParameter; /** * Holds xml representation of document information to be processed. * * @var xmlbuilder.XMLDocument | null Defaults to null. */ private xml: XMLBuilder; private proc; constructor() { // Load the XSLT file this.proc = readFileSync('public/assets2/datasetxml2oai.sef.json'); // tests // const xslPath = 'assets/datasetxml2oai-pmh.xslt'; // Replace with the actual path to your XSLT file // this.proc = readFileSync(xslPath, 'utf-8'); // this.configuration = new Configuration(); dayjs.extend(utc); dayjs.extend(timezone); } public async index({ response, request }: HttpContextContract): Promise { this.xml = create({ version: '1.0', encoding: 'UTF-8', standalone: true }, ''); // this.proc = new XSLTProcessor(); // const stylesheet = readFileSync(__dirname + "/datasetxml2oai.sef.json"); const xsltParameter = (this.xsltParameter = {}); let oaiRequest: Dictionary = {}; if (request.method() === 'POST') { oaiRequest = request.body(); } else if (request.method() === 'GET') { oaiRequest = request.qs(); } else { xsltParameter['oai_error_code'] = 'unknown'; xsltParameter['oai_error_message'] = 'Only POST and GET methods are allowed for OAI-PMH.'; } // const oaiRequest: OaiParameter = request.body; try { this.handleRequest(oaiRequest, request); } catch (error) { if (error instanceof OaiModelException) { const code = error.oaiCode; let oaiErrorCode: string | undefined = 'Unknown oai error code ' + code; if (OaiModelError.has(error.oaiCode) && OaiModelError.get(code) !== undefined) { oaiErrorCode = OaiModelError.get(error.oaiCode); } this.xsltParameter['oai_error_code'] = oaiErrorCode; this.xsltParameter['oai_error_message'] = error.message; } else { // // return next(error); // passing to default express middleware error handler this.xsltParameter['oai_error_code'] = 'unknown'; this.xsltParameter['oai_error_message'] = 'An internal error occured.'; } } const xmlString = this.xml.end({ prettyPrint: true }); let xmlOutput; try { const result = await transform({ // stylesheetFileName: `${config.TMP_BASE_DIR}/data-quality/rules/iati.sef.json`, stylesheetText: this.proc, destination: 'serialized', // sourceFileName: sourceFile, sourceText: xmlString, stylesheetParams: xsltParameter, // logLevel: 10, }); xmlOutput = result.principalResult; } catch (error) { return response.status(500).json({ message: 'An error occurred while creating the user', error: error.message, }); } response .header('Content-Type', 'application/xml; charset=utf-8') .header('Access-Control-Allow-Origin', '*') .header('Access-Control-Allow-Methods', 'GET,POST'); response.status(StatusCodes.OK).send(xmlOutput); } protected handleRequest(oaiRequest: Dictionary, request: RequestContract) { // Setup stylesheet // $this->loadStyleSheet('datasetxml2oai-pmh.xslt'); // Set response time const now: Dayjs = dayjs(); this.xsltParameter['responseDate'] = now.format('YYYY-MM-DDTHH:mm:ss[Z]'); this.xsltParameter['unixTimestamp'] = now.unix(); // set OAI base url const baseDomain = process.env.BASE_DOMAIN || 'localhost'; this.xsltParameter['baseURL'] = baseDomain + '/oai'; this.xsltParameter['repURL'] = request.protocol() + '://' + request.hostname(); this.xsltParameter['downloadLink'] = request.protocol() + '://' + request.hostname() + '/file/download/'; this.xsltParameter['doiLink'] = 'https://doi.org/'; this.xsltParameter['doiPrefix'] = 'info:eu-repo/semantics/altIdentifier/doi/'; if (oaiRequest['verb']) { const verb = oaiRequest['verb']; this.xsltParameter['oai_verb'] = verb; if (verb === 'Identify') { this.handleIdentify(); } else if (verb === 'ListMetadataFormats') { this.handleListMetadataFormats(); } // else if (verb == "GetRecord") { // await this.handleGetRecord(oaiRequest); // } else if (verb == "ListRecords") { // await this.handleListRecords(oaiRequest); // } else if (verb == "ListIdentifiers") { // await this.handleListIdentifiers(oaiRequest); // } else if (verb == "ListSets") { // await this.handleListSets(); // } else { this.handleIllegalVerb(); } } else { // // try { // // console.log("Async code example.") // const err = new PageNotFoundException("verb not found"); // throw err; // // } catch (error) { // manually catching // // next(error); // passing to default middleware error handler // // } throw new OaiModelException( StatusCodes.INTERNAL_SERVER_ERROR, 'The verb provided in the request is illegal.', OaiErrorCodes.BADVERB, ); } } protected handleIdentify() { const email = process.env.OAI_EMAIL || 'repository@geosphere.at'; const repositoryName = 'Tethys RDR'; const repIdentifier = 'tethys.at'; const sampleIdentifier = 'oai:' + repIdentifier + ':1'; //$this->_configuration->getSampleIdentifier(); // Dataset::earliestPublicationDate()->server_date_published->format('Y-m-d\TH:i:s\Z') : null; // earliestDateFromDb!= null && (this.xsltParameter['earliestDatestamp'] = earliestDateFromDb?.server_date_published); // set parameters for oai-pmh.xslt this.xsltParameter['email'] = email; this.xsltParameter['repositoryName'] = repositoryName; this.xsltParameter['repIdentifier'] = repIdentifier; this.xsltParameter['sampleIdentifier'] = sampleIdentifier; // $this->proc->setParameter('', 'earliestDatestamp', $earliestDateFromDb); this.xml.root().ele('Datasets'); } protected handleListMetadataFormats() { this.xml.root().ele('Datasets'); } private handleIllegalVerb() { this.xsltParameter['oai_error_code'] = 'badVerb'; this.xsltParameter['oai_error_message'] = 'The verb provided in the request is illegal.'; } }