76067e322f6caf7e6a7f1379fa23e17087776a79
[mp-xquery-moved-to-github.git] / src / metaproxy_filter_xquery.cpp
1 /* This file is part of mp-xquery
2    Copyright (C) Index Data
3
4 Metaproxy is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8
9 Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18
19 #include <metaproxy/package.hpp>
20 #include <metaproxy/util.hpp>
21 #include <yaz/log.h>
22 #include <map>
23
24 namespace mp = metaproxy_1;
25 namespace yf = mp::filter;
26 namespace mp_util = metaproxy_1::util;
27 using namespace mp;
28
29 namespace metaproxy_1 {
30     namespace filter {
31         class XQuery : public Base {
32         public:
33             ~XQuery();
34             XQuery();
35             void process(metaproxy_1::Package & package) const;
36             void configure(const xmlNode * ptr, bool test_only,
37                            const char *path);
38             void start() const;
39             void stop(int signo) const;
40         private:
41             std::map<std::string, std::string> zorba_variables;
42             std::string zorba_filename;
43             std::string zorba_script;
44             std::string zorba_record_variable;
45         };
46     }
47 }
48
49 yf::XQuery::XQuery()
50 {
51 }
52
53 yf::XQuery::~XQuery()
54 {
55
56 }
57
58
59 void yf::XQuery::start() const
60 {
61 }
62
63 void yf::XQuery::stop(int signo) const
64 {
65 }
66
67 void yf::XQuery::process(Package &package) const
68 {
69     Z_GDU *gdu_req = package.request().get();
70     Z_PresentRequest *pr_req = 0;
71     Z_SearchRequest *sr_req = 0;
72
73     const char *input_schema = 0;
74     Odr_oid *input_syntax = 0;
75
76     if (gdu_req && gdu_req->which == Z_GDU_Z3950 &&
77         gdu_req->u.z3950->which == Z_APDU_presentRequest)
78     {
79         pr_req = gdu_req->u.z3950->u.presentRequest;
80
81         input_schema =
82             mp_util::record_composition_to_esn(pr_req->recordComposition);
83         input_syntax = pr_req->preferredRecordSyntax;
84     }
85     else if (gdu_req && gdu_req->which == Z_GDU_Z3950 &&
86              gdu_req->u.z3950->which == Z_APDU_searchRequest)
87     {
88         sr_req = gdu_req->u.z3950->u.searchRequest;
89
90         input_syntax = sr_req->preferredRecordSyntax;
91
92         // we don't know how many hits we're going to get and therefore
93         // the effective element set name.. Therefore we can only allow
94         // two cases.. Both equal or absent.. If not, we'll just have to
95         // disable the piggyback!
96         if (sr_req->smallSetElementSetNames
97             &&
98             sr_req->mediumSetElementSetNames
99             &&
100             sr_req->smallSetElementSetNames->which == Z_ElementSetNames_generic
101             &&
102             sr_req->mediumSetElementSetNames->which == Z_ElementSetNames_generic
103             &&
104             !strcmp(sr_req->smallSetElementSetNames->u.generic,
105                     sr_req->mediumSetElementSetNames->u.generic))
106         {
107             input_schema = sr_req->smallSetElementSetNames->u.generic;
108         }
109         else if (!sr_req->smallSetElementSetNames &&
110                  !sr_req->mediumSetElementSetNames)
111             ; // input_schema is 0 already
112         else
113         {
114             // disable piggyback (perhaps it was disabled already)
115             *sr_req->smallSetUpperBound = 0;
116             *sr_req->largeSetLowerBound = 0;
117             *sr_req->mediumSetPresentNumber = 0;
118             package.move();
119             return;
120         }
121         // we can handle it in record_transform.
122     }
123     else
124     {
125         package.move();
126         return;
127     }
128     package.move();
129 }
130
131 void yf::XQuery::configure(const xmlNode * ptr, bool test_only,
132                            const char *path)
133 {
134     for (ptr = ptr->children; ptr; ptr = ptr->next)
135     {
136         if (ptr->type != XML_ELEMENT_NODE)
137             continue;
138         if (!strcmp((const char *) ptr->name, "setVariable"))
139         {
140             std::string name;
141             std::string value;
142             struct _xmlAttr *attr;
143             for (attr = ptr->properties; attr; attr = attr->next)
144                 if (!strcmp((const char *) attr->name, "name"))
145                     name = mp::xml::get_text(attr->children);
146                 else if (!strcmp((const char *) attr->name, "value"))
147                     value = mp::xml::get_text(attr->children);
148                 else
149                     throw mp::filter::FilterException(
150                         "Bad attribute " + std::string((const char *)
151                                                        attr->name));
152             if (name.length() > 0)
153                 zorba_variables[name] = value;
154         }
155         else if (!strcmp((const char *) ptr->name, "filename"))
156         {
157             std::string value;
158             struct _xmlAttr *attr;
159             for (attr = ptr->properties; attr; attr = attr->next)
160                 if (!strcmp((const char *) attr->name, "value"))
161                     value = mp::xml::get_text(attr->children);
162                 else
163                     throw mp::filter::FilterException(
164                         "Bad attribute " + std::string((const char *)
165                                                        attr->name));
166             zorba_filename = value;
167         }
168         else if (!strcmp((const char *) ptr->name, "script"))
169         {
170             std::string value;
171             struct _xmlAttr *attr;
172             for (attr = ptr->properties; attr; attr = attr->next)
173                 if (!strcmp((const char *) attr->name, "value"))
174                     value = mp::xml::get_text(attr->children);
175                 else
176                     throw mp::filter::FilterException(
177                         "Bad attribute " + std::string((const char *)
178                                                        attr->name));
179             zorba_script = value;
180         }
181         else if (!strcmp((const char *) ptr->name, "record"))
182         {
183             std::string value;
184             struct _xmlAttr *attr;
185             for (attr = ptr->properties; attr; attr = attr->next)
186                 if (!strcmp((const char *) attr->name, "value"))
187                     value = mp::xml::get_text(attr->children);
188                 else
189                     throw mp::filter::FilterException(
190                         "Bad attribute " + std::string((const char *)
191                                                        attr->name));
192             zorba_record_variable = value;
193         }
194         else
195         {
196             throw mp::filter::FilterException("Bad element "
197                                                + std::string((const char *)
198                                                              ptr->name));
199         }
200     }
201     if (zorba_script.length() == 0)
202         throw mp::filter::FilterException("Missing element script");
203     if (zorba_record_variable.length() == 0)
204         throw mp::filter::FilterException("Missing element record");
205     if (zorba_filename.length() == 0)
206         throw mp::filter::FilterException("Missing element filename");
207 }
208
209 static yf::Base* filter_creator()
210 {
211     return new mp::filter::XQuery;
212 }
213
214 extern "C" {
215     struct metaproxy_1_filter_struct metaproxy_1_filter_xquery = {
216         0,
217         "xquery",
218         filter_creator
219     };
220 }
221
222
223 /*
224  * Local variables:
225  * c-basic-offset: 4
226  * c-file-style: "Stroustrup"
227  * indent-tabs-mode: nil
228  * End:
229  * vim: shiftwidth=4 tabstop=8 expandtab
230  */
231