YAZ version 1.4.
[yaz-moved-to-github.git] / retrieval / d1_expout.c
1 /*
2  * Copyright (c) 1995, Index Data.
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: d1_expout.c,v $
7  * Revision 1.3  1997-09-17 12:10:36  adam
8  * YAZ version 1.4.
9  *
10  * Revision 1.2  1995/12/14 16:28:30  quinn
11  * More explain stuff.
12  *
13  * Revision 1.1  1995/12/14  11:09:51  quinn
14  * Work on Explain
15  *
16  *
17  */
18
19 #include <assert.h>
20 #include <string.h>
21 #include <stdlib.h>
22
23 #include <log.h>
24 #include <proto.h>
25 #include <data1.h>
26
27 static int *f_integer(data1_node *c, ODR o)
28 {
29     int *r;
30     char intbuf[64];
31
32     if (!c->child || c->child->which != DATA1N_data ||
33         c->child->u.data.len > 63)
34         return 0;
35     r = odr_malloc(o, sizeof(*r));
36     sprintf(intbuf, "%.*s", 63, c->child->u.data.data);
37     *r = atoi(intbuf);
38     return r;
39 }
40
41 static char *f_string(data1_node *c, ODR o)
42 {
43     char *r;
44
45     if (!c->child || c->child->which != DATA1N_data)
46         return 0;
47     r = odr_malloc(o, c->child->u.data.len+1);
48     memcpy(r, c->child->u.data.data, c->child->u.data.len);
49     r[c->child->u.data.len] = '\0';
50     return r;
51 }
52
53 static bool_t *f_bool(data1_node *c, ODR o)
54 {
55     return 0;
56 }
57
58 static Z_IntUnit *f_intunit(data1_node *c, ODR o)
59 {
60     return 0;
61 }
62
63 static Z_HumanString *f_humstring(data1_node *c, ODR o)
64 {
65     Z_HumanString *r;
66     Z_HumanStringUnit *u;
67
68     if (!c->child || c->child->which != DATA1N_data)
69         return 0;
70     r = odr_malloc(o, sizeof(*r));
71     r->num_strings = 1;
72     r->strings = odr_malloc(o, sizeof(Z_HumanStringUnit*));
73     r->strings[0] = u = odr_malloc(o, sizeof(*u));
74     u->language = 0;
75     u->text = odr_malloc(o, c->child->u.data.len+1);
76     memcpy(u->text, c->child->u.data.data, c->child->u.data.len);
77     u->text[c->child->u.data.len] = '\0';
78     return r;
79 }
80
81 static Z_CommonInfo *f_commonInfo(data1_node *n, int select, ODR o)
82 {
83     Z_CommonInfo *res = odr_malloc(o, sizeof(*res));
84     data1_node *c;
85
86     res->dateAdded = 0;
87     res->dateChanged = 0;
88     res->expiry = 0;
89     res->humanStringLanguage = 0;
90     res->otherInfo = 0;
91
92     for (c = n->child; c; c = c->next)
93     {
94         if (c->which != DATA1N_tag || !c->u.tag.element)
95         {
96             logf(LOG_WARN, "Malformed explain record");
97             return 0;
98         }
99         if (select && !c->u.tag.node_selected)
100             continue;
101         switch (c->u.tag.element->tag->value.numeric)
102         {
103             case 601: res->dateAdded = f_string(c, o); break;
104             case 602: res->dateChanged = f_string(c, o); break;
105             case 603: res->expiry = f_string(c, o); break;
106             case 604: res->humanStringLanguage = f_string(c, o); break;
107             /* otherInfo? */
108             default:
109                 logf(LOG_WARN, "Bad child in commonInfo");
110                 return 0;
111         }
112     }
113     return res;
114 }
115
116 static Z_AccessInfo *f_accessInfo(data1_node *n, int select, ODR o)
117 {
118     Z_AccessInfo *res = odr_malloc(o, sizeof(*res));
119     data1_node *c;
120
121     res->num_queryTypesSupported = 0;
122     res->queryTypesSupported = 0;
123     res->num_diagnosticsSets = 0;
124     res->diagnosticsSets = 0;
125     res->num_attributeSetIds = 0;
126     res->attributeSetIds = 0;
127     res->num_schemas = 0;
128     res->schemas = 0;
129     res->num_recordSyntaxes = 0;
130     res->recordSyntaxes = 0;
131     res->num_resourceChallenges = 0;
132     res->resourceChallenges = 0;
133     res->restrictedAccess = 0;
134     res->costInfo = 0;
135     res->num_variantSets = 0;
136     res->variantSets = 0;
137     res->num_elementSetNames = 0;
138     res->elementSetNames = 0;
139     res->num_unitSystems = 0;
140     res->unitSystems = 0;
141
142     for (c = n->child; c; c = c->next)
143     {
144         if (c->which != DATA1N_tag || !c->u.tag.element)
145         {
146             logf(LOG_WARN, "Malformed explain record");
147             return 0;
148         }
149         if (select && !c->u.tag.node_selected)
150             continue;
151         /* switch-statement here */
152     }
153     return res;
154 }
155
156 static int *f_recordCount(data1_node *c, ODR o, void *which)
157 {
158     int *r= odr_malloc(o, sizeof(*r));
159     int *wp = which;
160     char intbuf[64];
161
162     if (!c->child || c->child->which != DATA1N_tag || !c->child->u.tag.element)
163         return 0;
164     if (c->u.tag.element->tag->value.numeric == 210)
165         *wp = Z_Exp_RecordCount_actualNumber;
166     else if (c->u.tag.element->tag->value.numeric == 211)
167         *wp = Z_Exp_RecordCount_approxNumber;
168     else
169         return 0;
170     c = c->child;
171     if (!c->child || c->child->which != DATA1N_data)
172         return 0;
173     sprintf(intbuf, "%.*s", 63, c->child->u.data.data);
174     *r = atoi(intbuf);
175     return r;
176 }
177
178 static Z_ContactInfo *f_contactInfo(data1_node *n, ODR o)
179 {
180     return 0;
181 }
182
183 static Z_TargetInfo *f_targetInfo(data1_node *n, int select, ODR o)
184 {
185     Z_TargetInfo *res = odr_malloc(o, sizeof(*res));
186     data1_node *c;
187     bool_t *fl = odr_malloc(o,sizeof(*fl));
188
189     *fl = 0;
190     res->commonInfo = 0;
191     res->name = 0;
192     res->recentNews = 0;
193     res->icon = 0;
194     res->namedResultSets = fl;
195     res->multipleDbSearch = fl;
196     res->maxResultSets = 0;
197     res->maxResultSize = 0;
198     res->maxTerms = 0;
199     res->timeoutInterval = 0;
200     res->welcomeMessage = 0;
201     res->contactInfo = 0;
202     res->description = 0;
203     res->num_nicknames = 0;
204     res->nicknames = 0;
205     res->usageRest = 0;
206     res->paymentAddr = 0;
207     res->hours = 0;
208     res->num_dbCombinations = 0;
209     res->dbCombinations = 0;
210     res->num_addresses = 0;
211     res->addresses = 0;
212     res->commonAccessInfo = 0;
213
214     for (c = n->child; c; c = c->next)
215     {
216         if (c->which != DATA1N_tag || !c->u.tag.element)
217         {
218             logf(LOG_WARN, "Malformed explain record");
219             return 0;
220         }
221         if (select && !c->u.tag.node_selected)
222             continue;
223         switch (c->u.tag.element->tag->value.numeric)
224         {
225             case 600: res->commonInfo = f_commonInfo(c, select, o);break;
226             case 102: res->name = f_string(c, o); break;
227             case 103: res->recentNews = f_humstring(c, o); break;
228             case 104: break; /* icon */
229             case 105: res->namedResultSets = f_bool(c, o); break;
230             case 106: res->multipleDbSearch = f_bool(c, o); break;
231             case 107: res->maxResultSets = f_integer(c, o); break;
232             case 108: res->maxResultSize = f_integer(c, o); break;
233             case 109: res->maxTerms = f_integer(c, o); break;
234             case 110: res->timeoutInterval = f_intunit(c, o); break;
235             case 111: res->welcomeMessage = f_humstring(c, o); break;
236             case 112: res->contactInfo = f_contactInfo(c, o); break;
237             case 113: res->description = f_humstring(c, o); break;
238             case 114: break; /* nicknames */
239             case 115: res->usageRest = f_humstring(c, o); break;
240             case 116: res->paymentAddr = f_humstring(c, o); break;
241             case 117: res->hours = f_humstring(c, o); break;
242             case 118: break; /* dbcombinations */
243             case 119: break; /* addresses */
244             case 500: res->commonAccessInfo = f_accessInfo(c, select, o); break;
245             default:
246                 logf(LOG_WARN, "Unknown target-info element");
247         }
248     }
249     return res;
250 }
251
252 static Z_DatabaseInfo *f_databaseInfo(data1_node *n, int select, ODR o)
253 {
254     Z_DatabaseInfo *res = odr_malloc(o, sizeof(*res));
255     data1_node *c;
256     bool_t *fl = odr_malloc(o,sizeof(*fl));
257     bool_t *tr = odr_malloc(o,sizeof(*tr));
258
259     *fl = 0;
260     *tr = 1;
261     res->commonInfo = 0;
262     res->name = 0;
263     res->explainDatabase = 0;
264     res->num_nicknames = 0;
265     res->nicknames = 0;
266     res->icon = 0;
267     res->userFee = fl;
268     res->available = tr;
269     res->titleString = 0;
270     res->num_keywords = 0;
271     res->keywords = 0;
272     res->description = 0;
273     res->associatedDbs = 0;
274     res->subDbs = 0;
275     res->disclaimers = 0;
276     res->news = 0;
277     res->recordCount = 0;
278     res->defaultOrder = 0;
279     res->avRecordSize = 0;
280     res->maxRecordSize = 0;
281     res->hours = 0;
282     res->bestTime = 0;
283     res->lastUpdate = 0;
284     res->updateInterval = 0;
285     res->coverage = 0;
286     res->proprietary = 0;
287     res->copyrightText = 0;
288     res->copyrightNotice = 0;
289     res->producerContactInfo = 0;
290     res->supplierContactInfo = 0;
291     res->submissionContactInfo = 0;
292     res->accessInfo = 0;
293
294     for (c = n->child; c; c = c->next)
295     {
296         if (c->which != DATA1N_tag || !c->u.tag.element)
297         {
298             logf(LOG_WARN, "Malformed explain record");
299             return 0;
300         }
301         if (select && !c->u.tag.node_selected)
302             continue;
303         switch (c->u.tag.element->tag->value.numeric)
304         {
305             case 600: res->commonInfo = f_commonInfo(c, select, o); break;
306             case 102: res->name = f_string(c, o); break;
307             case 226: res->explainDatabase = ODR_NULLVAL; break;
308             case 114:
309                 res->num_nicknames = 0; res->nicknames = 0; break; /* fix */
310             case 104: res->icon = 0; break;      /* fix */
311             case 201: res->userFee = f_bool(c, o); break;
312             case 202: res->available = f_bool(c, o); break;
313             case 203: res->titleString = f_humstring(c, o); break;
314             case 227: res->num_keywords = 0; res->keywords = 0; break; /* fix */
315             case 113: res->description = f_humstring(c, o); break;
316             case 205: res->associatedDbs = 0; break; /* fix */
317             case 206: res->subDbs = 0; break; /* fix */
318             case 207: res->disclaimers = f_humstring(c, o); break;
319             case 103: res->news = f_humstring(c, o); break;
320             case 209: res->recordCount =
321                 f_recordCount(c, o, &res->recordCount_which); break;
322             case 212: res->defaultOrder = f_humstring(c, o); break;
323             case 213: res->avRecordSize = f_integer(c, o); break;
324             case 214: res->maxRecordSize = f_integer(c, o); break;
325             case 215: res->hours = f_humstring(c, o); break;
326             case 216: res->bestTime = f_humstring(c, o); break;
327             case 217: res->lastUpdate = f_string(c, o); break;
328             case 218: res->updateInterval = f_intunit(c, o); break;
329             case 219: res->coverage = f_humstring(c, o); break;
330             case 220: res->proprietary = f_bool(c, o); break;
331             case 221: res->copyrightText = f_humstring(c, o); break;
332             case 222: res->copyrightNotice = f_humstring(c, o); break;
333             case 223: res->producerContactInfo = f_contactInfo(c, o); break;
334             case 224: res->supplierContactInfo = f_contactInfo(c, o); break;
335             case 225: res->submissionContactInfo = f_contactInfo(c, o); break;
336             case 500: res->accessInfo = f_accessInfo(c, select, o); break;
337             default:
338                 logf(LOG_WARN, "Unknown element in databaseInfo");
339         }
340     }
341     return res;
342 }
343
344 Z_ExplainRecord *data1_nodetoexplain (data1_handle dh, data1_node *n,
345                                       int select, ODR o)
346 {
347     Z_ExplainRecord *res = odr_malloc(o, sizeof(*res));
348
349     assert(n->which == DATA1N_root);
350     if (strcmp(n->u.root.type, "explain"))
351     {
352         logf(LOG_WARN, "Attempt to convert a non-Explain record");
353         return 0;
354     }
355     if (n->num_children != 1 || n->child->which != DATA1N_tag ||
356         !n->u.tag.element)
357     {
358         logf(LOG_WARN, "Explain record should have one exactly one child");
359         return 0;
360     }
361     switch (n->child->u.tag.element->tag->value.numeric)
362     {
363         case 0: res->which = Z_Explain_targetInfo;
364             if (!(res->u.targetInfo = f_targetInfo(n->child, select, o)))
365                 return 0;
366             break;
367         case 1: res->which = Z_Explain_databaseInfo;
368             if (!(res->u.databaseInfo = f_databaseInfo(n->child, select, o)))
369                 return 0;
370             break;
371         default:
372             logf(LOG_WARN, "Unknown explain category");
373             return 0;
374     }
375     return res;
376 }