diff --git a/index.js b/index.js index 4444431..682b161 100644 --- a/index.js +++ b/index.js @@ -9,9 +9,11 @@ xm = require('xml-mapping'), mkdirp = require('mkdirp'), mustache = require('mustache'), + request = require('request'), fs = require('fs'), path = require('path'), - extend = require('util')._extend; + extend = require('util')._extend, + child_process = require('child_process'); /* Constantes */ var JSON_EXTENSION = new RegExp(/(.json)$/g); @@ -231,7 +233,7 @@ // Création du répertoire mkdirp.sync(path); } -} +}; // Regroupe les fonctions liées aux traitement des XML object.XML = {}; @@ -290,6 +292,127 @@ object.dates.now = function(format) { var arg = format || 'dd-mm-yyyy'; return dateFormat(new Date(Date.now()), arg); -} +}; + +// Regroupe les fonctions liées aux services +object.services = {}; + +/** + * Effectue une requête HTTP (méthode POST) sur un service + * @param {object} options Objet comportant toutes les informations nécessaire à la requête : + * - {string} filename Nom du fichier + * - {object} headers Headers de la requête + * - {string} url Url d'accès au service + * @param {function} cb Callback appelée à la fin du traitement, avec comme paramètre disponible : + * - {Error} err Erreur de Lecture/Écriture + * - {object} res Résultat de la réponse, sous la forme : + * - {object} httpResponse Réponse HTTP + * - {string} body Body de la réponse + * @return {undefined} undefined + */ +object.services.post = function(options, cb) { + var _err = null, + _res = null; + // Vérification de l'existence du fichier à envoyer + fs.stat(options.filename, function(err, stats) { + // Lecture impossible + if (err) { + _err = new Error(err); + return cb(_err, _res); + } + // Création du form data + var formData = { + file: fs.createReadStream(options.filename) + }; + // Requête POST sur le service + request.post({ + headers: options.headers, + url: options.url, + formData: formData + }, function(err, httpResponse, body) { + // Erreur + if (err) { + _err = new Error(err); + return cb(_err, _res); + } + // Retourne le résultat de la requête + return cb(_err, { + "httpResponse": httpResponse, + "body": body + }); + }); + }); +}; + +/** + * Applique une feuille xslt sur un document XML (provenant d'un service) + * @param {object} options Objet comportant toutes les informations nécessaire à la création du chemin : + * - {string} output Chemin du Tempalte + * - {string} documentId Données à insérer dans le Template + * - {string} runId Données sur l'Output (voir : object.files.createPath) + * - {string} xsltFile Données sur l'Output (voir : object.files.createPath) + * - {string} xmlFile Données sur l'Output (voir : object.files.createPath) + * @param {function} cb Callback appelée à la fin du traitement, avec comme paramètre disponible : + * - {Error} err Erreur de Lecture/Écriture + * - {Object} res Résultat de l'opération, sous la forme + * - {object} logs Logs de stderr (array) et stdout (array) + * - {array} output Tableau contenant les différents logs dans l'ordre d'apparition + * - {integer} code Code de retour du process + * @return {undefined} Return undefined + */ +object.services.transformXML = function(options, cb) { + // Spawn du process qui effectura la transformation XSLT + var xsltproc = child_process.spawn('xsltproc', [ + '--output', + options.output, + '--stringparam', + 'documentId', + options.documentId, + '--stringparam', + 'runId', + options.runId, + options.xsltFile, + options.xmlFile + ]), + _err = null, + logs = { + 'stderr': [], + 'stdout': [] + }, + output = []; + + // Write stdout in Logs + xsltproc.stdout.on('data', function(data) { + var str = data.toString(); + logs.stdout.push(str); + return output.push('[stdout] ' + str); + }); + + // Write stderr in Logs + xsltproc.stderr.on('data', function(data) { + var str = data.toString(); + logs.stderr.push(str); + return output.push('[stderr] ' + data.toString()); + }); + + // On error + xsltproc.on('error', function(err) { + var res = { + 'logs': logs, + 'output': output + }; + return cb(err, res); + }); + + // On close + xsltproc.on('close', function(code) { + var res = { + 'logs': logs, + 'output': output, + 'code': code + }; + return cb(null, res); + }); +}; module.exports = object; \ No newline at end of file diff --git a/package.json b/package.json index b30c92a..2a4a4e3 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "mkdirp": "^0.5.1", "mocha": "^3.2.0", "mustache": "^2.2.1", + "request": "^2.74.0", "rd-tu": "git+ssh://vsistex.intra.inist.fr:22222/istex/rd-tu.git" } } diff --git a/test/dataset/in/data/services.json b/test/dataset/in/data/services.json new file mode 100644 index 0000000..a209057 --- /dev/null +++ b/test/dataset/in/data/services.json @@ -0,0 +1,90 @@ +{ + "post": [{ + "label": "Devrait fonctionner correctement", + "arguments": { + "options": { + "filename": "./test/dataset/in/resources/SUCCESS.pdf", + "headers": { + "Accept": "application/xml" + }, + "url": "http://vi-istex-gkn.intra.inist.fr:8070/processKeyTermArticlePDF" + } + }, + "result": { + "equal": null + } + }, { + "label": "Devrait renvoyer une erreur ENOENT", + "arguments": { + "options": { + "filename": "./test/dataset/in/resources/ERROR_ENOENT.pdf", + "headers": { + "Accept": "application/xml" + }, + "url": "http://vi-istex-gkn.intra.inist.fr:8070/processKeyTermArticlePDF" + } + }, + "result": { + "not": true, + "equal": null + } + }, { + "label": "Devrait renvoyer une erreur TIMEOUT", + "arguments": { + "options": { + "filename": "./test/dataset/in/resources/SUCCESS.pdf", + "headers": { + "Accept": "application/xml" + }, + "url": "http://vi-istex-gkn.intra.inist.fr:8060/processKeyTermArticlePDF" + } + }, + "result": { + "not": true, + "equal": null + } + }], + "transformXML": [{ + "label": "Devrait correctement lancer la transformation du fichier XML", + "arguments": { + "options": { + "output": "./test/dataset/out/keyterm.transformed.xml", + "documentId": "0000000000000000000000000000000000000000", + "runId": "1", + "xsltFile": "./test/dataset/in/resources/transform.xslt", + "xmlFile": "./test/dataset/in/resources/keyterm.xml" + } + }, + "result": { + "equal": 0 + } + }, { + "label": "Ne devrait pas trouver le fichier XML", + "arguments": { + "options": { + "output": "./test/dataset/out/keyterm.transformed.xml", + "documentId": "0000000000000000000000000000000000000000", + "runId": "1", + "xsltFile": "./test/dataset/in/resources/transform.xslt", + "xmlFile": "./test/dataset/in/resources/ERROR_ENOENT.xml" + } + }, + "result": { + "equal": 6 + } + }, { + "label": "Ne devrait pas trouver le fichier XSLT", + "arguments": { + "options": { + "output": "./test/dataset/out/keyterm.transformed.xml", + "documentId": "0000000000000000000000000000000000000000", + "runId": "1", + "xsltFile": "./test/dataset/in/resources/ERROR_ENOENT.xslt", + "xmlFile": "./test/dataset/in/resources/keyterm.xml" + } + }, + "result": { + "equal": 4 + } + }] +} \ No newline at end of file diff --git a/test/dataset/in/resources/SUCCESS.pdf b/test/dataset/in/resources/SUCCESS.pdf new file mode 100644 index 0000000..469ce46 --- /dev/null +++ b/test/dataset/in/resources/SUCCESS.pdf Binary files differ diff --git a/test/dataset/in/resources/keyterm.xml b/test/dataset/in/resources/keyterm.xml new file mode 100644 index 0000000..884a471 --- /dev/null +++ b/test/dataset/in/resources/keyterm.xml @@ -0,0 +1,123 @@ + + + + + + Key phrase, key concept and category extraction + + + + + + + + + + + + + + + The Free Encyclopedia + + + + + The Free Encyclopedia + + + + + + + + + + + + + Crocodylus intermedius + Orinoco crocodile + crocodile populations + las poblaciones + crocodile population + population recovery + Caiman crocodilus + crocodile Crocodylus + Orinoco + crocodiles + spectacled caiman + populations remain + isolated areas + Orinoco crocodiles + hatchling crocodiles + crocodile + en el + poblaciones + population + Caiman + Venezuela + Orinoco crocodile Crocodylus + nocturnal spotlight + las + populations + River + Tucupido + counts reveal + spotlight counts + Crocodylus + intermedius + Apure + habitat + se encuentran + del + spotlight counts reveal + nocturnal spotlight counts + severely depleted + rivers + Capanaparo + recovery + llanos + rio + los + taken place + reduced hunting + + + + + + + Orinoco crocodile + Spectacled caiman + Orinoco + Crocodile + Venezuela + Caimaninae + Habitat + Population + River + Crocodylus + Llanos + Apure River + Rio (windowing system) + + + + + + + Crocodilians + Reptiles of South America + Crocodylidae + Megafauna of South America + International rivers of South America + South American countries + Habitat (ecology) terminology + + + + \ No newline at end of file diff --git a/test/dataset/in/resources/transform.xslt b/test/dataset/in/resources/transform.xslt new file mode 100644 index 0000000..131bec9 --- /dev/null +++ b/test/dataset/in/resources/transform.xslt @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + enrichissement indexation ISTEX-RD + ISTEX-RD + + + + + + +

