X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Ffilter_record_transform.cpp;h=c872e76f18cd66d6db48c7338c48e9e0dba985be;hb=586d78659d671683f33ec55f4a7d32b28e345ccd;hp=d3709bc4cee5664b052bcd2d38a4cc89d964dccc;hpb=a219ca4725cc04435d474dd33178324ac0253244;p=metaproxy-moved-to-github.git diff --git a/src/filter_record_transform.cpp b/src/filter_record_transform.cpp index d3709bc..c872e76 100644 --- a/src/filter_record_transform.cpp +++ b/src/filter_record_transform.cpp @@ -1,5 +1,5 @@ /* This file is part of Metaproxy. - Copyright (C) 2005-2012 Index Data + Copyright (C) Index Data Metaproxy is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free @@ -25,6 +25,14 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #include #include +#include + +#include + +#if HAVE_USEMARCON +#include +#include +#endif #include @@ -46,8 +54,124 @@ namespace 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) { } @@ -68,14 +192,14 @@ void yf::RecordTransform::process(mp::Package &package) const } -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); } @@ -90,8 +214,8 @@ void yf::RecordTransform::Impl::configure(const xmlNode *xml_node, // 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) @@ -100,8 +224,16 @@ void yf::RecordTransform::Impl::configure(const xmlNode *xml_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); @@ -139,20 +271,20 @@ void yf::RecordTransform::Impl::process(mp::Package &package) const // 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 @@ -171,7 +303,7 @@ void yf::RecordTransform::Impl::process(mp::Package &package) const package.move(); return; } - + mp::odr odr_en(ODR_ENCODE); // setting up variables for conversion state @@ -183,7 +315,7 @@ void yf::RecordTransform::Impl::process(mp::Package &package) const 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, @@ -238,7 +370,7 @@ void yf::RecordTransform::Impl::process(mp::Package &package) const if (sr_req) { - if (backend_syntax) + if (backend_syntax) sr_req->preferredRecordSyntax = odr_oiddup(odr_en, backend_syntax); else sr_req->preferredRecordSyntax = 0; @@ -249,7 +381,7 @@ void yf::RecordTransform::Impl::process(mp::Package &package) const = (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; } @@ -261,23 +393,23 @@ void yf::RecordTransform::Impl::process(mp::Package &package) const } 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 @@ -288,7 +420,7 @@ void yf::RecordTransform::Impl::process(mp::Package &package) const package.request() = gdu_req; package.move(); - + Z_GDU *gdu_res = package.response().get(); // see if we have a records list to patch! @@ -297,9 +429,9 @@ void yf::RecordTransform::Impl::process(mp::Package &package) const 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) @@ -311,9 +443,9 @@ void yf::RecordTransform::Impl::process(mp::Package &package) const 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) @@ -321,7 +453,7 @@ void yf::RecordTransform::Impl::process(mp::Package &package) const records = sr_res->records->u.databaseOrSurDiagnostics; } } - + if (records) { int i; @@ -330,39 +462,72 @@ void yf::RecordTransform::Impl::process(mp::Package &package) const Z_NamePlusRecord *npr = records->records[i]; if (npr->which == Z_NamePlusRecord_databaseRecord) { - WRBUF output_record = wrbuf_alloc(); + const char *details = 0; + mp::wrbuf output_record; Z_External *r = npr->u.databaseRecord; - int ret_trans = 0; + int ret_trans = -1; if (r->which == Z_External_OPAC) { ret_trans = yaz_record_conv_opac_record(rc, r->u.opac, output_record); + details = yaz_record_conv_get_error(rc); } - 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); + details = yaz_record_conv_get_error(rc); } - if (ret_trans == 0) + else { - npr->u.databaseRecord = - z_ext_record_oid(odr_en, match_syntax, - wrbuf_buf(output_record), - wrbuf_len(output_record)); + details = "unsupported record type for record_conv"; } - else + if (ret_trans) { records->records[i] = zget_surrogateDiagRec( odr_en, npr->databaseName, YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS, - yaz_record_conv_get_error(rc)); + details); + } + else + { + if (!oid_oidcmp(match_syntax, yaz_oid_recsyn_opac)) + { + yaz_marc_t mt = yaz_marc_create(); + Z_OPACRecord *opac = 0; + if (yaz_xml_to_opac(mt, output_record.buf(), + output_record.len(), + &opac, 0 /* iconv */, + ((ODR )odr_en)->mem, 0) + && opac) + { + npr->u.databaseRecord = + z_ext_record_oid(odr_en, match_syntax, + (const char *) opac, -1); + } + else + { + records->records[i] = + zget_surrogateDiagRec( + odr_en, npr->databaseName, + YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS, + "XML to OPAC conversion failed"); + } + yaz_marc_destroy(mt); + } + else + { + npr->u.databaseRecord = + z_ext_record_oid(odr_en, match_syntax, + output_record.buf(), + output_record.len()); + } } - wrbuf_destroy(output_record); } } package.response() = gdu_res;