1 /* $Id: filter_record_transform.cpp,v 1.6 2006-10-10 09:17:24 adam Exp $
2 Copyright (c) 2005-2006, 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_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;
194 // now re-coding the z3950 backend present request
196 // z3950'fy record syntax
197 if (backend_syntax) // TODO: this seems not to work - why ??
198 pr_req->preferredRecordSyntax = backend_syntax;
200 pr_req->preferredRecordSyntax
201 = yaz_oidval_to_z3950oid(odr_en, CLASS_RECSYN, VAL_NONE);
204 // z3950'fy record schema
207 pr_req->recordComposition
208 = (Z_RecordComposition *)
209 odr_malloc(odr_en, sizeof(Z_RecordComposition));
210 pr_req->recordComposition->which
211 = Z_RecordComp_simple;
212 pr_req->recordComposition->u.simple
213 = (Z_ElementSetNames *)
214 odr_malloc(odr_en, sizeof(Z_ElementSetNames));
215 pr_req->recordComposition->u.simple->which = Z_ElementSetNames_generic;
216 pr_req->recordComposition->u.simple->u.generic
217 = odr_strdup(odr_en, backend_schema);
220 // attaching Z3950 package to filter chain
221 package.request() = gdu_req;
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)
232 std::cout << "record-transform: error back present\n";
233 package.session().close();
238 // everything fine, continuing
239 // std::cout << "z3950_present_request OK\n";
240 // std::cout << "back z3950 " << *gdu_res << "\n";
242 Z_PresentResponse * pr_res = gdu_res->u.z3950->u.presentResponse;
244 // let non surrogate dioagnostics in Z3950 present response package
245 // pass to frontend - just return
247 && pr_res->records->which == Z_Records_NSD
248 && pr_res->records->u.nonSurrogateDiagnostic)
250 // we might do more clever tricks to "reverse"
253 //*pr_res->records->u.nonSurrogateDiagnostic->condition =
254 // YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
257 // record transformation must take place
259 && pr_res->numberOfRecordsReturned
260 && *(pr_res->numberOfRecordsReturned) > 0
262 && pr_res->records->which == Z_Records_DBOSD
263 && pr_res->records->u.databaseOrSurDiagnostics->num_records)
265 //transform all records
267 i < pr_res->records->u.databaseOrSurDiagnostics->num_records;
270 Z_NamePlusRecord *npr
271 = pr_res->records->u.databaseOrSurDiagnostics->records[i];
272 if (npr->which == Z_NamePlusRecord_databaseRecord)
274 Z_External *r = npr->u.databaseRecord;
275 //oident *ent = oid_getentbyoid(r->direct_reference);
276 if (r->which == Z_External_octet)
278 WRBUF output_record = wrbuf_alloc();
280 = yaz_record_conv_record(rc,
282 r->u.octet_aligned->buf,
283 r->u.octet_aligned->len,
287 struct oident *ident = oid_getentbyoid(match_syntax);
288 npr->u.databaseRecord =
289 z_ext_record(odr_en, ident->value,
290 wrbuf_buf(output_record),
291 wrbuf_len(output_record));
296 u.databaseOrSurDiagnostics->records[i]
297 = zget_surrogateDiagRec(
298 odr_en, npr->databaseName,
299 YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS,
300 yaz_record_conv_get_error(rc));
302 wrbuf_free(output_record, 1);
307 package.response() = gdu_res;
312 static mp::filter::Base* filter_creator()
314 return new mp::filter::RecordTransform;
318 struct metaproxy_1_filter_struct metaproxy_1_filter_record_transform = {
329 * indent-tabs-mode: nil
330 * c-file-style: "stroustrup"
332 * vim: shiftwidth=4 tabstop=8 expandtab