L’élément standOff de ce document est distribué sous licence Creative Commons 4.0 non transposée (CC BY 4.0)

+

Ce standOff a été créé dans le cadre du projet ISTEX – Initiative d’Excellence en Information Scientifique et Technique

+
+
+
+ + + + + + + + + + + + Indexation de documents ISTEX + + + + + + + + #istex-rd + # + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/test/run.js b/test/run.js index 99fe31b..a66ec97 100644 --- a/test/run.js +++ b/test/run.js @@ -16,7 +16,8 @@ "enrichments": require('./dataset/in/data/enrichments.json'), "directories": require('./dataset/in/data/directories.json'), "XML": require('./dataset/in/data/XML.json'), - "URL": require('./dataset/in/data/URL.json') + "URL": require('./dataset/in/data/URL.json'), + "services": require('./dataset/in/data/services.json') }; // Mapping indiquant quelle fonction de test et quelles données utiliser pour chaque fonction @@ -42,10 +43,14 @@ }, "XML": { "load": testOf_xmlLoad, - "select": testOf_xmlSelect + "select": testOf_xmlSelect, }, "URL": { "addParameters": testOf_urlAddParameters + }, + "services": { + "post": testOf_servicesPost, + "transformXML": testOf_servicesTransformXML } }; @@ -122,7 +127,7 @@ var before = (item.arguments.enrichments && item.arguments.enrichments[item.arguments.options.label]) ? item.arguments.enrichments[item.arguments.options.label].length : 0, // Nombre d'enrichissement avant result = fn(item.arguments.enrichments, item.arguments.options), after = result[item.arguments.options.label].length; // Nombre d'enrichissement aprés - cb(after - before); + return cb(after - before); } /** @@ -130,8 +135,8 @@ * - myObject.enrichments.write() */ function testOf_enrichmentsWrite(fn, item, cb) { - fn(item.arguments.options, function(err) { - cb(err); + return fn(item.arguments.options, function(err) { + return cb(err); }); } @@ -162,6 +167,26 @@ return cb(fn(item.arguments.url, item.arguments.parameters)); } +/** + * Fonction de test à appliquée pour : + * - myObject.services.post() + */ +function testOf_servicesPost(fn, item, cb) { + return fn(item.arguments.options, function(err, res) { + return cb(err); + }); +} + +/** + * Fonction de test à appliquée pour : + * - myObject.services.transformXML() + */ +function testOf_servicesTransformXML(fn, item, cb) { + return fn(item.arguments.options, function(err, res) { + return cb(res.code); + }); +} + // Set une regex pour chaque clée demandée function setRegex(keys, options) { for (var i = 0; i < keys.length; i++) {