Arno Kaimbacher
4714dfdd94
All checks were successful
CI Pipeline / japa-tests (push) Successful in 46s
- npm normal updates - add all xslt and style asstes in extra folder public/assets2 - linting corrections - delete local .env.test from git tracking: git rm --cached .env.test - add .env.test into .gitignore file - add edit functionality for editing by submitter - npm updates -added xslt3 packeage for builfing sef files - added Language.ts class vor language table - added version to datasetxml2oai-pmh.xslt
190 lines
7.8 KiB
TypeScript
190 lines
7.8 KiB
TypeScript
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<void> {
|
|
this.xml = create({ version: '1.0', encoding: 'UTF-8', standalone: true }, '<root></root>');
|
|
|
|
// 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.';
|
|
}
|
|
}
|