add support for XInclude in the main configuration file
[pazpar2-moved-to-github.git] / src / pazpar2_config.c
index fdd4ba8..a4503b7 100644 (file)
@@ -1,5 +1,5 @@
 /* This file is part of Pazpar2.
-   Copyright (C) 2006-2013 Index Data
+   Copyright (C) Index Data
 
 Pazpar2 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
@@ -26,6 +26,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 #include <libxml/parser.h>
 #include <libxml/tree.h>
+#include <libxml/xinclude.h>
 
 #include <yaz/yaz-util.h>
 #include <yaz/nmem.h>
@@ -78,7 +79,7 @@ static char *xml_context(const xmlNode *ptr, char *res, size_t len)
         off = off - l;
         memcpy(res + off, attr->name, l);
         res[--off] = '@';
-    } 
+    }
     while (ptr && ptr->type == XML_ELEMENT_NODE)
     {
         size_t l = strlen((const char *) ptr->name);
@@ -207,7 +208,7 @@ static struct conf_sortkey *conf_service_add_sortkey(
     struct conf_service *service,
     int field_id,
     const char *name,
-    enum conf_sortkey_type type)
+    enum conf_metadata_type type)
 {
     struct conf_sortkey *sk = 0;
     NMEM nmem = service->nmem;
@@ -281,8 +282,6 @@ void service_destroy(struct conf_service *service)
 
 void service_incref(struct conf_service *service)
 {
-    yaz_log(YLOG_LOG, "service_incref. p=%p cnt=%d", service,
-            service->ref_count);
     pazpar2_incref(&service->ref_count, service->mutex);
 }
 
@@ -394,6 +393,8 @@ static int parse_metadata(struct conf_service *service, xmlNode *n,
             type = Metadata_type_year;
         else if (!strcmp((const char *) xml_type, "date"))
             type = Metadata_type_date;
+        else if (!strcmp((const char *) xml_type, "float"))
+            type = Metadata_type_float;
         else
         {
             yaz_log(YLOG_FATAL,
@@ -435,7 +436,7 @@ static int parse_metadata(struct conf_service *service, xmlNode *n,
         else
         {
             yaz_log(YLOG_FATAL,
-                    "Unknown value for medadata/setting: %s", xml_setting);
+                    "Unknown value for metadata/setting: %s", xml_setting);
             return -1;
         }
     }
@@ -443,17 +444,29 @@ static int parse_metadata(struct conf_service *service, xmlNode *n,
     // add a sortkey if so specified
     if (xml_sortkey && strcmp((const char *) xml_sortkey, "no"))
     {
-        enum conf_sortkey_type sk_type;
+        enum conf_metadata_type sk_type = type;
         if (merge == Metadata_merge_no)
         {
             yaz_log(YLOG_FATAL,
                     "Can't specify sortkey on a non-merged field");
             return -1;
         }
+        if (!strcmp((const char *) xml_sortkey, "yes"))
+            ;
         if (!strcmp((const char *) xml_sortkey, "numeric"))
-            sk_type = Metadata_sortkey_numeric;
+            ;
         else if (!strcmp((const char *) xml_sortkey, "skiparticle"))
-            sk_type = Metadata_sortkey_skiparticle;
+        {
+            if (sk_type == Metadata_type_generic)
+                sk_type = Metadata_type_skiparticle;
+            else
+            {
+                yaz_log(YLOG_FATAL,
+                        "skiparticle only supported for type=generic: %s",
+                    xml_type);
+                return -1;
+            }
+        }
         else
         {
             yaz_log(YLOG_FATAL,
@@ -1015,66 +1028,71 @@ static void info_service_metadata(struct conf_service *service, WRBUF w)
             }
             if (md->sortkey_offset > 0) {
                 wrbuf_puts(w, " sortkey=\"");
-                switch (service->sortkeys[md->sortkey_offset].type) {
-                    case Metadata_sortkey_relevance:
-                        wrbuf_puts(w, "relevance");
-                        break;
-                    case Metadata_sortkey_numeric:
-                        wrbuf_puts(w, "numeric");
-                        break;
-                    case Metadata_sortkey_skiparticle:
-                        wrbuf_puts(w, "skiparticle");
-                        break;
-                    case Metadata_sortkey_string:
-                        wrbuf_puts(w, "string");
-                        break;
-                    case Metadata_sortkey_position:
-                        wrbuf_puts(w, "position");
-                        break;
-                }
-                wrbuf_puts(w, "\"");
-            }
-
-            switch (md->type) {
-                case Metadata_type_generic:
-                    break;
-                case Metadata_type_year:
-                    wrbuf_puts(w, " type=\"year\"");
-                    break;
-                case Metadata_type_date:
-                    wrbuf_puts(w, " type=\"date\"");
-                    break;
-            }
-
-            switch (md->merge) {
-                case Metadata_merge_no:
-                    break;
-                case Metadata_merge_unique:
-                    wrbuf_puts(w, " merge=\"unique\"");
-                    break;
-                case Metadata_merge_longest:
-                    wrbuf_puts(w, " merge=\"longest\"");
+                switch (service->sortkeys[md->sortkey_offset].type)
+                {
+                case Metadata_type_relevance:
+                    wrbuf_puts(w, "relevance");
                     break;
-                case Metadata_merge_range:
-                    wrbuf_puts(w, " merge=\"range\"");
+                case Metadata_type_skiparticle:
+                    wrbuf_puts(w, "skiparticle");
                     break;
-                case Metadata_merge_all:
-                    wrbuf_puts(w, " merge=\"all\"");
+                case Metadata_type_position:
+                    wrbuf_puts(w, "position");
                     break;
-                case Metadata_merge_first:
-                    wrbuf_puts(w, " merge=\"first\"");
+                default:
+                    wrbuf_puts(w, "yes");
                     break;
+                }
+                wrbuf_puts(w, "\"");
             }
-
-            switch (md->mergekey) {
-                case Metadata_mergekey_no:
-                    break;
-                case Metadata_mergekey_optional:
-                    wrbuf_puts(w, " mergekey=\"optional\"");
-                    break;
-                case Metadata_mergekey_required:
-                    wrbuf_puts(w, " mergekey=\"required\"");
-                    break;
+            switch (md->type)
+            {
+            case Metadata_type_generic:
+            case Metadata_type_skiparticle:
+                break;
+            case Metadata_type_year:
+                wrbuf_puts(w, " type=\"year\"");
+                break;
+            case Metadata_type_date:
+                wrbuf_puts(w, " type=\"date\"");
+                break;
+            case Metadata_type_float:
+                wrbuf_puts(w, " type=\"float\"");
+                break;
+            case Metadata_type_relevance:
+            case Metadata_type_position:
+                break;
+            }
+            switch (md->merge)
+            {
+            case Metadata_merge_no:
+                break;
+            case Metadata_merge_unique:
+                wrbuf_puts(w, " merge=\"unique\"");
+                break;
+            case Metadata_merge_longest:
+                wrbuf_puts(w, " merge=\"longest\"");
+                break;
+            case Metadata_merge_range:
+                wrbuf_puts(w, " merge=\"range\"");
+                break;
+            case Metadata_merge_all:
+                wrbuf_puts(w, " merge=\"all\"");
+                break;
+            case Metadata_merge_first:
+                wrbuf_puts(w, " merge=\"first\"");
+                break;
+            }
+            switch (md->mergekey)
+            {
+            case Metadata_mergekey_no:
+                break;
+            case Metadata_mergekey_optional:
+                wrbuf_puts(w, " mergekey=\"optional\"");
+                break;
+            case Metadata_mergekey_required:
+                wrbuf_puts(w, " mergekey=\"required\"");
+                break;
             }
             wrbuf_puts(w, " />\n");
         }
@@ -1093,16 +1111,18 @@ static void info_service_databases(struct conf_service *service, WRBUF w)
         for(db = service->databases; db; db = db->next)
         {
             wrbuf_puts(w, "    <database");
-            if (db->id) {
-                    wrbuf_puts(w, " id=\"");
-                    wrbuf_printf(w, "%s", db->id);
-                    wrbuf_puts(w, "\"");
+            if (db->id)
+            {
+                wrbuf_puts(w, " id=\"");
+                wrbuf_printf(w, "%s", db->id);
+                wrbuf_puts(w, "\"");
             }
             wrbuf_puts(w, ">\n");
             for (i = 0; i < db->num_settings; i++)
             {
                 s = db->settings[i];
-                while (s != NULL) {
+                while (s != NULL)
+                {
                     wrbuf_puts(w, "     <setting");
                     wrbuf_puts(w, " name=\"");
                     wrbuf_xmlputs(w, s->name);
@@ -1116,7 +1136,6 @@ static void info_service_databases(struct conf_service *service, WRBUF w)
             }
             wrbuf_puts(w, "    </database>\n");
         }
-
         wrbuf_puts(w, "   </databases>\n");
     }
 }
@@ -1126,7 +1145,6 @@ void info_services(struct conf_server *server, WRBUF w)
     struct conf_service *s = server->service;
     int i;
     struct setting *S;
-    struct database *db;
 
     wrbuf_puts(w, " <services>\n");
     for (; s; s = s->next)
@@ -1215,7 +1233,10 @@ static int parse_config(struct conf_config *config, xmlNode *root)
 
 struct conf_config *config_create(const char *fname, int verbose)
 {
-    xmlDoc *doc = xmlParseFile(fname);
+    xmlDoc *doc = xmlReadFile(fname,
+                              NULL,
+                              XML_PARSE_XINCLUDE + XML_PARSE_NOBLANKS
+                              + XML_PARSE_NSCLEAN + XML_PARSE_NONET );
     xmlNode *n;
     const char *p;
     int r;
@@ -1231,6 +1252,14 @@ struct conf_config *config_create(const char *fname, int verbose)
         return 0;
     }
 
+    // Perform XInclude.
+    r = xmlXIncludeProcess(doc);
+    if (r == -1)
+    {
+        yaz_log(YLOG_FATAL, "XInclude processing failed");
+        return 0;
+    }
+
     config->nmem = nmem;
     config->servers = 0;
     config->no_threads = 0;
@@ -1287,7 +1316,6 @@ void server_destroy(struct conf_server *server)
         s = s_next;
     }
     pp2_charset_fact_destroy(server->charsets);
-    yaz_log(YLOG_LOG, "server_destroy server=%p", server);
     http_server_destroy(server->http_server);
 }