YAZ 5.37.0
sru_facet.c
Go to the documentation of this file.
1/* This file is part of the YAZ toolkit.
2 * Copyright (C) Index Data
3 * See the file LICENSE for details.
4 */
9#if HAVE_CONFIG_H
10#include <config.h>
11#endif
12
13#include <stdlib.h>
14
15#include <yaz/srw.h>
16#include <yaz/wrbuf.h>
17#if YAZ_HAVE_XML2
18#include <libxml/parser.h>
19#include <libxml/tree.h>
20#include <assert.h>
21#endif
22
23#include "sru-p.h"
24#include <yaz/pquery.h>
25#include <yaz/facet.h>
26#include <yaz/snprintf.h>
27
28static void insert_field(WRBUF w, const char *field, size_t length,
29 const char *attr)
30{
31 const char *cp0 = wrbuf_cstr(w);
32 const char *cp = cp0;
33
34 while (1)
35 {
36 const char *cp2 = strstr(cp, "@attr 1=");
37 if (!cp2)
38 break;
39 cp = cp2 + 8;
40 if (!strncmp(cp, field, length) &&
41 (cp[length] == ' ' || cp[length] == ',' || cp[length] == '\0'))
42 {
43 /* found the field */
44
45 cp += length;
46 wrbuf_insert(w, cp - cp0, attr, strlen(attr));
47 wrbuf_insert(w, cp - cp0, " ", 1);
48 return;
49 }
50 while (*cp && *cp != ',')
51 cp++;
52 }
53 if (wrbuf_len(w))
54 wrbuf_puts(w, ",");
55 wrbuf_puts(w, "@attr 1=");
56 wrbuf_write(w, field, length);
57 wrbuf_puts(w, " ");
58 wrbuf_puts(w, attr);
59}
60
61void yaz_sru_facet_request(ODR o, Z_FacetList **facetList, const char **limit,
62 const char **start, const char **sort)
63{
64 if (o->direction == ODR_ENCODE)
65 {
66 Z_FacetList *fl = *facetList;
67 if (fl)
68 {
69 WRBUF w_limit = wrbuf_alloc();
70 int general_start = -1;
71 int general_sortorder = -1;
72 int general_limit = -1;
73 int i;
74 for (i = 0; i < fl->num; i++)
75 {
76 struct yaz_facet_attr av;
78 av.start = -1;
79 av.sortorder = -1;
80 av.limit = -1;
82 &av);
83 if (av.errcode == 0)
84 {
85 if (av.limit != -1)
86 {
87 if (av.useattr)
88 {
89 wrbuf_printf(w_limit, "%d:%s", av.limit,
90 av.useattr);
91 wrbuf_puts(w_limit, ",");
92 }
93 else
94 general_limit = av.limit;
95 }
96 if (av.start != -1)
97 general_start = av.start;
98 if (av.sortorder != -1)
99 general_sortorder = av.sortorder;
100 }
101 }
102 if (general_limit != -1)
103 {
104 char tmp[32];
105 yaz_snprintf(tmp, sizeof tmp, "%d,", general_limit);
106 wrbuf_insert(w_limit, 0, tmp, strlen(tmp));
107 }
108 if (wrbuf_len(w_limit) > 1)
109 {
110 wrbuf_cut_right(w_limit, 1);
111 *limit = odr_strdup(o, wrbuf_cstr(w_limit));
112 }
113 if (general_start != -1)
114 {
115 char tmp[32];
116 yaz_snprintf(tmp, sizeof tmp, "%d", general_start);
117 *start = odr_strdup(o, tmp);
118 }
119 if (general_sortorder == 1)
120 {
121 *sort = odr_strdup(o, "alphanumeric");
122 }
123 wrbuf_destroy(w_limit);
124 }
125 }
126 else if (o->direction == ODR_DECODE)
127 {
128 WRBUF w = wrbuf_alloc();
129 int general_limit = -1;
130
131 if (*limit)
132 {
133 const char *cp = *limit;
134 int nor = 0;
135 int val = 0;
136 while (sscanf(cp, "%d%n", &val, &nor) >= 1 && nor > 0)
137 {
138 cp += nor;
139 if (*cp == ':') /* field name follows */
140 {
141 char tmp[40];
142 const char *cp0 = ++cp;
143 while (*cp && *cp != ',')
144 cp++;
145 yaz_snprintf(tmp, sizeof tmp, "@attr 3=%d", val);
146 insert_field(w, cp0, cp - cp0, tmp);
147
148 if (*start && strlen(*start) < 20)
149 {
150 yaz_snprintf(tmp, sizeof tmp, "@attr 4=%s", *start);
151 insert_field(w, cp0, cp - cp0, tmp);
152 }
153 if (*sort && !strcmp(*sort, "alphanumeric"))
154 insert_field(w, cp0, cp - cp0, "@attr 2=1");
155 else
156 insert_field(w, cp0, cp - cp0, "@attr 2=0");
157 }
158 else
159 general_limit = val;
160
161 if (*cp != ',')
162 break;
163 cp++;
164 }
165 }
166 if (*sort || *start || general_limit != -1)
167 {
168 if (wrbuf_len(w))
169 wrbuf_puts(w, ",");
170 if (*sort && !strcmp(*sort, "alphanumeric"))
171 wrbuf_printf(w, " @attr 2=1");
172 else
173 wrbuf_printf(w, " @attr 2=0");
174 if (general_limit != -1)
175 wrbuf_printf(w, " @attr 3=%d", general_limit);
176 if (*start)
177 {
178 wrbuf_printf(w, " @attr 4=%s", *start);
179 }
180 }
181 if (wrbuf_len(w))
182 *facetList = yaz_pqf_parse_facet_list(o, wrbuf_cstr(w));
183 else
184 *facetList = 0;
185 wrbuf_destroy(w);
186 }
187}
188
189#if YAZ_HAVE_XML2
190void yaz_sru_facet_response(ODR o, Z_FacetList **facetList, xmlNodePtr n)
191{
192 if (o->direction == ODR_ENCODE)
193 {
194 Z_FacetList *fl = *facetList;
195 if (fl)
196 {
197 int i;
198 const char *ns =
199 "http://docs.oasis-open.org/ns/search-ws/facetedResults";
200 xmlNode *p1 = xmlNewChild(n, 0, BAD_CAST "facetedResults", 0);
201 xmlNsPtr ns_fr = xmlNewNs(p1, BAD_CAST ns, BAD_CAST "fr");
202 for (i = 0; i < fl->num; i++)
203 {
204 Z_FacetField *ff = fl->elements[i];
205 xmlNode *p2 = xmlNewChild(p1, ns_fr, BAD_CAST "facet", 0);
206 int j;
207 xmlNode *p3;
208 struct yaz_facet_attr av;
211 add_xsd_string(p2, "index", av.useattr);
212 p3 = xmlNewChild(p2, 0, BAD_CAST "terms", 0);
213 for (j = 0; j < ff->num_terms; j++)
214 {
215 Z_FacetTerm *ft = ff->terms[j];
216 Z_Term *zt = ft->term;
217 xmlNode *p4 = xmlNewChild(p3, 0, BAD_CAST "term", 0);
218 if (zt->which == Z_Term_general)
219 add_xsd_string_n(p4, "actualTerm",
220 (char *) zt->u.general->buf,
221 zt->u.general->len);
222 if (ft->count)
223 add_xsd_integer(p4, "count", ft->count);
224 }
225 }
226 }
227 }
228 else if (o->direction == ODR_DECODE)
229 {
230 Z_FacetList *fl = (Z_FacetList *) odr_malloc(o, sizeof(*fl));
231 xmlNode *p1;
232
233 fl->num = 0;
234 for (p1 = n->children; p1; p1 = p1->next)
235 if (yaz_match_xsd_element(p1, "facet"))
236 fl->num++;
237 if (fl->num > 0)
238 {
239 int i = 0;
240 *facetList = fl;
241 fl->elements = (Z_FacetField **)
242 odr_malloc(o, sizeof(*fl->elements) * fl->num);
243 for (p1 = n->children; p1; p1 = p1->next)
244 if (yaz_match_xsd_element(p1, "facet"))
245 {
246 char *index_name = 0;
247 xmlNode *p_terms = 0;
248 xmlNode *p2 = p1->children;
249 Z_FacetField *ff = (Z_FacetField *)
250 odr_malloc(o, sizeof(*ff));
251 fl->elements[i++] = ff;
252 ff->attributes = 0;
253 ff->num_terms = 0;
254 ff->terms = 0;
255 for (; p2; p2 = p2->next)
256 {
257 if (yaz_match_xsd_string(p2, "index", o, &index_name))
258 ;
259 else if (yaz_match_xsd_element(p2, "terms"))
260 p_terms = p2;
261 }
262 if (index_name)
263 ff->attributes =
264 zget_AttributeList_use_string(o, index_name);
265 if (p_terms)
266 {
267 xmlNode *p;
268 int i = 0;
269 for (p = p_terms->children; p; p = p->next)
270 {
271 if (yaz_match_xsd_element(p, "term"))
272 ff->num_terms++;
273 }
274 if (ff->num_terms)
275 ff->terms = (Z_FacetTerm **)
276 odr_malloc(o,
277 sizeof(*ff->terms) * ff->num_terms);
278 for (p = p_terms->children; p; p = p->next)
279 {
280 if (yaz_match_xsd_element(p, "term"))
281 {
282 char *cstr = 0;
283 Odr_int *count = 0;
284 xmlNode *p2 = p->children;
285 for (; p2; p2 = p2->next)
286 {
287 if (yaz_match_xsd_string(p2, "actualTerm", o,
288 &cstr))
289 ;
290 else if (yaz_match_xsd_integer(p2, "count", o,
291 &count))
292 ;
293 else
294 ;
295 }
296 if (cstr && count)
297 {
298 ff->terms[i++] =
299 facet_term_create_cstr(o, cstr, *count);
300 }
301 }
302 }
303 ff->num_terms = i;
304 if (ff->num_terms == 0)
305 ff->terms = 0;
306 }
307 }
308
309 }
310 }
311}
312
313#endif
314
315
316/*
317 * Local variables:
318 * c-basic-offset: 4
319 * c-file-style: "Stroustrup"
320 * indent-tabs-mode: nil
321 * End:
322 * vim: shiftwidth=4 tabstop=8 expandtab
323 */
324
Z_FacetTerm * facet_term_create_cstr(ODR odr, const char *cstr, Odr_int freq)
Definition facet.c:190
void yaz_facet_attr_init(struct yaz_facet_attr *attr_values)
Definition facet.c:69
void yaz_facet_attr_get_z_attributes(const Z_AttributeList *attributes, struct yaz_facet_attr *av)
Definition facet.c:148
Header for the facet utilities.
#define ODR_DECODE
Definition odr.h:95
struct odr * ODR
Definition odr.h:121
nmem_int_t Odr_int
Definition odr.h:47
#define ODR_ENCODE
Definition odr.h:96
void * odr_malloc(ODR o, size_t size)
Definition odr_mem.c:31
char * odr_strdup(ODR o, const char *str)
Definition odr_mem.c:36
Z_FacetList * yaz_pqf_parse_facet_list(ODR o, const char *qbuf)
Definition pquery.c:882
Z_AttributeList * zget_AttributeList_use_string(ODR o, const char *name)
creates AttributeList with type=1(use) and string value
Definition pquery.c:310
Header for PQF parsing.
void yaz_snprintf(char *buf, size_t size, const char *fmt,...)
Definition snprintf.c:31
Header for config file reading utilities.
SRU private header.
int yaz_match_xsd_element(xmlNodePtr ptr, const char *elem)
Definition xml_match.c:18
void add_xsd_integer(xmlNodePtr ptr, const char *elem, const Odr_int *val)
Definition xml_add.c:68
xmlNodePtr add_xsd_string(xmlNodePtr ptr, const char *elem, const char *val)
Definition xml_add.c:63
int yaz_match_xsd_string(xmlNodePtr ptr, const char *elem, ODR o, char **val)
Definition xml_match.c:72
xmlNodePtr add_xsd_string_n(xmlNodePtr ptr, const char *elem, const char *val, int len)
Definition xml_add.c:37
int yaz_match_xsd_integer(xmlNodePtr ptr, const char *elem, ODR o, Odr_int **val)
Definition xml_match.c:124
void yaz_sru_facet_request(ODR o, Z_FacetList **facetList, const char **limit, const char **start, const char **sort)
Definition sru_facet.c:61
void yaz_sru_facet_response(ODR o, Z_FacetList **facetList, xmlNodePtr n)
Definition sru_facet.c:190
static void insert_field(WRBUF w, const char *field, size_t length, const char *attr)
Definition sru_facet.c:28
Header for SRW/SRU.
Z_AttributeList * attributes
Definition z-facet-1.h:36
Z_FacetTerm ** terms
Definition z-facet-1.h:38
Z_FacetField ** elements
Definition z-facet-1.h:32
Odr_int * count
Definition z-facet-1.h:43
Z_Term * term
Definition z-facet-1.h:42
union Z_Term::@023217361022206241314262227377164117366363003164 u
Odr_oct * general
Definition z-core.h:539
int which
Definition z-core.h:537
int len
Definition odr.h:102
char * buf
Definition odr.h:101
int direction
Definition odr.h:126
int sortorder
Definition facet.h:60
const char * useattr
Definition facet.h:56
int errcode
Definition facet.h:54
void wrbuf_destroy(WRBUF b)
destroy WRBUF and its buffer
Definition wrbuf.c:38
void wrbuf_insert(WRBUF b, size_t pos, const char *buf, size_t size)
inserts buffer into WRBUF at some position
Definition wrbuf.c:78
const char * wrbuf_cstr(WRBUF b)
returns WRBUF content as C-string
Definition wrbuf.c:299
WRBUF wrbuf_alloc(void)
construct WRBUF
Definition wrbuf.c:25
void wrbuf_printf(WRBUF b, const char *fmt,...)
writes printf result to WRBUF
Definition wrbuf.c:189
void wrbuf_cut_right(WRBUF b, size_t no_to_remove)
cut size of WRBUF
Definition wrbuf.c:315
void wrbuf_puts(WRBUF b, const char *buf)
appends C-string to WRBUF
Definition wrbuf.c:89
void wrbuf_write(WRBUF b, const char *buf, size_t size)
append constant size buffer to WRBUF
Definition wrbuf.c:68
Header for WRBUF (growing buffer).
#define wrbuf_len(b)
Definition wrbuf.h:269
struct wrbuf * WRBUF
#define Z_Term_general
Definition z-core.h:547