2 * Copyright (C) 2005-2006, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: retrieval.c,v 1.12 2006-10-10 09:13:52 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>
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 sa "dc" */
56 /** \brief record syntax */
58 /** \brief backend name */
59 const char *backend_name;
60 /** \brief backend syntax */
63 /** \brief record conversion */
64 yaz_record_conv_t record_conv;
66 /** \brief next element in list */
67 struct yaz_retrieval_elem *next;
70 static void yaz_retrieval_reset(yaz_retrieval_t p);
72 yaz_retrieval_t yaz_retrieval_create()
74 yaz_retrieval_t p = xmalloc(sizeof(*p));
75 p->odr = odr_createmem(ODR_ENCODE);
76 p->nmem = p->odr->mem;
77 p->wr_error = wrbuf_alloc();
80 yaz_retrieval_reset(p);
84 void yaz_retrieval_destroy(yaz_retrieval_t p)
88 yaz_retrieval_reset(p);
90 wrbuf_free(p->wr_error, 1);
96 void yaz_retrieval_reset(yaz_retrieval_t p)
98 struct yaz_retrieval_elem *el = p->list;
99 for(; el; el = el->next)
100 yaz_record_conv_destroy(el->record_conv);
102 wrbuf_rewind(p->wr_error);
106 p->list_p = &p->list;
109 /** \brief parse retrieval XML config */
110 static int conf_retrieval(yaz_retrieval_t p, const xmlNode *ptr)
113 struct _xmlAttr *attr;
114 struct yaz_retrieval_elem *el = nmem_malloc(p->nmem, sizeof(*el));
119 el->backend_name = 0;
120 el->backend_syntax = 0;
124 for (attr = ptr->properties; attr; attr = attr->next)
126 if (!xmlStrcmp(attr->name, BAD_CAST "syntax") &&
127 attr->children && attr->children->type == XML_TEXT_NODE)
129 el->syntax = yaz_str_to_z3950oid(
130 p->odr, CLASS_RECSYN,
131 (const char *) attr->children->content);
134 wrbuf_printf(p->wr_error, "Bad syntax '%s'",
135 (const char *) attr->children->content);
139 else if (!xmlStrcmp(attr->name, BAD_CAST "identifier") &&
140 attr->children && attr->children->type == XML_TEXT_NODE)
142 nmem_strdup(p->nmem, (const char *) attr->children->content);
143 else if (!xmlStrcmp(attr->name, BAD_CAST "schema") &&
144 attr->children && attr->children->type == XML_TEXT_NODE)
146 wrbuf_printf(p->wr_error, "Bad attribute 'schema'. "
147 "Use 'name' instead");
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);
154 else if (!xmlStrcmp(attr->name, BAD_CAST "backendschema") &&
155 attr->children && attr->children->type == XML_TEXT_NODE)
157 wrbuf_printf(p->wr_error, "Bad attribute 'backendschema'. "
158 "Use 'backendname' instead");
161 else if (!xmlStrcmp(attr->name, BAD_CAST "backendname") &&
162 attr->children && attr->children->type == XML_TEXT_NODE)
164 nmem_strdup(p->nmem, (const char *) attr->children->content);
165 else if (!xmlStrcmp(attr->name, BAD_CAST "backendsyntax") &&
166 attr->children && attr->children->type == XML_TEXT_NODE)
168 el->backend_syntax = yaz_str_to_z3950oid(
169 p->odr, CLASS_RECSYN,
170 (const char *) attr->children->content);
171 if (!el->backend_syntax)
173 wrbuf_printf(p->wr_error, "Bad backendsyntax '%s'",
174 (const char *) attr->children->content);
180 wrbuf_printf(p->wr_error, "Bad attribute '%s'.", attr->name);
186 wrbuf_printf(p->wr_error, "Missing 'syntax' attribute");
190 el->record_conv = 0; /* OK to have no 'convert' sub content */
191 for (ptr = ptr->children; ptr; ptr = ptr->next)
193 if (ptr->type == XML_ELEMENT_NODE)
195 el->record_conv = yaz_record_conv_create();
197 yaz_record_conv_set_path(el->record_conv, p->path);
199 if (yaz_record_conv_configure(el->record_conv, ptr))
201 wrbuf_printf(p->wr_error, "%s",
202 yaz_record_conv_get_error(el->record_conv));
203 yaz_record_conv_destroy(el->record_conv);
210 p->list_p = &el->next;
214 int yaz_retrieval_configure(yaz_retrieval_t p, const void *ptr_v)
216 const xmlNode *ptr = ptr_v;
218 yaz_retrieval_reset(p);
220 if (ptr && ptr->type == XML_ELEMENT_NODE &&
221 !strcmp((const char *) ptr->name, "retrievalinfo"))
223 for (ptr = ptr->children; ptr; ptr = ptr->next)
225 if (ptr->type != XML_ELEMENT_NODE)
227 if (!strcmp((const char *) ptr->name, "retrieval"))
229 if (conf_retrieval(p, ptr))
234 wrbuf_printf(p->wr_error, "Bad element '%s'."
235 " Expected 'retrieval'", ptr->name);
242 wrbuf_printf(p->wr_error, "Missing 'retrievalinfo' element");
248 int yaz_retrieval_request(yaz_retrieval_t p,
249 const char *schema, int *syntax,
250 const char **match_schema, int **match_syntax,
251 yaz_record_conv_t *rc,
252 const char **backend_schema,
253 int **backend_syntax)
255 struct yaz_retrieval_elem *el = p->list;
256 int syntax_matches = 0;
257 int schema_matches = 0;
259 wrbuf_rewind(p->wr_error);
262 for(; el; el = el->next)
271 if (el->name && !strcmp(schema, el->name))
273 if (el->identifier && !strcmp(schema, el->identifier))
275 if (!el->name && !el->identifier)
279 if (syntax && el->syntax && !oid_oidcmp(syntax, el->syntax))
288 if (syntax_ok && schema_ok)
290 *match_syntax = el->syntax;
292 *match_schema = el->identifier;
297 if (el->backend_name)
298 *backend_schema = el->backend_name;
300 *backend_schema = el->name;
302 *backend_schema = schema;
306 if (el->backend_syntax)
307 *backend_syntax = el->backend_syntax;
309 *backend_syntax = el->syntax;
312 *rc = el->record_conv;
316 if (!syntax_matches && syntax)
318 char buf[OID_STR_MAX];
319 wrbuf_printf(p->wr_error, "%s", oid_to_dotstring(syntax, buf));
323 wrbuf_printf(p->wr_error, "%s", schema);
329 const char *yaz_retrieval_get_error(yaz_retrieval_t p)
331 return wrbuf_buf(p->wr_error);
334 void yaz_retrieval_set_path(yaz_retrieval_t p, const char *path)
339 p->path = xstrdup(path);
347 * indent-tabs-mode: nil
349 * vim: shiftwidth=4 tabstop=8 expandtab