blob: c834d1e7c0d462b86b5aca6344abe1bd272927cb [file] [log] [blame]
Akrone51eaa32020-11-10 09:35:53 +01001"use strict";
2
Nils Diewald0e6992a2015-04-14 20:13:52 +00003define(['util'], function () {
Akronbf713fc2020-10-13 10:44:35 +02004
5 // TODO:
6 // - https://github.com/honza/140medley/blob/master/140medley.js
7 // - https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
8 // - https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest
9 // - r.addEventListener("progress", updateProgress, false);
10 // - http://www.javascriptkit.com/javatutors/loadjavascriptcss.shtml
11 // - http://stackoverflow.com/questions/6112744/load-javascript-on-demand
Nils Diewald58141332015-04-07 16:18:45 +000012
Leo Reppa6aba9a2021-01-23 20:16:43 +010013 // See https://flaviocopes.com/http-request-headers/ for a list of headers
14
Akron4c33c622018-11-12 13:43:27 +010015 KorAP.URL = KorAP.URL !== undefined ? KorAP.URL : '';
Nils Diewald4347ee92015-05-04 20:32:48 +000016 KorAP.API = KorAP.API || {};
Akronb89863a2018-11-13 16:43:59 +010017
Akronbf713fc2020-10-13 10:44:35 +020018 const legacySigle = new RegExp('^([^_]+)_([^\\.]+)\\.(.+?)$');
19
Akron48b1e4d2015-06-17 18:47:01 +020020 /**
21 * Retrieve information about a match
22 */
Nils Diewald4347ee92015-05-04 20:32:48 +000023 KorAP.API.getMatchInfo = function (match, param, cb) {
Nils Diewald58141332015-04-07 16:18:45 +000024
Nils Diewald4347ee92015-05-04 20:32:48 +000025 // match is a KorAP.Match object
Akronbf713fc2020-10-13 10:44:35 +020026 let url = KorAP.URL + '/corpus';
Akron0b489ad2018-02-02 16:49:32 +010027 /*
28 url += '/' + match.corpusID;
29 url += '/' + match.docID;
30 url += '/' + match.textID;
31 */
Akron19d97fe2016-09-06 20:47:05 +020032
Akron19d97fe2016-09-06 20:47:05 +020033 // This is for legacy support
Akronbf713fc2020-10-13 10:44:35 +020034 const legacy = legacySigle.exec(match.textSigle);
35 let docFragment = "";
Akron7f613e02016-11-07 02:50:44 +010036 if (legacy !== null && legacy[0]) {
Akronb89863a2018-11-13 16:43:59 +010037 docFragment = legacy[1] + '/' + legacy[2] + '/' + legacy[3];
Akron19d97fe2016-09-06 20:47:05 +020038 }
39 else {
Akronb89863a2018-11-13 16:43:59 +010040 docFragment = match.textSigle;
Akron19d97fe2016-09-06 20:47:05 +020041 }
Akronb89863a2018-11-13 16:43:59 +010042
43 docFragment += '/' + match.matchID;
44 url += '/' + docFragment;
Nils Diewald58141332015-04-07 16:18:45 +000045
Nils Diewald4347ee92015-05-04 20:32:48 +000046 // { spans: true, layer:x, foundry : y}
47 if (param['spans'] == true) {
48 url += '?spans=true';
Akronb89863a2018-11-13 16:43:59 +010049 docFragment += ' +spans ';
50 if (param['foundry'] !== undefined) {
Akron515851a2017-05-02 12:53:17 +020051 url += '&foundry=' + param['foundry'];
Akronb89863a2018-11-13 16:43:59 +010052 docFragment += param['foundry'];
53 };
54 if (param['layer'] !== undefined) {
Akron515851a2017-05-02 12:53:17 +020055 url += '&layer=' + param['layer'];
Akronb89863a2018-11-13 16:43:59 +010056 docFragment += '/'+param['layer'];
57 }
Nils Diewald58141332015-04-07 16:18:45 +000058 }
Nils Diewald4347ee92015-05-04 20:32:48 +000059
60 // { spans : false, layer: [Array of KorAP.InfoLayer] }
61 else {
62 // TODO
Akronb89863a2018-11-13 16:43:59 +010063 docFragment += ' -spans';
Nils Diewald4347ee92015-05-04 20:32:48 +000064 url += '?spans=false';
65 }
66
Akronb89863a2018-11-13 16:43:59 +010067 KorAP.API.getJSON(url, cb, "MatchInfo: " + docFragment);
Nils Diewald58141332015-04-07 16:18:45 +000068 };
Nils Diewald4347ee92015-05-04 20:32:48 +000069
Akron0b489ad2018-02-02 16:49:32 +010070
Akron48b1e4d2015-06-17 18:47:01 +020071 /**
Akron0ad7cd22018-02-08 18:03:06 +010072 * Retrieve information about a document.
73 */
74 KorAP.API.getTextInfo = function (doc, param, cb) {
75
76 // doc is a KorAP.Match object
Akronbf713fc2020-10-13 10:44:35 +020077 let url = KorAP.URL + '/corpus' + '/' + doc.textSigle;
Akron0ad7cd22018-02-08 18:03:06 +010078
79 if (param['fields'] !== undefined) {
80 url += '?fields='; // TODO!
81 }
82 else {
Akron4bbd8b32018-03-06 19:19:44 +010083 url += '?fields=@all'; // TODO: Maybe '*'?
Akron0ad7cd22018-02-08 18:03:06 +010084 }
Akronbf713fc2020-10-13 10:44:35 +020085
Akronb89863a2018-11-13 16:43:59 +010086 KorAP.API.getJSON(url, cb, "TextInfo: " + doc.textSigle);
Akron0ad7cd22018-02-08 18:03:06 +010087 };
88
89
90 /**
Akroncd42a142019-07-12 18:55:37 +020091 * Retrieve information about virtual corpora
Akron48b1e4d2015-06-17 18:47:01 +020092 */
93 KorAP.API.getCollections = function (cb) {
Akronb89863a2018-11-13 16:43:59 +010094 KorAP.API.getJSON(KorAP.URL + '/collection', cb, "CorpusInfo");
Akron48b1e4d2015-06-17 18:47:01 +020095 };
96
hebasta0ee50802018-06-20 10:24:45 +020097
98 /**
99 * Retrieve information about corpus statistic
100 *
101 * Example URL: /corpus?cq=availability+%3D+%2FCC-BY.*%2F+%26+textClass+%3D+%22kultur%22
102 *
Leo Reppa6aba9a2021-01-23 20:16:43 +0100103 * @param cq corpus query (formerly collectionQuery)
hebasta0ee50802018-06-20 10:24:45 +0200104 *
105 * Adress the MOJO-Endpoint for example with
106 * http://localhost:3000/corpus?cq=availability+%3D+%2FCC-BY.*%2F+%26+textClass+%3D+%22kultur%22
107 */
108 KorAP.API.getCorpStat = function (cq, cb){
Akronbf713fc2020-10-13 10:44:35 +0200109 let url = KorAP.URL + "/corpus?cq=" + encodeURIComponent(cq);
Akronb89863a2018-11-13 16:43:59 +0100110 KorAP.API.getJSON(url, cb, "CorpusInfo: " + cq);
hebasta0ee50802018-06-20 10:24:45 +0200111 };
Akron8dda1c62021-01-20 10:27:32 +0100112
113
114 /**
115 * Retrieve a list of all plugin objects to
116 * establish in the frontend.
117 */
118 KorAP.API.getPluginList = function (url, cb) {
119 KorAP.API.getJSON(url, cb, "Plugin-List")
120 };
Akronbf713fc2020-10-13 10:44:35 +0200121
hebasta4ba496a2018-06-05 15:56:01 +0200122 /**
Leo Reppa6aba9a2021-01-23 20:16:43 +0100123 * General function to communicate JS Objects with the server
124 *
125 * @param {HTTMLRequestType} requestType Should be "GET", "PUT", "POST" or "DELETE"
126 * @param {String} url The url that specifies where the JSON file is ("GET"), will be ("PUT" and "POST") or will have been ("DELETE")
127 * @param {String} title How to store this request in the logs
128 * @param {JSObj} jsObj For "PUT" and "POST". The JS Object that is getting transfered. This function stringifies it.
129 * @param {function} returnValueCB For "GET". The callback function that receives the retrieved JS object (already parsed) as a parameter, or undefined if none is eligible
130 * @param {function} errorCB Optional. Callback function for error handling, receives JS object with status and statusText attribute
131 */
132 function _actionJSON (requestType, url, title, jsObj, returnValueCB, errorCB) {
Leo Repp58b9f112021-11-22 11:57:47 +0100133 //console.log(arguments);
Akronbf713fc2020-10-13 10:44:35 +0200134 const req = new XMLHttpRequest();
Leo Reppa6aba9a2021-01-23 20:16:43 +0100135 req.open(requestType, url, true);
136 // Dispatch global "window" event. See Kalamar::Plugin::Piwik
Akronbf713fc2020-10-13 10:44:35 +0200137 const reqE = new CustomEvent('korapRequest', {
Akron4c33c622018-11-12 13:43:27 +0100138 bubbles : false,
Akronb89863a2018-11-13 16:43:59 +0100139 detail: {
140 "url" : url,
141 "title" : title
142 }
Akron4c33c622018-11-12 13:43:27 +0100143 });
144 window.dispatchEvent(reqE);
145
Nils Diewald4347ee92015-05-04 20:32:48 +0000146 req.setRequestHeader("Accept", "application/json");
Leo Reppa6aba9a2021-01-23 20:16:43 +0100147 req.setRequestHeader("Content-Type", "application/json");
148 req.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
Leo Repp57997402021-08-18 16:37:52 +0200149 //req.setRequestHeader('Origin',"API");
Nils Diewald4347ee92015-05-04 20:32:48 +0000150 req.onreadystatechange = function () {
151 /*
Akron0b489ad2018-02-02 16:49:32 +0100152 States:
153 0 - unsent (prior to open)
154 1 - opened (prior to send)
155 2 - headers received
156 3 - loading (responseText has partial data)
157 4 - done
Nils Diewald4347ee92015-05-04 20:32:48 +0000158 */
159 if (this.readyState == 4) {
Akron515851a2017-05-02 12:53:17 +0200160
Leo Reppa6aba9a2021-01-23 20:16:43 +0100161 if (requestType === "GET") { //GET
162 let retJSObj;
163 try {
164 retJSObj = JSON.parse(this.responseText);
165 }
166 catch (e) {
167 KorAP.log(0, e);
168 console.log(e);
169 returnValueCB(undefined);
170 return;
171 };
172
173 if (retJSObj !== undefined && retJSObj["errors"] !== undefined) {
174 retJSObj["errors"].forEach(
175 e => KorAP.log(e[0], e[1] || "Unknown")
176 );
177 }
178
179 else if (this.status !== 200) {
180 KorAP.log(this.status, this.statusText, "Remote service error (XMLHttpRequest) under URL: " + url);
181 };
182
183 if (this.status === 200) {
184 returnValueCB(retJSObj);
185 }
186
187 else {
188 returnValueCB(undefined);
189 };
190
191 } else { // PUT, POST, DELETE
192 if (this.status >= 300 || this.status < 200) { //Error
193 KorAP.log(this.status, this.statusText, "Remote service error (XMLHttpRequest) under URL: " + url);
194 };
Akronb5d05d72018-02-12 15:09:12 +0100195 };
Leo Reppa6aba9a2021-01-23 20:16:43 +0100196 // Call the callback function (no matter requestType) if one is given.
197 if (typeof(errorCB) === "function"){
Leo Repp58b9f112021-11-22 11:57:47 +0100198 var statusTextErrors = ""; // For some reason, the errors created in QueryReference.pm have their text stored in this.responseText.
199 // Here we try to extract this information
200 try {
201 JSON.parse(this.responseText).errors.forEach(
202 e => statusTextErrors = statusTextErrors + e["message"] || ""
203 );
204 } catch {
205 try {
206 if (requestType !== "GET"){
207 statusTextErrors += JSON.parse(this.responseText);
208 }
209 } catch {
210 //Nothing
211 }
212 }
Leo Reppa6aba9a2021-01-23 20:16:43 +0100213 errorCB({
214 "status" : this.status,
Leo Repp58b9f112021-11-22 11:57:47 +0100215 "statusText" : this.statusText + " - " + (statusTextErrors || "")
216 //responseText: A DOMString which contains either the textual data received using the
217 // XMLHttpRequest or null if the request failed or "" if the request has not yet been sent by calling send().
Leo Reppa6aba9a2021-01-23 20:16:43 +0100218 });
219 };
220 };
Nils Diewald4347ee92015-05-04 20:32:48 +0000221 };
Akronbf713fc2020-10-13 10:44:35 +0200222
Leo Reppa6aba9a2021-01-23 20:16:43 +0100223 /*Set a value for .timeout to use this functionality */
224 //req.ontimeout = function () {
225 // KorAP.log(0, 'Request Timeout');
226 //};
227 if (requestType === "POST" || requestType === "PUT") {
228 req.send(JSON.stringify(jsObj));
229 } else { //GET, DELETE
230 req.send();
Nils Diewald4347ee92015-05-04 20:32:48 +0000231 };
Leo Reppa6aba9a2021-01-23 20:16:43 +0100232 };
233
234 /**
235 * General method to get JSON information.
236 *
237 * @param {String} url The url at which the JSON File will be located
238 * @param {function} returnValueCB The callback function that receives the retrieved JS object (already parsed) as a parameter, or undefined if none is eligible
239 * @param {String} title How to store this request in the logs
240 * @param {function} errorCB Optional. Callback function for error handling, receives JS object with status and statusText attribute
241 */
242 KorAP.API.getJSON = function (url, returnValueCB, title, errorCB) {
243 _actionJSON("GET", url, title, undefined, returnValueCB, errorCB);
244 };
245
246 /**
247 * General method to put JSON information.
248 *
249 * @param {String} url The url at which the JSON File will be located
250 * @param {JSObj} jsObj The JS object that is getting transfered. This will be stringified
251 * @param {String} title How to store this request in the logs
252 * @param {function} errorCB Optional. Callback function for error handling, receives JS object with status and statusText attribute
253 */
254 KorAP.API.putJSON = function (url, jsObj, title, errorCB) {
255 _actionJSON("PUT", url, title, jsObj, undefined, errorCB);
256 };
257
258 /**
259 * General method to post JSON information.
260 *
261 * @param {String} url The url at which the JSON File will be located
262 * @param {JSObj} jsObj The JS object that is getting transfered. This will be stringified
263 * @param {String} title How to store this request in the logs
264 * @param {function} errorCB Optional. Callback function for error handling, receives JS object with status and statusText attribute
265 */
266 KorAP.API.postJSON = function (url, jsObj, title, errorCB) {
267 _actionJSON("POST", url, title, jsObj, undefined, errorCB);
268 };
269
270 /**
271 * General method to delete a file at a specific URL
272 *
273 * @param {String} url The url at which the to be deleted file is located
274 * @param {String} title How to store this request in the logs
275 * @param {function} errorCB Optional. Callback function for error handling, receives JS object with status and statusText attribute
276 */
277 KorAP.API.deleteJSON = function (url, title, errorCB) {
278 _actionJSON("DELETE", url, title, undefined, undefined, errorCB);
279 };
280
281
282 // Stored query related functions
283
284 /**
285 * Retrieve saved list of queries
286 *
287 * @param {function} returnValueCB The callback function that receives the JS object Listof queries, already parsed
288 * @param {function} errorCB Optional. Callback function for error handling, receives JS object with status and statusText attribute
289 */
290 KorAP.API.getQueryList = function (returnValueCB, errorCB){
291 KorAP.API.getJSON(KorAP.URL + "/query/", returnValueCB, "getSavedQueryList", errorCB);
292 };
293
294 /**
295 * Retrieve specific saved query by query name
296 *
297 * @param {String} qn The name of the query to be retrieved. Must be a string
298 * @param {function} returnValueCB The callback function that receives the query JS object Object, already parsed
299 * @param {function} errorCB Optional. Callback function for error handling, receives JS object with status and statusText attribute
300 */
301 KorAP.API.getQuery = function (qn, returnValueCB, errorCB){
302 KorAP.API.getJSON(KorAP.URL + "/query/" + qn, returnValueCB, "getSavedQuery of name "+ qn, errorCB);
303 };
304
305 /**
306 * Put new query by query name
307 *
308 * @param {String} qn The name of the new query
309 * @param {JSObj} jsObj The query. This will be stringified
310 * @param {function} errorCB Optional. Callback function for error handling, receives JS object with status and statusText attribute
311 */
312 KorAP.API.putQuery = function (qn, jsObj, errorCB){
313 KorAP.API.putJSON(KorAP.URL + "/query/" + qn, jsObj, "putQuery of name "+ qn, errorCB);
314 };
315
316 /**
317 * Post new query by query name
Leo Repp58b9f112021-11-22 11:57:47 +0100318<<<<<<< HEAD
319=======
320 * CAUTION: Currently not supported by the QueryReference Plugin.
321>>>>>>> Demo for query storing
Leo Reppa6aba9a2021-01-23 20:16:43 +0100322 *
323 * @param {String} qn The name of the new query
324 * @param {JSObj} jsObj The query. This will be stringified
325 * @param {function} errorCB Optional. Callback function for error handling, receives JS object with status and statusText attribute
326 */
327 KorAP.API.postQuery = function (qn, jsObj, errorCB){
328 KorAP.API.postJSON(KorAP.URL + "/query/" + qn, jsObj, "postQuery of name "+ qn, errorCB);
329 };
330
331 /**
332 * delete query by query name
333 *
334 * @param {String} qn The name of the to be deleted query
335 * @param {function} errorCB Optional. Callback function for error handling, receives JS object with status and statusText attribute
336 */
337 KorAP.API.deleteQuery = function (qn, errorCB){
338 KorAP.API.deleteJSON(KorAP.URL + "/query/" + qn, "deleteQuery of name "+ qn, errorCB);
339 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000340});