2 * Copyright (C) 2005-2007, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: retrieval.c,v 1.22 2008-01-25 16:28:26 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/match_glob.h>
23 #include <yaz/proto.h>
24 #include <yaz/oid_db.h>
27 #include <libxml/parser.h>
28 #include <libxml/tree.h>
29 #include <libxml/xinclude.h>
31 /** \brief The internal structure for yaz_retrieval_t */
32 struct yaz_retrieval_struct {
33 /** \brief ODR memory for configuration */
36 /** \brief odr's NMEM memory (odr->mem) */
39 /** \brief string buffer for error messages */
42 /** \brief path for opening files */
45 /** \brief retrieval list */
46 struct yaz_retrieval_elem *list;
48 /** \brief last pointer in retrieval list */
49 struct yaz_retrieval_elem **list_p;
52 /** \brief information per 'retrieval' construct */
53 struct yaz_retrieval_elem {
54 /** \brief schema identifier */
55 const char *identifier;
56 /** \brief schema name , short-hand such as "dc" */
58 /** \brief record syntax */
61 /** \brief backend name */
62 const char *backend_name;
63 /** \brief backend syntax */
64 Odr_oid *backend_syntax;
66 /** \brief record conversion */
67 yaz_record_conv_t record_conv;
69 /** \brief next element in list */
70 struct yaz_retrieval_elem *next;
73 static void yaz_retrieval_reset(yaz_retrieval_t p);
75 yaz_retrieval_t yaz_retrieval_create()
77 yaz_retrieval_t p = (yaz_retrieval_t) xmalloc(sizeof(*p));
78 p->odr = odr_createmem(ODR_ENCODE);
79 p->nmem = odr_getmem(p->odr);
80 p->wr_error = wrbuf_alloc();
83 yaz_retrieval_reset(p);
87 void yaz_retrieval_destroy(yaz_retrieval_t p)
91 yaz_retrieval_reset(p);
93 wrbuf_destroy(p->wr_error);
99 void yaz_retrieval_reset(yaz_retrieval_t p)
101 struct yaz_retrieval_elem *el = p->list;
102 for(; el; el = el->next)
103 yaz_record_conv_destroy(el->record_conv);
105 wrbuf_rewind(p->wr_error);
109 p->list_p = &p->list;
112 /** \brief parse retrieval XML config */
113 static int conf_retrieval(yaz_retrieval_t p, const xmlNode *ptr)
116 struct _xmlAttr *attr;
117 struct yaz_retrieval_elem *el = (struct yaz_retrieval_elem *)
118 nmem_malloc(p->nmem, sizeof(*el));
123 el->backend_name = 0;
124 el->backend_syntax = 0;
128 for (attr = ptr->properties; attr; attr = attr->next)
130 if (!xmlStrcmp(attr->name, BAD_CAST "syntax") &&
131 attr->children && attr->children->type == XML_TEXT_NODE)
133 el->syntax = yaz_string_to_oid_odr(
136 (const char *) attr->children->content,
140 wrbuf_printf(p->wr_error, "Element <retrieval>: "
141 " unknown attribute value syntax='%s'",
142 (const char *) attr->children->content);
146 else if (!xmlStrcmp(attr->name, BAD_CAST "identifier") &&
147 attr->children && attr->children->type == XML_TEXT_NODE)
149 nmem_strdup(p->nmem, (const char *) attr->children->content);
150 else if (!xmlStrcmp(attr->name, BAD_CAST "name") &&
151 attr->children && attr->children->type == XML_TEXT_NODE)
153 nmem_strdup(p->nmem, (const char *) attr->children->content);
156 wrbuf_printf(p->wr_error, "Element <retrieval>: "
157 " expected attributes 'syntax', identifier' or "
158 "'name', got '%s'", attr->name);
165 wrbuf_printf(p->wr_error, "Missing 'syntax' attribute");
169 /* parsing backend element */
171 el->record_conv = 0; /* OK to have no 'backend' sub content */
172 for (ptr = ptr->children; ptr; ptr = ptr->next)
174 if (ptr->type != XML_ELEMENT_NODE)
176 if (strcmp((const char *) ptr->name, "backend")){
177 wrbuf_printf(p->wr_error, "Element <retrieval>: expected"
178 " zero or one element <backend>, got <%s>",
179 (const char *) ptr->name);
185 /* parsing attributees */
186 struct _xmlAttr *attr;
187 for (attr = ptr->properties; attr; attr = attr->next){
189 if (!xmlStrcmp(attr->name, BAD_CAST "name")
191 && attr->children->type == XML_TEXT_NODE)
193 = nmem_strdup(p->nmem,
194 (const char *) attr->children->content);
196 else if (!xmlStrcmp(attr->name, BAD_CAST "syntax")
198 && attr->children->type == XML_TEXT_NODE){
200 = yaz_string_to_oid_odr(
203 (const char *) attr->children->content,
205 if (!el->backend_syntax){
206 wrbuf_printf(p->wr_error,
207 "Element <backend syntax='%s'>: "
208 "attribute 'syntax' has invalid "
210 attr->children->content,
211 attr->children->content);
216 wrbuf_printf(p->wr_error, "Element <backend>: expected "
217 "attributes 'syntax' or 'name, got '%s'",
224 /* parsing internal of record conv */
225 el->record_conv = yaz_record_conv_create();
227 yaz_record_conv_set_path(el->record_conv, p->path);
230 if (yaz_record_conv_configure(el->record_conv, ptr))
232 wrbuf_printf(p->wr_error, "%s",
233 yaz_record_conv_get_error(el->record_conv));
234 yaz_record_conv_destroy(el->record_conv);
241 p->list_p = &el->next;
245 int yaz_retrieval_configure(yaz_retrieval_t p, const xmlNode *ptr)
247 yaz_retrieval_reset(p);
249 if (ptr && ptr->type == XML_ELEMENT_NODE &&
250 !strcmp((const char *) ptr->name, "retrievalinfo"))
252 for (ptr = ptr->children; ptr; ptr = ptr->next)
254 if (ptr->type != XML_ELEMENT_NODE)
256 if (!strcmp((const char *) ptr->name, "retrieval"))
258 if (conf_retrieval(p, ptr))
263 wrbuf_printf(p->wr_error, "Element <retrievalinfo>: "
264 "expected element <retrieval>, got <%s>",
272 wrbuf_printf(p->wr_error, "Expected element <retrievalinfo>");
278 int yaz_retrieval_request(yaz_retrieval_t p,
279 const char *schema, Odr_oid *syntax,
280 const char **match_schema, Odr_oid **match_syntax,
281 yaz_record_conv_t *rc,
282 const char **backend_schema,
283 Odr_oid **backend_syntax)
285 struct yaz_retrieval_elem *el = p->list;
286 int syntax_matches = 0;
287 int schema_matches = 0;
289 wrbuf_rewind(p->wr_error);
292 for(; el; el = el->next)
301 if (el->name && yaz_match_glob(el->name, schema))
303 if (el->identifier && !strcmp(schema, el->identifier))
305 if (!el->name && !el->identifier)
309 if (syntax && el->syntax && !oid_oidcmp(syntax, el->syntax))
318 if (syntax_ok && schema_ok)
320 *match_syntax = el->syntax;
322 *match_schema = el->identifier;
327 if (el->backend_name)
328 *backend_schema = el->backend_name;
330 *backend_schema = el->name;
332 *backend_schema = schema;
336 if (el->backend_syntax)
337 *backend_syntax = el->backend_syntax;
339 *backend_syntax = el->syntax;
342 *rc = el->record_conv;
346 if (!syntax_matches && syntax)
348 char buf[OID_STR_MAX];
349 wrbuf_printf(p->wr_error, "%s", oid_oid_to_dotstring(syntax, buf));
353 wrbuf_printf(p->wr_error, "%s", schema);
359 const char *yaz_retrieval_get_error(yaz_retrieval_t p)
361 return wrbuf_cstr(p->wr_error);
364 void yaz_retrieval_set_path(yaz_retrieval_t p, const char *path)
369 p->path = xstrdup(path);
377 * indent-tabs-mode: nil
379 * vim: shiftwidth=4 tabstop=8 expandtab