IDZEBRA 2.2.8
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
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
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
36static 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 */
53static 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
70static 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
109static 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
151static 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
335static 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
356int 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
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 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
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
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
static int match_node_and_attr(data1_node *c, const char *spec)
Definition d1_doespec.c:151
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
int data1_doespec1(data1_handle dh, data1_node *n, Z_Espec1 *e)
Definition d1_doespec.c:356
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
#define DATA1N_variant
Definition data1.h:280
data1_node * data1_get_root_tag(data1_handle dh, data1_node *n)
Definition d1_read.c:36
#define DATA1T_string
Definition data1.h:205
#define data1_matchstr(s1, s2)
Definition data1.h:36
#define DATA1N_tag
Definition data1.h:276
#define DATA1T_numeric
Definition data1.h:204
struct data1_node * child
Definition data1.h:341
char * tag
Definition data1.h:296
struct data1_node * next
Definition data1.h:340
union data1_node::@2 u
int which
Definition data1.h:285
int which
Definition data1.h:206
int numeric
Definition data1.h:209
struct data1_tagset * tagset
Definition data1.h:214
union data1_tag::@1 value
char * string
Definition data1.h:210
char * value
Definition data1.h:261
char * name
Definition data1.h:260
struct data1_xattr * next
Definition data1.h:262