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