renamed methods and restructured code to follow coding guidelines set in filter-templ...
authorMarc Cromme <marc@indexdata.dk>
Mon, 15 Jan 2007 15:07:59 +0000 (15:07 +0000)
committerMarc Cromme <marc@indexdata.dk>
Mon, 15 Jan 2007 15:07:59 +0000 (15:07 +0000)
added 'cql_rpn' filter to sru server config
added cql2pqf.txt text based config file
still missing documentation
still missing removing of unused, commented-out code in implementation file

etc/config-sru-to-z3950.xml
etc/cql2pqf.txt [new file with mode: 0644]
src/filter_cql_to_rpn.cpp
src/filter_cql_to_rpn.hpp

index e5a655e..aa194db 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-<!-- $Id: config-sru-to-z3950.xml,v 1.12 2007-01-08 13:07:38 marc Exp $ -->
+<!-- $Id: config-sru-to-z3950.xml,v 1.13 2007-01-15 15:07:59 marc Exp $ -->
 <metaproxy 
     xmlns="http://indexdata.com/metaproxy" 
     version="1.0">
@@ -16,6 +16,9 @@
       </database>
       <database name="Dummy"/>
     </filter>
+      <filter id="cql" type="cql_rpn">
+        <conversion file="etc/cql2pqf.txt"/>
+      </filter>
     <filter id="backend" type="z3950_client">
      <timeout>30</timeout>
     </filter>
           <target>localhost:9998/Default</target>
         </virtual>
       </filter>
+      <filter type="log">
+        <message>CQL</message>
+      </filter>
+      <filter refid="cql"/>
+      <filter type="log">
+        <message>PQF</message>
+      </filter>
       <filter type="backend_test"/>
       <!--
       <filter refid="backend"/>
diff --git a/etc/cql2pqf.txt b/etc/cql2pqf.txt
new file mode 100644 (file)
index 0000000..f61d3dd
--- /dev/null
@@ -0,0 +1,85 @@
+
+# Propeties file to drive org.z3950.zing.cql.CQLNode's toPQF()
+# back-end and the YAZ CQL-to-PQF converter.  This specifies the
+# interpretation of various CQL indexes, relations, etc. in terms
+# of Type-1 query attributes.
+#
+# This file is created from a valid ZeeRex Explain XML record using the 
+# XSLT transformation 'explain2cqlpqftxt.xsl'
+#
+# xsltproc explain2cqlpqf.xsl explain.xml
+    
+
+# Title: Metaproxy SRU explain record
+
+# Set info
+# Default set
+set = info:srw/cql-context-set/1/cql-v1.1
+
+set.cql = info:srw/cql-context-set/1/cql-v1.1
+set.rec = info:srw/cql-context-set/2/rec-1.0
+set.dc = info:srw/cql-context-set/1/dc-v1.1
+set.bib1 = 1.2.840.10003.3.1
+
+# Index info
+index.cql.serverChoice = 1=1010 
+index.cql.all = 1=1010 
+index.rec.id = 1=12 4=3 
+index.dc.title = 1=4 
+index.dc.creator = 1=1003 
+index.dc.subject = 1=47 
+index.dc.description = 1=62 
+index.dc.publisher = 1=1018 
+index.dc.contributor = 1=1003 
+index.dc.date = 1=30 
+index.dc.type = 1=1034 
+index.dc.format = 1=1013 
+index.dc.identifier = 1=7 
+index.dc.source = 1=1019 
+
+# Relation info
+relation.<  = 2=1
+relation.eq  = 2=3
+relation.>  = 2=5
+
+
+# Default Relation
+relation.scr = 2=3
+
+# RelationModifier info
+
+
+# Position attributes 
+position.first                          = 3=1 6=1
+position.any                            = 3=3 6=1
+position.last                           = 3=4 6=1
+position.firstAndLast                   = 3=3 6=3
+
+# Structure attributes may be specified for individual relations; a
+# default structure attribute my be specified by the pseudo-relation
+# "*", to be used whenever a relation not listed here occurs.
+#
+structure.exact                         = 4=108
+structure.all                           = 4=2
+structure.any                           = 4=2
+structure.*                             = 4=1
+structure.eq                            = 4=3
+
+# Truncation attributes used to implement CQL wildcard patterns.  The
+# simpler forms, left, right- and both-truncation will be used for the
+# simplest patterns, so that we produce PQF queries that conform more
+# closely to the Bath Profile.  However, when a more complex pattern
+# such as "foo*bar" is used, we fall back on Z39.58-style masking.
+#
+truncation.right                        = 5=1
+truncation.left                         = 5=2
+truncation.both                         = 5=3
+truncation.none                         = 5=100
+truncation.z3958                        = 5=104
+
+# Finally, any additional attributes that should always be included
+# with each term can be specified in the "always" property.
+#
+# always                                        = 6=1
+# 6=1: completeness = incomplete subfield
+    
\ No newline at end of file
index fccf623..1089403 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter_cql_to_rpn.cpp,v 1.2 2007-01-12 10:17:23 adam Exp $
+/* $Id: filter_cql_to_rpn.cpp,v 1.3 2007-01-15 15:07:59 marc Exp $
    Copyright (c) 2005-2006, Index Data.
 
    See the LICENSE file for details
@@ -36,31 +36,100 @@ 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;
+        class CQLtoRPN::Impl {
+            //friend class CQLtoRPN;
+        public:
+            Impl();
+            ~Impl();
+            void process(metaproxy_1::Package & package);
+            void configure(const xmlNode * ptr);
+        private:
+            yazpp_1::Yaz_cql2rpn m_cql2rpn;
         };
     }
 }
 
-yf::CQL_to_RPN::Rep::Rep()
+
+// define Pimpl wrapper forwarding to Impl
+yf::CQLtoRPN::CQLtoRPN() : m_p(new Impl)
 {
+}
 
+yf::CQLtoRPN::~CQLtoRPN()
+{  // must have a destructor because of boost::scoped_ptr
 }
 
-yf::CQL_to_RPN::CQL_to_RPN() : m_p(new CQL_to_RPN::Rep)
+void yf::CQLtoRPN::configure(const xmlNode *xmlnode)
 {
+    m_p->configure(xmlnode);
 }
 
-yf::CQL_to_RPN::~CQL_to_RPN()
+void yf::CQLtoRPN::process(mp::Package &package) const
 {
+    m_p->process(package);
+}
+
+
+// define Implementation stuff
 
+yf::CQLtoRPN::Impl::Impl()
+{
+}
+
+yf::CQLtoRPN::Impl::~Impl()
+{ 
+}
+
+void yf::CQLtoRPN::Impl::configure(const xmlNode *xmlnode)
+{
+
+    /*
+      <filter type="cql_rpn">
+      <conversion file="pqf.properties"/>
+      </filter>
+    */
+    
+    std::string fname;
+    for (xmlnode = xmlnode->children; xmlnode; xmlnode = xmlnode->next)
+    {
+        if (xmlnode->type != XML_ELEMENT_NODE)
+            continue;
+        if (!strcmp((const char *) xmlnode->name, "conversion"))
+        {
+            const struct _xmlAttr *attr;
+            for (attr = xmlnode->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 *)
+                                                             xmlnode->name));
+        }
+    }
+    if (fname.length() == 0)
+    {
+        throw mp::filter::FilterException("Missing conversion spec for "
+                                          "filter cql_rpn");
+    }
+
+    int error = 0;
+    if (!m_cql2rpn.parse_spec_file(fname.c_str(), &error))
+    {
+        throw mp::filter::FilterException("Bad or missing CQL to RPN spec "
+                                          + fname);
+    }
 }
 
