X-Git-Url: http://git.indexdata.com/?p=mp-xquery-moved-to-github.git;a=blobdiff_plain;f=src%2Fmetaproxy_filter_xquery.cpp;h=4864ce419d979b8edd48cb5f05ddbe972c5cf538;hp=76067e322f6caf7e6a7f1379fa23e17087776a79;hb=1cea5f5d2d4290b91b272a179a5b747f34919131;hpb=03818d91fe9f98d27fe8033a7cc70c81e08c770b diff --git a/src/metaproxy_filter_xquery.cpp b/src/metaproxy_filter_xquery.cpp index 76067e3..4864ce4 100644 --- a/src/metaproxy_filter_xquery.cpp +++ b/src/metaproxy_filter_xquery.cpp @@ -19,12 +19,26 @@ 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 +#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 +52,32 @@ 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; + std::string elementset_input; + std::string elementset_output; + Zorba *lZorba; + XQuery_t lQuery; }; } } yf::XQuery::XQuery() { + lZorba = 0; } yf::XQuery::~XQuery() { - + if (lZorba) + lZorba->shutdown(); } - void yf::XQuery::start() const { } @@ -64,6 +86,37 @@ 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); + } + std::string rec_content = "raw:" + std::string(input_buf, input_len); + lItem = lZorba->getItemFactory()->createString(rec_content); + lDynamicContext->setVariable(zorba_record_variable, lItem); + + try { + std::stringstream ss; + tQuery->execute(ss); + result = ss.str(); + return true; + } catch ( ZorbaException &e) { + result = e.what(); + yaz_log(YLOG_WARN, "XQuery execute: %s", result.c_str()); + return false; + } +} + void yf::XQuery::process(Package &package) const { Z_GDU *gdu_req = package.request().get(); @@ -125,7 +178,140 @@ 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, elementset_input.c_str()) && + (!input_syntax || !oid_oidcmp(input_syntax, yaz_oid_recsyn_xml))) + { + backend_schema = elementset_output.c_str(); + 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()); + } + else + { + *npr = zget_surrogateDiagRec( + odr_en, (*npr)->databaseName, + YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS, + result.c_str()); + } + } + } + } + package.response() = gdu_res; + } } void yf::XQuery::configure(const xmlNode * ptr, bool test_only, @@ -135,61 +321,61 @@ void yf::XQuery::configure(const xmlNode * ptr, bool test_only, { if (ptr->type != XML_ELEMENT_NODE) continue; - if (!strcmp((const char *) ptr->name, "setVariable")) + if (!strcmp((const char *) ptr->name, "elementset")) { - std::string name; - std::string value; struct _xmlAttr *attr; for (attr = ptr->properties; attr; attr = attr->next) if (!strcmp((const char *) attr->name, "name")) - name = mp::xml::get_text(attr->children); - else if (!strcmp((const char *) attr->name, "value")) - value = mp::xml::get_text(attr->children); + elementset_input = mp::xml::get_text(attr->children); + else if (!strcmp((const char *) attr->name, "backend")) + elementset_output = mp::xml::get_text(attr->children); else throw mp::filter::FilterException( "Bad attribute " + std::string((const char *) attr->name)); - if (name.length() > 0) - zorba_variables[name] = value; } - else if (!strcmp((const char *) ptr->name, "filename")) + else if (!strcmp((const char *) ptr->name, "variable")) { + std::string name; std::string value; struct _xmlAttr *attr; for (attr = ptr->properties; attr; attr = attr->next) - if (!strcmp((const char *) attr->name, "value")) + if (!strcmp((const char *) attr->name, "name")) + name = mp::xml::get_text(attr->children); + else if (!strcmp((const char *) attr->name, "value")) value = mp::xml::get_text(attr->children); else throw mp::filter::FilterException( "Bad attribute " + std::string((const char *) attr->name)); - zorba_filename = value; + if (name.length() > 0) + zorba_variables[name] = value; } else if (!strcmp((const char *) ptr->name, "script")) { - std::string value; + std::string name; struct _xmlAttr *attr; for (attr = ptr->properties; attr; attr = attr->next) - if (!strcmp((const char *) attr->name, "value")) - value = mp::xml::get_text(attr->children); + if (!strcmp((const char *) attr->name, "name")) + name = mp::xml::get_text(attr->children); else throw mp::filter::FilterException( "Bad attribute " + std::string((const char *) attr->name)); - zorba_script = value; + zorba_script = name; } else if (!strcmp((const char *) ptr->name, "record")) { - std::string value; + std::string name; struct _xmlAttr *attr; for (attr = ptr->properties; attr; attr = attr->next) - if (!strcmp((const char *) attr->name, "value")) - value = mp::xml::get_text(attr->children); + if (!strcmp((const char *) attr->name, "name")) + name = mp::xml::get_text(attr->children); else throw mp::filter::FilterException( "Bad attribute " + std::string((const char *) attr->name)); - zorba_record_variable = value; + zorba_record_variable = name; } else { @@ -202,8 +388,27 @@ void yf::XQuery::configure(const xmlNode * ptr, bool test_only, throw mp::filter::FilterException("Missing element script"); if (zorba_record_variable.length() == 0) 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(); + + try { + size_t t = zorba_script.find_last_of('/'); + if (t != std::string::npos) + lQuery->setFileName(zorba_script.substr(0, t + 1)); + std::unique_ptr qfile( + new std::ifstream(zorba_script.c_str())); + Zorba_CompilerHints lHints; + lQuery->compile(*qfile, lHints); + } catch ( ZorbaException &e) { + std::string msg = "XQuery compile: "; + msg += e.what(); + throw mp::filter::FilterException(msg); + } + } } static yf::Base* filter_creator()