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