YAZ  5.34.0
retrieval.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  */
10 #if HAVE_CONFIG_H
11 #include <config.h>
12 #endif
13 
14 #include <string.h>
15 #include <yaz/retrieval.h>
16 #include <yaz/wrbuf.h>
17 #include <yaz/xmalloc.h>
18 #include <yaz/nmem.h>
19 #include <yaz/tpath.h>
20 #include <yaz/match_glob.h>
21 #include <yaz/proto.h>
22 #include <yaz/oid_db.h>
23 
24 #if YAZ_HAVE_XML2
25 #include <libxml/parser.h>
26 #include <libxml/tree.h>
27 #include <libxml/xinclude.h>
28 
33 
36 
39 
41  char *path;
42 
45 
48 };
49 
53  const char *identifier;
55  const char *name;
59  const char *split;
60 
62  const char *backend_name;
65 
68 
71 };
72 
74 
76 {
77  yaz_retrieval_t p = (yaz_retrieval_t) xmalloc(sizeof(*p));
79  p->nmem = odr_getmem(p->odr);
80  p->wr_error = wrbuf_alloc();
81  p->list = 0;
82  p->path = 0;
84  return p;
85 }
86 
88 {
89  if (p)
90  {
92  odr_destroy(p->odr);
94  xfree(p->path);
95  xfree(p);
96  }
97 }
98 
100 {
101  struct yaz_retrieval_elem *el = p->list;
102  for(; el; el = el->next)
104 
106  odr_reset(p->odr);
107 
108  p->list = 0;
109  p->list_p = &p->list;
110 }
111 
113 static int conf_retrieval(yaz_retrieval_t p, const xmlNode *ptr,
114  struct yaz_record_conv_type *types)
115 {
116  struct _xmlAttr *attr;
117  struct yaz_retrieval_elem *el = (struct yaz_retrieval_elem *)
118  nmem_malloc(p->nmem, sizeof(*el));
119 
120  el->syntax = 0;
121  el->identifier = 0;
122  el->name = 0;
123  el->split = 0;
124  el->backend_name = 0;
125  el->backend_syntax = 0;
126 
127  el->next = 0;
128 
129  for (attr = ptr->properties; attr; attr = attr->next)
130  {
131  if (!xmlStrcmp(attr->name, BAD_CAST "syntax") &&
132  attr->children && attr->children->type == XML_TEXT_NODE)
133  {
135  yaz_oid_std(),
136  CLASS_RECSYN,
137  (const char *) attr->children->content,
138  p->odr);
139  if (!el->syntax)
140  {
141  wrbuf_printf(p->wr_error, "Element <retrieval>: "
142  " unknown attribute value syntax='%s'",
143  (const char *) attr->children->content);
144  return -1;
145  }
146  }
147  else if (!xmlStrcmp(attr->name, BAD_CAST "identifier") &&
148  attr->children && attr->children->type == XML_TEXT_NODE)
149  el->identifier =
150  nmem_strdup(p->nmem, (const char *) attr->children->content);
151  else if (!xmlStrcmp(attr->name, BAD_CAST "name") &&
152  attr->children && attr->children->type == XML_TEXT_NODE)
153  el->name =
154  nmem_strdup(p->nmem, (const char *) attr->children->content);
155  else if (!xmlStrcmp(attr->name, BAD_CAST "split") &&
156  attr->children && attr->children->type == XML_TEXT_NODE)
157  el->split =
158  nmem_strdup(p->nmem, (const char *) attr->children->content);
159  else
160  {
161  wrbuf_printf(p->wr_error, "Element <retrieval>: "
162  " expected attributes 'syntax', identifier' or "
163  "'name', got '%s'", attr->name);
164  return -1;
165  }
166  }
167 
168  if (!el->syntax)
169  {
170  wrbuf_printf(p->wr_error, "Missing 'syntax' attribute");
171  return -1;
172  }
173 
174  /* parsing backend element */
175 
176  el->record_conv = 0; /* OK to have no 'backend' sub content */
177  for (ptr = ptr->children; ptr; ptr = ptr->next)
178  {
179  if (ptr->type != XML_ELEMENT_NODE)
180  continue;
181  if (strcmp((const char *) ptr->name, "backend"))
182  {
183  wrbuf_printf(p->wr_error, "Element <retrieval>: expected"
184  " zero or one element <backend>, got <%s>",
185  (const char *) ptr->name);
186  return -1;
187  }
188  else
189  {
190  struct _xmlAttr *attr;
191  if (el->record_conv)
192  {
193  wrbuf_printf(p->wr_error, "Element <retrieval>: "
194  "only one <backend> allowed");
196  return -1;
197  }
198  /* parsing attributees */
199  for (attr = ptr->properties; attr; attr = attr->next)
200  {
201  if (!xmlStrcmp(attr->name, BAD_CAST "name")
202  && attr->children
203  && attr->children->type == XML_TEXT_NODE)
204  el->backend_name
205  = nmem_strdup(p->nmem,
206  (const char *) attr->children->content);
207 
208  else if (!xmlStrcmp(attr->name, BAD_CAST "syntax")
209  && attr->children
210  && attr->children->type == XML_TEXT_NODE)
211  {
212  el->backend_syntax
214  yaz_oid_std(),
215  CLASS_RECSYN,
216  (const char *) attr->children->content,
217  p->odr);
218  if (!el->backend_syntax)
219  {
221  "Element <backend syntax='%s'>: "
222  "attribute 'syntax' has invalid "
223  "value '%s'",
224  attr->children->content,
225  attr->children->content);
226  return -1;
227  }
228  }
229  else
230  {
231  wrbuf_printf(p->wr_error, "Element <backend>: expected "
232  "attributes 'syntax' or 'name, got '%s'",
233  attr->name);
234  return -1;
235  }
236  }
237 
238  /* parsing internal of record conv */
240 
242 
243  if (yaz_record_conv_configure_t(el->record_conv, ptr, types))
244  {
245  wrbuf_printf(p->wr_error, "%s",
248  return -1;
249  }
250  }
251  }
252 
253  *p->list_p = el;
254  p->list_p = &el->next;
255  return 0;
256 }
257 
258 int yaz_retrieval_configure_t(yaz_retrieval_t p, const xmlNode *ptr,
259  struct yaz_record_conv_type *types)
260 {
262 
263  if (ptr && ptr->type == XML_ELEMENT_NODE &&
264  !strcmp((const char *) ptr->name, "retrievalinfo"))
265  {
266  for (ptr = ptr->children; ptr; ptr = ptr->next)
267  {
268  if (ptr->type != XML_ELEMENT_NODE)
269  continue;
270  if (!strcmp((const char *) ptr->name, "retrieval"))
271  {
272  if (conf_retrieval(p, ptr, types))
273  return -1;
274  }
275  else
276  {
277  wrbuf_printf(p->wr_error, "Element <retrievalinfo>: "
278  "expected element <retrieval>, got <%s>",
279  ptr->name);
280  return -1;
281  }
282  }
283  }
284  else
285  {
286  wrbuf_printf(p->wr_error, "Expected element <retrievalinfo>");
287  return -1;
288  }
289  return 0;
290 }
291 
292 int yaz_retrieval_configure(yaz_retrieval_t p, const xmlNode *ptr)
293 {
294  return yaz_retrieval_configure_t(p, ptr, 0);
295 }
296 
298  const char *schema, const Odr_oid *syntax,
299  const char **match_schema, Odr_oid **match_syntax,
300  yaz_record_conv_t *rc,
301  const char **backend_schema,
302  Odr_oid **backend_syntax)
303 {
304  struct yaz_retrieval_elem *el = p->list;
305  int syntax_matches = 0;
306  int schema_matches = 0;
307  struct yaz_retrieval_elem *el_best = 0;
308  WRBUF w = 0;
309 
310  if (!el)
311  return 0;
312  w = wrbuf_alloc();
313  for (; el; el = el->next)
314  {
315  int schema_ok = 0;
316  int syntax_ok = 0;
317  if (!schema)
318  schema_ok = 1;
319  else
320  {
321  char *cp = 0;
322  wrbuf_rewind(w);
323  if (el->split && *el->split && (cp = strchr(schema, *el->split)))
324  wrbuf_write(w, schema, cp - schema);
325  else
326  wrbuf_puts(w, schema);
327  if (el->name && yaz_match_glob2(el->name, wrbuf_cstr(w), 1))
328  schema_ok = 2;
329  if (el->identifier && !strcmp(schema, el->identifier))
330  schema_ok = 2;
331  if (!el->name && !el->identifier)
332  schema_ok = 1;
333  }
334 
335  if (syntax && el->syntax && !oid_oidcmp(syntax, el->syntax))
336  syntax_ok = 1;
337  if (!syntax)
338  syntax_ok = 1;
339 
340  if (syntax_ok)
341  syntax_matches++;
342  if (schema_ok)
343  schema_matches++;
344  if (syntax_ok && schema_ok)
345  {
346  if (!el_best || schema_ok == 2)
347  el_best = el;
348  }
349  }
350  if (el_best)
351  {
352  el = el_best;
353  *match_syntax = el->syntax;
354  if (el->identifier)
355  *match_schema = el->identifier;
356  else
357  *match_schema = 0;
358  if (backend_schema)
359  {
360  if (el->backend_name)
361  {
362  if (*el->backend_name)
363  {
364  char *cp;
365  wrbuf_rewind(w);
366  wrbuf_puts(w, el->backend_name);
367  if (el->split && *el->split && schema
368  && (cp = strchr(schema, *el->split)))
369  {
370  wrbuf_puts(w, cp);
371  }
372  *backend_schema = wrbuf_cstr(w);
373  }
374  }
375  else
376  *backend_schema = schema;
377  }
378  if (backend_syntax)
379  {
380  if (el->backend_syntax)
382  else
383  *backend_syntax = el->syntax;
384  }
385  if (rc)
386  *rc = el->record_conv;
387  return 0;
388  }
389  if (!syntax_matches && syntax)
390  {
391  char buf[OID_STR_MAX];
393  return 2;
394  }
395  if (schema)
396  wrbuf_printf(p->wr_error, "%s", schema);
397  if (!schema_matches)
398  return 1;
399  return 3;
400 }
401 
403 {
404  return wrbuf_cstr(p->wr_error);
405 }
406 
407 void yaz_retrieval_set_path(yaz_retrieval_t p, const char *path)
408 {
409  xfree(p->path);
410  p->path = 0;
411  if (path)
412  p->path = xstrdup(path);
413 }
414 
415 #endif
416 
417 /*
418  * Local variables:
419  * c-basic-offset: 4
420  * c-file-style: "Stroustrup"
421  * indent-tabs-mode: nil
422  * End:
423  * vim: shiftwidth=4 tabstop=8 expandtab
424  */
425 
int yaz_match_glob2(const char *glob, const char *text, int case_insensitive)
matches a glob expression against text
Definition: match_glob.c:27
Glob expression matcher.
void * nmem_malloc(NMEM n, size_t size)
allocates memory block on NMEM handle
Definition: nmem.c:145
Header for Nibble Memory functions.
char * nmem_strdup(NMEM mem, const char *src)
allocates string on NMEM handle (similar strdup)
Definition: nmemsdup.c:18
ODR odr_createmem(int direction)
Definition: odr.c:200
void odr_destroy(ODR o)
Definition: odr.c:253
void odr_reset(ODR o)
Definition: odr.c:226
#define odr_getmem(o)
Definition: odr.h:216
#define ODR_ENCODE
Definition: odr.h:96
yaz_oid_db_t yaz_oid_std(void)
returns standard OID database
Definition: oid_db.c:33
Odr_oid * yaz_string_to_oid_odr(yaz_oid_db_t oid_list, oid_class oclass, const char *name, ODR o)
creates ODR malloc'ed OID from string
Definition: oid_db.c:72
Header for OID database.
@ CLASS_RECSYN
Definition: oid_db.h:53
int oid_oidcmp(const Odr_oid *o1, const Odr_oid *o2)
compares OIDs
Definition: oid_util.c:34
char * oid_oid_to_dotstring(const Odr_oid *oid, char *oidbuf)
converts OID to string (dot notation)
Definition: oid_util.c:59
short Odr_oid
Definition: oid_util.h:42
#define OID_STR_MAX
Definition: oid_util.h:40
Header for Z39.50 Protocol.
int yaz_record_conv_configure_t(yaz_record_conv_t p, const xmlNode *ptr, struct yaz_record_conv_type *types)
Definition: record_conv.c:1135
void yaz_record_conv_destroy(yaz_record_conv_t p)
Definition: record_conv.c:94
const char * yaz_record_conv_get_error(yaz_record_conv_t p)
Definition: record_conv.c:1298
void yaz_record_conv_set_path(yaz_record_conv_t p, const char *path)
Definition: record_conv.c:1303
yaz_record_conv_t yaz_record_conv_create()
Definition: record_conv.c:1311
static void yaz_retrieval_reset(yaz_retrieval_t p)
Definition: retrieval.c:99
void yaz_retrieval_destroy(yaz_retrieval_t p)
Definition: retrieval.c:87
int yaz_retrieval_configure(yaz_retrieval_t p, const xmlNode *ptr)
Definition: retrieval.c:292
const char * yaz_retrieval_get_error(yaz_retrieval_t p)
Definition: retrieval.c:402
int yaz_retrieval_configure_t(yaz_retrieval_t p, const xmlNode *ptr, struct yaz_record_conv_type *types)
Definition: retrieval.c:258
int yaz_retrieval_request(yaz_retrieval_t p, const char *schema, const Odr_oid *syntax, const char **match_schema, Odr_oid **match_syntax, yaz_record_conv_t *rc, const char **backend_schema, Odr_oid **backend_syntax)
Definition: retrieval.c:297
yaz_retrieval_t yaz_retrieval_create()
Definition: retrieval.c:75
static int conf_retrieval(yaz_retrieval_t p, const xmlNode *ptr, struct yaz_record_conv_type *types)
parse retrieval XML config
Definition: retrieval.c:113
void yaz_retrieval_set_path(yaz_retrieval_t p, const char *path)
Definition: retrieval.c:407
Retrieval utility.
struct yaz_retrieval_struct * yaz_retrieval_t
Definition: retrieval.h:45
Definition: odr.h:125
string buffer
Definition: wrbuf.h:43
The internal structure for yaz_record_conv_t.
Definition: record_conv.c:44
information per 'retrieval' construct
Definition: retrieval.c:51
struct yaz_retrieval_elem * next
next element in list
Definition: retrieval.c:70
const char * backend_name
backend name
Definition: retrieval.c:62
Odr_oid * syntax
record syntax
Definition: retrieval.c:57
const char * split
split name for some separator
Definition: retrieval.c:59
yaz_record_conv_t record_conv
record conversion
Definition: retrieval.c:67
const char * identifier
schema identifier
Definition: retrieval.c:53
Odr_oid * backend_syntax
backend syntax
Definition: retrieval.c:64
const char * name
schema name , short-hand such as "dc"
Definition: retrieval.c:55
The internal structure for yaz_retrieval_t.
Definition: retrieval.c:30
ODR odr
ODR memory for configuration.
Definition: retrieval.c:32
struct yaz_retrieval_elem * list
retrieval list
Definition: retrieval.c:44
WRBUF wr_error
string buffer for error messages
Definition: retrieval.c:38
struct yaz_retrieval_elem ** list_p
last pointer in retrieval list
Definition: retrieval.c:47
NMEM nmem
odr's NMEM memory (odr->mem)
Definition: retrieval.c:35
char * path
path for opening files
Definition: retrieval.c:41
File Path utilities.
void wrbuf_destroy(WRBUF b)
destroy WRBUF and its buffer
Definition: wrbuf.c:38
void wrbuf_rewind(WRBUF b)
empty WRBUF content (length of buffer set to 0)
Definition: wrbuf.c:47
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
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)
Header for memory handling functions.
#define xstrdup(s)
utility macro which calls xstrdup_f
Definition: xmalloc.h:55
#define xfree(x)
utility macro which calls xfree_f
Definition: xmalloc.h:53
#define xmalloc(x)
utility macro which calls malloc_f
Definition: xmalloc.h:49