Implement yaz_retrieval_configure.
[yaz-moved-to-github.git] / src / retrieval.c
1 /*
2  * Copyright (C) 2005-2006, Index Data ApS
3  * See the file LICENSE for details.
4  *
5  * $Id: retrieval.c,v 1.2 2006-05-05 18:37:08 adam Exp $
6  */
7 /**
8  * \file retrieval.c
9  * \brief Retrieval utility
10  */
11
12 #if HAVE_CONFIG_H
13 #include <config.h>
14 #endif
15
16 #include <string.h>
17 #include <yaz/retrieval.h>
18 #include <yaz/wrbuf.h>
19 #include <yaz/xmalloc.h>
20 #include <yaz/nmem.h>
21 #include <yaz/tpath.h>
22
23 #if HAVE_XSLT
24 #include <libxml/parser.h>
25 #include <libxml/tree.h>
26 #include <libxml/xinclude.h>
27 #include <libxslt/xsltutils.h>
28 #include <libxslt/transform.h>
29
30 /** \brief The internal structure for yaz_retrieval_t */
31 struct yaz_retrieval_struct {
32     /** \brief memory for configuration */
33     NMEM nmem;
34
35     /** \brief string buffer for error messages */
36     WRBUF wr_error;
37
38     /** \brief path for opening files  */
39     char *path;
40
41     /** \brief retrieval list */
42     struct yaz_retrieval_elem *list;
43
44     /** \brief last pointer in retrieval list */
45     struct yaz_retrieval_elem **list_p;
46 };
47
48 /** \brief information per 'retrieval' construct */
49 struct yaz_retrieval_elem {
50     /** \brief schema identifier */
51     const char *identifier;
52     /** \brief schema short-hand (such sa "dc") */
53     const char *schema;
54     /** \brief record syntax */
55     const char *syntax;
56     /** \brief backend schema */
57     const char *backend_schema;
58     /** \brief backend syntax */
59     const char *backend_syntax;
60
61     /** \brief record conversion */
62     yaz_record_conv_t record_conv;
63
64     /** \breif next element in list */
65     struct yaz_retrieval_elem *next;
66 };
67
68 static void yaz_retrieval_reset(yaz_retrieval_t p);
69
70 yaz_retrieval_t yaz_retrieval_create()
71 {
72     yaz_retrieval_t p = xmalloc(sizeof(*p));
73     p->nmem = nmem_create();
74     p->wr_error = wrbuf_alloc();
75     p->list = 0;
76     p->path = 0;
77     yaz_retrieval_reset(p);
78     return p;
79 }
80
81 void yaz_retrieval_destroy(yaz_retrieval_t p)
82 {
83     if (p)
84     {
85         yaz_retrieval_reset(p);
86         nmem_destroy(p->nmem);
87         wrbuf_free(p->wr_error, 1);
88         xfree(p->path);
89         xfree(p);
90     }
91 }
92
93 void yaz_retrieval_reset(yaz_retrieval_t p)
94 {
95     struct yaz_retrieval_elem *el = p->list;
96     for(; el; el = el->next)
97         yaz_record_conv_destroy(el->record_conv);
98
99     wrbuf_rewind(p->wr_error);
100     nmem_reset(p->nmem);
101
102     p->list = 0;
103     p->list_p = &p->list;
104 }
105
106 /** \brief parse retrieval XML config */
107 static int conf_retrieval(yaz_retrieval_t p, const xmlNode *ptr)
108 {
109
110     struct _xmlAttr *attr;
111     struct yaz_retrieval_elem *el = nmem_malloc(p->nmem, sizeof(*el));
112
113     el->syntax = 0;
114     el->identifier = 0;
115     el->schema = 0;
116     el->backend_schema = 0;
117     el->backend_syntax = 0;
118
119     el->next = 0;
120
121     for (attr = ptr->properties; attr; attr = attr->next)
122     {
123         if (!xmlStrcmp(attr->name, BAD_CAST "syntax") &&
124             attr->children && attr->children->type == XML_TEXT_NODE)
125             el->syntax = 
126                 nmem_strdup(p->nmem, (const char *) attr->children->content);
127         else if (!xmlStrcmp(attr->name, BAD_CAST "identifier") &&
128             attr->children && attr->children->type == XML_TEXT_NODE)
129             el->identifier =
130                 nmem_strdup(p->nmem, (const char *) attr->children->content);
131         else if (!xmlStrcmp(attr->name, BAD_CAST "schema") &&
132                  attr->children && attr->children->type == XML_TEXT_NODE)
133             el->schema = 
134                 nmem_strdup(p->nmem, (const char *) attr->children->content);
135         else if (!xmlStrcmp(attr->name, BAD_CAST "backendschema") &&
136                  attr->children && attr->children->type == XML_TEXT_NODE)
137             el->backend_schema = 
138                 nmem_strdup(p->nmem, (const char *) attr->children->content);
139         else if (!xmlStrcmp(attr->name, BAD_CAST "backendsyntax") &&
140                  attr->children && attr->children->type == XML_TEXT_NODE)
141             el->backend_syntax = 
142                 nmem_strdup(p->nmem, (const char *) attr->children->content);
143         else
144         {
145             wrbuf_printf(p->wr_error, "Bad attribute '%s'.", attr->name);
146             return -1;
147         }
148     }
149     el->record_conv = yaz_record_conv_create();
150
151     yaz_record_conv_set_path(el->record_conv, p->path);
152     
153     if (yaz_record_conv_configure(el->record_conv, ptr->children))
154     {
155         wrbuf_printf(p->wr_error, "%s",
156                      yaz_record_conv_get_error(el->record_conv));
157         yaz_record_conv_destroy(el->record_conv);
158         return -1;
159     }
160     
161     *p->list_p = el;
162     p->list_p = &el->next;
163     return 0;
164 }
165
166 int yaz_retrieval_configure(yaz_retrieval_t p, const void *ptr_v)
167 {
168     const xmlNode *ptr = ptr_v; 
169
170     yaz_retrieval_reset(p);
171
172     if (ptr && ptr->type == XML_ELEMENT_NODE &&
173         !strcmp((const char *) ptr->name, "retrievalinfo"))
174     {
175         for (ptr = ptr->children; ptr; ptr = ptr->next)
176         {
177             if (ptr->type != XML_ELEMENT_NODE)
178                 continue;
179             if (!strcmp((const char *) ptr->name, "retrieval"))
180             {
181                 if (conf_retrieval(p, ptr))
182                     return -1;
183             }
184             else
185             {
186                 wrbuf_printf(p->wr_error, "Bad element '%s'."
187                              " Expected 'retrieval'", ptr->name);
188                 return -1;
189             }
190         }
191     }
192     else
193     {
194         wrbuf_printf(p->wr_error, "Missing 'retrievalinfo' element");
195         return -1;
196     }
197     return 0;
198 }
199
200 int yaz_retrieval_request(yaz_retrieval_t p, const char *schema,
201                           const char *syntax, yaz_record_conv_t *rc)
202 {
203     wrbuf_rewind(p->wr_error);
204     wrbuf_printf(p->wr_error, "yaz_retrieval_request: not implemented");
205     return -1;
206 }
207
208 const char *yaz_retrieval_get_error(yaz_retrieval_t p)
209 {
210     return wrbuf_buf(p->wr_error);
211 }
212
213 void yaz_retrieval_set_path(yaz_retrieval_t p, const char *path)
214 {
215     xfree(p->path);
216     p->path = 0;
217     if (path)
218         p->path = xstrdup(path);
219 }
220
221 #endif
222
223 /*
224  * Local variables:
225  * c-basic-offset: 4
226  * indent-tabs-mode: nil
227  * End:
228  * vim: shiftwidth=4 tabstop=8 expandtab
229  */
230