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