-void yf::CQL_to_RPN::process(mp::Package &package) const
+void yf::CQLtoRPN::Impl::process(mp::Package &package)
 {
     Z_GDU *gdu = package.request().get();
 
@@ -76,7 +145,7 @@ void yf::CQL_to_RPN::process(mp::Package &package) const
             Z_RPNQuery *rpnquery = 0;
             mp::odr odr;
             
-            int r = m_p->cql2rpn.query_transform(sr->query->u.type_104->u.cql,
+            int r = m_cql2rpn.query_transform(sr->query->u.type_104->u.cql,
                                                  &rpnquery, odr,
                                                  &addinfo);
             if (r == -3)
@@ -112,63 +181,133 @@ void yf::CQL_to_RPN::process(mp::Package &package) const
     package.move();
 }
 
-void yf::CQL_to_RPN::configure(const xmlNode *ptr)
-{
 
-    /*
-      <filter type="cql_to_rpn">
-      <conversion file="pqf.properties"/>
-      </filter>
-    */
+// yf::CQLtoRPN::Rep::Rep()
+// {
+
+// }
+
+// yf::CQLtoRPN::CQLtoRPN() : m_p(new CQLtoRPN::Rep)
+// {
+// }
+
+// yf::CQLtoRPN::~CQLtoRPN()
+// {
+
+// }
+
+// void yf::CQLtoRPN::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::CQLtoRPN::configure(const xmlNode *ptr)
+// {
+
+//     /*
+//       <filter type="cql_rpn">
+//       <conversion file="pqf.properties"/>
+//       </filter>
+//     */
     
-    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");
-    }
+//     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_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);
+//     }
+// }
+
+
 
-    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;
+    return new mp::filter::CQLtoRPN;
 }
 
 extern "C" {
     struct metaproxy_1_filter_struct metaproxy_1_filter_cql_to_rpn = {
         0,
-        "cql_to_rpn",
+        "cql_rpn",
         filter_creator
     };
 }
index d1c4de5..691f8f2 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter_cql_to_rpn.hpp,v 1.1 2007-01-12 10:16:21 adam Exp $
+/* $Id: filter_cql_to_rpn.hpp,v 1.2 2007-01-15 15:07:59 marc Exp $
    Copyright (c) 2005-2006, Index Data.
 
    See the LICENSE file for details
 
 namespace metaproxy_1 {
     namespace filter {
-        class CQL_to_RPN : public Base {
-            class Rep;
+        class CQLtoRPN : public Base {
+            class Impl;
+            boost::scoped_ptr<Impl> m_p;
         public:
-            CQL_to_RPN();
-            ~CQL_to_RPN();
+            CQLtoRPN();
+            ~CQLtoRPN();
             void process(metaproxy_1::Package & package) const;
             void configure(const xmlNode * ptr);
         private:
-            class Impl;
-            boost::scoped_ptr<Rep> m_p;
         };
     }
 }