hq-engine-xqilla 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/src/Makefile +14 -0
- data/src/Rakefile +10 -0
- data/src/xquery-server.cc +826 -0
- metadata +161 -0
data/src/Makefile
ADDED
data/src/Rakefile
ADDED
|
@@ -0,0 +1,826 @@
|
|
|
1
|
+
|
|
2
|
+
// c++ libraries
|
|
3
|
+
|
|
4
|
+
#include <iostream>
|
|
5
|
+
#include <sstream>
|
|
6
|
+
#include <string>
|
|
7
|
+
|
|
8
|
+
// c libraries
|
|
9
|
+
|
|
10
|
+
#include <stdlib.h>
|
|
11
|
+
#include <unistd.h>
|
|
12
|
+
|
|
13
|
+
// json library
|
|
14
|
+
|
|
15
|
+
#include <jsoncpp/json/json.h>
|
|
16
|
+
|
|
17
|
+
// xqilla xquery library
|
|
18
|
+
|
|
19
|
+
#include <xqilla/xqilla-simple.hpp>
|
|
20
|
+
|
|
21
|
+
#include <xqilla/context/ExternalFunctionResolver.hpp>
|
|
22
|
+
#include <xqilla/functions/ExternalFunction.hpp>
|
|
23
|
+
#include <xqilla/update/PendingUpdateList.hpp>
|
|
24
|
+
|
|
25
|
+
// xerces library
|
|
26
|
+
|
|
27
|
+
#include <xercesc/framework/MemBufInputSource.hpp>
|
|
28
|
+
#include <xercesc/util/XMLEntityResolver.hpp>
|
|
29
|
+
|
|
30
|
+
using namespace std;
|
|
31
|
+
|
|
32
|
+
XQilla xqilla;
|
|
33
|
+
|
|
34
|
+
struct Session :
|
|
35
|
+
public MessageListener,
|
|
36
|
+
public ModuleResolver,
|
|
37
|
+
public xercesc::XMLEntityResolver {
|
|
38
|
+
|
|
39
|
+
map <string, string> modules;
|
|
40
|
+
map <string, Sequence *> record_cache;
|
|
41
|
+
map <string, Sequence *> find_cache;
|
|
42
|
+
|
|
43
|
+
XQQuery * query;
|
|
44
|
+
|
|
45
|
+
Session () {
|
|
46
|
+
query = NULL;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
virtual ~Session () {
|
|
50
|
+
|
|
51
|
+
if (query)
|
|
52
|
+
delete query;
|
|
53
|
+
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
void set_query (XQQuery * query) {
|
|
57
|
+
|
|
58
|
+
if (this->query)
|
|
59
|
+
delete this->query;
|
|
60
|
+
|
|
61
|
+
this->query = query;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
virtual bool resolveModuleLocation (
|
|
65
|
+
VectorOfStrings * result,
|
|
66
|
+
const XMLCh * uri_xmlch,
|
|
67
|
+
const StaticContext * context) {
|
|
68
|
+
|
|
69
|
+
result->push_back (uri_xmlch);
|
|
70
|
+
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
virtual xercesc::InputSource * resolveEntity (
|
|
75
|
+
xercesc::XMLResourceIdentifier * resource_id) {
|
|
76
|
+
|
|
77
|
+
string system_id =
|
|
78
|
+
UTF8 (resource_id->getSystemId ());
|
|
79
|
+
|
|
80
|
+
if (! modules.count (system_id))
|
|
81
|
+
return NULL;
|
|
82
|
+
|
|
83
|
+
string & module_text =
|
|
84
|
+
modules [system_id];
|
|
85
|
+
|
|
86
|
+
return new xercesc::MemBufInputSource (
|
|
87
|
+
(XMLByte *) module_text.data (),
|
|
88
|
+
module_text.size (),
|
|
89
|
+
X (system_id.c_str ()));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
virtual void warning (
|
|
93
|
+
const XMLCh * message,
|
|
94
|
+
const LocationInfo * location) {
|
|
95
|
+
|
|
96
|
+
cerr << "WARN: " << UTF8 (message) << "\n";
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
virtual void trace (
|
|
100
|
+
const XMLCh * label,
|
|
101
|
+
const Sequence & sequence,
|
|
102
|
+
const LocationInfo * location,
|
|
103
|
+
const DynamicContext * context) {
|
|
104
|
+
|
|
105
|
+
cerr << "TRACE: " << UTF8 (label) << "\n";
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
struct CallbackFunction :
|
|
111
|
+
public ExternalFunction {
|
|
112
|
+
|
|
113
|
+
Session * session;
|
|
114
|
+
|
|
115
|
+
CallbackFunction (
|
|
116
|
+
const char * name,
|
|
117
|
+
int args,
|
|
118
|
+
Session * session,
|
|
119
|
+
XPath2MemoryManager * mm)
|
|
120
|
+
|
|
121
|
+
: ExternalFunction (
|
|
122
|
+
X ("hq"),
|
|
123
|
+
X (name),
|
|
124
|
+
args,
|
|
125
|
+
mm),
|
|
126
|
+
|
|
127
|
+
session (session) {
|
|
128
|
+
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
Sequence * makeFuncCall (
|
|
132
|
+
DynamicContext * context,
|
|
133
|
+
const char * name,
|
|
134
|
+
Json::Value & arguments) const {
|
|
135
|
+
|
|
136
|
+
// send function request
|
|
137
|
+
|
|
138
|
+
Json::Value func_call = Json::objectValue;
|
|
139
|
+
|
|
140
|
+
func_call ["name"] = "function call";
|
|
141
|
+
func_call ["arguments"] = Json::objectValue;
|
|
142
|
+
func_call ["arguments"] ["name"] = name;
|
|
143
|
+
func_call ["arguments"] ["arguments"] = arguments;
|
|
144
|
+
|
|
145
|
+
Json::FastWriter writer;
|
|
146
|
+
string func_call_str = writer.write (func_call);
|
|
147
|
+
cout << func_call_str.size () << "\n" << func_call_str;
|
|
148
|
+
|
|
149
|
+
ItemFactory * itemFactory =
|
|
150
|
+
context->getItemFactory ();
|
|
151
|
+
|
|
152
|
+
// read function response
|
|
153
|
+
|
|
154
|
+
int func_return_len;
|
|
155
|
+
cin >> func_return_len;
|
|
156
|
+
|
|
157
|
+
char func_return_buf [func_return_len];
|
|
158
|
+
cin.read (func_return_buf, func_return_len);
|
|
159
|
+
string func_return_str (func_return_buf, func_return_len);
|
|
160
|
+
|
|
161
|
+
Json::Value func_return;
|
|
162
|
+
Json::Reader reader;
|
|
163
|
+
|
|
164
|
+
bool parsingSuccessful =
|
|
165
|
+
reader.parse (func_return_str, func_return);
|
|
166
|
+
|
|
167
|
+
if (! parsingSuccessful) {
|
|
168
|
+
|
|
169
|
+
cerr << "Failed to parse request\n"
|
|
170
|
+
<< reader.getFormattedErrorMessages ();
|
|
171
|
+
|
|
172
|
+
exit (1);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// return as sequence
|
|
176
|
+
|
|
177
|
+
Json::Value values =
|
|
178
|
+
func_return ["arguments"] ["values"];
|
|
179
|
+
|
|
180
|
+
Sequence * return_sequence =
|
|
181
|
+
new Sequence ();
|
|
182
|
+
|
|
183
|
+
for (int i = 0; i < values.size (); i++) {
|
|
184
|
+
|
|
185
|
+
string value_str =
|
|
186
|
+
values [i].asString ();
|
|
187
|
+
|
|
188
|
+
xercesc::MemBufInputSource input_source (
|
|
189
|
+
(XMLByte *) value_str.c_str (),
|
|
190
|
+
value_str.size (),
|
|
191
|
+
X ("value.xml"));
|
|
192
|
+
|
|
193
|
+
Node::Ptr value_document =
|
|
194
|
+
context->parseDocument (
|
|
195
|
+
input_source);
|
|
196
|
+
|
|
197
|
+
Result result =
|
|
198
|
+
value_document->dmChildren (context, NULL);
|
|
199
|
+
|
|
200
|
+
Item::Ptr item =
|
|
201
|
+
result->next (context);
|
|
202
|
+
|
|
203
|
+
return_sequence->addItem (item);
|
|
204
|
+
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return return_sequence;
|
|
208
|
+
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
struct GetByIdFunction :
|
|
214
|
+
public CallbackFunction {
|
|
215
|
+
|
|
216
|
+
GetByIdFunction (
|
|
217
|
+
Session * session,
|
|
218
|
+
XPath2MemoryManager * mm)
|
|
219
|
+
|
|
220
|
+
: CallbackFunction (
|
|
221
|
+
"get",
|
|
222
|
+
1,
|
|
223
|
+
session,
|
|
224
|
+
mm) {
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
Result execute (
|
|
228
|
+
const Arguments * args,
|
|
229
|
+
DynamicContext * context) const {
|
|
230
|
+
|
|
231
|
+
// determine id
|
|
232
|
+
|
|
233
|
+
Result result =
|
|
234
|
+
args->getArgument (0, context);
|
|
235
|
+
|
|
236
|
+
Item::Ptr item =
|
|
237
|
+
result->next (context);
|
|
238
|
+
|
|
239
|
+
string id =
|
|
240
|
+
UTF8 (item->asString (context));
|
|
241
|
+
|
|
242
|
+
// check cache
|
|
243
|
+
|
|
244
|
+
if (session->record_cache.count (id))
|
|
245
|
+
return * session->record_cache [id];
|
|
246
|
+
|
|
247
|
+
// make call
|
|
248
|
+
|
|
249
|
+
Json::Value arguments = Json::objectValue;
|
|
250
|
+
|
|
251
|
+
arguments ["id"] = id;
|
|
252
|
+
|
|
253
|
+
Sequence * ret =
|
|
254
|
+
makeFuncCall (
|
|
255
|
+
context,
|
|
256
|
+
"get record by id",
|
|
257
|
+
arguments);
|
|
258
|
+
|
|
259
|
+
// store in cache
|
|
260
|
+
|
|
261
|
+
session->record_cache [id] = ret;
|
|
262
|
+
|
|
263
|
+
// and return
|
|
264
|
+
|
|
265
|
+
return * ret;
|
|
266
|
+
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
struct GetByIdPartsFunction :
|
|
272
|
+
public CallbackFunction {
|
|
273
|
+
|
|
274
|
+
GetByIdPartsFunction (
|
|
275
|
+
Session * session,
|
|
276
|
+
XPath2MemoryManager * mm)
|
|
277
|
+
|
|
278
|
+
: CallbackFunction (
|
|
279
|
+
"get",
|
|
280
|
+
2,
|
|
281
|
+
session,
|
|
282
|
+
mm) {
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
Result execute (
|
|
286
|
+
const Arguments * args,
|
|
287
|
+
DynamicContext * context) const {
|
|
288
|
+
|
|
289
|
+
// determine id - start with type
|
|
290
|
+
|
|
291
|
+
Result result =
|
|
292
|
+
args->getArgument (0, context);
|
|
293
|
+
|
|
294
|
+
Item::Ptr item =
|
|
295
|
+
result->next (context);
|
|
296
|
+
|
|
297
|
+
string id =
|
|
298
|
+
UTF8 (item->asString (context));
|
|
299
|
+
|
|
300
|
+
// determine id - then id parts
|
|
301
|
+
|
|
302
|
+
Result id_parts_result =
|
|
303
|
+
args->getArgument (1, context);
|
|
304
|
+
|
|
305
|
+
while (
|
|
306
|
+
Item::Ptr id_part_item =
|
|
307
|
+
id_parts_result->next (context)
|
|
308
|
+
) {
|
|
309
|
+
|
|
310
|
+
id.append ("/");
|
|
311
|
+
id.append (UTF8 (id_part_item->asString (context)));
|
|
312
|
+
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// check cache
|
|
316
|
+
|
|
317
|
+
if (session->record_cache.count (id))
|
|
318
|
+
return * session->record_cache [id];
|
|
319
|
+
|
|
320
|
+
// make function call
|
|
321
|
+
|
|
322
|
+
Json::Value arguments = Json::objectValue;
|
|
323
|
+
|
|
324
|
+
arguments ["id"] = id;
|
|
325
|
+
|
|
326
|
+
Sequence * ret =
|
|
327
|
+
makeFuncCall (
|
|
328
|
+
context,
|
|
329
|
+
"get record by id",
|
|
330
|
+
arguments);
|
|
331
|
+
|
|
332
|
+
// update cache
|
|
333
|
+
|
|
334
|
+
session->record_cache [id] = ret;
|
|
335
|
+
|
|
336
|
+
// and return
|
|
337
|
+
|
|
338
|
+
return * ret;
|
|
339
|
+
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
struct FindByTypeFunction :
|
|
345
|
+
public CallbackFunction {
|
|
346
|
+
|
|
347
|
+
FindByTypeFunction (
|
|
348
|
+
Session * session,
|
|
349
|
+
XPath2MemoryManager * mm)
|
|
350
|
+
|
|
351
|
+
: CallbackFunction (
|
|
352
|
+
"find",
|
|
353
|
+
1,
|
|
354
|
+
session,
|
|
355
|
+
mm) {
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
Result execute (
|
|
359
|
+
const Arguments * args,
|
|
360
|
+
DynamicContext * context) const {
|
|
361
|
+
|
|
362
|
+
// determine type
|
|
363
|
+
|
|
364
|
+
Result result =
|
|
365
|
+
args->getArgument (0, context);
|
|
366
|
+
|
|
367
|
+
Item::Ptr item =
|
|
368
|
+
result->next (context);
|
|
369
|
+
|
|
370
|
+
string type =
|
|
371
|
+
UTF8 (item->asString (context));
|
|
372
|
+
|
|
373
|
+
// check cache
|
|
374
|
+
|
|
375
|
+
if (session->find_cache.count (type))
|
|
376
|
+
return * session->find_cache [type];
|
|
377
|
+
|
|
378
|
+
// make function call
|
|
379
|
+
|
|
380
|
+
Json::Value arguments = Json::objectValue;
|
|
381
|
+
|
|
382
|
+
arguments ["type"] =
|
|
383
|
+
type;
|
|
384
|
+
|
|
385
|
+
Sequence * ret =
|
|
386
|
+
makeFuncCall (
|
|
387
|
+
context,
|
|
388
|
+
"search records",
|
|
389
|
+
arguments);
|
|
390
|
+
|
|
391
|
+
// update cache
|
|
392
|
+
|
|
393
|
+
session->find_cache [type] = ret;
|
|
394
|
+
|
|
395
|
+
// return
|
|
396
|
+
|
|
397
|
+
return * ret;
|
|
398
|
+
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
struct FindByTypeCriteriaFunction :
|
|
404
|
+
public CallbackFunction {
|
|
405
|
+
|
|
406
|
+
FindByTypeCriteriaFunction (
|
|
407
|
+
Session * session,
|
|
408
|
+
XPath2MemoryManager * mm)
|
|
409
|
+
|
|
410
|
+
: CallbackFunction (
|
|
411
|
+
"find",
|
|
412
|
+
2,
|
|
413
|
+
session,
|
|
414
|
+
mm) {
|
|
415
|
+
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
Result execute (
|
|
419
|
+
const Arguments * args,
|
|
420
|
+
DynamicContext * context) const {
|
|
421
|
+
|
|
422
|
+
Json::Value arguments = Json::objectValue;
|
|
423
|
+
|
|
424
|
+
Result result =
|
|
425
|
+
args->getArgument (0, context);
|
|
426
|
+
|
|
427
|
+
Item::Ptr item =
|
|
428
|
+
result->next (context);
|
|
429
|
+
|
|
430
|
+
arguments ["type"] =
|
|
431
|
+
UTF8 (item->asString (context));
|
|
432
|
+
|
|
433
|
+
// add criteria
|
|
434
|
+
|
|
435
|
+
Json::Value & criteria_json =
|
|
436
|
+
arguments ["criteria"];
|
|
437
|
+
|
|
438
|
+
criteria_json =
|
|
439
|
+
Json::objectValue;
|
|
440
|
+
|
|
441
|
+
Result criteria_result =
|
|
442
|
+
args->getArgument (1, context);
|
|
443
|
+
|
|
444
|
+
while (
|
|
445
|
+
Item::Ptr criteria_item =
|
|
446
|
+
criteria_result->next (context)
|
|
447
|
+
) {
|
|
448
|
+
|
|
449
|
+
string criteria_str =
|
|
450
|
+
UTF8 (criteria_item->asString (context));
|
|
451
|
+
|
|
452
|
+
int pos =
|
|
453
|
+
criteria_str.find ('=');
|
|
454
|
+
|
|
455
|
+
if (pos == string::npos) {
|
|
456
|
+
cerr << "ERROR 64168123\n";
|
|
457
|
+
exit (1);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
string criteria_key_str =
|
|
461
|
+
criteria_str.substr (0, pos);
|
|
462
|
+
|
|
463
|
+
string criteria_value_str =
|
|
464
|
+
criteria_str.substr (pos + 1);
|
|
465
|
+
|
|
466
|
+
criteria_json [criteria_key_str] =
|
|
467
|
+
criteria_value_str;
|
|
468
|
+
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
Sequence * ret =
|
|
472
|
+
makeFuncCall (
|
|
473
|
+
context,
|
|
474
|
+
"search records",
|
|
475
|
+
arguments);
|
|
476
|
+
|
|
477
|
+
return * ret;
|
|
478
|
+
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
};
|
|
482
|
+
|
|
483
|
+
struct MyFunctionResolver :
|
|
484
|
+
public ExternalFunctionResolver {
|
|
485
|
+
|
|
486
|
+
Session * session;
|
|
487
|
+
|
|
488
|
+
virtual ExternalFunction * resolveExternalFunction (
|
|
489
|
+
const XMLCh * uri_xmlch,
|
|
490
|
+
const XMLCh * name_xmlch,
|
|
491
|
+
size_t numArgs,
|
|
492
|
+
const StaticContext * context) {
|
|
493
|
+
|
|
494
|
+
string uri = UTF8 (uri_xmlch);
|
|
495
|
+
string name = UTF8 (name_xmlch);
|
|
496
|
+
|
|
497
|
+
if (uri != "hq")
|
|
498
|
+
return NULL;
|
|
499
|
+
|
|
500
|
+
XPath2MemoryManager * mm (context->getMemoryManager ());
|
|
501
|
+
|
|
502
|
+
if (name == "get") {
|
|
503
|
+
|
|
504
|
+
if (numArgs == 1)
|
|
505
|
+
return new GetByIdFunction (session, mm);
|
|
506
|
+
|
|
507
|
+
if (numArgs == 2)
|
|
508
|
+
return new GetByIdPartsFunction (session, mm);
|
|
509
|
+
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
if (name == "get" && numArgs == 1)
|
|
513
|
+
return new GetByIdFunction (session, mm);
|
|
514
|
+
|
|
515
|
+
if (name == "find") {
|
|
516
|
+
|
|
517
|
+
if (numArgs == 1)
|
|
518
|
+
return new FindByTypeFunction (session, mm);
|
|
519
|
+
|
|
520
|
+
if (numArgs == 2)
|
|
521
|
+
return new FindByTypeCriteriaFunction (session, mm);
|
|
522
|
+
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
return NULL;
|
|
526
|
+
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
};
|
|
530
|
+
|
|
531
|
+
map <string, Session *> sessions;
|
|
532
|
+
|
|
533
|
+
Session & get_session (string session_id) {
|
|
534
|
+
|
|
535
|
+
Session * session =
|
|
536
|
+
sessions [session_id];
|
|
537
|
+
|
|
538
|
+
if (session != NULL)
|
|
539
|
+
return * session;
|
|
540
|
+
|
|
541
|
+
session = new Session ();
|
|
542
|
+
|
|
543
|
+
sessions [session_id] =
|
|
544
|
+
session;
|
|
545
|
+
|
|
546
|
+
return * session;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
void set_error (
|
|
550
|
+
Json::Value & reply,
|
|
551
|
+
XQException & error) {
|
|
552
|
+
|
|
553
|
+
reply ["name"] =
|
|
554
|
+
"error";
|
|
555
|
+
|
|
556
|
+
reply ["arguments"] ["type"] =
|
|
557
|
+
UTF8 (error.getType ());
|
|
558
|
+
|
|
559
|
+
reply ["arguments"] ["error"] =
|
|
560
|
+
UTF8 (error.getError ());
|
|
561
|
+
|
|
562
|
+
reply ["arguments"] ["file"] =
|
|
563
|
+
UTF8 (error.getXQueryFile ());
|
|
564
|
+
|
|
565
|
+
reply ["arguments"] ["line"] =
|
|
566
|
+
error.getXQueryLine ();
|
|
567
|
+
|
|
568
|
+
reply ["arguments"] ["column"] =
|
|
569
|
+
error.getXQueryColumn ();
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
void compile_xquery (
|
|
573
|
+
Json::Value & reply,
|
|
574
|
+
string session_id,
|
|
575
|
+
string xquery_text,
|
|
576
|
+
string filename) {
|
|
577
|
+
|
|
578
|
+
Session & session =
|
|
579
|
+
get_session (session_id);
|
|
580
|
+
|
|
581
|
+
session.record_cache.clear ();
|
|
582
|
+
session.find_cache.clear ();
|
|
583
|
+
|
|
584
|
+
try {
|
|
585
|
+
|
|
586
|
+
AutoDelete<DynamicContext> static_context (
|
|
587
|
+
xqilla.createContext ());
|
|
588
|
+
|
|
589
|
+
static_context->setProjection (false);
|
|
590
|
+
|
|
591
|
+
static_context->setMessageListener (& session);
|
|
592
|
+
|
|
593
|
+
static_context->setModuleResolver (& session);
|
|
594
|
+
|
|
595
|
+
DocumentCache * documentCache =
|
|
596
|
+
static_context->getDocumentCache ();
|
|
597
|
+
|
|
598
|
+
documentCache->setXMLEntityResolver (& session);
|
|
599
|
+
|
|
600
|
+
// set function resolver
|
|
601
|
+
|
|
602
|
+
MyFunctionResolver * myFuncResolver =
|
|
603
|
+
new MyFunctionResolver;
|
|
604
|
+
|
|
605
|
+
myFuncResolver->session = & session;
|
|
606
|
+
|
|
607
|
+
static_context->setExternalFunctionResolver (
|
|
608
|
+
myFuncResolver);
|
|
609
|
+
|
|
610
|
+
// create input source
|
|
611
|
+
|
|
612
|
+
xercesc::MemBufInputSource input_source (
|
|
613
|
+
(XMLByte *) xquery_text.data (),
|
|
614
|
+
xquery_text.size (),
|
|
615
|
+
X (filename.c_str ()));
|
|
616
|
+
|
|
617
|
+
// parse query
|
|
618
|
+
|
|
619
|
+
AutoDelete<XQQuery> query (
|
|
620
|
+
xqilla.parse (
|
|
621
|
+
input_source,
|
|
622
|
+
static_context.adopt ()));
|
|
623
|
+
|
|
624
|
+
session.set_query (query.adopt ());
|
|
625
|
+
|
|
626
|
+
} catch (XQException & error) {
|
|
627
|
+
|
|
628
|
+
//cerr << UTF8 (error.getError ()) << "\n";
|
|
629
|
+
|
|
630
|
+
set_error (reply, error);
|
|
631
|
+
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// send reply
|
|
636
|
+
|
|
637
|
+
reply ["name"] =
|
|
638
|
+
"ok";
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
void run_xquery (
|
|
642
|
+
Json::Value & reply,
|
|
643
|
+
string session_id,
|
|
644
|
+
string input_text) {
|
|
645
|
+
|
|
646
|
+
Session & session =
|
|
647
|
+
get_session (session_id);
|
|
648
|
+
|
|
649
|
+
// fail if there is no query
|
|
650
|
+
|
|
651
|
+
if (! session.query) {
|
|
652
|
+
|
|
653
|
+
reply ["name"] =
|
|
654
|
+
"usage error";
|
|
655
|
+
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
// perform query
|
|
660
|
+
|
|
661
|
+
string result_text;
|
|
662
|
+
|
|
663
|
+
try {
|
|
664
|
+
|
|
665
|
+
xercesc::MemBufInputSource input_source (
|
|
666
|
+
(XMLByte *) input_text.data (),
|
|
667
|
+
input_text.size (),
|
|
668
|
+
X ("input.xml"));
|
|
669
|
+
|
|
670
|
+
AutoDelete<DynamicContext> dynamic_context (
|
|
671
|
+
session.query->createDynamicContext ());
|
|
672
|
+
|
|
673
|
+
Node::Ptr input_document =
|
|
674
|
+
dynamic_context->parseDocument (
|
|
675
|
+
input_source);
|
|
676
|
+
|
|
677
|
+
dynamic_context->setContextItem (input_document);
|
|
678
|
+
dynamic_context->setContextPosition (1);
|
|
679
|
+
dynamic_context->setContextSize (1);
|
|
680
|
+
|
|
681
|
+
Result result =
|
|
682
|
+
session.query->execute (dynamic_context);
|
|
683
|
+
|
|
684
|
+
ostringstream result_stream;
|
|
685
|
+
|
|
686
|
+
while (Item::Ptr item = result->next (dynamic_context)) {
|
|
687
|
+
result_stream << UTF8 (item->asString (dynamic_context));
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
result_text = result_stream.str ();
|
|
691
|
+
|
|
692
|
+
} catch (XQException & error) {
|
|
693
|
+
|
|
694
|
+
cerr << UTF8 (error.getError ()) << "\n";
|
|
695
|
+
|
|
696
|
+
set_error (reply, error);
|
|
697
|
+
|
|
698
|
+
return;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
// send reply
|
|
702
|
+
|
|
703
|
+
reply ["name"] =
|
|
704
|
+
"ok";
|
|
705
|
+
|
|
706
|
+
reply ["arguments"] ["result text"] =
|
|
707
|
+
result_text;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
void set_library_module (
|
|
711
|
+
Json::Value & reply,
|
|
712
|
+
string session_id,
|
|
713
|
+
string module_name,
|
|
714
|
+
string module_text) {
|
|
715
|
+
|
|
716
|
+
Session & session =
|
|
717
|
+
get_session (session_id);
|
|
718
|
+
|
|
719
|
+
// set module
|
|
720
|
+
|
|
721
|
+
session.modules [module_name] =
|
|
722
|
+
module_text;
|
|
723
|
+
|
|
724
|
+
// send reply
|
|
725
|
+
|
|
726
|
+
reply ["name"] =
|
|
727
|
+
"ok";
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
string handle_request (
|
|
731
|
+
string request_string) {
|
|
732
|
+
|
|
733
|
+
// decode
|
|
734
|
+
|
|
735
|
+
Json::Value request;
|
|
736
|
+
|
|
737
|
+
Json::Reader reader;
|
|
738
|
+
|
|
739
|
+
bool parsingSuccessful =
|
|
740
|
+
reader.parse (request_string, request);
|
|
741
|
+
|
|
742
|
+
if (! parsingSuccessful) {
|
|
743
|
+
|
|
744
|
+
cerr << "Failed to parse request\n"
|
|
745
|
+
<< reader.getFormattedErrorMessages ();
|
|
746
|
+
|
|
747
|
+
exit (1);
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
// lookup function
|
|
751
|
+
|
|
752
|
+
string request_name =
|
|
753
|
+
request ["name"].asString ();
|
|
754
|
+
|
|
755
|
+
Json::Value request_arguments =
|
|
756
|
+
request ["arguments"];
|
|
757
|
+
|
|
758
|
+
Json::Value reply (Json::objectValue);
|
|
759
|
+
|
|
760
|
+
reply ["arguments"] =
|
|
761
|
+
Json::Value (Json::objectValue);
|
|
762
|
+
|
|
763
|
+
if (request_name == "compile xquery") {
|
|
764
|
+
|
|
765
|
+
compile_xquery (
|
|
766
|
+
reply,
|
|
767
|
+
request_arguments ["session id"].asString (),
|
|
768
|
+
request_arguments ["xquery text"].asString (),
|
|
769
|
+
request_arguments ["xquery filename"].asString ());
|
|
770
|
+
|
|
771
|
+
} else if (request_name == "run xquery") {
|
|
772
|
+
|
|
773
|
+
run_xquery (
|
|
774
|
+
reply,
|
|
775
|
+
request_arguments ["session id"].asString (),
|
|
776
|
+
request_arguments ["input text"].asString ());
|
|
777
|
+
|
|
778
|
+
} else if (request_name == "set library module") {
|
|
779
|
+
|
|
780
|
+
set_library_module (
|
|
781
|
+
reply,
|
|
782
|
+
request_arguments ["session id"].asString (),
|
|
783
|
+
request_arguments ["module name"].asString (),
|
|
784
|
+
request_arguments ["module text"].asString ());
|
|
785
|
+
|
|
786
|
+
} else {
|
|
787
|
+
|
|
788
|
+
cerr << "Invalid function name: " << request_name << "\n";
|
|
789
|
+
|
|
790
|
+
exit (1);
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
// send reply
|
|
794
|
+
|
|
795
|
+
Json::FastWriter writer;
|
|
796
|
+
|
|
797
|
+
return writer.write (reply);
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
int main (int argc, char * argv []) {
|
|
801
|
+
|
|
802
|
+
while (true) {
|
|
803
|
+
|
|
804
|
+
// read request
|
|
805
|
+
|
|
806
|
+
int request_len;
|
|
807
|
+
cin >> request_len;
|
|
808
|
+
|
|
809
|
+
char request_buf [request_len];
|
|
810
|
+
cin.read (request_buf, request_len);
|
|
811
|
+
string request_string (request_buf, request_len);
|
|
812
|
+
|
|
813
|
+
// handle
|
|
814
|
+
|
|
815
|
+
string reply_string =
|
|
816
|
+
handle_request (request_string);
|
|
817
|
+
|
|
818
|
+
// send reply
|
|
819
|
+
|
|
820
|
+
cout << reply_string.size () << "\n";
|
|
821
|
+
|
|
822
|
+
cout << reply_string;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
return EXIT_SUCCESS;
|
|
826
|
+
}
|
metadata
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: hq-engine-xqilla
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- James Pharaoh
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2013-04-17 00:00:00.000000000 Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: hq-engine
|
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
|
17
|
+
none: false
|
|
18
|
+
requirements:
|
|
19
|
+
- - '='
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: 0.0.2
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
none: false
|
|
26
|
+
requirements:
|
|
27
|
+
- - '='
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: 0.0.2
|
|
30
|
+
- !ruby/object:Gem::Dependency
|
|
31
|
+
name: capybara
|
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
|
33
|
+
none: false
|
|
34
|
+
requirements:
|
|
35
|
+
- - ! '>='
|
|
36
|
+
- !ruby/object:Gem::Version
|
|
37
|
+
version: 2.0.2
|
|
38
|
+
type: :development
|
|
39
|
+
prerelease: false
|
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
41
|
+
none: false
|
|
42
|
+
requirements:
|
|
43
|
+
- - ! '>='
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: 2.0.2
|
|
46
|
+
- !ruby/object:Gem::Dependency
|
|
47
|
+
name: cucumber
|
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
|
49
|
+
none: false
|
|
50
|
+
requirements:
|
|
51
|
+
- - ! '>='
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: 1.2.1
|
|
54
|
+
type: :development
|
|
55
|
+
prerelease: false
|
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
57
|
+
none: false
|
|
58
|
+
requirements:
|
|
59
|
+
- - ! '>='
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: 1.2.1
|
|
62
|
+
- !ruby/object:Gem::Dependency
|
|
63
|
+
name: rake
|
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
|
65
|
+
none: false
|
|
66
|
+
requirements:
|
|
67
|
+
- - ! '>='
|
|
68
|
+
- !ruby/object:Gem::Version
|
|
69
|
+
version: 10.0.3
|
|
70
|
+
type: :development
|
|
71
|
+
prerelease: false
|
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
73
|
+
none: false
|
|
74
|
+
requirements:
|
|
75
|
+
- - ! '>='
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
version: 10.0.3
|
|
78
|
+
- !ruby/object:Gem::Dependency
|
|
79
|
+
name: rspec
|
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
|
81
|
+
none: false
|
|
82
|
+
requirements:
|
|
83
|
+
- - ! '>='
|
|
84
|
+
- !ruby/object:Gem::Version
|
|
85
|
+
version: 2.12.0
|
|
86
|
+
type: :development
|
|
87
|
+
prerelease: false
|
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
89
|
+
none: false
|
|
90
|
+
requirements:
|
|
91
|
+
- - ! '>='
|
|
92
|
+
- !ruby/object:Gem::Version
|
|
93
|
+
version: 2.12.0
|
|
94
|
+
- !ruby/object:Gem::Dependency
|
|
95
|
+
name: rspec_junit_formatter
|
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
|
97
|
+
none: false
|
|
98
|
+
requirements:
|
|
99
|
+
- - ! '>='
|
|
100
|
+
- !ruby/object:Gem::Version
|
|
101
|
+
version: '0'
|
|
102
|
+
type: :development
|
|
103
|
+
prerelease: false
|
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
105
|
+
none: false
|
|
106
|
+
requirements:
|
|
107
|
+
- - ! '>='
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '0'
|
|
110
|
+
- !ruby/object:Gem::Dependency
|
|
111
|
+
name: simplecov
|
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
|
113
|
+
none: false
|
|
114
|
+
requirements:
|
|
115
|
+
- - ! '>='
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '0'
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
none: false
|
|
122
|
+
requirements:
|
|
123
|
+
- - ! '>='
|
|
124
|
+
- !ruby/object:Gem::Version
|
|
125
|
+
version: '0'
|
|
126
|
+
description: HQ engine plugin to use the xqilla xquery library
|
|
127
|
+
email:
|
|
128
|
+
- james@phsys.co.uk
|
|
129
|
+
executables: []
|
|
130
|
+
extensions:
|
|
131
|
+
- src/Rakefile
|
|
132
|
+
extra_rdoc_files: []
|
|
133
|
+
files:
|
|
134
|
+
- src/Makefile
|
|
135
|
+
- src/Rakefile
|
|
136
|
+
- src/xquery-server.cc
|
|
137
|
+
homepage: https://github.com/jamespharaoh/hq-engine-xqilla
|
|
138
|
+
licenses: []
|
|
139
|
+
post_install_message:
|
|
140
|
+
rdoc_options: []
|
|
141
|
+
require_paths:
|
|
142
|
+
- lib
|
|
143
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
144
|
+
none: false
|
|
145
|
+
requirements:
|
|
146
|
+
- - ! '>='
|
|
147
|
+
- !ruby/object:Gem::Version
|
|
148
|
+
version: '0'
|
|
149
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
150
|
+
none: false
|
|
151
|
+
requirements:
|
|
152
|
+
- - ! '>='
|
|
153
|
+
- !ruby/object:Gem::Version
|
|
154
|
+
version: 1.3.6
|
|
155
|
+
requirements: []
|
|
156
|
+
rubyforge_project: hq-engine-xqilla
|
|
157
|
+
rubygems_version: 1.8.23
|
|
158
|
+
signing_key:
|
|
159
|
+
specification_version: 3
|
|
160
|
+
summary: HQ engine xqilla
|
|
161
|
+
test_files: []
|