Towards working facets
authorAdam Dickmeiss <adam@indexdata.dk>
Mon, 9 Sep 2013 13:18:37 +0000 (15:18 +0200)
committerAdam Dickmeiss <adam@indexdata.dk>
Mon, 9 Sep 2013 13:18:37 +0000 (15:18 +0200)
include/yaz/srw.h
src/Makefile.am
src/facet.c
src/seshigh.c
src/sru-p.h
src/sru_facet.c [new file with mode: 0644]
src/srw.c
src/srwutil.c
win/makefile

index b86b790..b29562a 100644 (file)
@@ -37,7 +37,7 @@
 #include <yaz/zgdu.h>
 #include <yaz/diagsrw.h>
 #include <yaz/diagsru_update.h>
 #include <yaz/zgdu.h>
 #include <yaz/diagsrw.h>
 #include <yaz/diagsru_update.h>
-#include "facet.h"
+#include <yaz/z-facet-1.h>
 
 YAZ_BEGIN_CDECL
 
 
 YAZ_BEGIN_CDECL
 
index 2e7f700..b5bdd97 100644 (file)
@@ -90,7 +90,7 @@ libyaz_la_SOURCES=base64.c version.c options.c log.c \
   otherinfo.c pquery.c sortspec.c charneg.c initopt.c init_diag.c \
   zoom-c.c zoom-z3950.c zoom-sru.c zoom-query.c zoom-record-cache.c \
   zoom-event.c \
   otherinfo.c pquery.c sortspec.c charneg.c initopt.c init_diag.c \
   zoom-c.c zoom-z3950.c zoom-sru.c zoom-query.c zoom-record-cache.c \
   zoom-event.c \
-  record_render.c zoom-socket.c zoom-opt.c zoom-p.h sru-p.h \
+  record_render.c zoom-socket.c zoom-opt.c zoom-p.h sru_facet.c sru-p.h \
   grs1disp.c zgdu.c soap.c srw.c srwutil.c uri.c solr.c diag_map.c \
   opac_to_xml.c xml_to_opac.c \
   cclfind.c ccltoken.c cclerrms.c cclqual.c cclptree.c cclp.h \
   grs1disp.c zgdu.c soap.c srw.c srwutil.c uri.c solr.c diag_map.c \
   opac_to_xml.c xml_to_opac.c \
   cclfind.c ccltoken.c cclerrms.c cclqual.c cclptree.c cclp.h \
