Year 2007.
[metaproxy-moved-to-github.git] / src / filter_record_transform.cpp
index 6201697..4570ac5 100644 (file)
@@ -1,5 +1,5 @@
-/* $Id: filter_record_transform.cpp,v 1.2 2006-10-04 11:21:47 marc Exp $
-   Copyright (c) 2005-2006, Index Data.
+/* $Id: filter_record_transform.cpp,v 1.8 2007-01-25 14:05:54 adam Exp $
+   Copyright (c) 2005-2007, Index Data.
 
    See the LICENSE file for details
  */
@@ -12,6 +12,7 @@
 #include "gduutil.hpp"
 #include "xmlutil.hpp"
 
+#include <yaz/diagbib1.h>
 #include <yaz/zgdu.h>
 #include <yaz/retrieval.h>
 
@@ -21,6 +22,7 @@
 
 namespace mp = metaproxy_1;
 namespace yf = mp::filter;
+namespace mp_util = metaproxy_1::util;
 
 namespace metaproxy_1 {
     namespace filter {
@@ -93,7 +95,7 @@ void yf::RecordTransform::Impl::configure(const xmlNode *xml_node)
         if (0 == strcmp((const char *) retrieval_node->name, "retrievalinfo"))
             break;
     }
-    
+
     // read configuration
     if ( 0 != yaz_retrieval_configure(m_retrieval, retrieval_node)){
         std::string msg("RecordTransform filter config: ");
@@ -117,46 +119,107 @@ void yf::RecordTransform::Impl::process(mp::Package &package) const
     }
     
     // getting original present request
-    Z_PresentRequest *pr = gdu_req->u.z3950->u.presentRequest;
+    Z_PresentRequest *pr_req = gdu_req->u.z3950->u.presentRequest;
 
     // setting up ODR's for memory during encoding/decoding
     //mp::odr odr_de(ODR_DECODE);  
     mp::odr odr_en(ODR_ENCODE);
 
-    // now re-insructing the z3950 backend present request
-     
-    // z3950'fy record syntax
-    //Odr_oid odr_oid;
-    if(pr->preferredRecordSyntax){
-        (pr->preferredRecordSyntax)
-            = yaz_str_to_z3950oid(odr_en, CLASS_RECSYN, "xml");
-        
-        // = yaz_oidval_to_z3950oid (odr_en, CLASS_RECSYN, VAL_TEXT_XML);
+    // setting up variables for conversion state
+    yaz_record_conv_t rc = 0;
+    int ret_code;
+
+    const char *input_schema = 0;
+    Odr_oid *input_syntax = 0;
+
+    if(pr_req->recordComposition){
+        input_schema 
+            = mp_util::record_composition_to_esn(pr_req->recordComposition);
+    }
+    if(pr_req->preferredRecordSyntax){
+        input_syntax = pr_req->preferredRecordSyntax;
+    }
+    
+    const char *match_schema = 0;
+    int *match_syntax = 0;
+
+    const char *backend_schema = 0;
+    Odr_oid *backend_syntax = 0;
+
+    ret_code 
+        = yaz_retrieval_request(m_retrieval,
+                                input_schema, input_syntax,
+                                &match_schema, &match_syntax,
+                                &rc,
+                                &backend_schema, &backend_syntax);
+
+    // error handling
+    if (ret_code != 0)
+    {
+        // need to construct present error package and send back
+
+        Z_APDU *apdu = 0;
+
+        const char *details = 0;
+        if (ret_code == -1) /* error ? */
+        {
+           details = yaz_retrieval_get_error(m_retrieval);
+           apdu = odr_en.create_presentResponse(
+               gdu_req->u.z3950,
+               YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS, details);
+        }
+        else if (ret_code == 1 || ret_code == 3)
+        {
+            details = input_schema;
+            apdu = odr_en.create_presentResponse(
+                gdu_req->u.z3950,
+                YAZ_BIB1_ELEMENT_SET_NAMES_UNSUPP, details);
+        }
+        else if (ret_code == 2)
+        {
+            char oidbuf[OID_STR_MAX];
+            oid_to_dotstring(input_syntax, oidbuf);
+            details = odr_strdup(odr_en, oidbuf);
+            
+            apdu = odr_en.create_presentResponse(
+                gdu_req->u.z3950,
+                YAZ_BIB1_RECORD_SYNTAX_UNSUPP, details);
+        }
+        package.response() = apdu;
+        return;
     }
-    // Odr_oid *yaz_str_to_z3950oid (ODR o, int oid_class,
-    //                                         const char *str);
-    // const char *yaz_z3950oid_to_str (Odr_oid *oid, int *oid_class);
 
 
+
+    // now re-coding the z3950 backend present request
+     
+    // z3950'fy record syntax
+    if (backend_syntax)  // TODO: this seems not to work - why ??
+        pr_req->preferredRecordSyntax = backend_syntax;
+    else
+        pr_req->preferredRecordSyntax
+            = yaz_oidval_to_z3950oid(odr_en, CLASS_RECSYN, VAL_NONE);
+    
+
     // z3950'fy record schema
-    //if ()
-    // {
-    //     pr->recordComposition 
-    //         = (Z_RecordComposition *) 
-    //           odr_malloc(odr_en, sizeof(Z_RecordComposition));
-    //     pr->recordComposition->which 
-    //         = Z_RecordComp_simple;
-    //     pr->recordComposition->u.simple 
-    //         = build_esn_from_schema(odr_en, 
-    //                                 (const char *) sr_req->recordSchema); 
-    // }
+    if (backend_schema)
+    {
+        pr_req->recordComposition 
+            = (Z_RecordComposition *) 
+              odr_malloc(odr_en, sizeof(Z_RecordComposition));
+        pr_req->recordComposition->which 
+            = Z_RecordComp_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 
+            = odr_strdup(odr_en, backend_schema);
+    }
 
     // attaching Z3950 package to filter chain
     package.request() = gdu_req;
 
-    // std::cout << "z3950_present_request " << *apdu << "\n";   
-
-    // sending package
     package.move();
 
    //check successful Z3950 present response
@@ -176,7 +239,72 @@ void yf::RecordTransform::Impl::process(mp::Package &package) const
     // std::cout << "z3950_present_request OK\n";
     // std::cout << "back z3950 " << *gdu_res << "\n";
 
+    Z_PresentResponse * pr_res = gdu_res->u.z3950->u.presentResponse;
+
+    // let non surrogate dioagnostics in Z3950 present response package
+    // pass to frontend - just return
+    if (pr_res->records 
+        && pr_res->records->which == Z_Records_NSD
+        && pr_res->records->u.nonSurrogateDiagnostic)
+    {
+        // we might do more clever tricks to "reverse"
+        // these error(s).
 
+        //*pr_res->records->u.nonSurrogateDiagnostic->condition = 
+        // YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
+    }
+
+    // record transformation must take place 
+    if (rc && pr_res 
+        && pr_res->numberOfRecordsReturned 
+        && *(pr_res->numberOfRecordsReturned) > 0
+        && pr_res->records
+        && pr_res->records->which == Z_Records_DBOSD
+        && pr_res->records->u.databaseOrSurDiagnostics->num_records)
+    {
+         //transform all records
+         for (int i = 0; 
+              i < pr_res->records->u.databaseOrSurDiagnostics->num_records; 
+              i++)
+         {
+             Z_NamePlusRecord *npr 
+                 = pr_res->records->u.databaseOrSurDiagnostics->records[i];
+             if (npr->which == Z_NamePlusRecord_databaseRecord)
+             {
+                 Z_External *r = npr->u.databaseRecord;
+                 //oident *ent = oid_getentbyoid(r->direct_reference);
+                 if (r->which == Z_External_octet) 
+                 {
+                     WRBUF output_record = wrbuf_alloc();
+                     int ret_trans 
+                         =  yaz_record_conv_record(rc,
+                                                   (const char *)
+                                                   r->u.octet_aligned->buf, 
+                                                   r->u.octet_aligned->len,
+                                                   output_record);
+                     if (ret_trans == 0)
+                     {
+                         struct oident *ident = oid_getentbyoid(match_syntax);
+                         npr->u.databaseRecord =
+                             z_ext_record(odr_en, ident->value,
+                                          wrbuf_buf(output_record),
+                                          wrbuf_len(output_record));
+                     }
+                     else
+                     {
+                         pr_res->records->
+                             u.databaseOrSurDiagnostics->records[i] 
+                             =  zget_surrogateDiagRec(
+                                 odr_en, npr->databaseName,
+                                 YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS,
+                                 yaz_record_conv_get_error(rc));
+                     }
+                     wrbuf_free(output_record, 1);
+                 }
+             }
+         }
+    }
+    package.response() = gdu_res;
     return;
 }