IDZEBRA  2.1.2
d1_doespec.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 
25 #if HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 #include <assert.h>
29 #include <stdlib.h>
30 
31 #include <yaz/log.h>
32 #include <yaz/proto.h>
33 #include <yaz/oid_db.h>
34 #include <idzebra/data1.h>
35 
36 static int match_children(data1_handle dh, data1_node *n,
37  Z_Espec1 *e, int i, Z_ETagUnit **t,
38  int num,
39  int select_flag);
40 
42  Z_Espec1 *e, int i,
43  Z_ETagUnit **t, int num)
44 {
45  return 0;
46 }
47 
48 /*
49  * Locate a specific triple within a variant.
50  * set is the set to look for, universal set is the set that applies to a
51  * triple with an unknown set.
52  */
53 static Z_Triple *find_triple(Z_Variant *var, const Odr_oid *universal_oid,
54  const Odr_oid *var_oid, int zclass, int type)
55 {
56  int i;
57 
58  for (i = 0; i < var->num_triples; i++)
59  {
60  const Odr_oid *cur_oid = var->triples[i]->variantSetId;
61  if (!cur_oid)
62  cur_oid = var->globalVariantSetId;
63  if (cur_oid && var_oid
64  && !oid_oidcmp(var_oid, cur_oid) && *var->triples[i]->type == type)
65  return var->triples[i];
66  }
67  return 0;
68 }
69 
70 static void mark_subtree(data1_node *n, int make_variantlist, int no_data,
71  int get_bytes, Z_Variant *vreq, int select_flag)
72 {
73  data1_node *c;
74 
75 #if 1
76  if (n->which == DATA1N_tag)
77 #else
78  if (n->which == DATA1N_tag && (!n->child || n->child->which != DATA1N_tag))
79  /*
80  * This seems to cause multi-level elements to fall out when only a
81  * top-level elementRequest has been given... Problem is, I can't figure
82  * out what it was supposed to ACHIEVE.... delete when code has been
83  * verified.
84  */
85 #endif
86  {
87  n->u.tag.node_selected = select_flag;
88  n->u.tag.make_variantlist = make_variantlist;
89  n->u.tag.no_data_requested = no_data;
90  n->u.tag.get_bytes = get_bytes;
91  }
92 
93  for (c = n->child; c; c = c->next)
94  {
95  if (c->which == DATA1N_tag && (!n->child ||
96  n->child->which != DATA1N_tag))
97  {
98  c->u.tag.node_selected = select_flag;
99  c->u.tag.make_variantlist = make_variantlist;
100  c->u.tag.no_data_requested = no_data;
101  c->u.tag.get_bytes = get_bytes;
102  }
103  mark_subtree(c, make_variantlist, no_data, get_bytes, vreq,
104  select_flag);
105  }
106 }
107 
108 
109 static void match_triple(data1_handle dh, Z_Variant *vreq,
110  const Odr_oid *def_oid,
111  const Odr_oid *var_oid, data1_node *n)
112 {
113  data1_node **c;
114 
115  if (!(n = n->child))
116  return;
117  if (n->which != DATA1N_variant)
118  return;
119  c = &n->child;
120  while (*c)
121  {
122  int remove_flag = 0;
123  Z_Triple *r;
124 
125  assert ((*c)->which == DATA1N_variant);
126 
127  if ((*c)->u.variant.type->zclass->zclass == 4 &&
128  (*c)->u.variant.type->type == 1)
129  {
130  if ((r = find_triple(vreq, def_oid, var_oid, 4, 1)) &&
131  (r->which == Z_Triple_internationalString))
132  {
133  const char *string_value =
134  r->value.internationalString;
135  if (strcmp ((*c)->u.variant.value, string_value))
136  remove_flag = 1;
137  }
138  }
139  if (remove_flag)
140  {
141  *c = (*c)->next;
142  }
143  else
144  {
145  match_triple(dh, vreq, def_oid, var_oid, *c);
146  c = &(*c)->next;
147  }
148  }
149 }
150 
151 static int match_node_and_attr (data1_node *c, const char *spec)
152 {
153 
154  char predicate[64];
155  char elem[64];
156  char attr[64];
157  char value[64];
158  char dummy_ch;
159 
160  data1_tag *tag = 0;
161  if (c->u.tag.element)
162  tag = c->u.tag.element->tag;
163 
164  *predicate = '\0';
165  sscanf(spec, "%63[^[]%c%63[^]]", elem, &dummy_ch, predicate);
166  if (data1_matchstr(elem, tag ? tag->value.string : c->u.tag.tag))
167  return 0;
168 
169  if (*predicate == '\0')
170  return 1;
171  else if (sscanf(predicate, "@%63[^=]=%63s", attr, value) == 2)
172  {
173  data1_xattr *xa;
174  for (xa = c->u.tag.attributes; xa; xa = xa->next)
175  if (!strcmp(xa->name, attr) &&
176  !strcmp(xa->value, value))
177  return 1;
178  return 0;
179  }
180  else if (sscanf(predicate, "@%63s", attr) == 1)
181  {
182  data1_xattr *xa;
183  for (xa = c->u.tag.attributes; xa; xa = xa->next)
184  if (!strcmp(xa->name, attr))
185  return 1;
186  }
187  else
188  {
189  yaz_log(YLOG_WARN, "Bad simpleelement component: '%s'", spec);
190  }
191  return 0;
192 }
193 
195  Z_Espec1 *e, int i,
196  Z_ETagUnit **t, int num,
197  int select_flag)
198 {
199  int counter = 0, hits = 0;
200  data1_node *c;
201  Z_ETagUnit *tp = *t;
202  Z_Occurrences *occur;
203 
204  for (c = n->child; c ; c = c->next)
205  {
206  data1_tag *tag = 0;
207 
208  if (c->which != DATA1N_tag)
209  continue;
210 
211  if (tp->which == Z_ETagUnit_specificTag)
212  {
213  Z_SpecificTag *want = tp->u.specificTag;
214  occur = want->occurrences;
215  if (c->u.tag.element)
216  tag = c->u.tag.element->tag;
217  if (*want->tagType != ((tag && tag->tagset) ? tag->tagset->type :
218  3))
219  continue;
220  if (want->tagValue->which == Z_StringOrNumeric_numeric)
221  {
222  if (!tag || tag->which != DATA1T_numeric)
223  continue;
224  if (*want->tagValue->u.numeric != tag->value.numeric)
225  continue;
226  }
227  else if (want->tagValue->which == Z_StringOrNumeric_string)
228  {
229  const char *str_val = want->tagValue->u.string;
230  if (str_val[0] == '!')
231  {
232  str_val++;
233  select_flag = 0;
234  }
235  if (tag && tag->which != DATA1T_string)
236  continue;
237 #if 1
238  if (!match_node_and_attr(c, str_val))
239  continue;
240 #else
241  if (data1_matchstr(str_val,
242  tag ? tag->value.string : c->u.tag.tag))
243  continue;
244 #endif
245  }
246  else
247  {
248  yaz_log(YLOG_WARN, "Bad SpecificTag type: %d",
249  want->tagValue->which);
250  continue;
251  }
252  }
253  else if (tp->which == Z_ETagUnit_wildThing)
254  occur = tp->u.wildThing;
255  else
256  continue;
257  /*
258  * Ok, so we have a matching tag. Are we within occurrences-range?
259  */
260  counter++;
261  if (occur && occur->which == Z_Occurrences_last)
262  {
263  yaz_log(YLOG_WARN, "Can't do occurrences=last (yet)");
264  return 0;
265  }
266  if (!occur || occur->which == Z_Occurrences_all ||
267  (occur->which == Z_Occurrences_values && counter >=
268  *occur->u.values->start))
269  {
270  if (match_children(dh, c, e, i, t + 1, num - 1, select_flag))
271  {
272  c->u.tag.node_selected = select_flag;
273  /*
274  * Consider the variant specification if this is a complete
275  * match.
276  */
277  if (num == 1)
278  {
279  int show_variantlist = 0;
280  int no_data = 0;
281  int get_bytes = -1;
282 
283  Z_Variant *vreq =
284  e->elements[i]->u.simpleElement->variantRequest;
285 
286  const Odr_oid *var_oid = yaz_oid_varset_variant_1;
287  if (!vreq)
288  vreq = e->defaultVariantRequest;
289 
290  if (vreq)
291  {
292  Z_Triple *r;
293 
294  /*
295  * 6,5: meta-data requested, variant list.
296  */
297  if (find_triple(vreq, e->defaultVariantSetId,
298  var_oid, 6, 5))
299  show_variantlist = 1;
300  /*
301  * 9,1: Miscellaneous, no data requested.
302  */
303  if (find_triple(vreq, e->defaultVariantSetId,
304  var_oid, 9, 1))
305  no_data = 1;
306 
307  /* howmuch */
308  if ((r = find_triple(vreq, e->defaultVariantSetId,
309  var_oid, 5, 5)))
310  if (r->which == Z_Triple_integer)
311  get_bytes = *r->value.integer;
312 
313  if (!show_variantlist)
314  match_triple(dh, vreq, e->defaultVariantSetId,
315  var_oid, c);
316  }
317  mark_subtree(c, show_variantlist, no_data, get_bytes, vreq,
318  select_flag);
319  }
320  hits++;
321  /*
322  * have we looked at enough children?
323  */
324  if (!occur || (occur->which == Z_Occurrences_values &&
325  (!occur->u.values->howMany ||
326  counter - *occur->u.values->start >=
327  *occur->u.values->howMany - 1)))
328  return hits;
329  }
330  }
331  }
332  return hits;
333 }
334 
335 static int match_children(data1_handle dh, data1_node *n, Z_Espec1 *e,
336  int i, Z_ETagUnit **t, int num, int select_flag)
337 {
338  int res;
339 
340  if (!num)
341  return 1;
342  switch (t[0]->which)
343  {
344  case Z_ETagUnit_wildThing:
345  case Z_ETagUnit_specificTag:
346  res = match_children_here(dh, n, e, i, t, num, select_flag);
347  break;
348  case Z_ETagUnit_wildPath:
349  res = match_children_wildpath(dh, n, e, i, t, num); break;
350  default:
351  abort();
352  }
353  return res;
354 }
355 
356 int data1_doespec1 (data1_handle dh, data1_node *n, Z_Espec1 *e)
357 {
358  int i;
359 
360  n = data1_get_root_tag (dh, n);
361  if (n && n->which == DATA1N_tag)
362  n->u.tag.node_selected = 1;
363 
364  for (i = 0; i < e->num_elements; i++)
365  {
366  if (e->elements[i]->which != Z_ERequest_simpleElement)
367  return 100;
368  match_children(dh, n, e, i,
369  e->elements[i]->u.simpleElement->path->tags,
370  e->elements[i]->u.simpleElement->path->num_tags,
371  1 /* select (include) by default */ );
372  }
373  return 0;
374 }
375 /*
376  * Local variables:
377  * c-basic-offset: 4
378  * c-file-style: "Stroustrup"
379  * indent-tabs-mode: nil
380  * End:
381  * vim: shiftwidth=4 tabstop=8 expandtab
382  */
383 
#define DATA1T_string
Definition: data1.h:205
#define DATA1N_tag
Definition: data1.h:276
static void mark_subtree(data1_node *n, int make_variantlist, int no_data, int get_bytes, Z_Variant *vreq, int select_flag)
Definition: d1_doespec.c:70
static int match_children_wildpath(data1_handle dh, data1_node *n, Z_Espec1 *e, int i, Z_ETagUnit **t, int num)
Definition: d1_doespec.c:41
char * name
Definition: data1.h:260
struct data1_xattr * next
Definition: data1.h:262
#define data1_matchstr(s1, s2)
Definition: data1.h:36
char * value
Definition: data1.h:261
data1_node * data1_get_root_tag(data1_handle dh, data1_node *n)
Definition: d1_read.c:35
static int match_children(data1_handle dh, data1_node *n, Z_Espec1 *e, int i, Z_ETagUnit **t, int num, int select_flag)
Definition: d1_doespec.c:335
int numeric
Definition: data1.h:209
struct data1_tagset * tagset
Definition: data1.h:214
char * tag
Definition: data1.h:296
union data1_node::@2 u
struct data1_node * child
Definition: data1.h:341
int which
Definition: data1.h:206
union data1_tag::@1 value
int which
Definition: data1.h:285
static int match_node_and_attr(data1_node *c, const char *spec)
Definition: d1_doespec.c:151
int data1_doespec1(data1_handle dh, data1_node *n, Z_Espec1 *e)
Definition: d1_doespec.c:356
int type
Definition: data1.h:222
#define DATA1T_numeric
Definition: data1.h:204
struct data1_node * next
Definition: data1.h:340
#define DATA1N_variant
Definition: data1.h:280
static void match_triple(data1_handle dh, Z_Variant *vreq, const Odr_oid *def_oid, const Odr_oid *var_oid, data1_node *n)
Definition: d1_doespec.c:109
char * value
Definition: d1_absyn.c:129
static int match_children_here(data1_handle dh, data1_node *n, Z_Espec1 *e, int i, Z_ETagUnit **t, int num, int select_flag)
Definition: d1_doespec.c:194
static Z_Triple * find_triple(Z_Variant *var, const Odr_oid *universal_oid, const Odr_oid *var_oid, int zclass, int type)
Definition: d1_doespec.c:53
char * string
Definition: data1.h:210