From d625b10d219f5ece1aa7632e6cff2fcc5fcbd632 Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Fri, 12 Jan 2007 10:16:21 +0000 Subject: [PATCH] Implemented cql_to_rpn filter. Requires new yazpp from today's CVS. --- src/Makefile.am | 3 +- src/factory_static.cpp | 4 +- src/filter_cql_to_rpn.cpp | 176 +++++++++++++++++++++++++++++++++++++++++++++ src/filter_cql_to_rpn.hpp | 43 +++++++++++ src/xmlutil.cpp | 10 +-- 5 files changed, 229 insertions(+), 7 deletions(-) create mode 100644 src/filter_cql_to_rpn.cpp create mode 100644 src/filter_cql_to_rpn.hpp diff --git a/src/Makefile.am b/src/Makefile.am index b3fa8c0..9e2cd81 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,4 @@ -## $Id: Makefile.am,v 1.61 2007-01-02 15:35:36 marc Exp $ +## $Id: Makefile.am,v 1.62 2007-01-12 10:16:21 adam Exp $ MAINTAINERCLEANFILES = Makefile.in config.in config.hpp @@ -18,6 +18,7 @@ libmetaproxy_la_SOURCES = \ filter_auth_simple.cpp filter_auth_simple.hpp \ filter_backend_test.cpp filter_backend_test.hpp \ filter_bounce.cpp filter_bounce.hpp \ + filter_cql_to_rpn.cpp filter_cql_to_rpn.hpp \ filter_frontend_net.cpp filter_frontend_net.hpp \ filter_http_file.cpp filter_http_file.hpp \ filter_load_balance.cpp filter_load_balance.hpp \ diff --git a/src/factory_static.cpp b/src/factory_static.cpp index 6142d46..fbfb0f7 100644 --- a/src/factory_static.cpp +++ b/src/factory_static.cpp @@ -1,4 +1,4 @@ -/* $Id: factory_static.cpp,v 1.15 2007-01-02 15:35:36 marc Exp $ +/* $Id: factory_static.cpp,v 1.16 2007-01-12 10:16:21 adam Exp $ Copyright (c) 2005-2006, Index Data. See the LICENSE file for details @@ -18,6 +18,7 @@ #include "filter_auth_simple.hpp" #include "filter_backend_test.hpp" #include "filter_bounce.hpp" +#include "filter_cql_to_rpn.hpp" #include "filter_frontend_net.hpp" #include "filter_http_file.hpp" #include "filter_load_balance.hpp" @@ -40,6 +41,7 @@ mp::FactoryStatic::FactoryStatic() &metaproxy_1_filter_auth_simple, &metaproxy_1_filter_backend_test, &metaproxy_1_filter_bounce, + &metaproxy_1_filter_cql_to_rpn, &metaproxy_1_filter_frontend_net, &metaproxy_1_filter_http_file, &metaproxy_1_filter_load_balance, diff --git a/src/filter_cql_to_rpn.cpp b/src/filter_cql_to_rpn.cpp new file mode 100644 index 0000000..e47114f --- /dev/null +++ b/src/filter_cql_to_rpn.cpp @@ -0,0 +1,176 @@ +/* $Id: filter_cql_to_rpn.cpp,v 1.1 2007-01-12 10:16:21 adam Exp $ + Copyright (c) 2005-2006, Index Data. + + See the LICENSE file for details + */ + +#include "config.hpp" + +#include "filter.hpp" +#include "package.hpp" + +#include +#include +#include +#include +#include +#include + +#include "util.hpp" +#include "filter_cql_to_rpn.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mp = metaproxy_1; +namespace yf = metaproxy_1::filter; + +namespace metaproxy_1 { + namespace filter { + class CQL_to_RPN::Rep { + friend class CQL_to_RPN; + + Rep(); + + yazpp_1::Yaz_cql2rpn cql2rpn; + }; + } +} + +yf::CQL_to_RPN::Rep::Rep() +{ + +} + +yf::CQL_to_RPN::CQL_to_RPN() : m_p(new CQL_to_RPN::Rep) +{ +} + +yf::CQL_to_RPN::~CQL_to_RPN() +{ + +} + +void yf::CQL_to_RPN::process(mp::Package &package) const +{ + Z_GDU *gdu = package.request().get(); + + if (gdu && gdu->which == Z_GDU_Z3950 && gdu->u.z3950->which == + Z_APDU_searchRequest) + { + Z_APDU *apdu_req = gdu->u.z3950; + Z_SearchRequest *sr = gdu->u.z3950->u.searchRequest; + if (sr->query && sr->query->which == Z_Query_type_104 && + sr->query->u.type_104->which == Z_External_CQL) + { + char *addinfo = 0; + Z_RPNQuery *rpnquery = 0; + mp::odr odr; + + int r = m_p->cql2rpn.query_transform(sr->query->u.type_104->u.cql, + &rpnquery, odr, + &addinfo); + if (r == -3) + { + yaz_log(YLOG_LOG, "No CQL to RPN table"); + Z_APDU *f_apdu = + odr.create_searchResponse( + apdu_req, + YAZ_BIB1_TEMPORARY_SYSTEM_ERROR, + "Missing CQL to RPN spec"); + package.response() = f_apdu; + return; + } + else if (r) + { + int error_code = yaz_diag_srw_to_bib1(r); + + yaz_log(YLOG_LOG, "CQL Conversion error %d", r); + Z_APDU *f_apdu = + odr.create_searchResponse(apdu_req, error_code, addinfo); + package.response() = f_apdu; + return; + } + else + { // conversion OK + + sr->query->which = Z_Query_type_1; + sr->query->u.type_1 = rpnquery; + package.request() = gdu; + } + } + } + package.move(); +} + +void yf::CQL_to_RPN::configure(const xmlNode *ptr) +{ + std::string fname; + for (ptr = ptr->children; ptr; ptr = ptr->next) + { + if (ptr->type != XML_ELEMENT_NODE) + continue; + if (!strcmp((const char *) ptr->name, "conversion")) + { + const struct _xmlAttr *attr; + for (attr = ptr->properties; attr; attr = attr->next) + { + if (!strcmp((const char *) attr->name, "file")) + fname = mp::xml::get_text(attr); + else + throw mp::filter::FilterException( + "Bad attribute " + std::string((const char *) + attr->name)); + } + } + else + { + throw mp::filter::FilterException("Bad element " + + std::string((const char *) + ptr->name)); + } + } + if (fname.length() == 0) + { + throw mp::filter::FilterException("Missing conversion spec for " + "filter cql_to_rpn"); + } + + int error = 0; + if (!m_p->cql2rpn.parse_spec_file(fname.c_str(), &error)) + { + throw mp::filter::FilterException("Bad or missing CQL to RPN spec " + + fname); + } +} + +static mp::filter::Base* filter_creator() +{ + return new mp::filter::CQL_to_RPN; +} + +extern "C" { + struct metaproxy_1_filter_struct metaproxy_1_filter_cql_to_rpn = { + 0, + "cql_to_rpn", + filter_creator + }; +} + +/* + * Local variables: + * c-basic-offset: 4 + * indent-tabs-mode: nil + * c-file-style: "stroustrup" + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ diff --git a/src/filter_cql_to_rpn.hpp b/src/filter_cql_to_rpn.hpp new file mode 100644 index 0000000..d1c4de5 --- /dev/null +++ b/src/filter_cql_to_rpn.hpp @@ -0,0 +1,43 @@ +/* $Id: filter_cql_to_rpn.hpp,v 1.1 2007-01-12 10:16:21 adam Exp $ + Copyright (c) 2005-2006, Index Data. + + See the LICENSE file for details + */ + +#ifndef FILTER_CQL_TO_RPN_HPP +#define FILTER_CQL_TO_RPN_HPP + +#include +#include + +#include "filter.hpp" + +namespace metaproxy_1 { + namespace filter { + class CQL_to_RPN : public Base { + class Rep; + public: + CQL_to_RPN(); + ~CQL_to_RPN(); + void process(metaproxy_1::Package & package) const; + void configure(const xmlNode * ptr); + private: + class Impl; + boost::scoped_ptr m_p; + }; + } +} + +extern "C" { + extern struct metaproxy_1_filter_struct metaproxy_1_filter_cql_to_rpn; +} + +#endif +/* + * Local variables: + * c-basic-offset: 4 + * indent-tabs-mode: nil + * c-file-style: "stroustrup" + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ diff --git a/src/xmlutil.cpp b/src/xmlutil.cpp index 6fc8f13..5ea9e84 100644 --- a/src/xmlutil.cpp +++ b/src/xmlutil.cpp @@ -1,4 +1,4 @@ -/* $Id: xmlutil.cpp,v 1.11 2006-12-01 12:37:26 marc Exp $ +/* $Id: xmlutil.cpp,v 1.12 2007-01-12 10:16:21 adam Exp $ Copyright (c) 2005-2006, Index Data. See the LICENSE file for details @@ -17,15 +17,15 @@ static const std::string metaproxy_ns = "http://indexdata.com/metaproxy"; std::string mp_xml::get_text(const struct _xmlAttr *ptr) { - if (ptr->children->type == XML_TEXT_NODE) - return std::string((const char *) (ptr->children->content)); - return std::string(); + return get_text(ptr->children); } std::string mp_xml::get_text(const xmlNode *ptr) { std::string c; - for (ptr = ptr->children; ptr; ptr = ptr->next) + if (ptr && ptr->type != XML_TEXT_NODE) + ptr = ptr->children; + for (; ptr; ptr = ptr->next) if (ptr->type == XML_TEXT_NODE) c += std::string((const char *) (ptr->content)); return c; -- 1.7.10.4