1 /* $Id: filter_record_transform.cpp,v 1.10 2007-04-13 09:57:51 adam Exp $
2 Copyright (c) 2005-2007, Index Data.
4 See the LICENSE file for details
9 #include "filter_record_transform.hpp"
10 #include "package.hpp"
12 #include "gduutil.hpp"
13 #include "xmlutil.hpp"
15 #include <yaz/diagbib1.h>
17 #include <yaz/retrieval.h>
19 //#include <boost/thread/mutex.hpp>
23 namespace mp = metaproxy_1;
24 namespace yf = mp::filter;
25 namespace mp_util = metaproxy_1::util;
27 namespace metaproxy_1 {
29 class RecordTransform::Impl {
33 void process(metaproxy_1::Package & package) const;
34 void configure(const xmlNode * xml_node);
36 yaz_retrieval_t m_retrieval;
41 // define Pimpl wrapper forwarding to Impl
43 yf::RecordTransform::RecordTransform() : m_p(new Impl)
47 yf::RecordTransform::~RecordTransform()
48 { // must have a destructor because of boost::scoped_ptr
51 void yf::RecordTransform::configure(const xmlNode *xmlnode)
53 m_p->configure(xmlnode);
56 void yf::RecordTransform::process(mp::Package &package) const
58 m_p->process(package);
62 // define Implementation stuff
66 yf::RecordTransform::Impl::Impl()
68 m_retrieval = yaz_retrieval_create();
72 yf::RecordTransform::Impl::~Impl()
75 yaz_retrieval_destroy(m_retrieval);
78 void yf::RecordTransform::Impl::configure(const xmlNode *xml_node)
80 //const char *srcdir = getenv("srcdir");
82 // yaz_retrieval_set_path(m_retrieval, srcdir);
85 throw mp::XMLError("RecordTransform filter config: empty XML DOM");
87 // parsing down to retrieval node, which can be any of the children nodes
88 xmlNode *retrieval_node;
89 for (retrieval_node = xml_node->children;
91 retrieval_node = retrieval_node->next)
93 if (retrieval_node->type != XML_ELEMENT_NODE)
95 if (0 == strcmp((const char *) retrieval_node->name, "retrievalinfo"))
100 if ( 0 != yaz_retrieval_configure(m_retrieval, retrieval_node)){
101 std::string msg("RecordTransform filter config: ");
102 msg += yaz_retrieval_get_error(m_retrieval);
103 throw mp::XMLError(msg);
107 void yf::RecordTransform::Impl::process(mp::Package &package) const
110 Z_GDU *gdu_req = package.request().get();
112 // only working on z3950 present packages
114 || !(gdu_req->which == Z_GDU_Z3950)
115 || !(gdu_req->u.z3950->which == Z_APDU_presentRequest))
121 // getting original present request
122 Z_PresentRequest *pr_req = gdu_req->u.z3950->u.presentRequest;
124 // setting up ODR's for memory during encoding/decoding
125 //mp::odr odr_de(ODR_DECODE);
126 mp::odr odr_en(ODR_ENCODE);
128 // setting up variables for conversion state
129 yaz_record_conv_t rc = 0;
132 const char *input_schema = 0;
133 Odr_oid *input_syntax = 0;
135 if(pr_req->recordComposition){
137 = mp_util::record_composition_to_esn(pr_req->recordComposition);
139 if(pr_req->preferredRecordSyntax){
140 input_syntax = pr_req->preferredRecordSyntax;
143 const char *match_schema = 0;
144 int *match_syntax = 0;
146 const char *backend_schema = 0;
147 Odr_oid *backend_syntax = 0;
150 = yaz_retrieval_request(m_retrieval,
151 input_schema, input_syntax,
152 &match_schema, &match_syntax,
154 &backend_schema, &backend_syntax);
159 // need to construct present error package and send back
163 const char *details = 0;
164 if (ret_code == -1) /* error ? */
166 details = yaz_retrieval_get_error(m_retrieval);
167 apdu = odr_en.create_presentResponse(
169 YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS, details);
171 else if (ret_code == 1 || ret_code == 3)
173 details = input_schema;
174 apdu = odr_en.create_presentResponse(
176 YAZ_BIB1_ELEMENT_SET_NAMES_UNSUPP, details);
178 else if (ret_code == 2)
180 char oidbuf[OID_STR_MAX];
181 oid_oid_to_dotstring(input_syntax, oidbuf);
182 details = odr_strdup(odr_en, oidbuf);
184 apdu = odr_en.create_presentResponse(
186 YAZ_BIB1_RECORD_SYNTAX_UNSUPP, details);
188 package.response() = apdu;
192 // now re-coding the z3950 backend present request
195 pr_req->preferredRecordSyntax = odr_oiddup(odr_en, backend_syntax);
197 pr_req->preferredRecordSyntax = 0;
200 // z3950'fy record schema
203 pr_req->recordComposition
204 = (Z_RecordComposition *)
205 odr_malloc(odr_en, sizeof(Z_RecordComposition));
206 pr_req->recordComposition->which
207 = Z_RecordComp_simple;
208 pr_req->recordComposition->u.simple
209 = (Z_ElementSetNames *)
210 odr_malloc(odr_en, sizeof(Z_ElementSetNames));
211 pr_req->recordComposition->u.simple->which = Z_ElementSetNames_generic;
212 pr_req->recordComposition->u.simple->u.generic
213 = odr_strdup(odr_en, backend_schema);
216 // attaching Z3950 package to filter chain
217 package.request() = gdu_req;
221 //check successful Z3950 present response
222 Z_GDU *gdu_res = package.response().get();
223 if (!gdu_res || gdu_res->which != Z_GDU_Z3950
224 || gdu_res->u.z3950->which != Z_APDU_presentResponse
225 || !gdu_res->u.z3950->u.presentResponse)
228 std::cout << "record-transform: error back present\n";
229 package.session().close();
234 // everything fine, continuing
235 // std::cout << "z3950_present_request OK\n";
236 // std::cout << "back z3950 " << *gdu_res << "\n";
238 Z_PresentResponse * pr_res = gdu_res->u.z3950->u.presentResponse;
240 // let non surrogate dioagnostics in Z3950 present response package
241 // pass to frontend - just return
243 && pr_res->records->which == Z_Records_NSD
244 && pr_res->records->u.nonSurrogateDiagnostic)
246 // we might do more clever tricks to "reverse"
249 //*pr_res->records->u.nonSurrogateDiagnostic->condition =
250 // YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
253 // record transformation must take place
255 && pr_res->numberOfRecordsReturned
256 && *(pr_res->numberOfRecordsReturned) > 0
258 && pr_res->records->which == Z_Records_DBOSD
259 && pr_res->records->u.databaseOrSurDiagnostics->num_records)
261 //transform all records
263 i < pr_res->records->u.databaseOrSurDiagnostics->num_records;
266 Z_NamePlusRecord *npr
267 = pr_res->records->u.databaseOrSurDiagnostics->records[i];
268 if (npr->which == Z_NamePlusRecord_databaseRecord)
270 Z_External *r = npr->u.databaseRecord;
271 //oident *ent = oid_getentbyoid(r->direct_reference);
272 if (r->which == Z_External_octet)
274 WRBUF output_record = wrbuf_alloc();
276 = yaz_record_conv_record(rc,
278 r->u.octet_aligned->buf,
279 r->u.octet_aligned->len,
283 npr->u.databaseRecord =
284 z_ext_record_oid(odr_en, match_syntax,
285 wrbuf_buf(output_record),
286 wrbuf_len(output_record));
291 u.databaseOrSurDiagnostics->records[i]
292 = zget_surrogateDiagRec(
293 odr_en, npr->databaseName,
294 YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS,
295 yaz_record_conv_get_error(rc));
297 wrbuf_destroy(output_record);
302 package.response() = gdu_res;
307 static mp::filter::Base* filter_creator()
309 return new mp::filter::RecordTransform;
313 struct metaproxy_1_filter_struct metaproxy_1_filter_record_transform = {
324 * indent-tabs-mode: nil
325 * c-file-style: "stroustrup"
327 * vim: shiftwidth=4 tabstop=8 expandtab