Year 2007.
[metaproxy-moved-to-github.git] / src / filter_zeerex_explain.cpp
1 /* $Id: filter_zeerex_explain.cpp,v 1.4 2007-01-25 14:05:54 adam Exp $
2    Copyright (c) 2005-2007, Index Data.
3
4    See the LICENSE file for details
5  */
6
7 #include "config.hpp"
8 #include "filter.hpp"
9 #include "package.hpp"
10 #include "util.hpp"
11 #include "gduutil.hpp"
12 #include "sru_util.hpp"
13 #include "filter_zeerex_explain.hpp"
14
15 #include <yaz/zgdu.h>
16 #include <yaz/z-core.h>
17 #include <yaz/srw.h>
18 #include <yaz/pquery.h>
19
20 #include <boost/thread/mutex.hpp>
21
22 #include <iostream>
23 #include <sstream>
24 #include <string>
25 #include <algorithm>
26 #include <map>
27
28 namespace mp = metaproxy_1;
29 namespace mp_util = metaproxy_1::util;
30 namespace yf = mp::filter;
31
32
33 namespace metaproxy_1 {
34     namespace filter {
35         class ZeeRexExplain::Impl {
36         public:
37             void configure(const xmlNode *xmlnode);
38             void process(metaproxy_1::Package &package);
39         private:
40             std::map<std::string, const xmlNode *> m_database_explain;
41         };
42     }
43 }
44
45 yf::ZeeRexExplain::ZeeRexExplain() : m_p(new Impl)
46 {
47 }
48
49 yf::ZeeRexExplain::~ZeeRexExplain()
50 {  // must have a destructor because of boost::scoped_ptr
51 }
52
53 void yf::ZeeRexExplain::configure(const xmlNode *xmlnode)
54 {
55     m_p->configure(xmlnode);
56 }
57
58 void yf::ZeeRexExplain::process(mp::Package &package) const
59 {
60     m_p->process(package);
61 }
62
63 void yf::ZeeRexExplain::Impl::configure(const xmlNode *confignode)
64 {
65     const xmlNode * dbnode;
66     
67     for (dbnode = confignode->children; dbnode; dbnode = dbnode->next){
68         if (dbnode->type != XML_ELEMENT_NODE)
69             continue;
70         
71         std::string database;
72         mp::xml::check_element_mp(dbnode, "database");
73
74         for (struct _xmlAttr *attr = dbnode->properties; 
75              attr; attr = attr->next){
76             
77             mp::xml::check_attribute(attr, "", "name");
78             database = mp::xml::get_text(attr);
79             
80             std::cout << database << "\n";
81             
82             const xmlNode *explainnode;
83             for (explainnode = dbnode->children; 
84                  explainnode; explainnode = explainnode->next){
85                 if (explainnode->type != XML_ELEMENT_NODE)
86                     continue;
87                 if (explainnode)
88                     break;
89             }
90             // assigning explain node to database name - no check yet 
91             m_database_explain.insert(std::make_pair(database, explainnode));
92          }
93     }
94 }
95
96
97 void yf::ZeeRexExplain::Impl::process(mp::Package &package)
98 {
99     Z_GDU *zgdu_req = package.request().get();
100
101     // ignoring all non HTTP_Request packages
102     if (!zgdu_req || !(zgdu_req->which == Z_GDU_HTTP_Request)){
103         package.move();
104         return;
105     }
106     
107     // only working on  HTTP_Request packages now
108
109     mp::odr odr_de(ODR_DECODE);
110     Z_SRW_PDU *sru_pdu_req = 0;
111
112     mp::odr odr_en(ODR_ENCODE);
113     //Z_SRW_PDU *sru_pdu_res = 0;
114     Z_SRW_PDU *sru_pdu_res = yaz_srw_get(odr_en, Z_SRW_explain_response);
115
116     // finding correct SRU database and explain XML node fragment from config
117     mp_util::SRUServerInfo sruinfo = mp_util::get_sru_server_info(package);
118
119     const xmlNode *explainnode = 0;
120     std::map<std::string, const xmlNode *>::iterator idbexp;
121     idbexp = m_database_explain.find(sruinfo.database);
122
123     //std::cout << "Finding " << sruinfo.database << "\n";
124     if (idbexp != m_database_explain.end()){
125         //std::cout << "Found " << idbexp->first << " " << idbexp->second << "\n";
126         explainnode = idbexp->second;
127     }
128     else {
129         // need to emmit error ?? or just let package pass ??
130         //std::cout << "Missed " << sruinfo.database << "\n";
131         package.move();
132         return;
133     }
134     
135
136     // if SRU package could not be decoded, send minimal explain and
137     // close connection
138
139     Z_SOAP *soap = 0;
140     char *charset = 0;
141     char *stylesheet = 0;
142     if (! (sru_pdu_req = mp_util::decode_sru_request(package, odr_de, odr_en, 
143                                             sru_pdu_res, soap,
144                                             charset, stylesheet)))
145     {
146         mp_util::build_sru_explain(package, odr_en, sru_pdu_res, 
147                                    sruinfo, explainnode);
148         mp_util::build_sru_response(package, odr_en, soap, 
149                            sru_pdu_res, charset, stylesheet);
150         package.session().close();
151         return;
152     }
153     
154
155     if (sru_pdu_req->which != Z_SRW_explain_request){
156     // Let pass all other SRU actions
157         package.move();
158         return;
159     }
160     // except valid SRU explain request, construct ZeeRex Explain response
161     else {
162         Z_SRW_explainRequest *er_req = sru_pdu_req->u.explain_request;
163         //mp_util::build_simple_explain(package, odr_en, sru_pdu_res, 
164         //                           sruinfo, er_req);
165         mp_util::build_sru_explain(package, odr_en, sru_pdu_res, 
166                                    sruinfo, explainnode, er_req);
167         mp_util::build_sru_response(package, odr_en, soap, 
168                                     sru_pdu_res, charset, stylesheet);
169         return;
170     }
171
172     // should never arrive here
173     package.session().close();
174     return;   
175 }
176
177
178
179 static mp::filter::Base* filter_creator()
180 {
181     return new mp::filter::ZeeRexExplain;
182 }
183
184 extern "C" {
185     struct metaproxy_1_filter_struct metaproxy_1_filter_zeerex_explain = {
186         0,
187         "zeerex_explain",
188         filter_creator
189     };
190 }
191
192
193 /*
194  * Local variables:
195  * c-basic-offset: 4
196  * indent-tabs-mode: nil
197  * c-file-style: "stroustrup"
198  * End:
199  * vim: shiftwidth=4 tabstop=8 expandtab
200  */