computing backend record syntax and elementset name/schema
[metaproxy-moved-to-github.git] / src / filter_record_transform.cpp
1 /* $Id: filter_record_transform.cpp,v 1.3 2006-10-04 14:04:00 marc Exp $
2    Copyright (c) 2005-2006, Index Data.
3
4    See the LICENSE file for details
5  */
6
7 #include "config.hpp"
8 #include "filter.hpp"
9 #include "filter_record_transform.hpp"
10 #include "package.hpp"
11 #include "util.hpp"
12 #include "gduutil.hpp"
13 #include "xmlutil.hpp"
14
15 #include <yaz/zgdu.h>
16 #include <yaz/retrieval.h>
17
18 //#include <boost/thread/mutex.hpp>
19
20 #include <iostream>
21
22 namespace mp = metaproxy_1;
23 namespace yf = mp::filter;
24 namespace mp_util = metaproxy_1::util;
25
26 namespace metaproxy_1 {
27     namespace filter {
28         class RecordTransform::Impl {
29         public:
30             Impl();
31             ~Impl();
32             void process(metaproxy_1::Package & package) const;
33             void configure(const xmlNode * xml_node);
34         private:
35             yaz_retrieval_t m_retrieval;
36         };
37     }
38 }
39
40 // define Pimpl wrapper forwarding to Impl
41  
42 yf::RecordTransform::RecordTransform() : m_p(new Impl)
43 {
44 }
45
46 yf::RecordTransform::~RecordTransform()
47 {  // must have a destructor because of boost::scoped_ptr
48 }
49
50 void yf::RecordTransform::configure(const xmlNode *xmlnode)
51 {
52     m_p->configure(xmlnode);
53 }
54
55 void yf::RecordTransform::process(mp::Package &package) const
56 {
57     m_p->process(package);
58 }
59
60
61 // define Implementation stuff
62
63
64
65 yf::RecordTransform::Impl::Impl() 
66 {
67     m_retrieval = yaz_retrieval_create();
68     assert(m_retrieval);
69 }
70
71 yf::RecordTransform::Impl::~Impl()
72
73     if (m_retrieval)
74         yaz_retrieval_destroy(m_retrieval);
75 }
76
77 void yf::RecordTransform::Impl::configure(const xmlNode *xml_node)
78 {
79     //const char *srcdir = getenv("srcdir");
80     //if (srcdir)
81     //    yaz_retrieval_set_path(m_retrieval, srcdir);
82
83     if (!xml_node)
84         throw mp::XMLError("RecordTransform filter config: empty XML DOM");
85
86     // parsing down to retrieval node, which can be any of the children nodes
87     xmlNode *retrieval_node;
88     for (retrieval_node = xml_node->children; 
89          retrieval_node; 
90          retrieval_node = retrieval_node->next)
91     {
92         if (retrieval_node->type != XML_ELEMENT_NODE)
93             continue;
94         if (0 == strcmp((const char *) retrieval_node->name, "retrievalinfo"))
95             break;
96     }
97     
98     // read configuration
99     if ( 0 != yaz_retrieval_configure(m_retrieval, retrieval_node)){
100         std::string msg("RecordTransform filter config: ");
101         msg += yaz_retrieval_get_error(m_retrieval);
102         throw mp::XMLError(msg);
103     }
104 }
105
106 void yf::RecordTransform::Impl::process(mp::Package &package) const
107 {
108
109     Z_GDU *gdu_req = package.request().get();
110     
111     // only working on z3950 present packages
112     if (!gdu_req 
113         || !(gdu_req->which == Z_GDU_Z3950) 
114         || !(gdu_req->u.z3950->which == Z_APDU_presentRequest))
115     {
116         package.move();
117         return;
118     }
119     
120     // getting original present request
121     Z_PresentRequest *pr = gdu_req->u.z3950->u.presentRequest;
122
123     // setting up ODR's for memory during encoding/decoding
124     //mp::odr odr_de(ODR_DECODE);  
125     mp::odr odr_en(ODR_ENCODE);
126
127     // setting up variables for conversion state
128     yaz_record_conv_t rc = 0;
129     int ret_code;
130
131     const char *input_schema = 0;
132     Odr_oid *input_syntax = 0;
133
134     if(pr->recordComposition){
135         input_schema 
136             = mp_util::record_composition_to_esn(pr->recordComposition);
137     }
138     if(pr->preferredRecordSyntax){
139         input_syntax = pr->preferredRecordSyntax;
140     }
141     
142     const char *match_schema = 0;
143     int *match_syntax = 0;
144
145     const char *backend_schema = 0;
146     Odr_oid *backend_syntax = 0;
147
148     ret_code 
149         = yaz_retrieval_request(m_retrieval,
150                                 input_schema, input_syntax,
151                                 &match_schema, &match_syntax,
152                                 &rc,
153                                 &backend_schema, &backend_syntax);
154
155     std::cout << "ret_code " <<  ret_code << "\n";
156     std::cout << "match   " << (oid_getentbyoid(match_syntax))->desc << " " <<  match_schema << "\n";
157     std::cout << "backend " << (oid_getentbyoid(backend_syntax))->desc << " " <<  backend_schema << "\n";
158     
159
160 //         if (r == -1) /* error ? */
161 //         {
162 //             const char *details = yaz_retrieval_get_error(
163 //                 assoc->server->retrieval);
164
165 //             rr->errcode = YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
166 //             if (details)
167 //                 rr->errstring = odr_strdup(rr->stream, details);
168 //             return -1;
169 //         }
170 //         else if (r == 1 || r == 3)
171 //         {
172 //             const char *details = input_schema;
173 //             rr->errcode =  YAZ_BIB1_ELEMENT_SET_NAMES_UNSUPP;
174 //             if (details)
175 //                 rr->errstring = odr_strdup(rr->stream, details);
176 //             return -1;
177 //         }
178 //         else if (r == 2)
179 //         {
180 //             rr->errcode = YAZ_BIB1_RECORD_SYNTAX_UNSUPP;
181 //             if (input_syntax_raw)
182 //             {
183 //                 char oidbuf[OID_STR_MAX];
184 //                 oid_to_dotstring(input_syntax_raw, oidbuf);
185 //                 rr->errstring = odr_strdup(rr->stream, oidbuf);
186 //             }
187 //             return -1;
188 //     }
189
190
191     // now re-insructing the z3950 backend present request
192      
193     // z3950'fy record syntax
194     //Odr_oid odr_oid;
195
196         
197         // = yaz_oidval_to_z3950oid (odr_en, CLASS_RECSYN, VAL_TEXT_XML);
198     // }
199     // Odr_oid *yaz_str_to_z3950oid (ODR o, int oid_class,
200     //                                         const char *str);
201     // const char *yaz_z3950oid_to_str (Odr_oid *oid, int *oid_class);
202
203
204     // z3950'fy record schema
205     //if ()
206     // {
207     //     pr->recordComposition 
208     //         = (Z_RecordComposition *) 
209     //           odr_malloc(odr_en, sizeof(Z_RecordComposition));
210     //     pr->recordComposition->which 
211     //         = Z_RecordComp_simple;
212     //     pr->recordComposition->u.simple 
213     //         = build_esn_from_schema(odr_en, 
214     //                                 (const char *) sr_req->recordSchema); 
215     // }
216
217     // attaching Z3950 package to filter chain
218     package.request() = gdu_req;
219
220     // std::cout << "z3950_present_request " << *apdu << "\n";   
221
222     // sending package
223     package.move();
224
225    //check successful Z3950 present response
226     Z_GDU *gdu_res = package.response().get();
227     if (!gdu_res || gdu_res->which != Z_GDU_Z3950 
228         || gdu_res->u.z3950->which != Z_APDU_presentResponse
229         || !gdu_res->u.z3950->u.presentResponse)
230
231     {
232         std::cout << "record-transform: error back present\n";
233         package.session().close();
234         return;
235     }
236     
237
238     // everything fine, continuing
239     // std::cout << "z3950_present_request OK\n";
240     // std::cout << "back z3950 " << *gdu_res << "\n";
241
242 //         if (backend_schema)
243 //         {
244 //             set_esn(&rr->comp, backend_schema, rr->stream->mem);
245 //         }
246 //         if (backend_syntax)
247 //         {
248 //             oident *oident_syntax = oid_getentbyoid(backend_syntax);
249
250 //             rr->request_format_raw = backend_syntax;
251             
252 //             if (oident_syntax)
253 //                 rr->request_format = oident_syntax->value;
254 //             else
255 //                 rr->request_format = VAL_NONE;
256
257 //        }
258 //     }
259 //     (*assoc->init->bend_fetch)(assoc->backend, rr);
260 //     if (rc && rr->record && rr->errcode == 0 && rr->len > 0)
261 //     {   /* post conversion must take place .. */
262 //         WRBUF output_record = wrbuf_alloc();
263 //         int r = yaz_record_conv_record(rc, rr->record, rr->len, output_record);
264 //         if (r)
265 //         {
266 //             const char *details = yaz_record_conv_get_error(rc);
267 //             rr->errcode = YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
268 //             if (details)
269 //                 rr->errstring = odr_strdup(rr->stream, details);
270 //         }
271 //         else
272 //         {
273 //             rr->len = wrbuf_len(output_record);
274 //             rr->record = odr_malloc(rr->stream, rr->len);
275 //             memcpy(rr->record, wrbuf_buf(output_record), rr->len);
276 //         }
277 //         wrbuf_free(output_record, 1);
278 //     }
279 //     if (match_syntax)
280 //     {
281 //         struct oident *oi = oid_getentbyoid(match_syntax);
282 //         rr->output_format = oi ? oi->value : VAL_NONE;
283 //         rr->output_format_raw = match_syntax;
284 //     }
285 //     if (match_schema)
286 //         rr->schema = odr_strdup(rr->stream, match_schema);
287 //     return 0;
288
289     return;
290 }
291
292
293 static mp::filter::Base* filter_creator()
294 {
295     return new mp::filter::RecordTransform;
296 }
297
298 extern "C" {
299     struct metaproxy_1_filter_struct metaproxy_1_filter_record_transform = {
300         0,
301         "record_transform",
302         filter_creator
303     };
304 }
305
306
307 /*
308  * Local variables:
309  * c-basic-offset: 4
310  * indent-tabs-mode: nil
311  * c-file-style: "stroustrup"
312  * End:
313  * vim: shiftwidth=4 tabstop=8 expandtab
314  */