21 #include <metaproxy/package.hpp>
22 #include <metaproxy/util.hpp>
25 #include <yaz/diagbib1.h>
27 #include <yaz/retrieval.h>
28 #include <yaz/oid_db.h>
30 #include <boost/thread/mutex.hpp>
33 #include <usemarconlib.h>
39 namespace mp = metaproxy_1;
40 namespace yf = mp::filter;
41 namespace mp_util = metaproxy_1::util;
43 namespace metaproxy_1 {
49 void process(metaproxy_1::Package & package)
const;
50 void configure(
const xmlNode * xml_node,
const char *path);
58 struct info_usemarcon {
64 Usemarcon *usemarcon1;
65 Usemarcon *usemarcon2;
68 static int convert_usemarcon(
void *info, WRBUF record, WRBUF wr_error)
70 struct info_usemarcon *p = (
struct info_usemarcon *) info;
72 boost::mutex::scoped_lock lock(p->m_mutex);
80 p->usemarcon1->SetMarcRecord(wrbuf_buf(record), wrbuf_len(record));
81 res = p->usemarcon1->Convert();
84 wrbuf_printf(wr_error,
"usemarcon stage1 failed res=%d", res);
87 p->usemarcon1->GetMarcRecord(converted, convlen);
91 p->usemarcon2->SetMarcRecord(converted, convlen);
93 res = p->usemarcon2->Convert();
97 wrbuf_printf(wr_error,
"usemarcon stage2 failed res=%d",
101 p->usemarcon2->GetMarcRecord(converted, convlen);
103 wrbuf_rewind(record);
104 wrbuf_write(record, converted, convlen);
110 static void destroy_usemarcon(
void *info)
112 struct info_usemarcon *p = (
struct info_usemarcon *) info;
114 delete p->usemarcon1;
115 delete p->usemarcon2;
121 static void *construct_usemarcon(
const xmlNode *ptr,
const char *path,
124 struct _xmlAttr *attr;
125 if (strcmp((
const char *) ptr->name,
"usemarcon"))
128 struct info_usemarcon *p =
new(
struct info_usemarcon);
134 for (attr = ptr->properties; attr; attr = attr->next)
136 if (!xmlStrcmp(attr->name, BAD_CAST
"stage1") &&
137 attr->children && attr->children->type == XML_TEXT_NODE)
138 p->stage1 = xstrdup((
const char *) attr->children->content);
139 else if (!xmlStrcmp(attr->name, BAD_CAST
"stage2") &&
140 attr->children && attr->children->type == XML_TEXT_NODE)
141 p->stage2 = xstrdup((
const char *) attr->children->content);
144 wrbuf_printf(wr_error,
"Bad attribute '%s'"
145 "Expected stage1 or stage2.", attr->name);
146 destroy_usemarcon(p);
153 p->usemarcon1 =
new Usemarcon();
154 p->usemarcon1->SetIniFileName(p->stage1);
158 p->usemarcon2 =
new Usemarcon();
159 p->usemarcon2->SetIniFileName(p->stage2);
164 static void type_usemarcon(
struct yaz_record_conv_type *t)
167 t->construct = construct_usemarcon;
168 t->convert = convert_usemarcon;
169 t->destroy = destroy_usemarcon;
175 yf::RecordTransform::RecordTransform() : m_p(new Impl)
186 m_p->configure(xmlnode, path);
191 m_p->process(package);
195 yf::RecordTransform::Impl::Impl()
197 m_retrieval = yaz_retrieval_create();
201 yf::RecordTransform::Impl::~Impl()
204 yaz_retrieval_destroy(m_retrieval);
210 yaz_retrieval_set_path(m_retrieval, path);
213 throw mp::XMLError(
"RecordTransform filter config: empty XML DOM");
216 xmlNode *retrieval_node;
217 for (retrieval_node = xml_node->children;
219 retrieval_node = retrieval_node->next)
221 if (retrieval_node->type != XML_ELEMENT_NODE)
223 if (0 == strcmp((
const char *) retrieval_node->name,
"retrievalinfo"))
228 struct yaz_record_conv_type mt;
230 struct yaz_record_conv_type *t = &mt;
232 struct yaz_record_conv_type *t = 0;
236 if (0 != yaz_retrieval_configure_t(m_retrieval, retrieval_node, t))
238 std::string msg(
"RecordTransform filter config: ");
239 msg += yaz_retrieval_get_error(m_retrieval);
240 throw mp::XMLError(msg);
247 Z_GDU *gdu_req = package.request().get();
248 Z_PresentRequest *pr_req = 0;
249 Z_SearchRequest *sr_req = 0;
251 const char *input_schema = 0;
252 Odr_oid *input_syntax = 0;
254 if (gdu_req && gdu_req->which == Z_GDU_Z3950 &&
255 gdu_req->u.z3950->which == Z_APDU_presentRequest)
257 pr_req = gdu_req->u.z3950->u.presentRequest;
260 mp_util::record_composition_to_esn(pr_req->recordComposition);
261 input_syntax = pr_req->preferredRecordSyntax;
263 else if (gdu_req && gdu_req->which == Z_GDU_Z3950 &&
264 gdu_req->u.z3950->which == Z_APDU_searchRequest)
266 sr_req = gdu_req->u.z3950->u.searchRequest;
268 input_syntax = sr_req->preferredRecordSyntax;
274 if (sr_req->smallSetElementSetNames
276 sr_req->mediumSetElementSetNames
278 sr_req->smallSetElementSetNames->which == Z_ElementSetNames_generic
280 sr_req->mediumSetElementSetNames->which == Z_ElementSetNames_generic
282 !strcmp(sr_req->smallSetElementSetNames->u.generic,
283 sr_req->mediumSetElementSetNames->u.generic))
285 input_schema = sr_req->smallSetElementSetNames->u.generic;
287 else if (!sr_req->smallSetElementSetNames &&
288 !sr_req->mediumSetElementSetNames)
293 *sr_req->smallSetUpperBound = 0;
294 *sr_req->largeSetLowerBound = 0;
295 *sr_req->mediumSetPresentNumber = 0;
307 mp::odr odr_en(ODR_ENCODE);
310 yaz_record_conv_t rc = 0;
312 const char *match_schema = 0;
313 Odr_oid *match_syntax = 0;
315 const char *backend_schema = 0;
316 Odr_oid *backend_syntax = 0;
319 = yaz_retrieval_request(m_retrieval,
320 input_schema, input_syntax,
321 &match_schema, &match_syntax,
323 &backend_schema, &backend_syntax);
328 const char *details = 0;
332 details = yaz_retrieval_get_error(m_retrieval);
333 error_code = YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
335 else if (ret_code == 1 || ret_code == 3)
337 details = input_schema;
338 error_code = YAZ_BIB1_ELEMENT_SET_NAMES_UNSUPP;
340 else if (ret_code == 2)
342 char oidbuf[OID_STR_MAX];
343 oid_oid_to_dotstring(input_syntax, oidbuf);
344 details = odr_strdup(odr_en, oidbuf);
345 error_code = YAZ_BIB1_RECORD_SYNTAX_UNSUPP;
349 char *tmp = (
char*) odr_malloc(odr_en, 80);
351 "record_transform: yaz_retrieval_get_error returned %d",
354 error_code = YAZ_BIB1_UNSPECIFIED_ERROR;
359 apdu = odr_en.create_searchResponse(
360 gdu_req->u.z3950, error_code, details);
364 apdu = odr_en.create_presentResponse(
365 gdu_req->u.z3950, error_code, details);
367 package.response() = apdu;
374 sr_req->preferredRecordSyntax = odr_oiddup(odr_en, backend_syntax);
376 sr_req->preferredRecordSyntax = 0;
380 sr_req->smallSetElementSetNames
381 = (Z_ElementSetNames *)
382 odr_malloc(odr_en,
sizeof(Z_ElementSetNames));
383 sr_req->smallSetElementSetNames->which = Z_ElementSetNames_generic;
384 sr_req->smallSetElementSetNames->u.generic
385 = odr_strdup(odr_en, backend_schema);
386 sr_req->mediumSetElementSetNames = sr_req->smallSetElementSetNames;
390 sr_req->smallSetElementSetNames = 0;
391 sr_req->mediumSetElementSetNames = 0;
397 pr_req->preferredRecordSyntax = odr_oiddup(odr_en, backend_syntax);
399 pr_req->preferredRecordSyntax = 0;
403 pr_req->recordComposition
404 = (Z_RecordComposition *)
405 odr_malloc(odr_en,
sizeof(Z_RecordComposition));
406 pr_req->recordComposition->which
407 = Z_RecordComp_simple;
408 pr_req->recordComposition->u.simple
409 = (Z_ElementSetNames *)
410 odr_malloc(odr_en,
sizeof(Z_ElementSetNames));
411 pr_req->recordComposition->u.simple->which = Z_ElementSetNames_generic;
412 pr_req->recordComposition->u.simple->u.generic
413 = odr_strdup(odr_en, backend_schema);
416 pr_req->recordComposition = 0;
420 package.request() = gdu_req;
424 Z_GDU *gdu_res = package.response().get();
427 Z_NamePlusRecordList *records = 0;
428 if (gdu_res && gdu_res->which == Z_GDU_Z3950 &&
429 gdu_res->u.z3950->which == Z_APDU_presentResponse)
431 Z_PresentResponse * pr_res = gdu_res->u.z3950->u.presentResponse;
434 && pr_res->numberOfRecordsReturned
435 && *(pr_res->numberOfRecordsReturned) > 0
437 && pr_res->records->which == Z_Records_DBOSD)
439 records = pr_res->records->u.databaseOrSurDiagnostics;
442 if (gdu_res && gdu_res->which == Z_GDU_Z3950 &&
443 gdu_res->u.z3950->which == Z_APDU_searchResponse)
445 Z_SearchResponse *sr_res = gdu_res->u.z3950->u.searchResponse;
448 && sr_res->numberOfRecordsReturned
449 && *(sr_res->numberOfRecordsReturned) > 0
451 && sr_res->records->which == Z_Records_DBOSD)
453 records = sr_res->records->u.databaseOrSurDiagnostics;
460 for (i = 0; i < records->num_records; i++)
462 Z_NamePlusRecord *npr = records->records[i];
463 if (npr->which == Z_NamePlusRecord_databaseRecord)
465 const char *details = 0;
466 mp::wrbuf output_record;
467 Z_External *r = npr->u.databaseRecord;
469 if (r->which == Z_External_OPAC)
472 yaz_record_conv_opac_record(rc, r->u.opac,
474 details = yaz_record_conv_get_error(rc);
476 else if (r->which == Z_External_octet)
479 yaz_record_conv_record(rc, (
const char *)
480 r->u.octet_aligned->buf,
481 r->u.octet_aligned->len,
483 details = yaz_record_conv_get_error(rc);
487 details =
"unsupported record type for record_conv";
491 records->records[i] =
492 zget_surrogateDiagRec(
493 odr_en, npr->databaseName,
494 YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS,
499 if (!oid_oidcmp(match_syntax, yaz_oid_recsyn_opac))
501 yaz_marc_t mt = yaz_marc_create();
502 Z_OPACRecord *opac = 0;
503 if (yaz_xml_to_opac(mt, output_record.buf(),
506 ((ODR )odr_en)->mem, 0)
509 npr->u.databaseRecord =
510 z_ext_record_oid(odr_en, match_syntax,
511 (
const char *) opac, -1);
515 records->records[i] =
516 zget_surrogateDiagRec(
517 odr_en, npr->databaseName,
518 YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS,
519 "XML to OPAC conversion failed");
521 yaz_marc_destroy(mt);
525 npr->u.databaseRecord =
526 z_ext_record_oid(odr_en, match_syntax,
528 output_record.len());
533 package.response() = gdu_res;