Added skeleton for query charset conversion. Bug #977.
[yaz-moved-to-github.git] / src / retrieval.c
index c433d61..e041a2f 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (C) 2005-2006, Index Data ApS
+ * Copyright (C) 2005-2007, Index Data ApS
  * See the file LICENSE for details.
  *
- * $Id: retrieval.c,v 1.7 2006-05-08 19:48:26 adam Exp $
+ * $Id: retrieval.c,v 1.17 2007-03-19 14:40:07 adam Exp $
  */
 /**
  * \file retrieval.c
@@ -21,7 +21,7 @@
 #include <yaz/tpath.h>
 #include <yaz/proto.h>
 
-#if HAVE_XML2
+#if YAZ_HAVE_XML2
 #include <libxml/parser.h>
 #include <libxml/tree.h>
 #include <libxml/xinclude.h>
@@ -51,12 +51,13 @@ struct yaz_retrieval_struct {
 struct yaz_retrieval_elem {
     /** \brief schema identifier */
     const char *identifier;
-    /** \brief schema short-hand (such sa "dc") */
-    const char *schema;
+    /** \brief schema name , short-hand such as "dc" */
+    const char *name;
     /** \brief record syntax */
     int *syntax;
-    /** \brief backend schema */
-    const char *backend_schema;
+
+    /** \brief backend name */
+    const char *backend_name;
     /** \brief backend syntax */
     int *backend_syntax;
 
@@ -87,7 +88,7 @@ void yaz_retrieval_destroy(yaz_retrieval_t p)
     {
         yaz_retrieval_reset(p);
         odr_destroy(p->odr);
-        wrbuf_free(p->wr_error, 1);
+        wrbuf_destroy(p->wr_error);
         xfree(p->path);
         xfree(p);
     }
@@ -115,8 +116,8 @@ static int conf_retrieval(yaz_retrieval_t p, const xmlNode *ptr)
 
     el->syntax = 0;
     el->identifier = 0;
-    el->schema = 0;
-    el->backend_schema = 0;
+    el->name = 0;
+    el->backend_name = 0;
     el->backend_syntax = 0;
 
     el->next = 0;
@@ -131,56 +132,93 @@ static int conf_retrieval(yaz_retrieval_t p, const xmlNode *ptr)
                 (const char *) attr->children->content);
             if (!el->syntax)
             {
-                wrbuf_printf(p->wr_error, "Bad syntax '%s'",
+                wrbuf_printf(p->wr_error, "Element <retrieval>: "
+                             " unknown attribute value syntax='%s'",
                              (const char *) attr->children->content);
                 return -1;
             }
         }
         else if (!xmlStrcmp(attr->name, BAD_CAST "identifier") &&
-            attr->children && attr->children->type == XML_TEXT_NODE)
-            el->identifier =
-                nmem_strdup(p->nmem, (const char *) attr->children->content);
-        else if (!xmlStrcmp(attr->name, BAD_CAST "schema") &&
                  attr->children && attr->children->type == XML_TEXT_NODE)
-            el->schema = 
+            el->identifier =
                 nmem_strdup(p->nmem, (const char *) attr->children->content);
-        else if (!xmlStrcmp(attr->name, BAD_CAST "backendschema") &&
+        else if (!xmlStrcmp(attr->name, BAD_CAST "name") &&
                  attr->children && attr->children->type == XML_TEXT_NODE)
-            el->backend_schema = 
+            el->name = 
                 nmem_strdup(p->nmem, (const char *) attr->children->content);
-        else if (!xmlStrcmp(attr->name, BAD_CAST "backendsyntax") &&
-                 attr->children && attr->children->type == XML_TEXT_NODE)
-        {
-            el->backend_syntax = yaz_str_to_z3950oid(
-                p->odr, CLASS_RECSYN,
-                (const char *) attr->children->content);
-            if (!el->backend_syntax)
-            {
-                wrbuf_printf(p->wr_error, "Bad backendsyntax '%s'",
-                             (const char *) attr->children->content);
-                return -1;
-            }
-        }
         else
         {
-            wrbuf_printf(p->wr_error, "Bad attribute '%s'.", attr->name);
+            wrbuf_printf(p->wr_error, "Element <retrieval>: "
+                         " expected attributes 'syntax', identifier' or "
+                         "'name', got '%s'", attr->name);
             return -1;
         }
     }
+
     if (!el->syntax)
     {
         wrbuf_printf(p->wr_error, "Missing 'syntax' attribute");
         return -1;
     }
 
