IDZEBRA  2.1.2
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 
4 Zebra is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8 
9 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, 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 
34 static Z_GenericRecord *data1_nodetogr_r(data1_handle dh, data1_node *n,
35  int select, ODR o, int *len,
36  data1_tag *wellknown_tag);
37 
38 static 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  */
64 static 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  */
106 static 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  */
138 static 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 
173 static 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 
232 static int is_empty_data (data1_node *n)
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 
248 static 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 
351 static 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 
376 Z_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 =
387  data1_gettagbyname (dh, n->root->u.root.absyn->tagset,
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 
data1_datatype kind
Definition: data1.h:212
#define DATA1N_tag
Definition: data1.h:276
static int traverse_triples(data1_node *n, int level, Z_ElementMetaData *m, ODR o)
Definition: d1_grs.c:106
#define DATA1N_root
Definition: data1.h:274
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 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
#define DATA1I_oid
Definition: data1.h:318
data1_node * data1_get_root_tag(data1_handle dh, data1_node *n)
Definition: d1_read.c:35
Z_GenericRecord * data1_nodetogr(data1_handle dh, data1_node *n, int select, ODR o, int *len)
Definition: d1_grs.c:376
static Z_ElementMetaData * get_ElementMetaData(ODR o)
Definition: d1_grs.c:38
int numeric
Definition: data1.h:209
struct data1_tagset * tagset
Definition: data1.h:214
#define DATA1I_text
Definition: data1.h:314
char * tag
Definition: data1.h:296
union data1_node::@2 u
struct data1_node::@2::@3 root
struct data1_node * child
Definition: data1.h:341
#define D1_VARIANTARRAY
Definition: d1_grs.c:32
struct data1_node::@2::@6 variant
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
#define DATA1I_num
Definition: data1.h:316
int which
Definition: data1.h:206
union data1_tag::@1 value
int which
Definition: data1.h:285
struct data1_node * parent
Definition: data1.h:343
int type
Definition: data1.h:222
#define DATA1T_numeric
Definition: data1.h:204
struct data1_node * next
Definition: data1.h:340
char * data
Definition: data1.h:307
#define DATA1N_variant
Definition: data1.h:280
data1_tag * data1_gettagbyname(data1_handle dh, data1_tagset *s, const char *name)
Definition: d1_tagset.c:84
#define DATA1I_xmltext
Definition: data1.h:320
static Z_Variant * make_variant(data1_node *n, int num, ODR o)
Definition: d1_grs.c:64
struct data1_tag * next
Definition: data1.h:215
#define DATA1N_data
Definition: data1.h:278
#define d1_isspace(c)
Definition: data1.h:31
char * string
Definition: data1.h:210
static char * get_data(data1_node *n, int *len)
Definition: d1_grs.c:138