Old versions of GILS tables
[yaz-moved-to-github.git] / retrieval / d1_doespec.c
1 /*
2  * Copyright (c) 1995, Index Data.
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: d1_doespec.c,v $
7  * Revision 1.8  1997-05-14 06:54:02  adam
8  * C++ support.
9  *
10  * Revision 1.7  1997/04/30 08:52:11  quinn
11  * Null
12  *
13  * Revision 1.6  1996/10/11  11:57:22  quinn
14  * Smallish
15  *
16  * Revision 1.5  1996/07/06  19:58:34  quinn
17  * System headerfiles gathered in yconfig
18  *
19  * Revision 1.4  1996/06/07  11:04:32  quinn
20  * Fixed tag->tagset dependency
21  *
22  * Revision 1.3  1995/11/13  09:27:33  quinn
23  * Fiddling with the variant stuff.
24  *
25  * Revision 1.2  1995/11/01  13:54:45  quinn
26  * Minor adjustments
27  *
28  * Revision 1.1  1995/11/01  11:56:07  quinn
29  * Added Retrieval (data management) functions en masse.
30  *
31  *
32  */
33
34
35 #include <assert.h>
36 #include <oid.h>
37 #include <log.h>
38 #include <proto.h>
39 #include <data1.h>
40
41 static int match_children(data1_node *n, Z_Espec1 *e, int i, Z_ETagUnit **t,
42     int num);
43
44 static int match_children_wildpath(data1_node *n, Z_Espec1 *e, int i,
45     Z_ETagUnit **t, int num)
46 {return 0;}
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, oid_value universalset,
54     oid_value set, int zclass, int type)
55 {
56     int i;
57     oident *defaultsetent = oid_getentbyoid(var->globalVariantSetId);
58     oid_value defaultset = defaultsetent ? defaultsetent->value :
59         universalset;
60
61     for (i = 0; i < var->num_triples; i++)
62     {
63         oident *cursetent =
64             oid_getentbyoid(var->triples[i]->variantSetId);
65         oid_value curset = cursetent ? cursetent->value : defaultset;
66
67         if (set == curset &&
68             *var->triples[i]->zclass == zclass &&
69             *var->triples[i]->type == type)
70             return var->triples[i];
71     }
72     return 0;
73 }
74
75 static void mark_subtree(data1_node *n, int make_variantlist, int no_data,
76     int get_bytes, Z_Variant *vreq)
77 {
78     data1_node *c;
79
80     if (n->which == DATA1N_tag && (!n->child || n->child->which != DATA1N_tag))
81     {
82         n->u.tag.node_selected = 1;
83         n->u.tag.make_variantlist = make_variantlist;
84         n->u.tag.no_data_requested = no_data;
85         n->u.tag.get_bytes = get_bytes;
86     }
87
88     for (c = n->child; c; c = c->next)
89     {
90         if (c->which == DATA1N_tag && (!n->child ||
91             n->child->which != DATA1N_tag))
92         {
93             c->u.tag.node_selected = 1;
94             c->u.tag.make_variantlist = make_variantlist;
95             c->u.tag.no_data_requested = no_data;
96             c->u.tag.get_bytes = get_bytes;
97         }
98         mark_subtree(c, make_variantlist, no_data, get_bytes, vreq);
99     }
100 }
101
102 static int match_children_here(data1_node *n, Z_Espec1 *e, int i,
103     Z_ETagUnit **t, int num)
104 {
105     int counter = 0, hits = 0;
106     data1_node *c;
107     Z_ETagUnit *tp = *t;
108     Z_Occurrences *occur;
109
110     for (c = n->child; c ; c = c->next)
111     {
112         data1_tag *tag = 0;
113
114         if (c->which != DATA1N_tag)
115             return 0;
116
117         if (tp->which == Z_ETagUnit_specificTag)
118         {
119             Z_SpecificTag *want = tp->u.specificTag;
120             occur = want->occurrences;
121             if (c->u.tag.element)
122                 tag = c->u.tag.element->tag;
123             if (*want->tagType != ((tag && tag->tagset) ? tag->tagset->type :
124                 3))
125                 continue;
126             if (want->tagValue->which == Z_StringOrNumeric_numeric)
127             {
128                 if (!tag || tag->which != DATA1T_numeric)
129                     continue;
130                 if (*want->tagValue->u.numeric != tag->value.numeric)
131                     continue;
132             }
133             else
134             {
135                 assert(want->tagValue->which == Z_StringOrNumeric_string);
136                 if (tag && tag->which != DATA1T_string)
137                     continue;
138                 if (data1_matchstr(want->tagValue->u.string,
139                     tag ? tag->value.string : c->u.tag.tag))
140                     continue;
141             }
142         }
143         else
144             occur = tp->u.wildThing;
145
146         /*
147          * Ok, so we have a matching tag. Are we within occurrences-range?
148          */
149         counter++;
150         if (occur && occur->which == Z_Occurrences_last)
151         {
152             logf(LOG_WARN, "Can't do occurrences=last (yet)");
153             return 0;
154         }
155         if (!occur || occur->which == Z_Occurrences_all ||
156             (occur->which == Z_Occurrences_values && counter >=
157             *occur->u.values->start))
158         {
159             if (match_children(c, e, i, t + 1, num - 1))
160             {
161                 c->u.tag.node_selected = 1;
162                 /*
163                  * Consider the variant specification if this is a complete
164                  * match.
165                  */
166                 if (num == 1)
167                 {
168                     int show_variantlist = 0;
169                     int no_data = 0;
170                     int get_bytes = -1;
171
172                     Z_Variant *vreq =
173                         e->elements[i]->u.simpleElement->variantRequest;
174                     oident *defset = oid_getentbyoid(e->defaultVariantSetId);
175                     oid_value defsetval = defset ? defset->value : VAL_NONE;
176                     oid_value var1 = oid_getvalbyname("Variant-1");
177
178                     if (!vreq)
179                         vreq = e->defaultVariantRequest;
180
181                     if (vreq)
182                     {
183                         Z_Triple *r;
184
185                         /*
186                          * 6,5: meta-data requested, variant list.
187                          */
188                         if (find_triple(vreq, defsetval, var1, 6, 5))
189                             show_variantlist = 1;
190                         /*
191                          * 9,1: Miscellaneous, no data requested.
192                          */
193                         if (find_triple(vreq, defsetval, var1, 9, 1))
194                             no_data = 1;
195
196                         /* howmuch */
197                         if ((r = find_triple(vreq, defsetval, var1, 5, 5)))
198                             if (r->which == Z_Triple_integer)
199                                 get_bytes = *r->value.integer;
200                     }
201                     mark_subtree(c, show_variantlist, no_data, get_bytes, vreq);
202                 }
203                 hits++;
204                 /*
205                  * have we looked at enough children?
206                  */
207                 if (!occur || (occur->which == Z_Occurrences_values &&
208                     (!occur->u.values->howMany ||
209                     counter - *occur->u.values->start >=
210                     *occur->u.values->howMany - 1)))
211                     return hits;
212             }
213         }
214     }
215     return hits;
216 }
217
218 static int match_children(data1_node *n, Z_Espec1 *e, int i, Z_ETagUnit **t,
219     int num)
220 {
221     int res;
222
223     if (!num)
224         return 1;
225     switch (t[0]->which)
226     {
227         case Z_ETagUnit_wildThing:
228         case Z_ETagUnit_specificTag: res = match_children_here(n, e, i,
229             t, num); break;
230         case Z_ETagUnit_wildPath: res = match_children_wildpath(n, e, i,
231             t, num); break;
232         default:
233             abort();
234     }
235     return res;
236 }
237
238 int data1_doespec1(data1_node *n, Z_Espec1 *e)
239 {
240     int i;
241
242     for (i = 0; i < e->num_elements; i++)
243     {
244         if (e->elements[i]->which != Z_ERequest_simpleElement)
245             return 100;
246         match_children(n, e, i, e->elements[i]->u.simpleElement->path->tags,
247             e->elements[i]->u.simpleElement->path->num_tags);
248     }
249     return 0;
250 }