#include <yaz/zgdu.h>
#include <yaz/retrieval.h>
+#include <boost/thread/mutex.hpp>
+
+#if HAVE_USEMARCON
+#include <usemarconlib.h>
+#include <defines.h>
+#endif
+
#include <iostream>
namespace mp = metaproxy_1;
}
}
+#if HAVE_USEMARCON
+struct info_usemarcon {
+ boost::mutex m_mutex;
+
+ char *stage1;
+ char *stage2;
+
+ Usemarcon *usemarcon1;
+ Usemarcon *usemarcon2;
+};
+
+static int convert_usemarcon(void *info, WRBUF record, WRBUF wr_error)
+{
+ struct info_usemarcon *p = (struct info_usemarcon *) info;
+
+ boost::mutex::scoped_lock lock(p->m_mutex);
+
+ if (p->usemarcon1)
+ {
+ char *converted;
+ size_t convlen;
+ int res;
+
+ p->usemarcon1->SetMarcRecord(wrbuf_buf(record), wrbuf_len(record));
+ res = p->usemarcon1->Convert();
+ if (res != 0)
+ {
+ wrbuf_printf(wr_error, "usemarcon stage1 failed res=%d", res);
+ return -1;
+ }
+ p->usemarcon1->GetMarcRecord(converted, convlen);
+
+ if (p->usemarcon2)
+ {
+ p->usemarcon2->SetMarcRecord(converted, convlen);
+
+ res = p->usemarcon2->Convert();
+ free(converted);
+ if (res != 0)
+ {
+ wrbuf_printf(wr_error, "usemarcon stage2 failed res=%d",
+ res);
+ return -1;
+ }
+ p->usemarcon2->GetMarcRecord(converted, convlen);
+ }
+ wrbuf_rewind(record);
+ wrbuf_write(record, converted, convlen);
+ free(converted);
+ }
+ return 0;
+}
+
+static void destroy_usemarcon(void *info)
+{
+ struct info_usemarcon *p = (struct info_usemarcon *) info;
+
+ delete p->usemarcon1;
+ delete p->usemarcon2;
+ xfree(p->stage1);
+ xfree(p->stage2);
+ delete p;
+}
+
+static void *construct_usemarcon(const xmlNode *ptr, const char *path,
+ WRBUF wr_error)
+{
+ struct _xmlAttr *attr;
+ if (strcmp((const char *) ptr->name, "usemarcon"))
+ return 0;
+
+ struct info_usemarcon *p = new(struct info_usemarcon);
+ p->stage1 = 0;
+ p->stage2 = 0;
+ p->usemarcon1 = 0;
+ p->usemarcon2 = 0;
+
+ for (attr = ptr->properties; attr; attr = attr->next)
+ {
+ if (!xmlStrcmp(attr->name, BAD_CAST "stage1") &&
+ attr->children && attr->children->type == XML_TEXT_NODE)
+ p->stage1 = xstrdup((const char *) attr->children->content);
+ else if (!xmlStrcmp(attr->name, BAD_CAST "stage2") &&
+ attr->children && attr->children->type == XML_TEXT_NODE)
+ p->stage2 = xstrdup((const char *) attr->children->content);
+ else
+ {
+ wrbuf_printf(wr_error, "Bad attribute '%s'"
+ "Expected stage1 or stage2.", attr->name);
+ destroy_usemarcon(p);
+ return 0;
+ }
+ }
+
+ if (p->stage1)
+ {
+ p->usemarcon1 = new Usemarcon();
+ p->usemarcon1->SetIniFileName(p->stage1);
+ }
+ if (p->stage2)
+ {
+ p->usemarcon2 = new Usemarcon();
+ p->usemarcon2->SetIniFileName(p->stage2);
+ }
+ return p;
+}
+
+static void type_usemarcon(struct yaz_record_conv_type *t)
+{
+ t->next = 0;
+ t->construct = construct_usemarcon;
+ t->convert = convert_usemarcon;
+ t->destroy = destroy_usemarcon;
+}
+#endif
+
// define Pimpl wrapper forwarding to Impl
-
+
yf::RecordTransform::RecordTransform() : m_p(new Impl)
{
}
}
-yf::RecordTransform::Impl::Impl()
+yf::RecordTransform::Impl::Impl()
{
m_retrieval = yaz_retrieval_create();
assert(m_retrieval);
}
yf::RecordTransform::Impl::~Impl()
-{
+{
if (m_retrieval)
yaz_retrieval_destroy(m_retrieval);
}
// parsing down to retrieval node, which can be any of the children nodes
xmlNode *retrieval_node;
- for (retrieval_node = xml_node->children;
- retrieval_node;
+ for (retrieval_node = xml_node->children;
+ retrieval_node;
retrieval_node = retrieval_node->next)
{
if (retrieval_node->type != XML_ELEMENT_NODE)
break;
}
+#if HAVE_USEMARCON
+ struct yaz_record_conv_type mt;
+ type_usemarcon(&mt);
+ struct yaz_record_conv_type *t = &mt;
+#else
+ struct yaz_record_conv_type *t = 0;
+#endif
+
// read configuration
- if (0 != yaz_retrieval_configure(m_retrieval, retrieval_node))
+ if (0 != yaz_retrieval_configure_t(m_retrieval, retrieval_node, t))
{
std::string msg("RecordTransform filter config: ");
msg += yaz_retrieval_get_error(m_retrieval);
// the effective element set name.. Therefore we can only allow
// two cases.. Both equal or absent.. If not, we'll just have to
// disable the piggyback!
- if (sr_req->smallSetElementSetNames
+ if (sr_req->smallSetElementSetNames
&&
sr_req->mediumSetElementSetNames
&&
sr_req->smallSetElementSetNames->which == Z_ElementSetNames_generic
- &&
+ &&
sr_req->mediumSetElementSetNames->which == Z_ElementSetNames_generic
- &&
+ &&
!strcmp(sr_req->smallSetElementSetNames->u.generic,
sr_req->mediumSetElementSetNames->u.generic))
{
input_schema = sr_req->smallSetElementSetNames->u.generic;
}
- else if (!sr_req->smallSetElementSetNames &&
+ else if (!sr_req->smallSetElementSetNames &&
!sr_req->mediumSetElementSetNames)
; // input_schema is 0 already
else
package.move();
return;
}
-
+
mp::odr odr_en(ODR_ENCODE);
// setting up variables for conversion state
const char *backend_schema = 0;
Odr_oid *backend_syntax = 0;
- int ret_code
+ int ret_code
= yaz_retrieval_request(m_retrieval,
input_schema, input_syntax,
&match_schema, &match_syntax,
if (sr_req)
{
- if (backend_syntax)
+ if (backend_syntax)
sr_req->preferredRecordSyntax = odr_oiddup(odr_en, backend_syntax);
else
sr_req->preferredRecordSyntax = 0;
= (Z_ElementSetNames *)
odr_malloc(odr_en, sizeof(Z_ElementSetNames));
sr_req->smallSetElementSetNames->which = Z_ElementSetNames_generic;
- sr_req->smallSetElementSetNames->u.generic
+ sr_req->smallSetElementSetNames->u.generic
= odr_strdup(odr_en, backend_schema);
sr_req->mediumSetElementSetNames = sr_req->smallSetElementSetNames;
}
}
else if (pr_req)
{
- if (backend_syntax)
+ if (backend_syntax)
pr_req->preferredRecordSyntax = odr_oiddup(odr_en, backend_syntax);
else
pr_req->preferredRecordSyntax = 0;
-
+
if (backend_schema)
{
- pr_req->recordComposition
- = (Z_RecordComposition *)
+ pr_req->recordComposition
+ = (Z_RecordComposition *)
odr_malloc(odr_en, sizeof(Z_RecordComposition));
- pr_req->recordComposition->which
+ pr_req->recordComposition->which
= Z_RecordComp_simple;
- pr_req->recordComposition->u.simple
+ pr_req->recordComposition->u.simple
= (Z_ElementSetNames *)
odr_malloc(odr_en, sizeof(Z_ElementSetNames));
pr_req->recordComposition->u.simple->which = Z_ElementSetNames_generic;
- pr_req->recordComposition->u.simple->u.generic
+ pr_req->recordComposition->u.simple->u.generic
= odr_strdup(odr_en, backend_schema);
}
else
package.request() = gdu_req;
package.move();
-
+
Z_GDU *gdu_res = package.response().get();
// see if we have a records list to patch!
gdu_res->u.z3950->which == Z_APDU_presentResponse)
{
Z_PresentResponse * pr_res = gdu_res->u.z3950->u.presentResponse;
-
- if (rc && pr_res
- && pr_res->numberOfRecordsReturned
+
+ if (rc && pr_res
+ && pr_res->numberOfRecordsReturned
&& *(pr_res->numberOfRecordsReturned) > 0
&& pr_res->records
&& pr_res->records->which == Z_Records_DBOSD)
gdu_res->u.z3950->which == Z_APDU_searchResponse)
{
Z_SearchResponse *sr_res = gdu_res->u.z3950->u.searchResponse;
-
- if (rc && sr_res
- && sr_res->numberOfRecordsReturned
+
+ if (rc && sr_res
+ && sr_res->numberOfRecordsReturned
&& *(sr_res->numberOfRecordsReturned) > 0
&& sr_res->records
&& sr_res->records->which == Z_Records_DBOSD)
records = sr_res->records->u.databaseOrSurDiagnostics;
}
}
-
+
if (records)
{
int i;
Z_NamePlusRecord *npr = records->records[i];
if (npr->which == Z_NamePlusRecord_databaseRecord)
{
- WRBUF output_record = wrbuf_alloc();
+ mp::wrbuf output_record;
Z_External *r = npr->u.databaseRecord;
int ret_trans = 0;
if (r->which == Z_External_OPAC)
yaz_record_conv_opac_record(rc, r->u.opac,
output_record);
}
- else if (r->which == Z_External_octet)
+ else if (r->which == Z_External_octet)
{
ret_trans =
yaz_record_conv_record(rc, (const char *)
- r->u.octet_aligned->buf,
+ r->u.octet_aligned->buf,
r->u.octet_aligned->len,
output_record);
}
{
npr->u.databaseRecord =
z_ext_record_oid(odr_en, match_syntax,
- wrbuf_buf(output_record),
- wrbuf_len(output_record));
+ output_record.buf(),
+ output_record.len());
}
else
{
YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS,
yaz_record_conv_get_error(rc));
}
- wrbuf_destroy(output_record);
}
}
package.response() = gdu_res;