1 /* This file is part of mp-xquery
2 Copyright (C) Index Data
4 Metaproxy is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
9 Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #include <metaproxy/package.hpp>
20 #include <metaproxy/util.hpp>
22 #include <yaz/oid_db.h>
29 #include <zorba/zorba.h>
30 #include <zorba/store_manager.h>
31 #include <zorba/serializer.h>
32 #include <zorba/singleton_item_sequence.h>
33 #include <zorba/zorba_exception.h>
36 namespace mp = metaproxy_1;
37 namespace yf = mp::filter;
38 namespace mp_util = metaproxy_1::util;
40 using namespace zorba;
42 namespace metaproxy_1 {
44 class XQuery : public Base {
48 void process(metaproxy_1::Package & package) const;
49 void configure(const xmlNode * ptr, bool test_only,
52 void stop(int signo) const;
54 bool convert_one_record(const char *input_buf,
56 std::string &result) const;
57 std::map<std::string, std::string> zorba_variables;
58 std::string zorba_filename;
59 std::string zorba_script;
60 std::string zorba_record_variable;
78 void yf::XQuery::start() const
82 void yf::XQuery::stop(int signo) const
86 bool yf::XQuery::convert_one_record(const char *input_buf,
88 std::string &result) const
90 XQuery_t tQuery = lQuery->clone();
92 zorba::DynamicContext* lDynamicContext = tQuery->getDynamicContext();
95 std::map<std::string, std::string>::const_iterator it;
96 for (it = zorba_variables.begin(); it != zorba_variables.end(); it++)
98 lItem = lZorba->getItemFactory()->createString(it->second);
99 lDynamicContext->setVariable(it->first, lItem);
101 // TODO: Make tmp file here
102 lItem = lZorba->getItemFactory()->createString(
103 "/home/adam/proj/yaz/test/marc7.xml");
104 lDynamicContext->setVariable(zorba_record_variable, lItem);
106 std::stringstream ss;
112 void yf::XQuery::process(Package &package) const
114 Z_GDU *gdu_req = package.request().get();
115 Z_PresentRequest *pr_req = 0;
116 Z_SearchRequest *sr_req = 0;
118 const char *input_schema = 0;
119 Odr_oid *input_syntax = 0;
121 if (gdu_req && gdu_req->which == Z_GDU_Z3950 &&
122 gdu_req->u.z3950->which == Z_APDU_presentRequest)
124 pr_req = gdu_req->u.z3950->u.presentRequest;
127 mp_util::record_composition_to_esn(pr_req->recordComposition);
128 input_syntax = pr_req->preferredRecordSyntax;
130 else if (gdu_req && gdu_req->which == Z_GDU_Z3950 &&
131 gdu_req->u.z3950->which == Z_APDU_searchRequest)
133 sr_req = gdu_req->u.z3950->u.searchRequest;
135 input_syntax = sr_req->preferredRecordSyntax;
137 // we don't know how many hits we're going to get and therefore
138 // the effective element set name.. Therefore we can only allow
139 // two cases.. Both equal or absent.. If not, we'll just have to
140 // disable the piggyback!
141 if (sr_req->smallSetElementSetNames
143 sr_req->mediumSetElementSetNames
145 sr_req->smallSetElementSetNames->which == Z_ElementSetNames_generic
147 sr_req->mediumSetElementSetNames->which == Z_ElementSetNames_generic
149 !strcmp(sr_req->smallSetElementSetNames->u.generic,
150 sr_req->mediumSetElementSetNames->u.generic))
152 input_schema = sr_req->smallSetElementSetNames->u.generic;
154 else if (!sr_req->smallSetElementSetNames &&
155 !sr_req->mediumSetElementSetNames)
156 ; // input_schema is 0 already
159 // disable piggyback (perhaps it was disabled already)
160 *sr_req->smallSetUpperBound = 0;
161 *sr_req->largeSetLowerBound = 0;
162 *sr_req->mediumSetPresentNumber = 0;
166 // we can handle it in record_transform.
174 mp::odr odr_en(ODR_ENCODE);
176 const char *backend_schema = 0;
177 const Odr_oid *backend_syntax = 0;
179 if (input_schema && !strcmp(input_schema, "bibframe") &&
180 (!input_syntax || !oid_oidcmp(input_syntax, yaz_oid_recsyn_xml)))
182 backend_schema = "marcxml";
183 backend_syntax = yaz_oid_recsyn_xml;
194 sr_req->preferredRecordSyntax = odr_oiddup(odr_en, backend_syntax);
196 sr_req->preferredRecordSyntax = 0;
199 sr_req->smallSetElementSetNames
200 = (Z_ElementSetNames *)
201 odr_malloc(odr_en, sizeof(Z_ElementSetNames));
202 sr_req->smallSetElementSetNames->which = Z_ElementSetNames_generic;
203 sr_req->smallSetElementSetNames->u.generic
204 = odr_strdup(odr_en, backend_schema);
205 sr_req->mediumSetElementSetNames = sr_req->smallSetElementSetNames;
209 sr_req->smallSetElementSetNames = 0;
210 sr_req->mediumSetElementSetNames = 0;
216 pr_req->preferredRecordSyntax = odr_oiddup(odr_en, backend_syntax);
218 pr_req->preferredRecordSyntax = 0;
222 pr_req->recordComposition
223 = (Z_RecordComposition *)
224 odr_malloc(odr_en, sizeof(Z_RecordComposition));
225 pr_req->recordComposition->which
226 = Z_RecordComp_simple;
227 pr_req->recordComposition->u.simple
228 = (Z_ElementSetNames *)
229 odr_malloc(odr_en, sizeof(Z_ElementSetNames));
230 pr_req->recordComposition->u.simple->which = Z_ElementSetNames_generic;
231 pr_req->recordComposition->u.simple->u.generic
232 = odr_strdup(odr_en, backend_schema);
235 pr_req->recordComposition = 0;
239 Z_GDU *gdu_res = package.response().get();
241 // see if we have a records list to patch!
242 Z_NamePlusRecordList *records = 0;
243 if (gdu_res && gdu_res->which == Z_GDU_Z3950 &&
244 gdu_res->u.z3950->which == Z_APDU_presentResponse)
246 Z_PresentResponse * pr_res = gdu_res->u.z3950->u.presentResponse;
249 && pr_res->numberOfRecordsReturned
250 && *(pr_res->numberOfRecordsReturned) > 0
252 && pr_res->records->which == Z_Records_DBOSD)
254 records = pr_res->records->u.databaseOrSurDiagnostics;
257 if (gdu_res && gdu_res->which == Z_GDU_Z3950 &&
258 gdu_res->u.z3950->which == Z_APDU_searchResponse)
260 Z_SearchResponse *sr_res = gdu_res->u.z3950->u.searchResponse;
263 && sr_res->numberOfRecordsReturned
264 && *(sr_res->numberOfRecordsReturned) > 0
266 && sr_res->records->which == Z_Records_DBOSD)
268 records = sr_res->records->u.databaseOrSurDiagnostics;
274 for (i = 0; i < records->num_records; i++)
276 Z_NamePlusRecord *npr = records->records[i];
277 if (npr->which == Z_NamePlusRecord_databaseRecord)
279 const char *details = 0;
280 Z_External *r = npr->u.databaseRecord;
282 if (r->which == Z_External_octet &&
283 !oid_oidcmp(r->direct_reference, yaz_oid_recsyn_xml))
286 if (convert_one_record(
287 r->u.octet_aligned->buf, r->u.octet_aligned->len,
290 npr->u.databaseRecord =
291 z_ext_record_oid(odr_en, yaz_oid_recsyn_xml,
298 package.response() = gdu_res;
302 void yf::XQuery::configure(const xmlNode * ptr, bool test_only,
305 for (ptr = ptr->children; ptr; ptr = ptr->next)
307 if (ptr->type != XML_ELEMENT_NODE)
309 if (!strcmp((const char *) ptr->name, "setVariable"))
313 struct _xmlAttr *attr;
314 for (attr = ptr->properties; attr; attr = attr->next)
315 if (!strcmp((const char *) attr->name, "name"))
316 name = mp::xml::get_text(attr->children);
317 else if (!strcmp((const char *) attr->name, "value"))
318 value = mp::xml::get_text(attr->children);
320 throw mp::filter::FilterException(
321 "Bad attribute " + std::string((const char *)
323 if (name.length() > 0)
324 zorba_variables[name] = value;
326 else if (!strcmp((const char *) ptr->name, "filename"))
329 struct _xmlAttr *attr;
330 for (attr = ptr->properties; attr; attr = attr->next)
331 if (!strcmp((const char *) attr->name, "value"))
332 value = mp::xml::get_text(attr->children);
334 throw mp::filter::FilterException(
335 "Bad attribute " + std::string((const char *)
337 zorba_filename = value;
339 else if (!strcmp((const char *) ptr->name, "script"))
342 struct _xmlAttr *attr;
343 for (attr = ptr->properties; attr; attr = attr->next)
344 if (!strcmp((const char *) attr->name, "value"))
345 value = mp::xml::get_text(attr->children);
347 throw mp::filter::FilterException(
348 "Bad attribute " + std::string((const char *)
350 zorba_script = value;
352 else if (!strcmp((const char *) ptr->name, "record"))
355 struct _xmlAttr *attr;
356 for (attr = ptr->properties; attr; attr = attr->next)
357 if (!strcmp((const char *) attr->name, "value"))
358 value = mp::xml::get_text(attr->children);
360 throw mp::filter::FilterException(
361 "Bad attribute " + std::string((const char *)
363 zorba_record_variable = value;
367 throw mp::filter::FilterException("Bad element "
368 + std::string((const char *)
372 if (zorba_script.length() == 0)
373 throw mp::filter::FilterException("Missing element script");
374 if (zorba_record_variable.length() == 0)
375 throw mp::filter::FilterException("Missing element record");
376 if (zorba_filename.length() == 0)
377 throw mp::filter::FilterException("Missing element filename");
380 void* lStore = StoreManager::getStore();
381 lZorba = Zorba::getInstance(lStore);
383 lQuery = lZorba->createQuery();
385 lQuery->setFileName(zorba_filename);
387 std::unique_ptr<std::istream> qfile;
388 qfile.reset(new std::ifstream(zorba_script.c_str()));
390 Zorba_CompilerHints lHints;
391 lQuery->compile(*qfile, lHints);
395 static yf::Base* filter_creator()
397 return new mp::filter::XQuery;
401 struct metaproxy_1_filter_struct metaproxy_1_filter_xquery = {
412 * c-file-style: "Stroustrup"
413 * indent-tabs-mode: nil
415 * vim: shiftwidth=4 tabstop=8 expandtab