Added quick comment about config
[metaproxy-moved-to-github.git] / src / filter_cql_to_rpn.cpp
1 /* $Id: filter_cql_to_rpn.cpp,v 1.2 2007-01-12 10:17:23 adam Exp $
2    Copyright (c) 2005-2006, Index Data.
3
4    See the LICENSE file for details
5  */
6
7 #include "config.hpp"
8
9 #include "filter.hpp"
10 #include "package.hpp"
11
12 #include <boost/thread/mutex.hpp>
13 #include <boost/thread/condition.hpp>
14 #include <boost/thread/thread.hpp>
15 #include <boost/thread/xtime.hpp>
16 #include <boost/shared_ptr.hpp>
17 #include <boost/format.hpp>
18
19 #include "util.hpp"
20 #include "filter_cql_to_rpn.hpp"
21
22 #include <yaz/log.h>
23 #include <yaz/cql.h>
24 #include <yaz/zgdu.h>
25 #include <yaz/otherinfo.h>
26 #include <yaz/diagbib1.h>
27 #include <yaz/srw.h>
28 #include <yazpp/z-query.h>
29 #include <yazpp/cql2rpn.h>
30 #include <map>
31 #include <iostream>
32 #include <time.h>
33
34 namespace mp = metaproxy_1;
35 namespace yf = metaproxy_1::filter;
36
37 namespace metaproxy_1 {
38     namespace filter {
39         class CQL_to_RPN::Rep {
40             friend class CQL_to_RPN;
41
42             Rep();
43
44             yazpp_1::Yaz_cql2rpn cql2rpn;
45         };
46     }
47 }
48
49 yf::CQL_to_RPN::Rep::Rep()
50 {
51
52 }
53
54 yf::CQL_to_RPN::CQL_to_RPN() : m_p(new CQL_to_RPN::Rep)
55 {
56 }
57
58 yf::CQL_to_RPN::~CQL_to_RPN()
59 {
60
61 }
62
63 void yf::CQL_to_RPN::process(mp::Package &package) const
64 {
65     Z_GDU *gdu = package.request().get();
66
67     if (gdu && gdu->which == Z_GDU_Z3950 && gdu->u.z3950->which ==
68         Z_APDU_searchRequest)
69     {
70         Z_APDU *apdu_req = gdu->u.z3950;
71         Z_SearchRequest *sr = gdu->u.z3950->u.searchRequest;
72         if (sr->query && sr->query->which == Z_Query_type_104 &&
73             sr->query->u.type_104->which == Z_External_CQL)
74         {
75             char *addinfo = 0;
76             Z_RPNQuery *rpnquery = 0;
77             mp::odr odr;
78             
79             int r = m_p->cql2rpn.query_transform(sr->query->u.type_104->u.cql,
80                                                  &rpnquery, odr,
81                                                  &addinfo);
82             if (r == -3)
83             {
84                 yaz_log(YLOG_LOG, "No CQL to RPN table");
85                 Z_APDU *f_apdu = 
86                     odr.create_searchResponse(
87                         apdu_req, 
88                         YAZ_BIB1_TEMPORARY_SYSTEM_ERROR,
89                         "Missing CQL to RPN spec");
90                 package.response() = f_apdu;
91                 return;
92             }
93             else if (r)
94             {
95                 int error_code = yaz_diag_srw_to_bib1(r);
96
97                 yaz_log(YLOG_LOG, "CQL Conversion error %d", r);
98                 Z_APDU *f_apdu = 
99                     odr.create_searchResponse(apdu_req, error_code, addinfo);
100                 package.response() = f_apdu;
101                 return;
102             }
103             else
104             {   // conversion OK
105                 
106                 sr->query->which = Z_Query_type_1;
107                 sr->query->u.type_1 = rpnquery;
108                 package.request() = gdu;
109             }
110         }
111     }
112     package.move();
113 }
114
115 void yf::CQL_to_RPN::configure(const xmlNode *ptr)
116 {
117
118     /*
119       <filter type="cql_to_rpn">
120       <conversion file="pqf.properties"/>
121       </filter>
122     */
123     
124     std::string fname;
125     for (ptr = ptr->children; ptr; ptr = ptr->next)
126     {
127         if (ptr->type != XML_ELEMENT_NODE)
128             continue;
129         if (!strcmp((const char *) ptr->name, "conversion"))
130         {
131             const struct _xmlAttr *attr;
132             for (attr = ptr->properties; attr; attr = attr->next)
133             {
134                 if (!strcmp((const char *) attr->name, "file"))
135                     fname = mp::xml::get_text(attr);
136                 else
137                     throw mp::filter::FilterException(
138                         "Bad attribute " + std::string((const char *)
139                                                        attr->name));
140             }
141         }
142         else
143         {
144             throw mp::filter::FilterException("Bad element " 
145                                                + std::string((const char *)
146                                                              ptr->name));
147         }
148     }
149     if (fname.length() == 0)
150     {
151         throw mp::filter::FilterException("Missing conversion spec for "
152                                           "filter cql_to_rpn");
153     }
154
155     int error = 0;
156     if (!m_p->cql2rpn.parse_spec_file(fname.c_str(), &error))
157     {
158         throw mp::filter::FilterException("Bad or missing CQL to RPN spec "
159                                           + fname);
160     }
161 }
162
163 static mp::filter::Base* filter_creator()
164 {
165     return new mp::filter::CQL_to_RPN;
166 }
167
168 extern "C" {
169     struct metaproxy_1_filter_struct metaproxy_1_filter_cql_to_rpn = {
170         0,
171         "cql_to_rpn",
172         filter_creator
173     };
174 }
175
176 /*
177  * Local variables:
178  * c-basic-offset: 4
179  * indent-tabs-mode: nil
180  * c-file-style: "stroustrup"
181  * End:
182  * vim: shiftwidth=4 tabstop=8 expandtab
183  */