1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) Index Data
3 * See the file LICENSE for details.
7 * \brief Implements SRU 2.0 facets
16 #include <yaz/wrbuf.h>
18 #include <libxml/parser.h>
19 #include <libxml/tree.h>
24 #include <yaz/pquery.h>
25 #include <yaz/facet.h>
27 static void insert_field(WRBUF w, const char *field, size_t length,
30 const char *cp0 = wrbuf_cstr(w);
35 const char *cp2 = strstr(cp, "@attr 1=");
39 if (!strncmp(cp, field, length) &&
40 (cp[length] == ' ' || cp[length] == ',' || cp[length] == '\0'))
45 wrbuf_insert(w, cp - cp0, attr, strlen(attr));
46 wrbuf_insert(w, cp - cp0, " ", 1);
49 while (*cp && *cp != ',')
54 wrbuf_puts(w, "@attr 1=");
55 wrbuf_write(w, field, length);
60 void yaz_sru_facet_request(ODR o, Z_FacetList **facetList, const char **limit,
61 const char **start, const char **sort)
63 if (o->direction == ODR_ENCODE)
65 Z_FacetList *fl = *facetList;
68 WRBUF w_limit = wrbuf_alloc();
69 int general_start = -1;
70 int general_sortorder = -1;
71 int general_limit = -1;
73 for (i = 0; i < fl->num; i++)
75 struct yaz_facet_attr av;
76 yaz_facet_attr_init(&av);
80 yaz_facet_attr_get_z_attributes(fl->elements[i]->attributes,
88 wrbuf_printf(w_limit, "%d:%s", av.limit,
90 wrbuf_puts(w_limit, ",");
93 general_limit = av.limit;
96 general_start = av.start;
97 if (av.sortorder != -1)
98 general_sortorder = av.sortorder;
101 if (general_limit != -1)
104 sprintf(tmp, "%d,", general_limit);
105 wrbuf_insert(w_limit, 0, tmp, strlen(tmp));
107 if (wrbuf_len(w_limit) > 1)
109 wrbuf_cut_right(w_limit, 1);
110 *limit = odr_strdup(o, wrbuf_cstr(w_limit));
112 if (general_start != -1)
115 sprintf(tmp, "%d", general_start);
116 *start = odr_strdup(o, tmp);
118 if (general_sortorder == 1)
120 *sort = odr_strdup(o, "alphanumeric");
122 wrbuf_destroy(w_limit);
125 else if (o->direction == ODR_DECODE)
127 WRBUF w = wrbuf_alloc();
128 int general_limit = -1;
132 const char *cp = *limit;
135 while (sscanf(cp, "%d%n", &val, &nor) >= 1 && nor > 0)
138 if (*cp == ':') /* field name follows */
141 const char *cp0 = ++cp;
142 while (*cp && *cp != ',')
144 sprintf(tmp, "@attr 3=%d", val);
145 insert_field(w, cp0, cp - cp0, tmp);
147 if (*start && strlen(*start) < 20)
149 sprintf(tmp, "@attr 4=%s", *start);
150 insert_field(w, cp0, cp - cp0, tmp);
152 if (*sort && !strcmp(*sort, "alphanumeric"))
153 insert_field(w, cp0, cp - cp0, "@attr 2=1");
155 insert_field(w, cp0, cp - cp0, "@attr 2=0");
165 if (*sort || *start || general_limit != -1)
169 if (*sort && !strcmp(*sort, "alphanumeric"))
170 wrbuf_printf(w, " @attr 2=1");
172 wrbuf_printf(w, " @attr 2=0");
173 if (general_limit != -1)
174 wrbuf_printf(w, " @attr 3=%d", general_limit);
177 wrbuf_printf(w, " @attr 4=%s", *start);
181 *facetList = yaz_pqf_parse_facet_list(o, wrbuf_cstr(w));
189 void yaz_sru_facet_response(ODR o, Z_FacetList **facetList, xmlNodePtr n)
191 if (o->direction == ODR_ENCODE)
193 Z_FacetList *fl = *facetList;
198 "http://docs.oasis-open.org/ns/search-ws/facetedResults";
199 xmlNode *p1 = xmlNewChild(n, 0, BAD_CAST "facetedResults", 0);
200 xmlNsPtr ns_fr = xmlNewNs(p1, BAD_CAST ns, BAD_CAST "fr");
201 for (i = 0; i < fl->num; i++)
203 Z_FacetField *ff = fl->elements[i];
204 xmlNode *p2 = xmlNewChild(p1, ns_fr, BAD_CAST "facet", 0);
207 struct yaz_facet_attr av;
208 yaz_facet_attr_init(&av);
209 yaz_facet_attr_get_z_attributes(ff->attributes, &av);
210 add_xsd_string(p2, "index", av.useattr);
211 p3 = xmlNewChild(p2, 0, BAD_CAST "terms", 0);
212 for (j = 0; j < ff->num_terms; j++)
214 Z_FacetTerm *ft = ff->terms[j];
215 Z_Term *zt = ft->term;
216 xmlNode *p4 = xmlNewChild(p3, 0, BAD_CAST "term", 0);
217 if (zt->which == Z_Term_general)
218 add_xsd_string_n(p4, "actualTerm",
219 (char *) zt->u.general->buf,
222 add_xsd_integer(p4, "count", ft->count);
227 else if (o->direction == ODR_DECODE)
229 Z_FacetList *fl = (Z_FacetList *) odr_malloc(o, sizeof(*fl));
233 for (p1 = n->children; p1; p1 = p1->next)
234 if (yaz_match_xsd_element(p1, "facet"))
240 fl->elements = (Z_FacetField **)
241 odr_malloc(o, sizeof(*fl->elements) * fl->num);
242 for (p1 = n->children; p1; p1 = p1->next)
243 if (yaz_match_xsd_element(p1, "facet"))
245 char *index_name = 0;
246 xmlNode *p_terms = 0;
247 xmlNode *p2 = p1->children;
248 Z_FacetField *ff = (Z_FacetField *)
249 odr_malloc(o, sizeof(*ff));
250 fl->elements[i++] = ff;
254 for (; p2; p2 = p2->next)
256 if (yaz_match_xsd_string(p2, "index", o, &index_name))
258 else if (yaz_match_xsd_element(p2, "terms"))
262 ff->attributes = yaz_use_attribute_create(o,
268 for (p = p_terms->children; p; p = p->next)
270 if (yaz_match_xsd_element(p, "term"))
274 ff->terms = (Z_FacetTerm **)
276 sizeof(*ff->terms) * ff->num_terms);
277 for (p = p_terms->children; p; p = p->next)
279 if (yaz_match_xsd_element(p, "term"))
283 xmlNode *p2 = p->children;
284 for (; p2; p2 = p2->next)
286 if (yaz_match_xsd_string(p2, "actualTerm", o,
289 else if (yaz_match_xsd_integer(p2, "count", o,
296 facet_term_create_cstr(o, cstr, *count);
301 if (ff->num_terms == 0)
316 * c-file-style: "Stroustrup"
317 * indent-tabs-mode: nil
319 * vim: shiftwidth=4 tabstop=8 expandtab