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