1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2012 Index Data
3 * See the file LICENSE for details.
7 * \brief Retrieval utility
15 #include <yaz/retrieval.h>
16 #include <yaz/wrbuf.h>
17 #include <yaz/xmalloc.h>
19 #include <yaz/tpath.h>
20 #include <yaz/match_glob.h>
21 #include <yaz/proto.h>
22 #include <yaz/oid_db.h>
25 #include <libxml/parser.h>
26 #include <libxml/tree.h>
27 #include <libxml/xinclude.h>
29 /** \brief The internal structure for yaz_retrieval_t */
30 struct yaz_retrieval_struct {
31 /** \brief ODR memory for configuration */
34 /** \brief odr's NMEM memory (odr->mem) */
37 /** \brief string buffer for error messages */
40 /** \brief path for opening files */
43 /** \brief retrieval list */
44 struct yaz_retrieval_elem *list;
46 /** \brief last pointer in retrieval list */
47 struct yaz_retrieval_elem **list_p;
50 /** \brief information per 'retrieval' construct */
51 struct yaz_retrieval_elem {
52 /** \brief schema identifier */
53 const char *identifier;
54 /** \brief schema name , short-hand such as "dc" */
56 /** \brief record syntax */
59 /** \brief backend name */
60 const char *backend_name;
61 /** \brief backend syntax */
62 Odr_oid *backend_syntax;
64 /** \brief record conversion */
65 yaz_record_conv_t record_conv;
67 /** \brief next element in list */
68 struct yaz_retrieval_elem *next;
71 static void yaz_retrieval_reset(yaz_retrieval_t p);
73 yaz_retrieval_t yaz_retrieval_create()
75 yaz_retrieval_t p = (yaz_retrieval_t) xmalloc(sizeof(*p));
76 p->odr = odr_createmem(ODR_ENCODE);
77 p->nmem = odr_getmem(p->odr);
78 p->wr_error = wrbuf_alloc();
81 yaz_retrieval_reset(p);
85 void yaz_retrieval_destroy(yaz_retrieval_t p)
89 yaz_retrieval_reset(p);
91 wrbuf_destroy(p->wr_error);
97 void yaz_retrieval_reset(yaz_retrieval_t p)
99 struct yaz_retrieval_elem *el = p->list;
100 for(; el; el = el->next)
101 yaz_record_conv_destroy(el->record_conv);
103 wrbuf_rewind(p->wr_error);
107 p->list_p = &p->list;
110 /** \brief parse retrieval XML config */
111 static int conf_retrieval(yaz_retrieval_t p, const xmlNode *ptr)
113 struct _xmlAttr *attr;
114 struct yaz_retrieval_elem *el = (struct yaz_retrieval_elem *)
115 nmem_malloc(p->nmem, sizeof(*el));
120 el->backend_name = 0;
121 el->backend_syntax = 0;
125 for (attr = ptr->properties; attr; attr = attr->next)
127 if (!xmlStrcmp(attr->name, BAD_CAST "syntax") &&
128 attr->children && attr->children->type == XML_TEXT_NODE)
130 el->syntax = yaz_string_to_oid_odr(
133 (const char *) attr->children->content,
137 wrbuf_printf(p->wr_error, "Element <retrieval>: "
138 " unknown attribute value syntax='%s'",
139 (const char *) attr->children->content);
143 else if (!xmlStrcmp(attr->name, BAD_CAST "identifier") &&
144 attr->children && attr->children->type == XML_TEXT_NODE)
146 nmem_strdup(p->nmem, (const char *) attr->children->content);
147 else if (!xmlStrcmp(attr->name, BAD_CAST "name") &&
148 attr->children && attr->children->type == XML_TEXT_NODE)
150 nmem_strdup(p->nmem, (const char *) attr->children->content);
153 wrbuf_printf(p->wr_error, "Element <retrieval>: "
154 " expected attributes 'syntax', identifier' or "
155 "'name', got '%s'", attr->name);
162 wrbuf_printf(p->wr_error, "Missing 'syntax' attribute");
166 /* parsing backend element */
168 el->record_conv = 0; /* OK to have no 'backend' sub content */
169 for (ptr = ptr->children; ptr; ptr = ptr->next)
171 if (ptr->type != XML_ELEMENT_NODE)
173 if (strcmp((const char *) ptr->name, "backend"))
175 wrbuf_printf(p->wr_error, "Element <retrieval>: expected"
176 " zero or one element <backend>, got <%s>",
177 (const char *) ptr->name);
182 struct _xmlAttr *attr;
185 wrbuf_printf(p->wr_error, "Element <retrieval>: "
186 "only one <backend> allowed");
187 yaz_record_conv_destroy(el->record_conv);
190 /* parsing attributees */
191 for (attr = ptr->properties; attr; attr = attr->next)
193 if (!xmlStrcmp(attr->name, BAD_CAST "name")
195 && attr->children->type == XML_TEXT_NODE)
197 = nmem_strdup(p->nmem,
198 (const char *) attr->children->content);
200 else if (!xmlStrcmp(attr->name, BAD_CAST "syntax")
202 && attr->children->type == XML_TEXT_NODE)
205 = yaz_string_to_oid_odr(
208 (const char *) attr->children->content,
210 if (!el->backend_syntax)
212 wrbuf_printf(p->wr_error,
213 "Element <backend syntax='%s'>: "
214 "attribute 'syntax' has invalid "
216 attr->children->content,
217 attr->children->content);
223 wrbuf_printf(p->wr_error, "Element <backend>: expected "
224 "attributes 'syntax' or 'name, got '%s'",
230 /* parsing internal of record conv */
231 el->record_conv = yaz_record_conv_create();
233 yaz_record_conv_set_path(el->record_conv, p->path);
235 if (yaz_record_conv_configure(el->record_conv, ptr))
237 wrbuf_printf(p->wr_error, "%s",
238 yaz_record_conv_get_error(el->record_conv));
239 yaz_record_conv_destroy(el->record_conv);
246 p->list_p = &el->next;
250 int yaz_retrieval_configure(yaz_retrieval_t p, const xmlNode *ptr)
252 yaz_retrieval_reset(p);
254 if (ptr && ptr->type == XML_ELEMENT_NODE &&
255 !strcmp((const char *) ptr->name, "retrievalinfo"))
257 for (ptr = ptr->children; ptr; ptr = ptr->next)
259 if (ptr->type != XML_ELEMENT_NODE)
261 if (!strcmp((const char *) ptr->name, "retrieval"))
263 if (conf_retrieval(p, ptr))
268 wrbuf_printf(p->wr_error, "Element <retrievalinfo>: "
269 "expected element <retrieval>, got <%s>",
277 wrbuf_printf(p->wr_error, "Expected element <retrievalinfo>");
283 int yaz_retrieval_request(yaz_retrieval_t p,
284 const char *schema, Odr_oid *syntax,
285 const char **match_schema, Odr_oid **match_syntax,
286 yaz_record_conv_t *rc,
287 const char **backend_schema,
288 Odr_oid **backend_syntax)
290 struct yaz_retrieval_elem *el = p->list;
291 int syntax_matches = 0;
292 int schema_matches = 0;
294 wrbuf_rewind(p->wr_error);
297 for(; el; el = el->next)
306 if (el->name && yaz_match_glob(el->name, schema))
308 if (el->identifier && !strcmp(schema, el->identifier))
310 if (!el->name && !el->identifier)
314 if (syntax && el->syntax && !oid_oidcmp(syntax, el->syntax))
323 if (syntax_ok && schema_ok)
325 *match_syntax = el->syntax;
327 *match_schema = el->identifier;
332 if (el->backend_name)
333 *backend_schema = el->backend_name;
335 *backend_schema = el->name;
337 *backend_schema = schema;
341 if (el->backend_syntax)
342 *backend_syntax = el->backend_syntax;
344 *backend_syntax = el->syntax;
347 *rc = el->record_conv;
351 if (!syntax_matches && syntax)
353 char buf[OID_STR_MAX];
354 wrbuf_printf(p->wr_error, "%s", oid_oid_to_dotstring(syntax, buf));
358 wrbuf_printf(p->wr_error, "%s", schema);
364 const char *yaz_retrieval_get_error(yaz_retrieval_t p)
366 return wrbuf_cstr(p->wr_error);
369 void yaz_retrieval_set_path(yaz_retrieval_t p, const char *path)
374 p->path = xstrdup(path);
382 * c-file-style: "Stroustrup"
383 * indent-tabs-mode: nil
385 * vim: shiftwidth=4 tabstop=8 expandtab