Deal with resultCountPrecision - SRU 2.0
[yaz-moved-to-github.git] / src / querytowrbuf.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2013 Index Data
3  * See the file LICENSE for details.
4  */
5 /** \file querytowrbuf.c
6     \brief Convert Z39.50 Z_Query to PQF (as WRBUF string)
7  */
8 #if HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #include <stdio.h>
13 #include <assert.h>
14
15 #include <yaz/logrpn.h>
16 #include <yaz/querytowrbuf.h>
17 #include <yaz/oid_db.h>
18
19 void yaz_encode_pqf_term(WRBUF b, const char *term, int len)
20 {
21     int i;
22     for (i = 0; i < len; i++)
23         if (strchr(" \"{", term[i]))
24             break;
25     if (len > 0 && i == len)
26     {
27         if (term[0] == '@')
28             wrbuf_putc(b, '\\');
29         for (i = 0; i < len; i++)
30         {
31             if (term[i] == '\\')
32                 wrbuf_putc(b, '\\');
33             wrbuf_putc(b, term[i]);
34         }
35     }
36     else
37     {
38         wrbuf_putc(b, '"');
39         for (i = 0; i < len; i++)
40         {
41             if (term[i] == '"' || term[i] == '\\')
42                 wrbuf_putc(b, '\\');
43             wrbuf_putc(b, term[i]);
44         }
45         wrbuf_putc(b, '"');
46     }
47     wrbuf_putc(b, ' ');
48 }
49
50 static void yaz_attribute_element_to_wrbuf(WRBUF b,
51                                            const Z_AttributeElement *element)
52 {
53     int i;
54
55     wrbuf_puts(b, "@attr ");
56     if (element->attributeSet)
57     {
58         char oid_name_str[OID_STR_MAX];
59         const char *setname = yaz_oid_to_string_buf(element->attributeSet,
60                                                     0, oid_name_str);
61         if (setname)
62         {
63             wrbuf_puts(b, setname);
64             wrbuf_puts(b, " ");
65         }
66     }
67     wrbuf_printf(b, ODR_INT_PRINTF "=", *element->attributeType);
68     switch (element->which)
69     {
70     case Z_AttributeValue_numeric:
71         wrbuf_printf(b, ODR_INT_PRINTF, *element->value.numeric);
72         break;
73     case Z_AttributeValue_complex:
74         for (i = 0; i < element->value.complex->num_list; i++)
75         {
76             if (i)
77                 wrbuf_puts(b, ",");
78             if (element->value.complex->list[i]->which ==
79                 Z_StringOrNumeric_string)
80                 wrbuf_puts(b, element->value.complex->list[i]->u.string);
81             else if (element->value.complex->list[i]->which ==
82                      Z_StringOrNumeric_numeric)
83                 wrbuf_printf(b, ODR_INT_PRINTF,
84                              *element->value.complex->list[i]->u.numeric);
85         }
86         break;
87     default:
88         wrbuf_puts(b, "@attr 1=unknown");
89     }
90     wrbuf_puts(b, " ");
91 }
92
93 static const char *complex_op_name(const Z_Operator *op)
94 {
95     switch (op->which)
96     {
97     case Z_Operator_and:
98         return "and";
99     case Z_Operator_or:
100         return "or";
101     case Z_Operator_and_not:
102         return "not";
103     case Z_Operator_prox:
104         return "prox";
105     default:
106         return "unknown complex operator";
107     }
108 }
109
110 static void yaz_apt_to_wrbuf(WRBUF b, const Z_AttributesPlusTerm *zapt)
111 {
112     int num_attributes = zapt->attributes->num_attributes;
113     int i;
114     for (i = 0; i < num_attributes; i++)
115         yaz_attribute_element_to_wrbuf(b,zapt->attributes->attributes[i]);
116
117     switch (zapt->term->which)
118     {
119     case Z_Term_general:
120         yaz_encode_pqf_term(b, (const char *)zapt->term->u.general->buf,
121                             zapt->term->u.general->len);
122         break;
123     case Z_Term_characterString:
124         wrbuf_puts(b, "@term string ");
125         yaz_encode_pqf_term(b, zapt->term->u.characterString,
126                             strlen(zapt->term->u.characterString));
127         break;
128     case Z_Term_numeric:
129         wrbuf_printf(b, "@term numeric " ODR_INT_PRINTF " ",
130                      *zapt->term->u.numeric);
131         break;
132     case Z_Term_null:
133         wrbuf_puts(b, "@term null x");
134         break;
135     default:
136         wrbuf_printf(b, "@term null unknown%d ", zapt->term->which);
137     }
138 }
139
140 static void yaz_rpnstructure_to_wrbuf(WRBUF b, const Z_RPNStructure *zs)
141 {
142     if (zs->which == Z_RPNStructure_complex)
143     {
144         Z_Operator *op = zs->u.complex->roperator;
145         wrbuf_printf(b, "@%s ", complex_op_name(op) );
146         if (op->which== Z_Operator_prox)
147         {
148             if (!op->u.prox->exclusion)
149                 wrbuf_putc(b, 'n');
150             else if (*op->u.prox->exclusion)
151                 wrbuf_putc(b, '1');
152             else
153                 wrbuf_putc(b, '0');
154
155             wrbuf_printf(b, " " ODR_INT_PRINTF " %d "
156                          ODR_INT_PRINTF " ", *op->u.prox->distance,
157                          *op->u.prox->ordered,
158                          *op->u.prox->relationType);
159
160             switch(op->u.prox->which)
161             {
162             case Z_ProximityOperator_known:
163                 wrbuf_putc(b, 'k');
164                 break;
165             case Z_ProximityOperator_private:
166                 wrbuf_putc(b, 'p');
167                 break;
168             default:
169                 wrbuf_printf(b, "%d", op->u.prox->which);
170             }
171             if (op->u.prox->u.known)
172                 wrbuf_printf(b, " " ODR_INT_PRINTF " ", *op->u.prox->u.known);
173             else
174                 wrbuf_printf(b, " 0 ");
175         }
176         yaz_rpnstructure_to_wrbuf(b,zs->u.complex->s1);
177         yaz_rpnstructure_to_wrbuf(b,zs->u.complex->s2);
178     }
179     else if (zs->which == Z_RPNStructure_simple)
180     {
181         if (zs->u.simple->which == Z_Operand_APT)
182             yaz_apt_to_wrbuf(b, zs->u.simple->u.attributesPlusTerm);
183         else if (zs->u.simple->which == Z_Operand_resultSetId)
184         {
185             wrbuf_printf(b, "@set ");
186             yaz_encode_pqf_term(b, zs->u.simple->u.resultSetId,
187                                 strlen(zs->u.simple->u.resultSetId));
188         }
189         else
190             wrbuf_puts(b, "(unknown simple structure)");
191     }
192     else
193         wrbuf_puts(b, "(unknown structure)");
194 }
195
196 void yaz_rpnquery_to_wrbuf(WRBUF b, const Z_RPNQuery *rpn)
197 {
198     if (rpn->attributeSetId)
199     {
200         char oid_name_str[OID_STR_MAX];
201         const char *oid_name = yaz_oid_to_string_buf(rpn->attributeSetId,
202                                                      0, oid_name_str);
203         if (oid_name)
204             wrbuf_printf(b, "@attrset %s ", oid_name);
205     }
206     yaz_rpnstructure_to_wrbuf(b, rpn->RPNStructure);
207     wrbuf_chop_right(b);
208 }
209
210 void yaz_query_to_wrbuf(WRBUF b, const Z_Query *q)
211 {
212     assert(q);
213     assert(b);
214     switch (q->which)
215     {
216     case Z_Query_type_1:
217     case Z_Query_type_101:
218         wrbuf_puts(b,"RPN ");
219         yaz_rpnquery_to_wrbuf(b, q->u.type_1);
220         break;
221     case Z_Query_type_2:
222         wrbuf_puts(b, "CCL ");
223         wrbuf_write(b, (const char *) q->u.type_2->buf, q->u.type_2->len);
224         break;
225     case Z_Query_type_100:
226         wrbuf_puts(b, "Z39.58 ");
227         wrbuf_write(b, (const char *) q->u.type_100->buf, q->u.type_100->len);
228         break;
229     case Z_Query_type_104:
230         if (q->u.type_104->which == Z_External_CQL)
231         {
232             wrbuf_puts(b, "CQL ");
233             wrbuf_puts(b, q->u.type_104->u.cql);
234         }
235         else
236             wrbuf_printf(b,"UNKNOWN type 104 query %d", q->u.type_104->which);
237     }
238 }
239
240 void yaz_scan_to_wrbuf(WRBUF b, const Z_AttributesPlusTerm *zapt,
241                        const Odr_oid *attrbute_set)
242 {
243     /* should print attr set here */
244     wrbuf_puts(b, "RPN ");
245     yaz_apt_to_wrbuf(b, zapt);
246 }
247
248 void wrbuf_diags(WRBUF b, int num_diagnostics, Z_DiagRec **diags)
249 {
250     /* we only dump the first diag - that keeps the log cleaner. */
251     wrbuf_puts(b," ERROR ");
252     if (diags[0]->which != Z_DiagRec_defaultFormat)
253         wrbuf_puts(b,"(diag not in default format?)");
254     else
255     {
256         Z_DefaultDiagFormat *e = diags[0]->u.defaultFormat;
257         if (e->condition)
258             wrbuf_printf(b, ODR_INT_PRINTF " ",*e->condition);
259         else
260             wrbuf_puts(b, "?? ");
261         if ((e->which==Z_DefaultDiagFormat_v2Addinfo) && (e->u.v2Addinfo))
262             wrbuf_puts(b, e->u.v2Addinfo);
263         else if ((e->which==Z_DefaultDiagFormat_v3Addinfo) && (e->u.v3Addinfo))
264             wrbuf_puts(b, e->u.v3Addinfo);
265         wrbuf_puts(b, " ");
266     }
267 }
268
269 /*
270  * Local variables:
271  * c-basic-offset: 4
272  * c-file-style: "Stroustrup"
273  * indent-tabs-mode: nil
274  * End:
275  * vim: shiftwidth=4 tabstop=8 expandtab
276  */
277