From 0d191bf4a0a8f0196e0ba1c42f0070255c04c1b4 Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Tue, 8 Nov 2005 15:08:02 +0000 Subject: [PATCH] Added ZiNG Update Support. New codecs are defined in srw.h. Extended the GFS to support this as well. Backend handler, bend_srw_update, does the update work. Code contributed by Ko van der Sloot. --- NEWS | 4 + include/yaz/backend.h | 27 +++- include/yaz/srw.h | 49 +++++++- src/seshigh.c | 234 ++++++++++++++++++++++++++++++++-- src/srw.c | 333 +++++++++++++++++++++++++++++++++++++++++++++---- src/srwutil.c | 68 ++++++++-- 6 files changed, 670 insertions(+), 45 deletions(-) diff --git a/NEWS b/NEWS index eb54190..57c9bee 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +Added ZiNG Update Support. New codecs are defined in srw.h. Extended the +GFS to support this as well. Backend handler, bend_srw_update, does the +update work. Code contributed by Ko van der Sloot. + Allow retrieval of Search Result-1 information in ZOOM by the use of options that are attached to a result set. ZOOM documentation updated accordingly. diff --git a/include/yaz/backend.h b/include/yaz/backend.h index 5f6ad17..91a24d4 100644 --- a/include/yaz/backend.h +++ b/include/yaz/backend.h @@ -23,7 +23,7 @@ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. * - * $Id: backend.h,v 1.33 2005-09-11 18:39:11 adam Exp $ + * $Id: backend.h,v 1.34 2005-11-08 15:08:02 adam Exp $ */ /** @@ -39,6 +39,7 @@ #include #include +#include YAZ_BEGIN_CDECL @@ -144,6 +145,29 @@ typedef struct bend_scan_rr { char *scanClause; /* CQL scan clause */ } bend_scan_rr; +typedef struct bend_update_rr { + int num_bases; /* number of elements in databaselist */ + char **basenames; /* databases to search */ + Z_ReferenceId *referenceId; /* reference ID */ + ODR stream; /* encoding stream - memory source if required */ + ODR print; /* printing stream */ + char *operation; + char *operation_status; + char *record_id; + char *record_version; + char *record_checksum; + char *record_old_version; + char *record_packing; + char *record_schema; + char *record_data; + Z_SRW_extra_record *request_extra_record; + Z_SRW_extra_record *response_extra_record; + char *extra_request_data; + char *extra_response_data; + int errcode; + char *errstring; +} bend_update_rr; + /* delete handler */ typedef struct bend_delete_rr { int function; @@ -233,6 +257,7 @@ typedef struct bend_initrequest Z_External *charneg_response; int (*bend_explain)(void *handle, bend_explain_rr *rr); int (*bend_srw_scan)(void *handle, bend_scan_rr *rr); + int (*bend_srw_update)(void *handle, bend_update_rr *rr); } bend_initrequest; typedef struct bend_initresult diff --git a/include/yaz/srw.h b/include/yaz/srw.h index 24fd5d6..4e37f45 100644 --- a/include/yaz/srw.h +++ b/include/yaz/srw.h @@ -2,7 +2,7 @@ * Copyright (C) 1995-2005, Index Data ApS * See the file LICENSE for details. * - * $Id: srw.h,v 1.22 2005-06-25 15:46:03 adam Exp $ + * $Id: srw.h,v 1.23 2005-11-08 15:08:02 adam Exp $ */ /** * \file srw.h @@ -19,10 +19,21 @@ YAZ_BEGIN_CDECL typedef struct { + int type; + char *recordReviewCode; + char *recordReviewNote; + char *recordId; + char *nonDupRecordId; + char *recordLockStatus; + char *recordOldVersion; +} Z_SRW_extra_record; + +typedef struct { char *recordSchema; int recordPacking; #define Z_SRW_recordPacking_string 0 #define Z_SRW_recordPacking_XML 1 +#define Z_SRW_recordPacking_URL 2 char *recordData_buf; int recordData_len; int *recordPosition; @@ -76,6 +87,8 @@ typedef struct { Z_SRW_diagnostic *diagnostics; int num_diagnostics; int *nextRecordPosition; + + Z_SRW_extra_record **extra_records; /* of size num_records */ } Z_SRW_searchRetrieveResponse; typedef struct { @@ -88,6 +101,7 @@ typedef struct { Z_SRW_record record; Z_SRW_diagnostic *diagnostics; int num_diagnostics; + Z_SRW_extra_record *extra_record; } Z_SRW_explainResponse; typedef struct { @@ -117,12 +131,39 @@ typedef struct { int num_diagnostics; } Z_SRW_scanResponse; + +typedef struct { + char *database; + char *operation; + char *recordId; + char *recordVersion; + char *recordOldVersion; + Z_SRW_record record; + Z_SRW_extra_record *extra_record; + char *extraRequestData; + char *stylesheet; +} Z_SRW_updateRequest; + +typedef struct { + char *operationStatus; + char *recordId; + char *recordVersion; + char *recordChecksum; + char *extraResponseData; + Z_SRW_record record; + Z_SRW_extra_record *extra_record; + Z_SRW_diagnostic *diagnostics; + int num_diagnostics; +} Z_SRW_updateResponse; + #define Z_SRW_searchRetrieve_request 1 #define Z_SRW_searchRetrieve_response 2 #define Z_SRW_explain_request 3 #define Z_SRW_explain_response 4 #define Z_SRW_scan_request 5 #define Z_SRW_scan_response 6 +#define Z_SRW_update_request 7 +#define Z_SRW_update_response 8 typedef struct { int which; @@ -133,6 +174,8 @@ typedef struct { Z_SRW_explainResponse *explain_response; Z_SRW_scanRequest *scan_request; Z_SRW_scanResponse *scan_response; + Z_SRW_updateRequest *update_request; + Z_SRW_updateResponse *update_response; } u; char *srw_version; } Z_SRW_PDU; @@ -140,7 +183,11 @@ typedef struct { YAZ_EXPORT int yaz_srw_codec(ODR o, void * pptr, Z_SRW_PDU **handler_data, void *client_data, const char *ns); +YAZ_EXPORT int yaz_ucp_codec(ODR o, void * pptr, + Z_SRW_PDU **handler_data, + void *client_data, const char *ns); YAZ_EXPORT Z_SRW_PDU *yaz_srw_get(ODR o, int which); +YAZ_EXPORT Z_SRW_extra_record *yaz_srw_get_extra_record(ODR o); YAZ_EXPORT int yaz_diag_bib1_to_srw (int bib1_code); diff --git a/src/seshigh.c b/src/seshigh.c index 343eea2..1ff40da 100644 --- a/src/seshigh.c +++ b/src/seshigh.c @@ -2,7 +2,7 @@ * Copyright (C) 1995-2005, Index Data ApS * See the file LICENSE for details. * - * $Id: seshigh.c,v 1.63 2005-09-16 09:16:40 adam Exp $ + * $Id: seshigh.c,v 1.64 2005-11-08 15:08:02 adam Exp $ */ /** * \file seshigh.c @@ -474,6 +474,7 @@ static void assoc_init_reset(association *assoc) assoc->init->bend_fetch = NULL; assoc->init->bend_explain = NULL; assoc->init->bend_srw_scan = NULL; + assoc->init->bend_srw_update = NULL; assoc->init->charneg_request = NULL; assoc->init->charneg_response = NULL; @@ -852,18 +853,27 @@ static void srw_bend_search(association *assoc, request *req, int packing = Z_SRW_recordPacking_string; if (start + number > rr.hits) number = rr.hits - start + 1; - if (srw_req->recordPacking && - !strcmp(srw_req->recordPacking, "xml")) - packing = Z_SRW_recordPacking_XML; + if (srw_req->recordPacking){ + if (!strcmp(srw_req->recordPacking, "xml")) + packing = Z_SRW_recordPacking_XML; + if (!strcmp(srw_req->recordPacking, "url")) + packing = Z_SRW_recordPacking_URL; + } srw_res->records = (Z_SRW_record *) odr_malloc(assoc->encode, number * sizeof(*srw_res->records)); + + srw_res->extra_records = (Z_SRW_extra_record **) + odr_malloc(assoc->encode, + number*sizeof(*srw_res->extra_records)); + for (i = 0; irecords[j].recordPacking = packing; srw_res->records[j].recordData_buf = 0; + srw_res->extra_records[j] = 0; yaz_log(YLOG_DEBUG, "srw_bend_fetch %d", i+start); errcode = srw_bend_fetch(assoc, i+start, srw_req, srw_res->records + j); @@ -989,9 +999,13 @@ static void srw_bend_explain(association *assoc, request *req, if (rr.explain_buf) { int packing = Z_SRW_recordPacking_string; - if (srw_req->recordPacking && - !strcmp(srw_req->recordPacking, "xml")) - packing = Z_SRW_recordPacking_XML; + if (srw_req->recordPacking) + { + if (!strcmp(srw_req->recordPacking, "xml")) + packing = Z_SRW_recordPacking_XML; + else if (!strcmp(srw_req->recordPacking, "url")) + packing = Z_SRW_recordPacking_URL; + } srw_res->record.recordSchema = rr.schema; srw_res->record.recordPacking = packing; srw_res->record.recordData_buf = rr.explain_buf; @@ -1188,6 +1202,187 @@ static void srw_bend_scan(association *assoc, request *req, } +static void srw_bend_update(association *assoc, request *req, + Z_SRW_updateRequest *srw_req, + Z_SRW_updateResponse *srw_res, + int *http_code) +{ + yaz_log(YLOG_DEBUG, "Got SRW UpdateRequest"); + yaz_log(YLOG_DEBUG, "num_diag = %d", srw_res->num_diagnostics ); + *http_code = 404; + srw_bend_init(assoc, &srw_res->diagnostics, &srw_res->num_diagnostics); + if (assoc->init) + { + bend_update_rr rr; + + rr.stream = assoc->encode; + rr.print = assoc->print; + rr.num_bases = 1; + rr.basenames = &srw_req->database; + rr.operation = srw_req->operation; + rr.operation_status = "failed"; + rr.record_id = 0; + rr.record_version = 0; + rr.record_checksum = 0; + rr.record_old_version = 0; + rr.record_packing = "xml"; + rr.record_schema = 0; + rr.record_data = 0; + rr.request_extra_record = 0; + rr.response_extra_record = 0; + rr.extra_request_data = 0; + rr.extra_response_data = 0; + rr.errcode = 0; + rr.errstring = 0; + + yaz_log(YLOG_DEBUG, "basename = %s", rr.basenames[0] ); + yaz_log(YLOG_DEBUG, "Operation = %s", rr.operation ); + if ( !strcmp( rr.operation, "delete" ) ){ + if ( !srw_req->recordId ){ + yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + 7, "recordId" ); + } + else { + rr.record_id = srw_req->recordId; + } + if ( !srw_req->recordVersion ){ + yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + 7, "recordVersion" ); + } + else { + rr.record_version = odr_strdup( assoc->encode, + srw_req->recordVersion ); + + } + if ( srw_req->recordOldVersion ){ + rr.record_old_version = odr_strdup(assoc->encode, + srw_req->recordOldVersion ); + } + if ( srw_req->extraRequestData ){ + rr.extra_request_data = odr_strdup(assoc->encode, + srw_req->extraRequestData ); + } + } + else if ( !strcmp( rr.operation, "replace" ) ){ + if ( !srw_req->recordId ){ + yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + 7, "recordId" ); + } + else { + rr.record_id = srw_req->recordId; + } + if ( srw_req->record.recordSchema == 0 ){ + yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + 7, "recordSchema" ); + } + else { + rr.record_schema = odr_strdup(assoc->encode, + srw_req->record.recordSchema ); + } + switch (srw_req->record.recordPacking) + { + case Z_SRW_recordPacking_string: + rr.record_packing = "string"; + break; + case Z_SRW_recordPacking_XML: + rr.record_packing = "xml"; + break; + case Z_SRW_recordPacking_URL: + rr.record_packing = "url"; + break; + } + if ( srw_req->record.recordData_len ){ + rr.record_data = odr_strdupn(assoc->encode, + srw_req->record.recordData_buf, + srw_req->record.recordData_len ); + rr.request_extra_record = srw_req->extra_record; + } + else { + yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + 7, "recordData" ); + } + if (srw_req->extraRequestData) + rr.extra_request_data = odr_strdup(assoc->encode, + srw_req->extraRequestData ); + } + else if ( !strcmp( rr.operation, "insert" ) ) + { + if ( srw_req->record.recordSchema == 0 ){ + yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + 7, "recordSchema" ); + } + else { + rr.record_schema = odr_strdup(assoc->encode, + srw_req->record.recordSchema); + } + switch (srw_req->record.recordPacking) + { + case Z_SRW_recordPacking_string: + rr.record_packing = "string"; + break; + case Z_SRW_recordPacking_XML: + rr.record_packing = "xml"; + break; + case Z_SRW_recordPacking_URL: + rr.record_packing = "url"; + break; + } + + if (srw_req->record.recordData_len) + { + rr.record_data = odr_strdupn(assoc->encode, + srw_req->record.recordData_buf, + srw_req->record.recordData_len ); + rr.request_extra_record = srw_req->extra_record; + } + else + yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + 7, "recordData" ); + if ( srw_req->extraRequestData ) + rr.extra_request_data = odr_strdup(assoc->encode, + srw_req->extraRequestData ); + } + if (srw_res->num_diagnostics == 0) + { + if ( assoc->init->bend_srw_update) + (*assoc->init->bend_srw_update)(assoc->backend, &rr); + else { + yaz_log( YLOG_WARN, "Got No Update function!"); + return; + } + } + if (rr.errcode) + yaz_add_srw_diagnostic(assoc->encode, + &srw_res->diagnostics, + &srw_res->num_diagnostics, + rr.errcode, rr.errstring); + srw_res->recordId = rr.record_id; + srw_res->operationStatus = rr.operation_status; + srw_res->recordVersion = rr.record_version; + srw_res->recordChecksum = rr.record_checksum; + srw_res->extraResponseData = rr.extra_response_data; + srw_res->record.recordPosition = 0; + if (srw_res->num_diagnostics == 0 && rr.record_data) + { + srw_res->record.recordSchema = rr.record_schema; + srw_res->record.recordPacking = srw_req->record.recordPacking; + srw_res->record.recordData_buf = rr.record_data; + srw_res->record.recordData_len = strlen(rr.record_data); + srw_res->extra_record = rr.response_extra_record; + + } + else + srw_res->record.recordData_len = 0; + *http_code = 200; + } +} static void process_http_request(association *assoc, request *req) { @@ -1275,26 +1470,43 @@ static void process_http_request(association *assoc, request *req) res->u.scan_response->num_diagnostics = num_diagnostic; } srw_bend_scan(assoc, req, sr->u.scan_request, - res->u.scan_response, &http_code); + res->u.scan_response, &http_code); + if (http_code == 200) + soap_package->u.generic->p = res; + } + else if (sr->which == Z_SRW_update_request) + { + yaz_log(YLOG_DEBUG, "handling SRW UpdateRequest"); + Z_SRW_PDU *res = yaz_srw_get(o, Z_SRW_update_response); + if (num_diagnostic) + { + res->u.update_response->diagnostics = diagnostic; + res->u.update_response->num_diagnostics = num_diagnostic; + } + yaz_log(YLOG_DEBUG, "num_diag = %d", res->u.update_response->num_diagnostics ); + srw_bend_update(assoc, req, sr->u.update_request, + res->u.update_response, &http_code); if (http_code == 200) soap_package->u.generic->p = res; } else { yaz_log(log_request, "SOAP ERROR"); - /* FIXME - what error, what query */ + /* FIXME - what error, what query */ http_code = 500; z_soap_error(assoc->encode, soap_package, "SOAP-ENV:Client", "Bad method", 0); } if (http_code == 200 || http_code == 500) { - static Z_SOAP_Handler soap_handlers[3] = { + static Z_SOAP_Handler soap_handlers[4] = { #if HAVE_XML2 {"http://www.loc.gov/zing/srw/", 0, (Z_SOAP_fun) yaz_srw_codec}, {"http://www.loc.gov/zing/srw/v1.0/", 0, (Z_SOAP_fun) yaz_srw_codec}, + {"http://www.loc.gov/zing/srw/update/", 0, + (Z_SOAP_fun) yaz_ucp_codec}, #endif {0, 0, 0} }; @@ -1776,7 +1988,7 @@ static Z_APDU *process_initRequest(association *assoc, request *reqb) assoc->init->implementation_name, odr_prepend(assoc->encode, "GFS", resp->implementationName)); - version = odr_strdup(assoc->encode, "$Revision: 1.63 $"); + version = odr_strdup(assoc->encode, "$Revision: 1.64 $"); if (strlen(version) > 10) /* check for unexpanded CVS strings */ version[strlen(version)-2] = '\0'; resp->implementationVersion = odr_prepend(assoc->encode, diff --git a/src/srw.c b/src/srw.c index 3c77116..759e06e 100644 --- a/src/srw.c +++ b/src/srw.c @@ -2,7 +2,7 @@ * Copyright (C) 1995-2005, Index Data ApS * See the file LICENSE for details. * - * $Id: srw.c,v 1.36 2005-08-22 20:34:21 adam Exp $ + * $Id: srw.c,v 1.37 2005-11-08 15:08:02 adam Exp $ */ /** * \file srw.c @@ -10,7 +10,6 @@ */ #include - #if HAVE_XML2 #include #include @@ -171,53 +170,137 @@ static int match_xsd_integer(xmlNodePtr ptr, const char *elem, ODR o, int **val) return 1; } +static int yaz_srw_extra_record(ODR o, xmlNodePtr pptr, + Z_SRW_extra_record *rec, + void *client_data, const char *ns) +{ + if (o->direction == ODR_DECODE) + { + xmlNodePtr ptr; + rec->type = 1; + rec->recordId = 0; + rec->recordReviewCode = 0; + rec->recordReviewNote = 0; + rec->recordLockStatus = 0; + rec->recordOldVersion = 0; + rec->nonDupRecordId = 0; + for (ptr = pptr->children; ptr; ptr = ptr->next) + { + if (match_xsd_string(ptr, "recordId", o, + &rec->recordId )) + ; + else if (match_xsd_string(ptr, "recordReviewCode", o, + &rec->recordReviewCode )) + ; + else if (match_xsd_string(ptr, "recordReviewNote", o, + &rec->recordReviewNote )) + ; + else if (match_xsd_string(ptr, "nonDupRecordId", o, + &rec->nonDupRecordId )) + ; + else if (match_xsd_string(ptr, "recordLockStatus", o, + &rec->recordLockStatus )) + ; + else if (match_xsd_string(ptr, "recordOldVersion", o, + &rec->recordOldVersion )) + ; + } + } + else if (o->direction == ODR_ENCODE) + { + xmlNodePtr ptr = pptr; + if ( rec->recordId ) + add_xsd_string(ptr, "recordId", rec->recordId); + if ( rec->recordReviewCode ) + add_xsd_string(ptr, "recordReviewCode", rec->recordReviewCode); + if ( rec->recordReviewNote ) + add_xsd_string(ptr, "recordReviewNote", rec->recordReviewNote); + if ( rec->nonDupRecordId ) + add_xsd_string(ptr, "nonDupRecordId", rec->nonDupRecordId); + if ( rec->recordLockStatus ) + add_xsd_string(ptr, "recordLockStatus", rec->recordLockStatus); + if ( rec->recordOldVersion ) + add_xsd_string(ptr, "recordOldVersion", rec->recordOldVersion); + } + return 0; +} + static int yaz_srw_record(ODR o, xmlNodePtr pptr, Z_SRW_record *rec, + Z_SRW_extra_record **extra, void *client_data, const char *ns) { if (o->direction == ODR_DECODE) { + char *spack = 0; int pack = Z_SRW_recordPacking_string; xmlNodePtr ptr; + xmlNodePtr data_ptr; rec->recordSchema = 0; rec->recordData_buf = 0; rec->recordData_len = 0; rec->recordPosition = 0; + *extra = 0; for (ptr = pptr->children; ptr; ptr = ptr->next) { - char *spack = 0; if (match_xsd_string(ptr, "recordSchema", o, - &rec->recordSchema)) - ; + &rec->recordSchema)){ + } else if (match_xsd_string(ptr, "recordPacking", o, &spack)) { if (spack && !strcmp(spack, "xml")) pack = Z_SRW_recordPacking_XML; + if (spack && !strcmp(spack, "url")) + pack = Z_SRW_recordPacking_URL; if (spack && !strcmp(spack, "string")) pack = Z_SRW_recordPacking_string; } else if (match_xsd_integer(ptr, "recordPosition", o, &rec->recordPosition)) ; - else - { - if (pack == Z_SRW_recordPacking_XML) - match_xsd_XML_n(ptr, "recordData", o, - &rec->recordData_buf, - &rec->recordData_len); - if (pack == Z_SRW_recordPacking_string) - match_xsd_string_n(ptr, "recordData", o, - &rec->recordData_buf, - &rec->recordData_len); + else if (match_element(ptr, "recordData")){ + /* save position of Data until after the loop + then we will know the packing (hopefully), and + unpacking is done once + */ + data_ptr = ptr; + } + else if (match_element(ptr, "extraRecordData")){ + *extra = (Z_SRW_extra_record *) + odr_malloc(o, sizeof(Z_SRW_extra_record)); + yaz_srw_extra_record(o, ptr, *extra, client_data, ns); } } + switch(pack) + { + case Z_SRW_recordPacking_XML: + match_xsd_XML_n(data_ptr, "recordData", o, + &rec->recordData_buf, &rec->recordData_len); + break; + case Z_SRW_recordPacking_URL: + /* just store it as a string. + leave it to the backend to collect the document */ + match_xsd_string_n(ptr, "recordData", o, + &rec->recordData_buf, &rec->recordData_len); + break; + case Z_SRW_recordPacking_string: + match_xsd_string_n(ptr, "recordData", o, + &rec->recordData_buf, &rec->recordData_len); + break; + default: + rec->recordData_buf = 0; + rec->recordData_len = 0; + /* need some way to signal diagnostic here */ + } rec->recordPacking = pack; } else if (o->direction == ODR_ENCODE) { xmlNodePtr ptr = pptr; + int pack = rec->recordPacking; add_xsd_string(ptr, "recordSchema", rec->recordSchema); - switch(rec->recordPacking) + + switch(pack) { case Z_SRW_recordPacking_string: add_xsd_string(ptr, "recordPacking", "string"); @@ -229,13 +312,26 @@ static int yaz_srw_record(ODR o, xmlNodePtr pptr, Z_SRW_record *rec, add_XML_n(ptr, "recordData", rec->recordData_buf, rec->recordData_len); break; + case Z_SRW_recordPacking_URL: + add_xsd_string(ptr, "recordPacking", "url"); + add_xsd_string_n(ptr, "recordData", rec->recordData_buf, + rec->recordData_len); + break; + } + if (rec->recordPosition) + add_xsd_integer(ptr, "recordPosition", rec->recordPosition ); + if (*extra) + { + xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "extraRecordData", + 0); + yaz_srw_extra_record(o, rptr, *extra, client_data, ns); } - add_xsd_integer(ptr, "recordPosition", rec->recordPosition); } return 0; } static int yaz_srw_records(ODR o, xmlNodePtr pptr, Z_SRW_record **recs, + Z_SRW_extra_record ***extra, int *num, void *client_data, const char *ns) { if (o->direction == ODR_DECODE) @@ -252,12 +348,13 @@ static int yaz_srw_records(ODR o, xmlNodePtr pptr, Z_SRW_record **recs, if (!*num) return 1; *recs = (Z_SRW_record *) odr_malloc(o, *num * sizeof(**recs)); + *extra = (Z_SRW_extra_record **) odr_malloc(o, *num * sizeof(**extra)); for (i = 0, ptr = pptr->children; ptr; ptr = ptr->next) { if (ptr->type == XML_ELEMENT_NODE && !xmlStrcmp(ptr->name, BAD_CAST "record")) { - yaz_srw_record(o, ptr, (*recs)+i, client_data, ns); + yaz_srw_record(o, ptr, *recs + i, *extra + i, client_data, ns); i++; } } @@ -269,7 +366,7 @@ static int yaz_srw_records(ODR o, xmlNodePtr pptr, Z_SRW_record **recs, { xmlNodePtr rptr = xmlNewChild(pptr, 0, BAD_CAST "record", 0); - yaz_srw_record(o, rptr, (*recs)+i, client_data, ns); + yaz_srw_record(o, rptr, (*recs)+i, *extra + i, client_data, ns); } } return 0; @@ -542,8 +639,8 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data, ; else if (match_element(ptr, "records")) yaz_srw_records(o, ptr, &res->records, - &res->num_records, client_data, - ns); + &res->extra_records, + &res->num_records, client_data, ns); else if (match_xsd_integer(ptr, "nextRecordPosition", o, &res->nextRecordPosition)) ; @@ -601,7 +698,8 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data, &(*p)->srw_version)) ; else if (match_element(ptr, "record")) - yaz_srw_record(o, ptr, &res->record, client_data, ns); + yaz_srw_record(o, ptr, &res->record, &res->extra_record, + client_data, ns); else if (match_element(ptr, "diagnostics")) yaz_srw_diagnostics(o, ptr, &res->diagnostics, &res->num_diagnostics, @@ -748,7 +846,8 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data, if (res->num_records) { xmlNodePtr rptr = xmlNewChild(ptr, 0, BAD_CAST "records", 0); - yaz_srw_records(o, rptr, &res->records, &res->num_records, + yaz_srw_records(o, rptr, &res->records, &res->extra_records, + &res->num_records, client_data, ns); } add_xsd_integer(ptr, "nextRecordPosition", @@ -786,7 +885,8 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data, if (1) { xmlNodePtr ptr1 = xmlNewChild(ptr, 0, BAD_CAST "record", 0); - yaz_srw_record(o, ptr1, &res->record, client_data, ns); + yaz_srw_record(o, ptr1, &res->record, &res->extra_record, + client_data, ns); } if (res->num_diagnostics) { @@ -848,6 +948,191 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data, return 0; } +int yaz_ucp_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data, + void *client_data, const char *ns) +{ + xmlNodePtr pptr = (xmlNodePtr) vptr; + if (o->direction == ODR_DECODE) + { + Z_SRW_PDU **p = handler_data; + xmlNodePtr method = pptr->children; + + while (method && method->type == XML_TEXT_NODE) + method = method->next; + + if (!method) + return -1; + if (method->type != XML_ELEMENT_NODE) + return -1; + + *p = (Z_SRW_PDU *) odr_malloc(o, sizeof(**p)); + (*p)->srw_version = odr_strdup(o, "1.1"); + + if (!xmlStrcmp(method->name, BAD_CAST "updateRequest")) + { + xmlNodePtr ptr = method->children; + Z_SRW_updateRequest *req; + + (*p)->which = Z_SRW_update_request; + req = (*p)->u.update_request = (Z_SRW_updateRequest *) + odr_malloc(o, sizeof(*req)); + req->database = 0; + req->operation = 0; + req->recordId = 0; + req->recordVersion = 0; + req->recordOldVersion = 0; + req->record.recordData_buf = 0; + req->record.recordData_len = 0; + req->record.recordSchema = 0; + req->record.recordPacking = 0; + req->extra_record = 0; + req->extraRequestData = 0; + req->stylesheet = 0; + + char *oper = 0; + + for (; ptr; ptr = ptr->next) + { + if (match_xsd_string(ptr, "version", o, + &(*p)->srw_version)) + ; + else if (match_xsd_string(ptr, "operation", o, + &oper)){ + if ( oper ){ + if ( !strcmp(oper, "delete")) + req->operation = "delete"; + else if (!strcmp(oper,"replace" )) + req->operation = "replace"; + else if ( !strcmp( oper, "insert")) + req->operation = "insert"; + } + } + else if (match_xsd_string(ptr, "recordId", o, + &req->recordId)) + ; + else if (match_xsd_string(ptr, "recordVersion", o, + &req->recordVersion)) + ; + else if (match_element(ptr, "record")) + yaz_srw_record(o, ptr, &req->record, &req->extra_record, + client_data, ns); + else if (match_xsd_string(ptr, "stylesheet", o, + &req->stylesheet)) + ; + else if (match_xsd_string(ptr, "database", o, + &req->database)) + ; + } + } + else if (!xmlStrcmp(method->name, BAD_CAST "updateResponse")) + { + xmlNodePtr ptr = method->children; + Z_SRW_updateResponse *res; + + (*p)->which = Z_SRW_update_response; + res = (*p)->u.update_response = (Z_SRW_updateResponse *) + odr_malloc(o, sizeof(*res)); + + res->operationStatus = 0; + res->recordId = 0; + res->recordVersion = 0; + res->recordChecksum = 0; + res->diagnostics = 0; + res->num_diagnostics = 0; + res->record.recordData_buf = 0; + res->record.recordData_len = 0; + res->record.recordSchema = 0; + res->record.recordPacking = 0; + res->extra_record = 0; + res->extraResponseData = 0; + + for (; ptr; ptr = ptr->next) + { + if (match_xsd_string(ptr, "version", o, + &(*p)->srw_version)) + ; + else if (match_xsd_string(ptr, "operationStatus", o, + &res->operationStatus )) + ; + else if (match_xsd_string(ptr, "recordId", o, + &res->recordId)) + ; + else if (match_xsd_string(ptr, "recordVersion", o, + &res->recordVersion )) + ; + else if (match_element(ptr, "record")) + yaz_srw_record(o, ptr, &res->record, &res->extra_record, + client_data, ns); + else if (match_element(ptr, "diagnostics")) + yaz_srw_diagnostics(o, ptr, &res->diagnostics, + &res->num_diagnostics, + client_data, ns); + } + } + else if (!xmlStrcmp(method->name, BAD_CAST "explainUpdateRequest")) + { + } + else if (!xmlStrcmp(method->name, BAD_CAST "explainUpdateResponse")) + { + } + else + { + *p = 0; + return -1; + } + } + else if (o->direction == ODR_ENCODE) + { + Z_SRW_PDU **p = handler_data; + xmlNsPtr ns_srw; + + if ((*p)->which == Z_SRW_update_request) + { + Z_SRW_updateRequest *req = (*p)->u.update_request; + xmlNodePtr ptr = xmlNewChild(pptr, 0, "updateRequest", 0); + ns_srw = xmlNewNs(ptr, ns, "zu"); + xmlSetNs(ptr, ns_srw); + + add_xsd_string(ptr, "version", (*p)->srw_version); + add_xsd_string(ptr, "stylesheet", req->stylesheet); + add_xsd_string(ptr, "database", req->database); + } + else if ((*p)->which == Z_SRW_update_response) + { + Z_SRW_updateResponse *res = (*p)->u.update_response; + xmlNodePtr ptr = xmlNewChild(pptr, 0, "updateResponse", 0); + ns_srw = xmlNewNs(ptr, ns, "zu"); + xmlSetNs(ptr, ns_srw); + + add_xsd_string(ptr, "version", (*p)->srw_version); + add_xsd_string(ptr, "operationStatus", res->operationStatus ); + add_xsd_string(ptr, "recordId", res->recordId ); + if (res->recordVersion) + add_xsd_string(ptr, "recordVersion", res->recordVersion ); + if (res->recordChecksum) + add_xsd_string(ptr, "recordChecksum", res->recordChecksum ); + if (res->record.recordData_len) + { + xmlNodePtr rptr = xmlNewChild(ptr, 0, "record", 0); + yaz_srw_record(o, rptr, &res->record, &res->extra_record, + client_data, ns); + } + if (res->num_diagnostics) + { + xmlNodePtr rptr = xmlNewChild(ptr, 0, "diagnostics", 0); + yaz_srw_diagnostics(o, rptr, &res->diagnostics, + &res->num_diagnostics, client_data, ns); + } + if ( res->extraResponseData ) + add_xsd_string(ptr, "extraResponseData", res->extraResponseData); + } + else + return -1; + + } + return 0; +} + #endif diff --git a/src/srwutil.c b/src/srwutil.c index f7f0a1c..27840ce 100644 --- a/src/srwutil.c +++ b/src/srwutil.c @@ -2,7 +2,7 @@ * Copyright (C) 1995-2005, Index Data ApS * See the file LICENSE for details. * - * $Id: srwutil.c,v 1.31 2005-09-12 10:23:53 adam Exp $ + * $Id: srwutil.c,v 1.32 2005-11-08 15:08:03 adam Exp $ */ /** * \file srwutil.c @@ -178,12 +178,14 @@ int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu, int ret = -1; const char *charset_p = 0; - static Z_SOAP_Handler soap_handlers[3] = { + static Z_SOAP_Handler soap_handlers[4] = { #if HAVE_XML2 {"http://www.loc.gov/zing/srw/", 0, (Z_SOAP_fun) yaz_srw_codec}, {"http://www.loc.gov/zing/srw/v1.0/", 0, (Z_SOAP_fun) yaz_srw_codec}, + {"http://www.loc.gov/zing/srw/update/", 0, + (Z_SOAP_fun) yaz_ucp_codec}, #endif {0, 0, 0} }; @@ -230,6 +232,10 @@ int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu, (*srw_pdu)->u.scan_request->database == 0) (*srw_pdu)->u.scan_request->database = db; + if ((*srw_pdu)->which == Z_SRW_update_request && + (*srw_pdu)->u.update_request->database == 0) + (*srw_pdu)->u.update_request->database = db; + return 0; } return 1; @@ -526,6 +532,20 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu, return 2; } +Z_SRW_extra_record *yaz_srw_get_extra_record(ODR o) +{ + Z_SRW_extra_record *res = (Z_SRW_extra_record *) + odr_malloc(o, sizeof(*res)); + res->type = 1; + res->recordReviewCode = 0; + res->recordReviewNote = 0; + res->recordId = 0; + res->nonDupRecordId = 0; + res->recordLockStatus = 0; + res->recordOldVersion = 0; + return res; +} + Z_SRW_PDU *yaz_srw_get(ODR o, int which) { Z_SRW_PDU *sr = (Z_SRW_PDU *) odr_malloc(o, sizeof(*o)); @@ -561,6 +581,7 @@ Z_SRW_PDU *yaz_srw_get(ODR o, int which) sr->u.response->diagnostics = 0; sr->u.response->num_diagnostics = 0; sr->u.response->nextRecordPosition = 0; + sr->u.response->extra_records = 0; break; case Z_SRW_explain_request: sr->u.explain_request = (Z_SRW_explainRequest *) @@ -580,6 +601,7 @@ Z_SRW_PDU *yaz_srw_get(ODR o, int which) Z_SRW_recordPacking_string; sr->u.explain_response->diagnostics = 0; sr->u.explain_response->num_diagnostics = 0; + sr->u.explain_response->extra_record = 0; break; case Z_SRW_scan_request: sr->u.scan_request = (Z_SRW_scanRequest *) @@ -594,16 +616,46 @@ Z_SRW_PDU *yaz_srw_get(ODR o, int which) case Z_SRW_scan_response: sr->u.scan_response = (Z_SRW_scanResponse *) odr_malloc(o, sizeof(*sr->u.scan_response)); - sr->u.scan_response->terms = 0; - sr->u.scan_response->num_terms = 0; - sr->u.scan_response->diagnostics = 0; - sr->u.scan_response->num_diagnostics = 0; + sr->u.scan_response->terms = 0; + sr->u.scan_response->num_terms = 0; + sr->u.scan_response->diagnostics = 0; + sr->u.scan_response->num_diagnostics = 0; + case Z_SRW_update_request: + sr->u.update_request = (Z_SRW_updateRequest *) + odr_malloc(o, sizeof(*sr->u.update_request)); + sr->u.update_request->database = 0; + sr->u.update_request->stylesheet = 0; + sr->u.update_request->record.recordSchema = 0; + sr->u.update_request->record.recordPacking = Z_SRW_recordPacking_XML; + sr->u.update_request->recordId = 0; + sr->u.update_request->recordVersion = 0; + sr->u.update_request->recordOldVersion = 0; + sr->u.update_request->record.recordData_buf = 0; + sr->u.update_request->record.recordData_len = 0; + sr->u.update_request->extra_record = 0; + sr->u.update_request->extraRequestData = 0; + sr->u.request->database = 0; + break; + case Z_SRW_update_response: + sr->u.update_response = (Z_SRW_updateResponse *) + odr_malloc(o, sizeof(*sr->u.update_response)); + sr->u.update_response->operationStatus = 0; + sr->u.update_response->recordId = 0; + sr->u.update_response->recordVersion = 0; + sr->u.update_response->recordChecksum = 0; + sr->u.update_response->record.recordData_buf = 0; + sr->u.update_response->record.recordData_len = 0; + sr->u.update_response->record.recordSchema = 0; + sr->u.update_response->record.recordPacking = + Z_SRW_recordPacking_XML; + sr->u.update_response->extra_record = 0; + sr->u.update_response->extraResponseData = 0; + sr->u.update_response->diagnostics = 0; + sr->u.update_response->num_diagnostics = 0; } return sr; } - - /* bib1:srw */ static int srw_bib1_map[] = { 1, 1, -- 1.7.10.4