From faf0b40133276ba4d44e26b7b61d0a02a33f4ed2 Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Fri, 13 Jun 2014 14:55:15 +0200 Subject: [PATCH] Almost fully operational xquery MP module Missing is putting a tmpfile with record content somewhere. --- src/Makefile | 2 +- src/metaproxy_filter_xquery.cpp | 190 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 189 insertions(+), 3 deletions(-) diff --git a/src/Makefile b/src/Makefile index f3c94bc..f6f5061 100644 --- a/src/Makefile +++ b/src/Makefile @@ -28,4 +28,4 @@ run_tst: tst LD_LIBRARY_PATH=$(ZORBA)/lib ./tst run_mp: - LD_LIBRARY_PATH=$(ZORBA)/lib ../../metaproxy/src/metaproxy -c config.xml + LD_LIBRARY_PATH=$(ZORBA)/lib ../../metaproxy/src/metaproxy -c config.xml -X diff --git a/src/metaproxy_filter_xquery.cpp b/src/metaproxy_filter_xquery.cpp index 76067e3..994139f 100644 --- a/src/metaproxy_filter_xquery.cpp +++ b/src/metaproxy_filter_xquery.cpp @@ -19,12 +19,25 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #include #include +#include #include +#include +#include +#include + +#include +#include +#include +#include +#include + + namespace mp = metaproxy_1; namespace yf = mp::filter; namespace mp_util = metaproxy_1::util; using namespace mp; +using namespace zorba; namespace metaproxy_1 { namespace filter { @@ -38,24 +51,30 @@ namespace metaproxy_1 { void start() const; void stop(int signo) const; private: + bool convert_one_record(const char *input_buf, + size_t input_len, + std::string &result) const; std::map zorba_variables; std::string zorba_filename; std::string zorba_script; std::string zorba_record_variable; + Zorba *lZorba; + XQuery_t lQuery; }; } } yf::XQuery::XQuery() { + lZorba = 0; } yf::XQuery::~XQuery() { - + if (lZorba) + lZorba->shutdown(); } - void yf::XQuery::start() const { } @@ -64,6 +83,32 @@ void yf::XQuery::stop(int signo) const { } +bool yf::XQuery::convert_one_record(const char *input_buf, + size_t input_len, + std::string &result) const +{ + XQuery_t tQuery = lQuery->clone(); + + zorba::DynamicContext* lDynamicContext = tQuery->getDynamicContext(); + + zorba::Item lItem; + std::map::const_iterator it; + for (it = zorba_variables.begin(); it != zorba_variables.end(); it++) + { + lItem = lZorba->getItemFactory()->createString(it->second); + lDynamicContext->setVariable(it->first, lItem); + } + // TODO: Make tmp file here + lItem = lZorba->getItemFactory()->createString( + "/home/adam/proj/yaz/test/marc7.xml"); + lDynamicContext->setVariable(zorba_record_variable, lItem); + + std::stringstream ss; + tQuery->execute(ss); + result = ss.str(); + return true; +} + void yf::XQuery::process(Package &package) const { Z_GDU *gdu_req = package.request().get(); @@ -125,7 +170,133 @@ void yf::XQuery::process(Package &package) const package.move(); return; } + + mp::odr odr_en(ODR_ENCODE); + + const char *backend_schema = 0; + const Odr_oid *backend_syntax = 0; + + if (input_schema && !strcmp(input_schema, "bibframe") && + (!input_syntax || !oid_oidcmp(input_syntax, yaz_oid_recsyn_xml))) + { + backend_schema = "marcxml"; + backend_syntax = yaz_oid_recsyn_xml; + } + else + { + package.move(); + return; + } + + if (sr_req) + { + if (backend_syntax) + sr_req->preferredRecordSyntax = odr_oiddup(odr_en, backend_syntax); + else + sr_req->preferredRecordSyntax = 0; + if (backend_schema) + { + sr_req->smallSetElementSetNames + = (Z_ElementSetNames *) + odr_malloc(odr_en, sizeof(Z_ElementSetNames)); + sr_req->smallSetElementSetNames->which = Z_ElementSetNames_generic; + sr_req->smallSetElementSetNames->u.generic + = odr_strdup(odr_en, backend_schema); + sr_req->mediumSetElementSetNames = sr_req->smallSetElementSetNames; + } + else + { + sr_req->smallSetElementSetNames = 0; + sr_req->mediumSetElementSetNames = 0; + } + } + else if (pr_req) + { + if (backend_syntax) + pr_req->preferredRecordSyntax = odr_oiddup(odr_en, backend_syntax); + else + pr_req->preferredRecordSyntax = 0; + + if (backend_schema) + { + pr_req->recordComposition + = (Z_RecordComposition *) + odr_malloc(odr_en, sizeof(Z_RecordComposition)); + pr_req->recordComposition->which + = Z_RecordComp_simple; + pr_req->recordComposition->u.simple + = (Z_ElementSetNames *) + odr_malloc(odr_en, sizeof(Z_ElementSetNames)); + pr_req->recordComposition->u.simple->which = Z_ElementSetNames_generic; + pr_req->recordComposition->u.simple->u.generic + = odr_strdup(odr_en, backend_schema); + } + else + pr_req->recordComposition = 0; + } package.move(); + + Z_GDU *gdu_res = package.response().get(); + + // see if we have a records list to patch! + Z_NamePlusRecordList *records = 0; + if (gdu_res && gdu_res->which == Z_GDU_Z3950 && + gdu_res->u.z3950->which == Z_APDU_presentResponse) + { + Z_PresentResponse * pr_res = gdu_res->u.z3950->u.presentResponse; + + if (pr_res + && pr_res->numberOfRecordsReturned + && *(pr_res->numberOfRecordsReturned) > 0 + && pr_res->records + && pr_res->records->which == Z_Records_DBOSD) + { + records = pr_res->records->u.databaseOrSurDiagnostics; + } + } + if (gdu_res && gdu_res->which == Z_GDU_Z3950 && + gdu_res->u.z3950->which == Z_APDU_searchResponse) + { + Z_SearchResponse *sr_res = gdu_res->u.z3950->u.searchResponse; + + if (sr_res + && sr_res->numberOfRecordsReturned + && *(sr_res->numberOfRecordsReturned) > 0 + && sr_res->records + && sr_res->records->which == Z_Records_DBOSD) + { + records = sr_res->records->u.databaseOrSurDiagnostics; + } + } + if (records) + { + int i; + for (i = 0; i < records->num_records; i++) + { + Z_NamePlusRecord *npr = records->records[i]; + if (npr->which == Z_NamePlusRecord_databaseRecord) + { + const char *details = 0; + Z_External *r = npr->u.databaseRecord; + int ret_trans = -1; + if (r->which == Z_External_octet && + !oid_oidcmp(r->direct_reference, yaz_oid_recsyn_xml)) + { + std::string result; + if (convert_one_record( + r->u.octet_aligned->buf, r->u.octet_aligned->len, + result)) + { + npr->u.databaseRecord = + z_ext_record_oid(odr_en, yaz_oid_recsyn_xml, + result.c_str(), + result.length()); + } + } + } + } + package.response() = gdu_res; + } } void yf::XQuery::configure(const xmlNode * ptr, bool test_only, @@ -204,6 +375,21 @@ void yf::XQuery::configure(const xmlNode * ptr, bool test_only, throw mp::filter::FilterException("Missing element record"); if (zorba_filename.length() == 0) throw mp::filter::FilterException("Missing element filename"); + if (!test_only) + { + void* lStore = StoreManager::getStore(); + lZorba = Zorba::getInstance(lStore); + + lQuery = lZorba->createQuery(); + + lQuery->setFileName(zorba_filename); + + std::unique_ptr qfile; + qfile.reset(new std::ifstream(zorba_script.c_str())); + + Zorba_CompilerHints lHints; + lQuery->compile(*qfile, lHints); + } } static yf::Base* filter_creator() -- 1.7.10.4