IDZEBRA 2.2.8
d1_grs.c
Go to the documentation of this file.
1/* This file is part of the Zebra server.
2 Copyright (C) Index Data
3
4Zebra is free software; you can redistribute it and/or modify it under
5the terms of the GNU General Public License as published by the Free
6Software Foundation; either version 2, or (at your option) any later
7version.
8
9Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or
11FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
18*/
19
20/* converts data1 tree to GRS-1 record */
21
22#if HAVE_CONFIG_H
23#include <config.h>
24#endif
25#include <assert.h>
26#include <stdlib.h>
27
28#include <yaz/proto.h>
29#include <yaz/log.h>
30#include <d1_absyn.h>
31
32#define D1_VARIANTARRAY 20 /* fixed max length on sup'd variant-list. Lazy me */
33
34static Z_GenericRecord *data1_nodetogr_r(data1_handle dh, data1_node *n,
35 int select, ODR o, int *len,
36 data1_tag *wellknown_tag);
37
38static Z_ElementMetaData *get_ElementMetaData(ODR o)
39{
40 Z_ElementMetaData *r = (Z_ElementMetaData *)odr_malloc(o, sizeof(*r));
41
42 r->seriesOrder = 0;
43 r->usageRight = 0;
44 r->num_hits = 0;
45 r->hits = 0;
46 r->displayName = 0;
47 r->num_supportedVariants = 0;
48 r->supportedVariants = 0;
49 r->message = 0;
50 r->elementDescriptor = 0;
51 r->surrogateFor = 0;
52 r->surrogateElement = 0;
53 r->other = 0;
54
55 return r;
56}
57
58/*
59 * N should point to the *last* (leaf) triple in a sequence. Construct a variant
60 * from each of the triples beginning (ending) with 'n', up to the
61 * nearest parent tag. num should equal the number of triples in the
62 * sequence.
63 */
64static Z_Variant *make_variant(data1_node *n, int num, ODR o)
65{
66 Z_Variant *v = (Z_Variant *)odr_malloc(o, sizeof(*v));
67 data1_node *p;
68
69 v->globalVariantSetId = 0;
70 v->num_triples = num;
71 v->triples = (Z_Triple **)odr_malloc(o, sizeof(Z_Triple*) * num);
72
73 /*
74 * cycle back up through the tree of variants
75 * (traversing exactly 'level' variants).
76 */
77 for (p = n, num--; p && num >= 0; p = p->parent, num--)
78 {
79 Z_Triple *t;
80
81 assert(p->which == DATA1N_variant);
82 t = v->triples[num] = (Z_Triple *)odr_malloc(o, sizeof(*t));
83 t->variantSetId = 0;
84 t->zclass = odr_intdup(o, p->u.variant.type->zclass->zclass);
85 t->type = odr_intdup(o, p->u.variant.type->type);
86
87 switch (p->u.variant.type->datatype)
88 {
89 case DATA1K_string:
90 t->which = Z_Triple_internationalString;
91 t->value.internationalString =
92 odr_strdup(o, p->u.variant.value);
93 break;
94 default:
95 yaz_log(YLOG_WARN, "Unable to handle value for variant %s",
96 p->u.variant.type->name);
97 return 0;
98 }
99 }
100 return v;
101}
102
103/*
104 * Traverse the variant children of n, constructing a supportedVariant list.
105 */
106static int traverse_triples(data1_node *n, int level, Z_ElementMetaData *m,
107 ODR o)
108{
109 data1_node *c;
110
111 for (c = n->child; c; c = c->next)
112 if (c->which == DATA1N_data && level)
113 {
114 if (!m->supportedVariants)
115 m->supportedVariants = (Z_Variant **)odr_malloc(o, sizeof(Z_Variant*) *
117 else if (m->num_supportedVariants >= D1_VARIANTARRAY)
118 {
119 yaz_log(YLOG_WARN, "Too many variants (D1_VARIANTARRAY==%d)",
121 return -1;
122 }
123
124 if (!(m->supportedVariants[m->num_supportedVariants++] =
125 make_variant(n, level, o)))
126 return -1;
127 }
128 else if (c->which == DATA1N_variant)
129 if (traverse_triples(c, level+1, m, o) < 0)
130 return -1;
131 return 0;
132}
133
134/*
135 * Locate some data under this node. This routine should handle variants
136 * prettily.
137 */
138static char *get_data(data1_node *n, int *len)
139{
140 char *r;
141 data1_node *np = 0;
142
143 while (n)
144 {
145 if (n->which == DATA1N_data)
146 {
147 int i;
148 *len = n->u.data.len;
149
150 for (i = 0; i<*len; i++)
151 if (!d1_isspace(n->u.data.data[i]))
152 break;
153 while (*len && d1_isspace(n->u.data.data[*len - 1]))
154 (*len)--;
155 *len = *len - i;
156 if (*len > 0)
157 return n->u.data.data + i;
158 }
159 if (n->which == DATA1N_tag)
160 np = n->child;
161 n = n->next;
162 if (!n)
163 {
164 n = np;
165 np = 0;
166 }
167 }
168 r = "";
169 *len = strlen(r);
170 return r;
171}
172
173static Z_ElementData *nodetoelementdata(data1_handle dh, data1_node *n,
174 int select, int leaf,
175 ODR o, int *len,
176 data1_tag *wellknown_tag)
177{
178 Z_ElementData *res = (Z_ElementData *)odr_malloc(o, sizeof(*res));
179
180 if (!n)
181 {
182 res->which = Z_ElementData_elementNotThere;
183 res->u.elementNotThere = odr_nullval();
184 }
185 else if (n->which == DATA1N_data && leaf)
186 {
187 char str[64], *cp;
188 int toget = n->u.data.len;
189
190 cp = get_data (n, &toget);
191
192 switch (n->u.data.what)
193 {
194 case DATA1I_num:
195 res->which = Z_ElementData_numeric;
196 res->u.numeric = odr_intdup(o, atoi_n(cp, toget));
197 *len += 4;
198 break;
199 case DATA1I_text:
200 case DATA1I_xmltext:
201 res->which = Z_ElementData_string;
202 res->u.string = (char *)odr_malloc(o, toget+1);
203 if (toget)
204 memcpy(res->u.string, cp, toget);
205 res->u.string[toget] = '\0';
206 *len += toget;
207 break;
208 case DATA1I_oid:
209 res->which = Z_ElementData_oid;
210 if (toget > 63)
211 toget = 63;
212 memcpy (str, cp, toget);
213 str[toget] = '\0';
214 res->u.oid = odr_getoidbystr(o, str);
215 *len += oid_oidlen(res->u.oid) * sizeof(int);
216 break;
217 default:
218 yaz_log(YLOG_WARN, "Can't handle datatype.");
219 return 0;
220 }
221 }
222 else
223 {
224 res->which = Z_ElementData_subtree;
225 if (!(res->u.subtree = data1_nodetogr_r (dh, n->parent, select, o, len,
226 wellknown_tag )))
227 return 0;
228 }
229 return res;
230}
231
233{
234 if (n && n->which == DATA1N_data && (n->u.data.what == DATA1I_text
235 || n->u.data.what == DATA1I_xmltext))
236 {
237 int i = n->u.data.len;
238
239 while (i > 0 && d1_isspace(n->u.data.data[i-1]))
240 i--;
241 if (i == 0)
242 return 1;
243 }
244 return 0;
245}
246
247
248static Z_TaggedElement *nodetotaggedelement(data1_handle dh, data1_node *n,
249 int select, ODR o,
250 int *len,
251 data1_tag *wellknown_tag)
252{
253 Z_TaggedElement *res = (Z_TaggedElement *)odr_malloc(o, sizeof(*res));
254 data1_tag *tag = 0;
255 data1_node *data;
256 int leaf = 0;
257
258 if (n->which == DATA1N_tag)
259 {
260 if (n->u.tag.element)
261 tag = n->u.tag.element->tag;
262 data = n->child;
263
264 /* skip empty data children */
265 while (is_empty_data(data))
266 data = data->next;
267 if (!data)
268 data = n->child;
269 else
270 { /* got one. see if this is the only non-empty one */
271 data1_node *sub = data->next;
272 while (sub && is_empty_data(sub))
273 sub = sub->next;
274 if (!sub)
275 leaf = 1; /* all empty. 'data' is the only child */
276 }
277 }
278 /*
279 * If we're a data element at this point, we need to insert a
280 * wellKnown tag to wrap us up.
281 */
282 else if (n->which == DATA1N_data || n->which == DATA1N_variant)
283 {
284 tag = wellknown_tag;
285 if (!tag)
286 return 0;
287 data = n;
288 leaf = 1;
289 if (is_empty_data(data))
290 return 0;
291 }
292 else
293 {
294 yaz_log(YLOG_WARN, "Bad data.");
295 return 0;
296 }
297
298 res->tagType = odr_intdup(o, (tag && tag->tagset) ? tag->tagset->type : 3);
299 res->tagValue = (Z_StringOrNumeric *)odr_malloc(o, sizeof(Z_StringOrNumeric));
300 if (tag && tag->which == DATA1T_numeric)
301 {
302 res->tagValue->which = Z_StringOrNumeric_numeric;
303 res->tagValue->u.numeric = odr_intdup(o, tag->value.numeric);
304 }
305 else
306 {
307 char *tagstr;
308
309 if (n->which == DATA1N_tag)
310 tagstr = n->u.tag.tag; /* tag at node */
311 else if (tag)
312 tagstr = tag->value.string; /* no take from well-known */
313 else
314 return 0;
315 res->tagValue->which = Z_StringOrNumeric_string;
316 res->tagValue->u.string = odr_strdup(o, tagstr);
317 }
318 res->tagOccurrence = 0;
319 res->appliedVariant = 0;
320 res->metaData = 0;
321 if (n->which == DATA1N_variant || (data && data->which ==
322 DATA1N_variant && data->next == NULL))
323 {
324 int nvars = 0;
325
326 res->metaData = get_ElementMetaData(o);
327 if (n->which == DATA1N_tag && n->u.tag.make_variantlist)
328 if (traverse_triples(data, 0, res->metaData, o) < 0)
329 return 0;
330 while (data && data->which == DATA1N_variant)
331 {
332 nvars++;
333 data = data->child;
334 }
335 if (n->which != DATA1N_tag || !n->u.tag.no_data_requested)
336 res->appliedVariant = make_variant(data->parent, nvars-1, o);
337 }
338 if (n->which == DATA1N_tag && n->u.tag.no_data_requested)
339 {
340 res->content = (Z_ElementData *)odr_malloc(o, sizeof(*res->content));
341 res->content->which = Z_ElementData_noDataRequested;
342 res->content->u.noDataRequested = odr_nullval();
343 }
344 else if (!(res->content = nodetoelementdata (dh, data, select, leaf,
345 o, len, wellknown_tag)))
346 return 0;
347 *len += 10;
348 return res;
349}
350
351static Z_GenericRecord *data1_nodetogr_r(data1_handle dh, data1_node *n,
352 int select, ODR o, int *len,
353 data1_tag *wellknown_tag)
354{
355 Z_GenericRecord *res = (Z_GenericRecord *)odr_malloc(o, sizeof(*res));
356 data1_node *c;
357 int num_children = 0;
358
359 for (c = n->child; c; c = c->next)
360 num_children++;
361
362 res->elements = (Z_TaggedElement **)
363 odr_malloc(o, sizeof(Z_TaggedElement *) * num_children);
364 res->num_elements = 0;
365 for (c = n->child; c; c = c->next)
366 {
367 if (c->which == DATA1N_tag && select && !c->u.tag.node_selected)
368 continue;
369 if ((res->elements[res->num_elements] =
370 nodetotaggedelement (dh, c, select, o, len, wellknown_tag)))
371 res->num_elements++;
372 }
373 return res;
374}
375
376Z_GenericRecord *data1_nodetogr(data1_handle dh, data1_node *n,
377 int select, ODR o, int *len)
378
379{
380 data1_tag *wellknown_tag = 0;
381
382 if (n->which == DATA1N_root)
383 n = data1_get_root_tag (dh, n);
384
385 if (n->root->u.root.absyn &&
386 !(wellknown_tag =
388 "wellKnown")))
389 {
390 yaz_log(YLOG_WARN, "Unable to locate tag for 'wellKnown'");
391 wellknown_tag = odr_malloc(o, sizeof(*wellknown_tag));
392 wellknown_tag->which = DATA1T_numeric;
393 wellknown_tag->value.numeric = 19;
394 wellknown_tag->next = 0;
395 wellknown_tag->tagset = odr_malloc(o, sizeof(*wellknown_tag->tagset));
396 wellknown_tag->tagset->type = 1;
397 wellknown_tag->kind = DATA1K_string;
398 }
399 return data1_nodetogr_r(dh, n, select, o, len, wellknown_tag);
400}
401/*
402 * Local variables:
403 * c-basic-offset: 4
404 * c-file-style: "Stroustrup"
405 * indent-tabs-mode: nil
406 * End:
407 * vim: shiftwidth=4 tabstop=8 expandtab
408 */
409
#define D1_VARIANTARRAY
Definition d1_grs.c:32
static int traverse_triples(data1_node *n, int level, Z_ElementMetaData *m, ODR o)
Definition d1_grs.c:106
static Z_TaggedElement * nodetotaggedelement(data1_handle dh, data1_node *n, int select, ODR o, int *len, data1_tag *wellknown_tag)
Definition d1_grs.c:248
static int is_empty_data(data1_node *n)
Definition d1_grs.c:232
static char * get_data(data1_node *n, int *len)
Definition d1_grs.c:138
static Z_ElementMetaData * get_ElementMetaData(ODR o)
Definition d1_grs.c:38
Z_GenericRecord * data1_nodetogr(data1_handle dh, data1_node *n, int select, ODR o, int *len)
Definition d1_grs.c:376
static Z_GenericRecord * data1_nodetogr_r(data1_handle dh, data1_node *n, int select, ODR o, int *len, data1_tag *wellknown_tag)
Definition d1_grs.c:351
static Z_Variant * make_variant(data1_node *n, int num, ODR o)
Definition d1_grs.c:64
static Z_ElementData * nodetoelementdata(data1_handle dh, data1_node *n, int select, int leaf, ODR o, int *len, data1_tag *wellknown_tag)
Definition d1_grs.c:173
@ DATA1K_string
Definition data1.h:126
#define DATA1N_variant
Definition data1.h:280
data1_node * data1_get_root_tag(data1_handle dh, data1_node *n)
Definition d1_read.c:36
data1_tag * data1_gettagbyname(data1_handle dh, data1_tagset *s, const char *name)
Definition d1_tagset.c:84
#define DATA1I_oid
Definition data1.h:318
#define DATA1N_tag
Definition data1.h:276
#define DATA1N_data
Definition data1.h:278
#define d1_isspace(c)
Definition data1.h:31
#define DATA1N_root
Definition data1.h:274
#define DATA1I_num
Definition data1.h:316
#define DATA1I_text
Definition data1.h:314
#define DATA1T_numeric
Definition data1.h:204
#define DATA1I_xmltext
Definition data1.h:320
data1_tagset * tagset
Definition d1_absyn.h:51
struct data1_node::@2::@3 root
char * type
Definition data1.h:290
struct data1_node * parent
Definition data1.h:343
struct data1_node * child
Definition data1.h:341
char * tag
Definition data1.h:296
char * data
Definition data1.h:307
struct data1_node * next
Definition data1.h:340
struct data1_absyn * absyn
Definition data1.h:291
union data1_node::@2 u
int which
Definition data1.h:285
struct data1_node::@2::@6 variant
char * value
Definition data1.h:328
struct data1_tag * next
Definition data1.h:215
int which
Definition data1.h:206
int numeric
Definition data1.h:209
data1_datatype kind
Definition data1.h:212
struct data1_tagset * tagset
Definition data1.h:214
union data1_tag::@1 value
char * string
Definition data1.h:210