index a9d1ef9..40b5e1c 100644 (file)
@@ -43,17 +43,21 @@ void yaz_oi_set_facetlist(
 
 Z_FacetList *yaz_oi_get_facetlist(Z_OtherInformation **otherInformation)
 {
 
 Z_FacetList *yaz_oi_get_facetlist(Z_OtherInformation **otherInformation)
 {
-    int categoryValue = 1;
-    Z_External *z_external = 0;
-    Z_OtherInformationUnit *oi =
-        yaz_oi_update(otherInformation, 0, yaz_oid_userinfo_facet_1,
-                      categoryValue, 0);
-    if (!oi)
-        return 0;
-    z_external = oi->information.externallyDefinedInfo;
-
-    if (z_external && z_external->which == Z_External_userFacets)
-        return z_external->u.facetList;
+    Z_OtherInformation *oi = *otherInformation;
+    if (oi)
+    {
+        int i;
+        for (i = 0; i < oi->num_elements; i++)
+        {
+            Z_OtherInformationUnit *oiu = oi->list[i];
+            if (oiu->which == Z_OtherInfo_externallyDefinedInfo
+                && oiu->information.externallyDefinedInfo->which ==
+                Z_External_userFacets)
+            {
+                return oiu->information.externallyDefinedInfo->u.facetList;
+            }
+        }
+    }
     return 0;
 }
 
     return 0;
 }
 
index 07ee014..77539a7 100644 (file)
@@ -56,6 +56,7 @@
 #include <libxml/tree.h>
 #endif
 
 #include <libxml/tree.h>
 #endif
 
+#include <yaz/facet.h>
 #include <yaz/xmalloc.h>
 #include <yaz/comstack.h>
 #include "eventl.h"
 #include <yaz/xmalloc.h>
 #include <yaz/comstack.h>
 #include "eventl.h"
@@ -1008,6 +1009,11 @@ static void srw_bend_search(association *assoc,
             rr.errstring = 0;
             rr.search_info = 0;
             rr.search_input = 0;
             rr.errstring = 0;
             rr.search_info = 0;
             rr.search_input = 0;
+
+            if (srw_req->facetList)
+                yaz_oi_set_facetlist(&rr.search_input, assoc->encode,
+                                     srw_req->facetList);
+
             yaz_log_zquery_level(log_requestdetail,rr.query);
 
             (assoc->init->bend_search)(assoc->backend, &rr);
             yaz_log_zquery_level(log_requestdetail,rr.query);
 
             (assoc->init->bend_search)(assoc->backend, &rr);
@@ -1045,7 +1051,9 @@ static void srw_bend_search(association *assoc,
                     srw_res->resultSetIdleTime =
                         odr_intdup(assoc->encode, *rr.srw_setnameIdleTime );
                }
                     srw_res->resultSetIdleTime =
                         odr_intdup(assoc->encode, *rr.srw_setnameIdleTime );
                }
-
+                
+                srw_res->facetList = yaz_oi_get_facetlist(&rr.search_info);
+                yaz_log(YLOG_LOG, "facetList res = %p",srw_res->facetList);
                 if (start > rr.hits || start < 1)
                 {
                     /* if hits<=0 and start=1 we don't return a diagnostic */
                 if (start > rr.hits || start < 1)
                 {
                     /* if hits<=0 and start=1 we don't return a diagnostic */
index 7bd2762..aa3f3bf 100644 (file)
@@ -39,10 +39,23 @@ Z_AttributeList *yaz_use_attribute_create(ODR o, const char *name);
 
 char *yaz_negotiate_sru_version(char *input_ver);
 
 
 char *yaz_negotiate_sru_version(char *input_ver);
 
+void yaz_sru_facet_request(ODR, Z_FacetList **facetList, const char **limit);
+
 #if YAZ_HAVE_XML2
 #include <libxml/parser.h>
 #include <libxml/tree.h>
 #if YAZ_HAVE_XML2
 #include <libxml/parser.h>
 #include <libxml/tree.h>
-const char *yaz_element_attribute_value_get(xmlNodePtr ptr, const char *node_name, const char *attribute_name);
+
+xmlNodePtr add_xsd_string(xmlNodePtr ptr, const char *elem, const char *val);
+
+void add_xsd_integer(xmlNodePtr ptr, const char *elem, const Odr_int *val);
+
+xmlNodePtr add_xsd_string_n(xmlNodePtr ptr, const char *elem, const char *val,
+                            int len);
+
+void yaz_sru_facet_response(ODR o, Z_FacetList **facetList, xmlNodePtr n);
+
+const char *yaz_element_attribute_value_get(xmlNodePtr ptr,
+                                            const char *node_name, const char *attribute_name);
 #endif
 
 /*
 #endif
 
 /*
diff --git a/src/sru_facet.c b/src/sru_facet.c
new file mode 100644 (file)
index 0000000..093183c
--- /dev/null
@@ -0,0 +1,145 @@
+/* This file is part of the YAZ toolkit.
+ * Copyright (C) 1995-2013 Index Data
+ * See the file LICENSE for details.
+ */
+/**
+ * \file sru_facet.c
+ * \brief Implements SRU 2.0 facets
+ */
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include <yaz/srw.h>
+#include <yaz/wrbuf.h>
+#if YAZ_HAVE_XML2
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <assert.h>
+#endif
+
+#include "sru-p.h"
+#include <yaz/pquery.h>
+#include <yaz/facet.h>
+
+void yaz_sru_facet_request(ODR o, Z_FacetList **facetList, const char **limit)
+{
+    if (o->direction == ODR_ENCODE)
+    {
+        Z_FacetList *fl = *facetList;
+        if (fl)
+        {
+            int i;
+            WRBUF w = wrbuf_alloc();
+            for (i = 0; i < fl->num; i++)
+            {
+                struct yaz_facet_attr av;
+                yaz_facet_attr_init(&av);
+                yaz_facet_attr_get_z_attributes(fl->elements[i]->attributes,
+                                                &av);
+                if (av.errcode == 0)
+                {
+                    wrbuf_printf(w, "%d", av.limit ? av.limit : -1);
+                    if (av.useattr)
+                        wrbuf_printf(w, ":%s,", av.useattr);
+                    /* av.relation not considered yet */
+                }
+            }
+            if (wrbuf_len(w) > 0)
+            {
+                wrbuf_cut_right(w, 1); /* remove , */
+                *limit = odr_strdup(o, wrbuf_cstr(w));
+            }
+            wrbuf_destroy(w);
+        }
+    }
+    else if (o->direction == ODR_DECODE)
+    {
+        const char *cp = *limit;
+        *facetList = 0;
+        if (cp)
+        {
+            int nor = 0;
+            int limit_val = 0;
+            WRBUF w = wrbuf_alloc();
+            while (sscanf(cp, "%d%n", &limit_val, &nor) >= 1 && nor > 0)
+            {
+                cp += nor;
+                if (wrbuf_len(w))
+                    wrbuf_puts(w, ",");
+                if (*cp == ':') /* field name follows */
+                {
+                    wrbuf_puts(w, "@attr 1=");
+                    while (*++cp && *cp != ',')
+                        wrbuf_putc(w, *cp);
+                    wrbuf_puts(w, " ");
+                }
+                if (limit_val != -1)
+                    wrbuf_printf(w, "@attr 3=%d", limit_val);
+                if (*cp != ',')
+                    break;
+                cp++;
+            }
+            if (wrbuf_len(w))
+                *facetList = yaz_pqf_parse_facet_list(o, wrbuf_cstr(w));
+            wrbuf_destroy(w);
+        }
+    }
+}
+
+#if YAZ_HAVE_XML2
+void yaz_sru_facet_response(ODR o, Z_FacetList **facetList, xmlNodePtr n)
+{
+    if (o->direction == ODR_ENCODE)
+    {
+        Z_FacetList *fl = *facetList;
+        if (fl)
+        {
+            int i;
+            const char *ns =
+                "http://docs.oasis-open.org/ns/search-ws/facetedResults";
+            xmlNode *p1 = xmlNewChild(n, 0, BAD_CAST "facetedResults", 0);
+            xmlNsPtr ns_fr = xmlNewNs(p1, BAD_CAST ns, BAD_CAST "fr");
+            xmlSetNs(p1, ns_fr);
+            for (i = 0; i < fl->num; i++)
+            {
+                Z_FacetField *ff = fl->elements[i];
+                xmlNode *p2 = xmlNewChild(p1, 0, BAD_CAST "facet", 0);
+                int j;
+                xmlNode *p3;
+                struct yaz_facet_attr av;
+                yaz_facet_attr_init(&av);
+                yaz_facet_attr_get_z_attributes(ff->attributes, &av);
+                add_xsd_string(p2, "index", av.useattr);
+                p3 = xmlNewChild(p2, 0, BAD_CAST "terms", 0);
+                for (j = 0; j < ff->num_terms; j++)
+                {
+                    Z_FacetTerm *ft = ff->terms[j];
+                    Z_Term *zt = ft->term;
+                    xmlNode *p4 = xmlNewChild(p3, 0, BAD_CAST "term", 0);
+                    if (zt->which == Z_Term_general)
+                        add_xsd_string_n(p4, "actualTerm",
+                                         (char *) zt->u.general->buf,
+                                         zt->u.general->len);
+                    if (ft->count)
+                        add_xsd_integer(p4, "count", ft->count);
+                }
+            }
+        }
+    }
+}
+
+#endif
+
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
index 4013458..7f0cd29 100644 (file)
--- a/src/srw.c
+++ b/src/srw.c
@@ -18,7 +18,7 @@
 #include <libxml/parser.h>
 #include <libxml/tree.h>
 #include <assert.h>
 #include <libxml/parser.h>
 #include <libxml/tree.h>
 #include <assert.h>
-
+#include <yaz/facet.h>
 #include "sru-p.h"
 
 static void add_XML_n(xmlNodePtr ptr, const char *elem, char *val, int len,
 #include "sru-p.h"
 
 static void add_XML_n(xmlNodePtr ptr, const char *elem, char *val, int len,
@@ -68,7 +68,7 @@ xmlNodePtr add_xsd_string(xmlNodePtr ptr, const char *elem, const char *val)
     return add_xsd_string_ns(ptr, elem, val, 0);
 }
 
     return add_xsd_string_ns(ptr, elem, val, 0);
 }
 
-static void add_xsd_integer(xmlNodePtr ptr, const char *elem,
+void add_xsd_integer(xmlNodePtr ptr, const char *elem,
                             const Odr_int *val)
 {
     if (val)
                             const Odr_int *val)
 {
     if (val)
@@ -762,6 +762,7 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
             Z_SRW_searchRetrieveRequest *req;
             char *recordPacking = 0;
             char *recordXMLEscaping = 0;
             Z_SRW_searchRetrieveRequest *req;
             char *recordPacking = 0;
             char *recordXMLEscaping = 0;
+            const char *facetLimit = 0;
 
             (*p)->which = Z_SRW_searchRetrieve_request;
             req = (*p)->u.request = (Z_SRW_searchRetrieveRequest *)
 
             (*p)->which = Z_SRW_searchRetrieve_request;
             req = (*p)->u.request = (Z_SRW_searchRetrieveRequest *)
@@ -824,8 +825,11 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
                 else if (match_xsd_string(ptr, "stylesheet", o,
                                           &req->stylesheet))
                     ;
                 else if (match_xsd_string(ptr, "stylesheet", o,
                                           &req->stylesheet))
                     ;
-                else
-                    match_xsd_string(ptr, "database", o, &req->database);
+                else if (match_xsd_string(ptr, "database", o, &req->database))
+                    ;
+                else if (match_xsd_string(ptr, "facetLimit", o,
+                                          (char**) &facetLimit))
+                    ;
             }
             if (!req->query)
             {
             }
             if (!req->query)
             {
@@ -841,6 +845,7 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
             {
                 req->recordPacking = recordPacking;
             }
             {
                 req->recordPacking = recordPacking;
             }
+            yaz_sru_facet_request(o, &req->facetList, &facetLimit);
         }
         else if (!xmlStrcmp(method->name, BAD_CAST "searchRetrieveResponse"))
         {
         }
         else if (!xmlStrcmp(method->name, BAD_CAST "searchRetrieveResponse"))
         {
@@ -900,6 +905,8 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
                                         client_data, ns);
                 else if (match_element(ptr, "facet_analysis"))
                     yaz_sru_proxy_decode_facets(o, ptr, &res->facetList);
                                         client_data, ns);
                 else if (match_element(ptr, "facet_analysis"))
                     yaz_sru_proxy_decode_facets(o, ptr, &res->facetList);
+                else if (match_element(ptr, "facetedResults"))
+                    yaz_sru_facet_response(o, &res->facetList, ptr);
             }
         }
         else if (!xmlStrcmp(method->name, BAD_CAST "explainRequest"))
             }
         }
         else if (!xmlStrcmp(method->name, BAD_CAST "explainRequest"))