-    el->record_conv = 0; /* OK to have no 'convert' sub content */
+    /* parsing backend element */
+
+    el->record_conv = 0; /* OK to have no 'backend' sub content */
     for (ptr = ptr->children; ptr; ptr = ptr->next)
     {
-        if (ptr->type == XML_ELEMENT_NODE)
-        {
+        if (ptr->type != XML_ELEMENT_NODE)
+            continue;
+        if (strcmp((const char *) ptr->name, "backend")){
+            wrbuf_printf(p->wr_error, "Element <retrieval>: expected"
+                         " zero or one element <backend>, got <%s>",
+                         (const char *) ptr->name);
+            return -1;
+        }
+
+        else {
+
+            /* parsing attributees */
+            struct _xmlAttr *attr;
+            for (attr = ptr->properties; attr; attr = attr->next){
+            
+                if (!xmlStrcmp(attr->name, BAD_CAST "name") 
+                         && attr->children 
+                         && attr->children->type == XML_TEXT_NODE)
+                    el->backend_name 
+                        = nmem_strdup(p->nmem, 
+                                      (const char *) attr->children->content);
+
+                else if (!xmlStrcmp(attr->name, BAD_CAST "syntax") 
+                         && attr->children 
+                         && attr->children->type == XML_TEXT_NODE){
+                    el->backend_syntax 
+                    = yaz_str_to_z3950oid(p->odr, CLASS_RECSYN,
+                       (const char *) attr->children->content);
+                    
+                    if (!el->backend_syntax){
+                        wrbuf_printf(p->wr_error, 
+                                     "Element <backend syntax='%s'>: "
+                                     "attribute 'syntax' has invalid "
+                                     "value '%s'", 
+                                     attr->children->content,
+                                     attr->children->content);
+                        return -1;
+                    } 
+                }
+                else {
+                    wrbuf_printf(p->wr_error, "Element <backend>: expected "
+                                 "attributes 'syntax' or 'name, got '%s'", 
+                                 attr->name);
+                    return -1;
+                }
+            }
+          
+            /* parsing internal of record conv */
             el->record_conv = yaz_record_conv_create();
             
             yaz_record_conv_set_path(el->record_conv, p->path);
+
         
             if (yaz_record_conv_configure(el->record_conv, ptr))
             {
@@ -197,10 +235,8 @@ static int conf_retrieval(yaz_retrieval_t p, const xmlNode *ptr)
     return 0;
 }
 
-int yaz_retrieval_configure(yaz_retrieval_t p, const void *ptr_v)
+int yaz_retrieval_configure(yaz_retrieval_t p, const xmlNode *ptr)
 {
-    const xmlNode *ptr = ptr_v; 
-
     yaz_retrieval_reset(p);
 
     if (ptr && ptr->type == XML_ELEMENT_NODE &&
@@ -217,15 +253,16 @@ int yaz_retrieval_configure(yaz_retrieval_t p, const void *ptr_v)
             }
             else
             {
-                wrbuf_printf(p->wr_error, "Bad element '%s'."
-                             " Expected 'retrieval'", ptr->name);
+                wrbuf_printf(p->wr_error, "Element <retrievalinfo>: "
+                             "expected element <retrieval>, got <%s>", 
+                             ptr->name);
                 return -1;
             }
         }
     }
     else
     {
-        wrbuf_printf(p->wr_error, "Missing 'retrievalinfo' element");
+        wrbuf_printf(p->wr_error, "Expected element <retrievalinfo>");
         return -1;
     }
     return 0;
@@ -250,14 +287,17 @@ int yaz_retrieval_request(yaz_retrieval_t p,
         int schema_ok = 0;
         int syntax_ok = 0;
 
-        if (schema && el->schema && !strcmp(schema, el->schema))
-            schema_ok = 1;
-        if (schema && el->identifier && !strcmp(schema, el->identifier))
-            schema_ok = 1;
         if (!schema)
             schema_ok = 1;
-        if (schema && !el->schema)
-            schema_ok = 1;
+        else
+        {
+            if (el->name && !strcmp(schema, el->name))
+                schema_ok = 1;
+            if (el->identifier && !strcmp(schema, el->identifier))
+                schema_ok = 1;
+            if (!el->name && !el->identifier)
+                schema_ok = 1;
+        }
         
         if (syntax && el->syntax && !oid_oidcmp(syntax, el->syntax))
             syntax_ok = 1;
@@ -271,11 +311,26 @@ int yaz_retrieval_request(yaz_retrieval_t p,
         if (syntax_ok && schema_ok)
         {
             *match_syntax = el->syntax;
-            *match_schema = el->schema;
+            if (el->identifier)
+                *match_schema = el->identifier;
+            else
+                *match_schema = 0;
             if (backend_schema)
-                *backend_schema = el->backend_schema;
+            {
+                if (el->backend_name)
+                    *backend_schema = el->backend_name;
+                else if (el->name)
+                    *backend_schema = el->name;                    
+                else
+                    *backend_schema = schema;
+            }
             if (backend_syntax)
-                *backend_syntax = el->backend_syntax;
+            {
+                if (el->backend_syntax)
+                    *backend_syntax = el->backend_syntax;
+                else
+                    *backend_syntax = el->syntax;
+            }
             if (rc)
                 *rc = el->record_conv;
             return 0;
@@ -283,7 +338,8 @@ int yaz_retrieval_request(yaz_retrieval_t p,
     }
     if (!syntax_matches && syntax)
     {
-        wrbuf_printf(p->wr_error, "%s", syntax);
+        char buf[OID_STR_MAX];
+        wrbuf_printf(p->wr_error, "%s", oid_to_dotstring(syntax, buf));
         return 2;
     }
     if (schema)
@@ -295,7 +351,7 @@ int yaz_retrieval_request(yaz_retrieval_t p,
 
 const char *yaz_retrieval_get_error(yaz_retrieval_t p)
 {
-    return wrbuf_buf(p->wr_error);
+    return wrbuf_cstr(p->wr_error);
 }
 
 void yaz_retrieval_set_path(yaz_retrieval_t p, const char *path)