2 * Copyright (C) 2005-2007, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: retrieval.c,v 1.19 2007-04-12 20:47:28 adam Exp $
9 * \brief Retrieval utility
17 #include <yaz/retrieval.h>
18 #include <yaz/wrbuf.h>
19 #include <yaz/xmalloc.h>
21 #include <yaz/tpath.h>
22 #include <yaz/proto.h>
23 #include <yaz/oid_db.h>
26 #include <libxml/parser.h>
27 #include <libxml/tree.h>
28 #include <libxml/xinclude.h>
30 /** \brief The internal structure for yaz_retrieval_t */
31 struct yaz_retrieval_struct {
32 /** \brief ODR memory for configuration */
35 /** \brief odr's NMEM memory (odr->mem) */
38 /** \brief string buffer for error messages */
41 /** \brief path for opening files */
44 /** \brief retrieval list */
45 struct yaz_retrieval_elem *list;
47 /** \brief last pointer in retrieval list */
48 struct yaz_retrieval_elem **list_p;
51 /** \brief information per 'retrieval' construct */
52 struct yaz_retrieval_elem {
53 /** \brief schema identifier */
54 const char *identifier;
55 /** \brief schema name , short-hand such as "dc" */
57 /** \brief record syntax */
60 /** \brief backend name */
61 const char *backend_name;
62 /** \brief backend syntax */
65 /** \brief record conversion */
66 yaz_record_conv_t record_conv;
68 /** \brief next element in list */
69 struct yaz_retrieval_elem *next;
72 static void yaz_retrieval_reset(yaz_retrieval_t p);
74 yaz_retrieval_t yaz_retrieval_create()
76 yaz_retrieval_t p = xmalloc(sizeof(*p));
77 p->odr = odr_createmem(ODR_ENCODE);
78 p->nmem = odr_getmem(p->odr);
79 p->wr_error = wrbuf_alloc();
82 yaz_retrieval_reset(p);
86 void yaz_retrieval_destroy(yaz_retrieval_t p)
90 yaz_retrieval_reset(p);
92 wrbuf_destroy(p->wr_error);
98 void yaz_retrieval_reset(yaz_retrieval_t p)
100 struct yaz_retrieval_elem *el = p->list;
101 for(; el; el = el->next)
102 yaz_record_conv_destroy(el->record_conv);
104 wrbuf_rewind(p->wr_error);
108 p->list_p = &p->list;
111 /** \brief parse retrieval XML config */
112 static int conf_retrieval(yaz_retrieval_t p, const xmlNode *ptr)
115 struct _xmlAttr *attr;
116 struct yaz_retrieval_elem *el = nmem_malloc(p->nmem, sizeof(*el));
121 el->backend_name = 0;
122 el->backend_syntax = 0;
126 for (attr = ptr->properties; attr; attr = attr->next)
128 if (!xmlStrcmp(attr->name, BAD_CAST "syntax") &&
129 attr->children && attr->children->type == XML_TEXT_NODE)
131 el->syntax = yaz_string_to_oid_odr(
134 (const char *) attr->children->content,
138 wrbuf_printf(p->wr_error, "Element <retrieval>: "
139 " unknown attribute value syntax='%s'",
140 (const char *) attr->children->content);
144 else if (!xmlStrcmp(attr->name, BAD_CAST "identifier") &&
145 attr->children && attr->children->type == XML_TEXT_NODE)
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)
151 nmem_strdup(p->nmem, (const char *) attr->children->content);
154 wrbuf_printf(p->wr_error, "Element <retrieval>: "
155 " expected attributes 'syntax', identifier' or "
156 "'name', got '%s'", attr->name);
163 wrbuf_printf(p->wr_error, "Missing 'syntax' attribute");
167 /* parsing backend element */
169 el->record_conv = 0; /* OK to have no 'backend' sub content */
170 for (ptr = ptr->children; ptr; ptr = ptr->next)
172 if (ptr->type != XML_ELEMENT_NODE)
174 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);
183 /* parsing attributees */
184 struct _xmlAttr *attr;
185 for (attr = ptr->properties; attr; attr = attr->next){
187 if (!xmlStrcmp(attr->name, BAD_CAST "name")
189 && attr->children->type == XML_TEXT_NODE)
191 = nmem_strdup(p->nmem,
192 (const char *) attr->children->content);
194 else if (!xmlStrcmp(attr->name, BAD_CAST "syntax")
196 && attr->children->type == XML_TEXT_NODE){
198 = yaz_string_to_oid_odr(
201 (const char *) attr->children->content,
203 if (!el->backend_syntax){
204 wrbuf_printf(p->wr_error,
205 "Element <backend syntax='%s'>: "
206 "attribute 'syntax' has invalid "
208 attr->children->content,
209 attr->children->content);
214 wrbuf_printf(p->wr_error, "Element <backend>: expected "
215 "attributes 'syntax' or 'name, got '%s'",
222 /* parsing internal of record conv */
223 el->record_conv = yaz_record_conv_create();
225 yaz_record_conv_set_path(el->record_conv, p->path);
228 if (yaz_record_conv_configure(el->record_conv, ptr))
230 wrbuf_printf(p->wr_error, "%s",
231 yaz_record_conv_get_error(el->record_conv));
232 yaz_record_conv_destroy(el->record_conv);
239 p->list_p = &el->next;
243 int yaz_retrieval_configure(yaz_retrieval_t p, const xmlNode *ptr)
245 yaz_retrieval_reset(p);
247 if (ptr && ptr->type == XML_ELEMENT_NODE &&
248 !strcmp((const char *) ptr->name, "retrievalinfo"))
250 for (ptr = ptr->children; ptr; ptr = ptr->next)
252 if (ptr->type != XML_ELEMENT_NODE)
254 if (!strcmp((const char *) ptr->name, "retrieval"))
256 if (conf_retrieval(p, ptr))
261 wrbuf_printf(p->wr_error, "Element <retrievalinfo>: "
262 "expected element <retrieval>, got <%s>",
270 wrbuf_printf(p->wr_error, "Expected element <retrievalinfo>");
276 int yaz_retrieval_request(yaz_retrieval_t p,
277 const char *schema, int *syntax,
278 const char **match_schema, int **match_syntax,
279 yaz_record_conv_t *rc,
280 const char **backend_schema,
281 int **backend_syntax)
283 struct yaz_retrieval_elem *el = p->list;
284 int syntax_matches = 0;
285 int schema_matches = 0;
287 wrbuf_rewind(p->wr_error);
290 for(; el; el = el->next)
299 if (el->name && !strcmp(schema, el->name))
301 if (el->identifier && !strcmp(schema, el->identifier))
303 if (!el->name && !el->identifier)
307 if (syntax && el->syntax && !oid_oidcmp(syntax, el->syntax))
316 if (syntax_ok && schema_ok)
318 *match_syntax = el->syntax;
320 *match_schema = el->identifier;
325 if (el->backend_name)
326 *backend_schema = el->backend_name;
328 *backend_schema = el->name;
330 *backend_schema = schema;
334 if (el->backend_syntax)
335 *backend_syntax = el->backend_syntax;
337 *backend_syntax = el->syntax;
340 *rc = el->record_conv;
344 if (!syntax_matches && syntax)
346 char buf[OID_STR_MAX];
347 wrbuf_printf(p->wr_error, "%s", oid_oid_to_dotstring(syntax, buf));
351 wrbuf_printf(p->wr_error, "%s", schema);
357 const char *yaz_retrieval_get_error(yaz_retrieval_t p)
359 return wrbuf_cstr(p->wr_error);
362 void yaz_retrieval_set_path(yaz_retrieval_t p, const char *path)
367 p->path = xstrdup(path);
375 * indent-tabs-mode: nil
377 * vim: shiftwidth=4 tabstop=8 expandtab