@@ -1111,6 +1118,11 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
             }
             add_xsd_string(ptr, "stylesheet", req->stylesheet);
             add_xsd_string(ptr, "database", req->database);
             }
             add_xsd_string(ptr, "stylesheet", req->stylesheet);
             add_xsd_string(ptr, "database", req->database);
+            {
+                const char *limit = 0;
+                yaz_sru_facet_request(o, &req->facetList, &limit);
+                add_xsd_string(ptr, "facetLimit", limit);
+            }
         }
         else if ((*p)->which == Z_SRW_searchRetrieve_response)
         {
         }
         else if ((*p)->which == Z_SRW_searchRetrieve_response)
         {
@@ -1146,6 +1158,7 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
             if (res->resultCountPrecision)
                 add_xsd_string(ptr, "resultCountPrecision",
                                res->resultCountPrecision);
             if (res->resultCountPrecision)
                 add_xsd_string(ptr, "resultCountPrecision",
                                res->resultCountPrecision);
+            yaz_sru_facet_response(o, &res->facetList, ptr);
         }
         else if ((*p)->which == Z_SRW_explain_request)
         {
         }
         else if ((*p)->which == Z_SRW_explain_request)
         {
index c18ca64..1937a77 100644 (file)
@@ -397,6 +397,7 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
         char *startRecord = 0;
         char *maximumTerms = 0;
         char *responsePosition = 0;
         char *startRecord = 0;
         char *maximumTerms = 0;
         char *responsePosition = 0;
+        const char *facetLimit = 0;
         Z_SRW_extra_arg *extra_args = 0;
 #endif
         char **uri_name;
         Z_SRW_extra_arg *extra_args = 0;
 #endif
         char **uri_name;
@@ -468,6 +469,8 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
                     maximumTerms = v;
                 else if (!strcmp(n, "responsePosition"))
                     responsePosition = v;
                     maximumTerms = v;
                 else if (!strcmp(n, "responsePosition"))
                     responsePosition = v;
+                else if (!strcmp(n, "facetLimit"))
+                    facetLimit = v;
                 else if (!strcmp(n, "extraRequestData"))
                     ; /* ignoring extraRequestData */
                 else if (n[0] == 'x' && n[1] == '-')
                 else if (!strcmp(n, "extraRequestData"))
                     ; /* ignoring extraRequestData */
                 else if (n[0] == 'x' && n[1] == '-')
@@ -552,6 +555,8 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
             sr->u.request->recordPacking = recordXMLEscaping;
             sr->u.request->packing = recordPacking;
             sr->u.request->stylesheet = stylesheet;
             sr->u.request->recordPacking = recordXMLEscaping;
             sr->u.request->packing = recordPacking;
             sr->u.request->stylesheet = stylesheet;
+            yaz_sru_facet_request(decode , &sr->u.request->facetList,
+                                  &facetLimit);
 
             yaz_sru_decode_integer(decode, "maximumRecords", maximumRecords,
                                    &sr->u.request->maximumRecords,
 
             yaz_sru_decode_integer(decode, "maximumRecords", maximumRecords,
                                    &sr->u.request->maximumRecords,
@@ -954,6 +959,13 @@ static int yaz_get_sru_parms(const Z_SRW_PDU *srw_pdu, ODR encode,
                                srw_pdu->u.request->stylesheet);
         yaz_add_name_value_int(encode, name, value, &i, "resultSetTTL",
                                srw_pdu->u.request->resultSetTTL);
                                srw_pdu->u.request->stylesheet);
         yaz_add_name_value_int(encode, name, value, &i, "resultSetTTL",
                                srw_pdu->u.request->resultSetTTL);
+        {
+            const char *facetLimit = 0;
+            yaz_sru_facet_request(encode, &srw_pdu->u.request->facetList,
+                                  &facetLimit);
+            yaz_add_name_value_str(encode, name, value, &i, "facetLimit",
+                                   (char *) facetLimit);
+        }
         break;
     case Z_SRW_explain_request:
         value[i++] = "explain";
         break;
     case Z_SRW_explain_request:
         value[i++] = "explain";
@@ -1042,7 +1054,6 @@ int yaz_sru_get_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
         odr_malloc(encode, strlen(hreq->path) + strlen(uri_args) + 4);
 
     sprintf(path, "%s?%s", hreq->path, uri_args);
         odr_malloc(encode, strlen(hreq->path) + strlen(uri_args) + 4);
 
     sprintf(path, "%s?%s", hreq->path, uri_args);
-    yaz_log(YLOG_DEBUG, "SRU HTTP Get Request %s", path);
     hreq->path = path;
 
     z_HTTP_header_add_content_type(encode, &hreq->headers,
     hreq->path = path;
 
     z_HTTP_header_add_content_type(encode, &hreq->headers,
index 6204044..e04c57e 100644 (file)
@@ -495,6 +495,7 @@ MISC_OBJS= \
    $(OBJDIR)\soap.obj \
    $(OBJDIR)\solr.obj \
    $(OBJDIR)\solrtransform.obj \
    $(OBJDIR)\soap.obj \
    $(OBJDIR)\solr.obj \
    $(OBJDIR)\solrtransform.obj \
+   $(OBJDIR)\sru_facet.obj \
    $(OBJDIR)\srw.obj \
    $(OBJDIR)\srwutil.obj \
    $(OBJDIR)\zoom-c.obj \
    $(OBJDIR)\srw.obj \
    $(OBJDIR)\srwutil.obj \
    $(OBJDIR)\zoom-c.obj \