2 * Copyright (C) 2005-2006, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: retrieval.c,v 1.4 2006-05-07 17:45:41 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>
28 #include <libxslt/xsltutils.h>
29 #include <libxslt/transform.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 short-hand (such sa "dc") */
58 /** \brief record syntax */
60 /** \brief backend schema */
61 const char *backend_schema;
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 = p->odr->mem;
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_free(p->wr_error, 1);
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_schema = 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_str_to_z3950oid(
132 p->odr, CLASS_RECSYN,
133 (const char *) attr->children->content);
136 wrbuf_printf(p->wr_error, "Bad syntax '%s'",
137 (const char *) attr->children->content);
141 else if (!xmlStrcmp(attr->name, BAD_CAST "identifier") &&
142 attr->children && attr->children->type == XML_TEXT_NODE)
144 nmem_strdup(p->nmem, (const char *) attr->children->content);
145 else if (!xmlStrcmp(attr->name, BAD_CAST "schema") &&
146 attr->children && attr->children->type == XML_TEXT_NODE)
148 nmem_strdup(p->nmem, (const char *) attr->children->content);
149 else if (!xmlStrcmp(attr->name, BAD_CAST "backendschema") &&
150 attr->children && attr->children->type == XML_TEXT_NODE)
152 nmem_strdup(p->nmem, (const char *) attr->children->content);
153 else if (!xmlStrcmp(attr->name, BAD_CAST "backendsyntax") &&
154 attr->children && attr->children->type == XML_TEXT_NODE)
156 el->backend_syntax = yaz_str_to_z3950oid(
157 p->odr, CLASS_RECSYN,
158 (const char *) attr->children->content);
159 if (!el->backend_syntax)
161 wrbuf_printf(p->wr_error, "Bad backendsyntax '%s'",
162 (const char *) attr->children->content);
168 wrbuf_printf(p->wr_error, "Bad attribute '%s'.", attr->name);
174 wrbuf_printf(p->wr_error, "Missing 'syntax' attribute");
178 el->record_conv = 0; /* OK to have no 'convert' sub content */
179 for (ptr = ptr->children; ptr; ptr = ptr->next)
181 if (ptr->type == XML_ELEMENT_NODE)
183 el->record_conv = yaz_record_conv_create();
185 yaz_record_conv_set_path(el->record_conv, p->path);
187 if (yaz_record_conv_configure(el->record_conv, ptr))
189 wrbuf_printf(p->wr_error, "%s",
190 yaz_record_conv_get_error(el->record_conv));
191 yaz_record_conv_destroy(el->record_conv);
198 p->list_p = &el->next;
202 int yaz_retrieval_configure(yaz_retrieval_t p, const void *ptr_v)
204 const xmlNode *ptr = ptr_v;
206 yaz_retrieval_reset(p);
208 if (ptr && ptr->type == XML_ELEMENT_NODE &&
209 !strcmp((const char *) ptr->name, "retrievalinfo"))
211 for (ptr = ptr->children; ptr; ptr = ptr->next)
213 if (ptr->type != XML_ELEMENT_NODE)
215 if (!strcmp((const char *) ptr->name, "retrieval"))
217 if (conf_retrieval(p, ptr))
222 wrbuf_printf(p->wr_error, "Bad element '%s'."
223 " Expected 'retrieval'", ptr->name);
230 wrbuf_printf(p->wr_error, "Missing 'retrievalinfo' element");
236 int yaz_retrieval_request(yaz_retrieval_t p,
237 const char *schema, int *syntax,
238 const char **match_schema, int **match_syntax,
239 yaz_record_conv_t *rc,
240 const char **backend_schema,
241 int **backend_syntax)
243 struct yaz_retrieval_elem *el = p->list;
245 int syntax_matches = 0;
246 int schema_matches = 0;
247 for(; el; el = el->next)
252 if (schema && el->schema && !strcmp(schema, el->schema))
254 if (schema && el->identifier && !strcmp(schema, el->identifier))
259 if (syntax && el->syntax && !oid_oidcmp(syntax, el->syntax))
268 if (syntax_ok && schema_ok)
270 *match_syntax = el->syntax;
271 *match_schema = el->schema;
273 *backend_schema = el->backend_schema;
275 *backend_syntax = el->backend_syntax;
277 *rc = el->record_conv;
281 if (syntax_matches && !schema_matches)
283 if (!syntax_matches && schema_matches)
285 if (!syntax_matches && !schema_matches)
290 const char *yaz_retrieval_get_error(yaz_retrieval_t p)
292 return wrbuf_buf(p->wr_error);
295 void yaz_retrieval_set_path(yaz_retrieval_t p, const char *path)
300 p->path = xstrdup(path);
308 * indent-tabs-mode: nil
310 * vim: shiftwidth=4 tabstop=8 expandtab