New OID database - with public definitions in oid_db.h. Removed old OID
[yaz-moved-to-github.git] / src / logrpn.c
1 /*
2  * Copyright (C) 1995-2007, Index Data ApS
3  * All rights reserved.
4  *
5  * $Id: logrpn.c,v 1.16 2007-04-12 13:52:57 adam Exp $
6  */
7
8 /**
9  * \file logrpn.c
10  * \brief Implements Z39.50 Query Printing
11  */
12
13 #include <stdio.h>
14 #include <assert.h>
15
16 #include <yaz/log.h>
17 #include <yaz/logrpn.h>
18 #include <yaz/oid_db.h>
19
20 static const char *relToStr(int v)
21 {
22     const char *str = 0;
23     switch (v)
24     {
25     case 1: str = "Less than"; break;
26     case 2: str = "Less than or equal"; break;
27     case 3: str = "Equal"; break;
28     case 4: str = "Greater or equal"; break;
29     case 5: str = "Greater than"; break;
30     case 6: str = "Not equal"; break;
31     case 100: str = "Phonetic"; break;
32     case 101: str = "Stem"; break;
33     case 102: str = "Relevance"; break;
34     case 103: str = "AlwaysMatches"; break;
35     }
36     return str;
37 }
38
39 static void attrStr (int type, int value, char *str)
40 {
41     const char *rstr;
42     *str = '\0';
43     switch (type)
44     {
45     case 1:
46         sprintf (str, "use");
47         break;
48     case 2:
49         rstr = relToStr(value);
50         if (rstr)
51             sprintf(str, "relation=%s", rstr);
52         else
53             sprintf(str, "relation=%d", value);
54         break;
55     case 3:
56         switch (value)
57         {
58         case 1:
59             sprintf(str, "position=First in field");
60             break;
61         case 2:
62             sprintf(str, "position=First in any subfield");
63             break;
64         case 3:
65             sprintf(str, "position=Any position in field");
66             break;
67         default:
68             sprintf(str, "position");
69         }
70         break;
71     case 4:
72         switch (value)
73         {
74         case 1:
75             sprintf(str, "structure=Phrase");
76             break;
77         case 2:
78             sprintf(str, "structure=Word");
79             break;
80         case 3:
81             sprintf(str, "structure=Key");
82             break;
83         case 4:
84             sprintf(str, "structure=Year");
85             break;
86         case 5:
87             sprintf(str, "structure=Date");
88             break;
89         case 6:
90             sprintf(str, "structure=Word list");
91             break;
92         case 100:
93             sprintf(str, "structure=Date (un)");
94             break;
95         case 101:
96             sprintf(str, "structure=Name (norm)");
97             break;
98         case 102:
99             sprintf(str, "structure=Name (un)");
100             break;
101         case 103:
102             sprintf(str, "structure=Structure");
103             break;
104         case 104:
105             sprintf(str, "structure=urx");
106             break;
107         case 105:
108             sprintf(str, "structure=free-form-text");
109             break;
110         case 106:
111             sprintf(str, "structure=document-text");
112             break;
113         case 107:
114             sprintf(str, "structure=local-number");
115             break;
116         case 108:
117             sprintf(str, "structure=string");
118             break;
119         case 109:
120             sprintf(str, "structure=numeric string");
121             break;
122         default:
123             sprintf(str, "structure");
124         }
125         break;
126     case 5:
127         switch (value)
128         {
129         case 1:
130             sprintf(str, "truncation=Right");
131             break;
132         case 2:
133             sprintf(str, "truncation=Left");
134             break;
135         case 3:
136             sprintf(str, "truncation=Left&right");
137             break;
138         case 100:
139             sprintf(str, "truncation=Do not truncate");
140             break;
141         case 101:
142             sprintf(str, "truncation=Process #");
143             break;
144         case 102:
145             sprintf(str, "truncation=re-1");
146             break;
147         case 103:
148             sprintf(str, "truncation=re-2");
149             break;
150         case 104:
151             sprintf(str, "truncation=CCL");
152             break;
153         default:
154             sprintf(str, "truncation");
155         }
156         break;
157     case 6:
158         switch(value)
159         {
160         case 1:
161             sprintf(str, "completeness=Incomplete subfield");
162             break;
163         case 2:
164             sprintf(str, "completeness=Complete subfield");
165             break;
166         case 3:
167             sprintf(str, "completeness=Complete field");
168             break;
169         default:
170             sprintf(str, "completeness");
171         }
172         break;
173     }
174     if (*str)
175         sprintf(str + strlen(str), " (%d=%d)", type, value);
176     else
177         sprintf(str, "%d=%d", type, value);
178 }
179
180 /*
181  * zlog_attributes: print attributes of term
182  */
183 static void zlog_attributes(Z_AttributesPlusTerm *t, int depth,
184                             const int *ast, int loglevel)
185 {
186     int of, i;
187     char str[80];
188     int num_attributes = t->attributes->num_attributes;
189     
190     for (of = 0; of < num_attributes; of++)
191     {
192         char attset_name_buf[OID_STR_MAX];
193         const char *attset_name = 0;
194         Z_AttributeElement *element;
195         element = t->attributes->attributes[of];
196         if (element->attributeSet)
197         {
198             attset_name = yaz_oid_to_string_buf(element->attributeSet,
199                                                 0, attset_name_buf);
200         }
201         if (!attset_name)
202             attset_name = "";
203         switch (element->which) 
204         {
205         case Z_AttributeValue_numeric:
206             attrStr (*element->attributeType,
207                      *element->value.numeric, str);
208             yaz_log (loglevel, "%*.0s%s %s", depth, "", attset_name, str);
209             break;
210         case Z_AttributeValue_complex:
211             yaz_log (loglevel, "%*.0s%s attributeType=%d complex",
212                   depth, "", attset_name, *element->attributeType);
213             for (i = 0; i<element->value.complex->num_list; i++)
214             {
215                 if (element->value.complex->list[i]->which ==
216                     Z_StringOrNumeric_string)
217                     yaz_log (loglevel, "%*.0s  string: '%s'", depth, "",
218                              element->value.complex->list[i]->u.string);
219                 else if (element->value.complex->list[i]->which ==
220                          Z_StringOrNumeric_numeric)
221                     yaz_log (loglevel, "%*.0s  numeric: '%d'", depth, "",
222                              *element->value.complex->list[i]->u.numeric);
223             }
224             break;
225         default:
226             yaz_log (loglevel, "%.*s%s attribute unknown",
227                      depth, "", attset_name);
228         }
229     }
230 }
231
232 static char *complex_op_name(Z_Operator *op)
233 {
234     switch (op->which)
235     {
236     case Z_Operator_and:
237         return "and";
238     case Z_Operator_or:
239         return "or";
240     case Z_Operator_and_not:
241         return "not";
242     case Z_Operator_prox:
243         return "prox";
244     default:
245         return "unknown complex operator";
246     }
247 }
248
249 static char *prox_unit_name(Z_ProximityOperator *op)
250 {
251     if (op->which!=Z_ProximityOperator_known)
252          return "private";
253     switch(*op->u.known)
254     {
255         case Z_ProxUnit_character: return "character";
256         case Z_ProxUnit_word: return "word";
257         case Z_ProxUnit_sentence: return "sentence";
258         case Z_ProxUnit_paragraph: return "paragraph";
259         case Z_ProxUnit_section: return "section";
260         case Z_ProxUnit_chapter: return "chapter";
261         case Z_ProxUnit_document: return "document";
262         case Z_ProxUnit_element: return "element";
263         case Z_ProxUnit_subelement: return "subelement";
264         case Z_ProxUnit_elementType: return "elementType";
265         case Z_ProxUnit_byte: return "byte";
266         default: return "unknown";
267     }
268 }
269
270 static void zlog_structure(Z_RPNStructure *zs, int depth, 
271                            const int *ast, int loglevel)
272 {
273     if (zs->which == Z_RPNStructure_complex)
274     {
275         Z_Operator *op = zs->u.complex->roperator;
276         switch (op->which)
277         {
278         case Z_Operator_and:
279         case Z_Operator_or:
280         case Z_Operator_and_not:
281             yaz_log (loglevel, "%*.0s %s", depth, "", complex_op_name(op) );
282             break;
283         case Z_Operator_prox:
284             yaz_log (loglevel, "%*.0s prox excl=%s dist=%d order=%s "
285                      "rel=%s unit=%s",
286                      depth, "", op->u.prox->exclusion ?
287                      (*op->u.prox->exclusion ? "T" : "F") : "N", 
288                      *op->u.prox->distance,
289                      *op->u.prox->ordered ? "T" : "F",
290                      relToStr(*op->u.prox->relationType),
291                      prox_unit_name(op->u.prox) );
292             break;
293         default:
294             yaz_log (loglevel, "%*.0s unknown complex", depth, "");
295             return;
296         }
297         zlog_structure (zs->u.complex->s1, depth+2, ast, loglevel);
298         zlog_structure (zs->u.complex->s2, depth+2, ast, loglevel);
299     } 
300     else if (zs->which == Z_RPNStructure_simple)
301     {
302         if (zs->u.simple->which == Z_Operand_APT)
303         {
304             Z_AttributesPlusTerm *zapt = zs->u.simple->u.attributesPlusTerm;
305
306             switch (zapt->term->which)
307             {
308             case Z_Term_general:
309                 yaz_log (loglevel, "%*.0s term '%.*s' (general)", depth, "",
310                          zapt->term->u.general->len,
311                          zapt->term->u.general->buf);
312                 break;
313             case Z_Term_characterString:
314                 yaz_log (loglevel, "%*.0s term '%s' (string)", depth, "",
315                          zapt->term->u.characterString);
316                 break;
317             case Z_Term_numeric:
318                 yaz_log (loglevel, "%*.0s term '%d' (numeric)", depth, "",
319                          *zapt->term->u.numeric);
320                 break;
321             case Z_Term_null:
322                 yaz_log (loglevel, "%*.0s term (null)", depth, "");
323                 break;
324             default:
325                 yaz_log (loglevel, "%*.0s term (not general)", depth, "");
326             }
327             zlog_attributes(zapt, depth+2, ast, loglevel);
328         }
329         else if (zs->u.simple->which == Z_Operand_resultSetId)
330         {
331             yaz_log (loglevel, "%*.0s set '%s'", depth, "",
332                      zs->u.simple->u.resultSetId);
333         }
334         else
335             yaz_log (loglevel, "%*.0s unknown simple structure", depth, "");
336     }
337     else
338         yaz_log (loglevel, "%*.0s unknown structure", depth, "");
339 }
340
341 void log_rpn_query_level (int loglevel, Z_RPNQuery *rpn)
342 {
343     zlog_structure(rpn->RPNStructure, 0, rpn->attributeSetId, loglevel);
344 }
345
346 void log_rpn_query(Z_RPNQuery *rpn)
347 {
348     log_rpn_query_level(YLOG_LOG, rpn);
349 }
350
351 void log_scan_term_level(int loglevel, 
352                          Z_AttributesPlusTerm *zapt, const int *ast)
353 {
354     int depth = 0;
355     if (!loglevel)
356         return;
357     if (zapt->term->which == Z_Term_general) 
358     {
359         yaz_log (loglevel, "%*.0s term '%.*s' (general)", depth, "",
360                  zapt->term->u.general->len, zapt->term->u.general->buf);
361     }
362     else
363         yaz_log (loglevel, "%*.0s term (not general)", depth, "");
364     zlog_attributes(zapt, depth+2, ast, loglevel);
365 }
366
367 void log_scan_term(Z_AttributesPlusTerm *zapt, const int *ast)
368 {
369     log_scan_term_level (YLOG_LOG, zapt, ast);
370 }
371
372 void yaz_log_zquery_level (int loglevel, Z_Query *q)
373 {
374     if (!loglevel)
375         return; 
376     switch (q->which)
377     {
378     case Z_Query_type_1: case Z_Query_type_101:
379         log_rpn_query_level (loglevel, q->u.type_1);
380         break;
381     case Z_Query_type_2:
382         yaz_log(loglevel, "CCL: %.*s", q->u.type_2->len, q->u.type_2->buf);
383         break;
384     case Z_Query_type_100:
385         yaz_log(loglevel, "Z39.58: %.*s", q->u.type_100->len,
386                 q->u.type_100->buf);
387         break;
388     case Z_Query_type_104:
389         if (q->u.type_104->which == Z_External_CQL)
390             yaz_log (loglevel, "CQL: %s", q->u.type_104->u.cql);
391     }
392 }
393
394 void yaz_log_zquery (Z_Query *q)
395 {
396     yaz_log_zquery_level(YLOG_LOG, q);
397 }
398
399 void wrbuf_diags(WRBUF b, int num_diagnostics,Z_DiagRec **diags)
400 {
401     /* we only dump the first diag - that keeps the log cleaner. */
402     wrbuf_printf(b," ERROR ");
403     if (diags[0]->which != Z_DiagRec_defaultFormat)
404         wrbuf_printf(b,"(diag not in default format?)");
405     else
406     {
407         Z_DefaultDiagFormat *e=diags[0]->u.defaultFormat;
408         if (e->condition)
409             wrbuf_printf(b, "%d ",*e->condition);
410         else
411             wrbuf_printf(b, "?? ");
412         if ((e->which==Z_DefaultDiagFormat_v2Addinfo) && (e->u.v2Addinfo))
413             wrbuf_printf(b,"%s ",e->u.v2Addinfo);
414         else if ((e->which==Z_DefaultDiagFormat_v3Addinfo) && (e->u.v3Addinfo))
415             wrbuf_printf(b,"%s ",e->u.v3Addinfo);
416     }
417 }
418 /*
419  * Local variables:
420  * c-basic-offset: 4
421  * indent-tabs-mode: nil
422  * End:
423  * vim: shiftwidth=4 tabstop=8 expandtab
424  */
425