YAZ  4.2.60
retrieval.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  */
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;
58 
60  const char *backend_name;
63 
66 
69 };
70 
72 
74 {
75  yaz_retrieval_t p = (yaz_retrieval_t) xmalloc(sizeof(*p));
77  p->nmem = odr_getmem(p->odr);
78  p->wr_error = wrbuf_alloc();
79  p->list = 0;
80  p->path = 0;
82  return p;
83 }
84 
86 {
87  if (p)
88  {
90  odr_destroy(p->odr);
92  xfree(p->path);
93  xfree(p);
94  }
95 }
96 
98 {
99  struct yaz_retrieval_elem *el = p->list;
100  for(; el; el = el->next)
102 
104  odr_reset(p->odr);
105 
106  p->list = 0;
107  p->list_p = &p->list;
108 }
109 
111 static int conf_retrieval(yaz_retrieval_t p, const xmlNode *ptr,
112  struct yaz_record_conv_type *types)
113 {
114  struct _xmlAttr *attr;
115  struct yaz_retrieval_elem *el = (struct yaz_retrieval_elem *)
116  nmem_malloc(p->nmem, sizeof(*el));
117 
118  el->syntax = 0;
119  el->identifier = 0;
120  el->name = 0;
121  el->backend_name = 0;
122  el->backend_syntax = 0;
123 
124  el->next = 0;
125 
126  for (attr = ptr->properties; attr; attr = attr->next)
127  {
128  if (!xmlStrcmp(attr->name, BAD_CAST "syntax") &&
129  attr->children && attr->children->type == XML_TEXT_NODE)
130  {
132  yaz_oid_std(),
133  CLASS_RECSYN,
134  (const char *) attr->children->content,
135  p->odr);
136  if (!el->syntax)
137  {
138  wrbuf_printf(p->wr_error, "Element <retrieval>: "
139  " unknown attribute value syntax='%s'",
140  (const char *) attr->children->content);
141  return -1;
142  }
143  }
144  else if (!xmlStrcmp(attr->name, BAD_CAST "identifier") &&
145  attr->children && attr->children->type == XML_TEXT_NODE)
146  el->identifier =
147  nmem_strdup(p->nmem, (const char *) attr->children->content);
148  else if (!xmlStrcmp(attr->name, BAD_CAST "name") &&
149  attr->children && attr->children->type == XML_TEXT_NODE)
150  el->name =
151  nmem_strdup(p->nmem, (const char *) attr->children->content);
152  else
153  {
154  wrbuf_printf(p->wr_error, "Element <retrieval>: "
155  " expected attributes 'syntax', identifier' or "
156  "'name', got '%s'", attr->name);
157  return -1;
158  }
159  }
160 
161  if (!el->syntax)
162  {
163  wrbuf_printf(p->wr_error, "Missing 'syntax' attribute");
164  return -1;
165  }
166 
167  /* parsing backend element */
168 
169  el->record_conv = 0; /* OK to have no 'backend' sub content */
170  for (ptr = ptr->children; ptr; ptr = ptr->next)
171  {
172  if (ptr->type != XML_ELEMENT_NODE)
173  continue;
174  if (strcmp((const char *) ptr->name, "backend"))
175  {
176  wrbuf_printf(p->wr_error, "Element <retrieval>: expected"
177  " zero or one element <backend>, got <%s>",
178  (const char *) ptr->name);
179  return -1;
180  }
181  else
182  {
183  struct _xmlAttr *attr;
184  if (el->record_conv)
185  {
186  wrbuf_printf(p->wr_error, "Element <retrieval>: "
187  "only one <backend> allowed");
189  return -1;
190  }
191  /* parsing attributees */
192  for (attr = ptr->properties; attr; attr = attr->next)
193  {
194  if (!xmlStrcmp(attr->name, BAD_CAST "name")
195  && attr->children
196  && attr->children->type == XML_TEXT_NODE)
197  el->backend_name
198  = nmem_strdup(p->nmem,
199  (const char *) attr->children->content);
200 
201  else if (!xmlStrcmp(attr->name, BAD_CAST "syntax")
202  && attr->children
203  && attr->children->type == XML_TEXT_NODE)
204  {
205  el->backend_syntax
207  yaz_oid_std(),
208  CLASS_RECSYN,
209  (const char *) attr->children->content,
210  p->odr);
211  if (!el->backend_syntax)
212  {
214  "Element <backend syntax='%s'>: "
215  "attribute 'syntax' has invalid "
216  "value '%s'",
217  attr->children->content,
218  attr->children->content);
219  return -1;
220  }
221  }
222  else
223  {
224  wrbuf_printf(p->wr_error, "Element <backend>: expected "
225  "attributes 'syntax' or 'name, got '%s'",
226  attr->name);
227  return -1;
228  }
229  }
230 
231  /* parsing internal of record conv */
233 
235 
236  if (yaz_record_conv_configure_t(el->record_conv, ptr, types))
237  {
238  wrbuf_printf(p->wr_error, "%s",
241  return -1;
242  }
243  }
244  }
245 
246  *p->list_p = el;
247  p->list_p = &el->next;
248  return 0;
249 }
250 
251 int yaz_retrieval_configure_t(yaz_retrieval_t p, const xmlNode *ptr,
252  struct yaz_record_conv_type *types)
253 {
255 
256  if (ptr && ptr->type == XML_ELEMENT_NODE &&
257  !strcmp((const char *) ptr->name, "retrievalinfo"))
258  {
259  for (ptr = ptr->children; ptr; ptr = ptr->next)
260  {
261  if (ptr->type != XML_ELEMENT_NODE)
262  continue;
263  if (!strcmp((const char *) ptr->name, "retrieval"))
264  {
265  if (conf_retrieval(p, ptr, types))
266  return -1;
267  }
268  else
269  {
270  wrbuf_printf(p->wr_error, "Element <retrievalinfo>: "
271  "expected element <retrieval>, got <%s>",
272  ptr->name);
273  return -1;
274  }
275  }
276  }
277  else
278  {
279  wrbuf_printf(p->wr_error, "Expected element <retrievalinfo>");
280  return -1;
281  }
282  return 0;
283 }
284 
285 int yaz_retrieval_configure(yaz_retrieval_t p, const xmlNode *ptr)
286 {
287  return yaz_retrieval_configure_t(p, ptr, 0);
288 }
289 
291  const char *schema, Odr_oid *syntax,
292  const char **match_schema, Odr_oid **match_syntax,
293  yaz_record_conv_t *rc,
294  const char **backend_schema,
295  Odr_oid **backend_syntax)
296 {
297  struct yaz_retrieval_elem *el = p->list;
298  int syntax_matches = 0;
299  int schema_matches = 0;
300 
302  if (!el)
303  return 0;
304  for(; el; el = el->next)
305  {
306  int schema_ok = 0;
307  int syntax_ok = 0;
308 
309  if (!schema)
310  schema_ok = 1;
311  else
312  {
313  if (el->name && yaz_match_glob(el->name, schema))
314  schema_ok = 1;
315  if (el->identifier && !strcmp(schema, el->identifier))
316  schema_ok = 1;
317  if (!el->name && !el->identifier)
318  schema_ok = 1;
319  }
320 
321  if (syntax && el->syntax && !oid_oidcmp(syntax, el->syntax))
322  syntax_ok = 1;
323  if (!syntax)
324  syntax_ok = 1;
325 
326  if (syntax_ok)
327  syntax_matches++;
328  if (schema_ok)
329  schema_matches++;
330  if (syntax_ok && schema_ok)
331  {
332  *match_syntax = el->syntax;
333  if (el->identifier)
334  *match_schema = el->identifier;
335  else
336  *match_schema = 0;
337  if (backend_schema)
338  {
339  if (el->backend_name)
340  {
341  if (*el->backend_name)
342  *backend_schema = el->backend_name;
343  }
344  else if (el->name)
345  *backend_schema = el->name;
346  else
347  *backend_schema = schema;
348  }
349  if (backend_syntax)
350  {
351  if (el->backend_syntax)
352  *backend_syntax = el->backend_syntax;
353  else
354  *backend_syntax = el->syntax;
355  }
356  if (rc)
357  *rc = el->record_conv;
358  return 0;
359  }
360  }
361  if (!syntax_matches && syntax)
362  {
363  char buf[OID_STR_MAX];
364  wrbuf_printf(p->wr_error, "%s", oid_oid_to_dotstring(syntax, buf));
365  return 2;
366  }
367  if (schema)
368  wrbuf_printf(p->wr_error, "%s", schema);
369  if (!schema_matches)
370  return 1;
371  return 3;
372 }
373 
375 {
376  return wrbuf_cstr(p->wr_error);
377 }
378 
379 void yaz_retrieval_set_path(yaz_retrieval_t p, const char *path)
380 {
381  xfree(p->path);
382  p->path = 0;
383  if (path)
384  p->path = xstrdup(path);
385 }
386 
387 #endif
388 
389 /*
390  * Local variables:
391  * c-basic-offset: 4
392  * c-file-style: "Stroustrup"
393  * indent-tabs-mode: nil
394  * End:
395  * vim: shiftwidth=4 tabstop=8 expandtab
396  */
397