YAZ  4.2.57
rpn2solr.c
Go to the documentation of this file.
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2013 Index Data
3  * See the file LICENSE for details.
4  */
9 #if HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12 
13 #include <assert.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <yaz/rpn2solr.h>
17 #include <yaz/xmalloc.h>
18 #include <yaz/diagbib1.h>
19 #include <yaz/z-core.h>
20 #include <yaz/wrbuf.h>
21 
22 static void wrbuf_vputs(const char *buf, void *client_data)
23 {
24  wrbuf_write((WRBUF) client_data, buf, strlen(buf));
25 }
26 
27 static const char *lookup_index_from_string_attr(Z_AttributeList *attributes)
28 {
29  int j;
30  int server_choice = 1;
31  for (j = 0; j < attributes->num_attributes; j++)
32  {
33  Z_AttributeElement *ae = attributes->attributes[j];
34  if (*ae->attributeType == 1) /* use attribute */
35  {
37  {
39  int i;
40  for (i = 0; i < ca->num_list; i++)
41  {
42  Z_StringOrNumeric *son = ca->list[i];
43  if (son->which == Z_StringOrNumeric_string)
44  return son->u.string;
45  }
46  }
47  server_choice = 0; /* not serverChoice because we have use attr */
48  }
49  }
50  if (server_choice)
51  return "solr.serverChoice";
52  return 0;
53 }
54 
55 static const char *lookup_relation_index_from_attr(Z_AttributeList *attributes)
56 {
57  int j;
58  for (j = 0; j < attributes->num_attributes; j++)
59  {
60  Z_AttributeElement *ae = attributes->attributes[j];
61  if (*ae->attributeType == 2) /* relation attribute */
62  {
64  {
65  /* Only support for numeric relation */
66  Odr_int *relation = ae->value.numeric;
67  /* map this numeric to representation in SOLR */
68  switch (*relation)
69  {
70  /* Unsure on whether this is the relation attribute constants? */
72  return 0;
74  return 0;
76  return ":";
78  return 0;
80  return 0;
82  return 0;
83  case 100:
84  /* phonetic is not implemented*/
85  return 0;
86  case 101:
87  /* stem is not not implemented */
88  return 0;
89  case 102:
90  /* relevance is supported in SOLR, but not implemented yet */
91  return 0;
92  default:
93  /* Invalid relation */
94  return 0;
95  }
96  }
97  else {
98  /* Can we have a complex relation value?
99  Should we implement something?
100  */
101  }
102  }
103  }
104  return ":";
105 }
106 
108  Z_AttributeList *attributes, WRBUF w)
109 {
110  const char *relation = solr_lookup_reverse(ct, "relation.", attributes);
111  const char *index = solr_lookup_reverse(ct, "index.", attributes);
112  const char *structure = solr_lookup_reverse(ct, "structure.", attributes);
113 
114  /* if transform (properties) do not match, we'll just use a USE string attribute (bug #2978) */
115  if (!index)
116  index = lookup_index_from_string_attr(attributes);
117 
118  /* Attempt to fix bug #2978: Look for a relation attribute */
119  if (!relation)
120  relation = lookup_relation_index_from_attr(attributes);
121 
122  if (!index)
123  {
126  return -1;
127  }
128  /* for serverChoice we omit index+relation+structure */
129  if (strcmp(index, "solr.serverChoice"))
130  {
131  wrbuf_puts(w, index);
132  if (relation)
133  {
134  if (!strcmp(relation, "exact"))
135  /* TODO Verify if a exact SOLR exists */
136  relation = ":";
137  else if (!strcmp(relation, "eq"))
138  relation = ":";
139  else if (!strcmp(relation, "le")) {
140  /* TODO Not support as such, but could perhaps be transformed into a range
141  relation = ":[ * to ";
142  close_range = "]"
143  */
144  }
145  else if (!strcmp(relation, "ge")) {
146  /* TODO Not support as such, but could perhaps be transformed into a range
147  relation = "[";
148  relation = ":[ * to ";
149  close_range = "]"
150  */
151  }
152  /* Missing mapping of not equal, phonetic, stem and relevance */
153  wrbuf_puts(w, relation);
154  }
155  else
156  wrbuf_puts(w, ":");
157 
158  if (structure)
159  {
160  if (strcmp(structure, "*"))
161  {
162  wrbuf_puts(w, "/");
163  wrbuf_puts(w, structure);
164  wrbuf_puts(w, " ");
165  }
166  }
167  }
168  return 0;
169 }
170 
172 {
173  int j;
174  Z_AttributeList *attributes = apt->attributes;
175  for (j = 0; j < attributes->num_attributes; j++)
176  {
177  Z_AttributeElement *ae = attributes->attributes[j];
178  if (*ae->attributeType == 5) /* truncation attribute */
179  {
180  if (ae->which == Z_AttributeValue_numeric)
181  {
182  return *(ae->value.numeric);
183  }
184  else if (ae->which == Z_AttributeValue_complex) {
185  ;
186  //yaz_log(YLOG_DEBUG, "Z_Attribute_complex");
187  /* Complex: Shouldn't happen */
188  }
189  }
190  }
191  /* No truncation given */
192  return 0;
193 }
194 
195 #define SOLR_SPECIAL "+-&|!(){}[]^\"~*?:\\"
196 
198  void (*pr)(const char *buf, void *client_data),
199  void *client_data,
200  Z_Operand *q, WRBUF w)
201 {
202  int ret = 0;
203  if (q->which != Z_Operand_APT)
204  {
205  ret = -1;
207  }
208  else
209  {
211  Z_Term *term = apt->term;
212  const char *sterm = 0;
213  size_t lterm = 0;
214  Odr_int trunc = get_truncation(apt);
215 
216  wrbuf_rewind(w);
217  ret = rpn2solr_attr(ct, apt->attributes, w);
218 
219  if (trunc == 0 || trunc == 1 || trunc == 100 || trunc == 104)
220  ;
221  else
222  {
224  return -1;
225  }
226  switch (term->which)
227  {
228  case Z_Term_general:
229  lterm = term->u.general->len;
230  sterm = (const char *) term->u.general->buf;
231  break;
232  case Z_Term_numeric:
233  wrbuf_printf(w, ODR_INT_PRINTF, *term->u.numeric);
234  break;
236  sterm = term->u.characterString;
237  lterm = strlen(sterm);
238  break;
239  default:
240  ret = -1;
242  }
243 
244  if (sterm)
245  {
246  size_t i;
247  int must_quote = 0;
248 
249  for (i = 0 ; i < lterm; i++)
250  if (sterm[i] == ' ')
251  must_quote = 1;
252  if (must_quote)
253  wrbuf_puts(w, "\"");
254  for (i = 0 ; i < lterm; i++)
255  {
256  if (sterm[i] == '\\' && i < lterm - 1)
257  {
258  i++;
259  if (strchr(SOLR_SPECIAL, sterm[i]))
260  wrbuf_putc(w, '\\');
261  wrbuf_putc(w, sterm[i]);
262  }
263  else if (sterm[i] == '?' && trunc == 104)
264  {
265  wrbuf_putc(w, '*');
266  }
267  else if (sterm[i] == '#' && trunc == 104)
268  {
269  wrbuf_putc(w, '?');
270  }
271  else if (strchr(SOLR_SPECIAL, sterm[i]))
272  {
273  wrbuf_putc(w, '\\');
274  wrbuf_putc(w, sterm[i]);
275  }
276  else
277  wrbuf_putc(w, sterm[i]);
278  }
279  if (trunc == 1)
280  wrbuf_puts(w, "*");
281  if (must_quote)
282  wrbuf_puts(w, "\"");
283  }
284  if (ret == 0)
285  pr(wrbuf_cstr(w), client_data);
286  }
287  return ret;
288 }
289 
290 
292  void (*pr)(const char *buf, void *client_data),
293  void *client_data,
294  Z_RPNStructure *q, int nested,
295  WRBUF w)
296 {
297  if (q->which == Z_RPNStructure_simple)
298  return rpn2solr_simple(ct, pr, client_data, q->u.simple, w);
299  else
300  {
301  Z_Operator *op = q->u.complex->roperator;
302  int r;
303 
304  if (nested)
305  pr("(", client_data);
306 
307  r = rpn2solr_structure(ct, pr, client_data, q->u.complex->s1, 1, w);
308  if (r)
309  return r;
310  switch(op->which)
311  {
312  case Z_Operator_and:
313  pr(" AND ", client_data);
314  break;
315  case Z_Operator_or:
316  pr(" OR ", client_data);
317  break;
318  case Z_Operator_and_not:
319  pr(" AND NOT ", client_data);
320  break;
321  case Z_Operator_prox:
323  return -1;
324  }
325  r = rpn2solr_structure(ct, pr, client_data, q->u.complex->s2, 1, w);
326  if (nested)
327  pr(")", client_data);
328  return r;
329  }
330 }
331 
333  void (*pr)(const char *buf, void *client_data),
334  void *client_data,
335  Z_RPNQuery *q)
336 {
337  int r;
338  WRBUF w = wrbuf_alloc();
339  solr_transform_set_error(ct, 0, 0);
340  r = rpn2solr_structure(ct, pr, client_data, q->RPNStructure, 0, w);
341  wrbuf_destroy(w);
342  return r;
343 }
344 
345 
347  WRBUF w,
348  Z_RPNQuery *q)
349 {
351 }
352 
353 /*
354  * Local variables:
355  * c-basic-offset: 4
356  * c-file-style: "Stroustrup"
357  * indent-tabs-mode: nil
358  * End:
359  * vim: shiftwidth=4 tabstop=8 expandtab
360  */
361