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