From d2ed898832ae354c17254ff52c70c92278518efe Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Mon, 9 Sep 2013 15:18:37 +0200 Subject: [PATCH] Towards working facets --- include/yaz/srw.h | 2 +- src/Makefile.am | 2 +- src/facet.c | 26 ++++++---- src/seshigh.c | 10 +++- src/sru-p.h | 15 +++++- src/sru_facet.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/srw.c | 21 ++++++-- src/srwutil.c | 13 ++++- win/makefile | 1 + 9 files changed, 215 insertions(+), 20 deletions(-) create mode 100644 src/sru_facet.c diff --git a/include/yaz/srw.h b/include/yaz/srw.h index b86b790..b29562a 100644 --- a/include/yaz/srw.h +++ b/include/yaz/srw.h @@ -37,7 +37,7 @@ #include #include #include -#include "facet.h" +#include YAZ_BEGIN_CDECL diff --git a/src/Makefile.am b/src/Makefile.am index 2e7f700..b5bdd97 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 \ - 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 \ diff --git a/src/facet.c b/src/facet.c index a9d1ef9..40b5e1c 100644 --- a/src/facet.c +++ b/src/facet.c @@ -43,17 +43,21 @@ void yaz_oi_set_facetlist( 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; } diff --git a/src/seshigh.c b/src/seshigh.c index 07ee014..77539a7 100644 --- a/src/seshigh.c +++ b/src/seshigh.c @@ -56,6 +56,7 @@ #include #endif +#include #include #include #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; + + 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); @@ -1045,7 +1051,9 @@ static void srw_bend_search(association *assoc, 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 */ diff --git a/src/sru-p.h b/src/sru-p.h index 7bd2762..aa3f3bf 100644 --- a/src/sru-p.h +++ b/src/sru-p.h @@ -39,10 +39,23 @@ Z_AttributeList *yaz_use_attribute_create(ODR o, const char *name); 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 #include -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 /* diff --git a/src/sru_facet.c b/src/sru_facet.c new file mode 100644 index 0000000..093183c --- /dev/null +++ b/src/sru_facet.c @@ -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 +#endif + +#include + +#include +#include +#if YAZ_HAVE_XML2 +#include +#include +#include +#endif + +#include "sru-p.h" +#include +#include + +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 + */ + diff --git a/src/srw.c b/src/srw.c index 4013458..7f0cd29 100644 --- a/src/srw.c +++ b/src/srw.c @@ -18,7 +18,7 @@ #include #include #include - +#include #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); } -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) @@ -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; + const char *facetLimit = 0; (*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 - 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) { @@ -841,6 +845,7 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data, { req->recordPacking = recordPacking; } + yaz_sru_facet_request(o, &req->facetList, &facetLimit); } 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); + else if (match_element(ptr, "facetedResults")) + yaz_sru_facet_response(o, &res->facetList, ptr); } } 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); + { + 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) { @@ -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); + yaz_sru_facet_response(o, &res->facetList, ptr); } else if ((*p)->which == Z_SRW_explain_request) { diff --git a/src/srwutil.c b/src/srwutil.c index c18ca64..1937a77 100644 --- a/src/srwutil.c +++ b/src/srwutil.c @@ -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; + const char *facetLimit = 0; 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; + else if (!strcmp(n, "facetLimit")) + facetLimit = v; 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; + yaz_sru_facet_request(decode , &sr->u.request->facetList, + &facetLimit); 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); + { + 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"; @@ -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); - yaz_log(YLOG_DEBUG, "SRU HTTP Get Request %s", path); hreq->path = path; z_HTTP_header_add_content_type(encode, &hreq->headers, diff --git a/win/makefile b/win/makefile index 6204044..e04c57e 100644 --- a/win/makefile +++ b/win/makefile @@ -495,6 +495,7 @@ MISC_OBJS= \ $(OBJDIR)\soap.obj \ $(OBJDIR)\solr.obj \ $(OBJDIR)\solrtransform.obj \ + $(OBJDIR)\sru_facet.obj \ $(OBJDIR)\srw.obj \ $(OBJDIR)\srwutil.obj \ $(OBJDIR)\zoom-c.obj \ -- 1.7.10.4