2 * Copyright (C) 2005-2006, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: retrieval.c,v 1.5 2006-05-08 10:16:47 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 short-hand (such sa "dc") */
56 /** \brief record syntax */
58 /** \brief backend schema */
59 const char *backend_schema;
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_schema = 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 nmem_strdup(p->nmem, (const char *) attr->children->content);
147 else if (!xmlStrcmp(attr->name, BAD_CAST "backendschema") &&
148 attr->children && attr->children->type == XML_TEXT_NODE)
150 nmem_strdup(p->nmem, (const char *) attr->children->content);
151 else if (!xmlStrcmp(attr->name, BAD_CAST "backendsyntax") &&
152 attr->children && attr->children->type == XML_TEXT_NODE)
154 el->backend_syntax = yaz_str_to_z3950oid(
155 p->odr, CLASS_RECSYN,
156 (const char *) attr->children->content);
157 if (!el->backend_syntax)
159 wrbuf_printf(p->wr_error, "Bad backendsyntax '%s'",
160 (const char *) attr->children->content);
166 wrbuf_printf(p->wr_error, "Bad attribute '%s'.", attr->name);
172 wrbuf_printf(p->wr_error, "Missing 'syntax' attribute");
176 el->record_conv = 0; /* OK to have no 'convert' sub content */
177 for (ptr = ptr->children; ptr; ptr = ptr->next)
179 if (ptr->type == XML_ELEMENT_NODE)
181 el->record_conv = yaz_record_conv_create();
183 yaz_record_conv_set_path(el->record_conv, p->path);
185 if (yaz_record_conv_configure(el->record_conv, ptr))
187 wrbuf_printf(p->wr_error, "%s",
188 yaz_record_conv_get_error(el->record_conv));
189 yaz_record_conv_destroy(el->record_conv);
196 p->list_p = &el->next;
200 int yaz_retrieval_configure(yaz_retrieval_t p, const void *ptr_v)
202 const xmlNode *ptr = ptr_v;
204 yaz_retrieval_reset(p);
206 if (ptr && ptr->type == XML_ELEMENT_NODE &&
207 !strcmp((const char *) ptr->name, "retrievalinfo"))
209 for (ptr = ptr->children; ptr; ptr = ptr->next)
211 if (ptr->type != XML_ELEMENT_NODE)
213 if (!strcmp((const char *) ptr->name, "retrieval"))
215 if (conf_retrieval(p, ptr))
220 wrbuf_printf(p->wr_error, "Bad element '%s'."
221 " Expected 'retrieval'", ptr->name);
228 wrbuf_printf(p->wr_error, "Missing 'retrievalinfo' element");
234 int yaz_retrieval_request(yaz_retrieval_t p,
235 const char *schema, int *syntax,
236 const char **match_schema, int **match_syntax,
237 yaz_record_conv_t *rc,
238 const char **backend_schema,
239 int **backend_syntax)
241 struct yaz_retrieval_elem *el = p->list;
243 int syntax_matches = 0;
244 int schema_matches = 0;
245 for(; el; el = el->next)
250 if (schema && el->schema && !strcmp(schema, el->schema))
252 if (schema && el->identifier && !strcmp(schema, el->identifier))
257 if (syntax && el->syntax && !oid_oidcmp(syntax, el->syntax))
266 if (syntax_ok && schema_ok)
268 *match_syntax = el->syntax;
269 *match_schema = el->schema;
271 *backend_schema = el->backend_schema;
273 *backend_syntax = el->backend_syntax;
275 *rc = el->record_conv;
279 if (syntax_matches && !schema_matches)
281 if (!syntax_matches && schema_matches)
283 if (!syntax_matches && !schema_matches)
288 const char *yaz_retrieval_get_error(yaz_retrieval_t p)
290 return wrbuf_buf(p->wr_error);
293 void yaz_retrieval_set_path(yaz_retrieval_t p, const char *path)
298 p->path = xstrdup(path);
306 * indent-tabs-mode: nil
308 * vim: shiftwidth=4 tabstop=8 expandtab