Move main YAZ manual to book.xml; use nxml YAZ-758
[yaz-moved-to-github.git] / src / querytowrbuf.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 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_attributes_to_wrbuf(WRBUF w, const Z_AttributeList *al)
111 {
112     int i;
113     for (i = 0; i < al->num_attributes; i++)
114         yaz_attribute_element_to_wrbuf(w, al->attributes[i]);
115 }
116
117 static void yaz_apt_to_wrbuf(WRBUF b, const Z_AttributesPlusTerm *zapt)
118 {
119     yaz_attributes_to_wrbuf(b, zapt->attributes);
120     switch (zapt->term->which)
121     {
122     case Z_Term_general:
123         yaz_encode_pqf_term(b, (const char *)zapt->term->u.general->buf,
124                             zapt->term->u.general->len);
125         break;
126     case Z_Term_characterString:
127         wrbuf_puts(b, "@term string ");
128         yaz_encode_pqf_term(b, zapt->term->u.characterString,
129                             strlen(zapt->term->u.characterString));
130         break;
131     case Z_Term_numeric:
132         wrbuf_printf(b, "@term numeric " ODR_INT_PRINTF " ",
133                      *zapt->term->u.numeric);
134         break;
135     case Z_Term_null:
136         wrbuf_puts(b, "@term null x");
137         break;
138     default:
139         wrbuf_printf(b, "@term null unknown%d ", zapt->term->which);
140     }
141 }
142
143 static void yaz_rpnstructure_to_wrbuf(WRBUF b, const Z_RPNStructure *zs)
144 {
145     if (zs->which == Z_RPNStructure_complex)
146     {
147         Z_Operator *op = zs->u.complex->roperator;
148         wrbuf_printf(b, "@%s ", complex_op_name(op) );
149         if (op->which== Z_Operator_prox)
150         {
151             if (!op->u.prox->exclusion)
152                 wrbuf_putc(b, 'n');
153             else if (*op->u.prox->exclusion)
154                 wrbuf_putc(b, '1');
155             else
156                 wrbuf_putc(b, '0');
157
158             wrbuf_printf(b, " " ODR_INT_PRINTF " %d "
159                          ODR_INT_PRINTF " ", *op->u.prox->distance,
160                          *op->u.prox->ordered,
161                          *op->u.prox->relationType);
162
163             switch(op->u.prox->which)
164             {
165             case Z_ProximityOperator_known:
166                 wrbuf_putc(b, 'k');
167                 break;
168             case Z_ProximityOperator_private:
169                 wrbuf_putc(b, 'p');
170                 break;
171             default:
172                 wrbuf_printf(b, "%d", op->u.prox->which);
173             }
174             if (op->u.prox->u.known)
175                 wrbuf_printf(b, " " ODR_INT_PRINTF " ", *op->u.prox->u.known);
176             else
177                 wrbuf_printf(b, " 0 ");
178         }
179         yaz_rpnstructure_to_wrbuf(b,zs->u.complex->s1);
180         yaz_rpnstructure_to_wrbuf(b,zs->u.complex->s2);
181     }
182     else if (zs->which == Z_RPNStructure_simple)
183     {
184         if (zs->u.simple->which == Z_Operand_APT)
185             yaz_apt_to_wrbuf(b, zs->u.simple->u.attributesPlusTerm);
186         else if (zs->u.simple->which == Z_Operand_resultSetId)
187         {
188             wrbuf_printf(b, "@set ");
189             yaz_encode_pqf_term(b, zs->u.simple->u.resultSetId,
190                                 strlen(zs->u.simple->u.resultSetId));
191         }
192         else
193             wrbuf_puts(b, "(unknown simple structure)");
194     }
195     else
196         wrbuf_puts(b, "(unknown structure)");
197 }
198
199 void yaz_rpnquery_to_wrbuf(WRBUF b, const Z_RPNQuery *rpn)
200 {
201     if (rpn->attributeSetId)
202     {
203         char oid_name_str[OID_STR_MAX];
204         const char *oid_name = yaz_oid_to_string_buf(rpn->attributeSetId,
205                                                      0, oid_name_str);
206         if (oid_name)
207             wrbuf_printf(b, "@attrset %s ", oid_name);
208     }
209     yaz_rpnstructure_to_wrbuf(b, rpn->RPNStructure);
210     wrbuf_chop_right(b);
211 }
212
213 void yaz_query_to_wrbuf(WRBUF b, const Z_Query *q)
214 {
215     assert(q);
216     assert(b);
217     switch (q->which)
218     {
219     case Z_Query_type_1:
220     case Z_Query_type_101:
221         wrbuf_puts(b,"RPN ");
222         yaz_rpnquery_to_wrbuf(b, q->u.type_1);
223         break;
224     case Z_Query_type_2:
225         wrbuf_puts(b, "CCL ");
226         wrbuf_write(b, (const char *) q->u.type_2->buf, q->u.type_2->len);
227         break;
228     case Z_Query_type_100:
229         wrbuf_puts(b, "Z39.58 ");
230         wrbuf_write(b, (const char *) q->u.type_100->buf, q->u.type_100->len);
231         break;
232     case Z_Query_type_104:
233         if (q->u.type_104->which == Z_External_CQL)
234         {
235             wrbuf_puts(b, "CQL ");
236             wrbuf_puts(b, q->u.type_104->u.cql);
237         }
238         else
239             wrbuf_printf(b,"UNKNOWN type 104 query %d", q->u.type_104->which);
240     }
241 }
242
243 void yaz_scan_to_wrbuf(WRBUF b, const Z_AttributesPlusTerm *zapt,
244                        const Odr_oid *attrbute_set)
245 {
246     /* should print attr set here */
247     wrbuf_puts(b, "RPN ");
248     yaz_apt_to_wrbuf(b, zapt);
249 }
250
251 void wrbuf_diags(WRBUF b, int num_diagnostics, Z_DiagRec **diags)
252 {
253     /* we only dump the first diag - that keeps the log cleaner. */
254     wrbuf_puts(b," ERROR ");
255     if (diags[0]->which != Z_DiagRec_defaultFormat)
256         wrbuf_puts(b,"(diag not in default format?)");
257     else
258     {
259         Z_DefaultDiagFormat *e = diags[0]->u.defaultFormat;
260         if (e->condition)
261             wrbuf_printf(b, ODR_INT_PRINTF " ",*e->condition);
262         else
263             wrbuf_puts(b, "?? ");
264         if ((e->which==Z_DefaultDiagFormat_v2Addinfo) && (e->u.v2Addinfo))
265             wrbuf_puts(b, e->u.v2Addinfo);
266         else if ((e->which==Z_DefaultDiagFormat_v3Addinfo) && (e->u.v3Addinfo))
267             wrbuf_puts(b, e->u.v3Addinfo);
268         wrbuf_puts(b, " ");
269     }
270 }
271
272 void yaz_facet_list_to_wrbuf(WRBUF w, const Z_FacetList *fl)
273 {
274     int i;
275     for (i = 0; i < fl->num; i++)
276     {
277         Z_FacetField *ff = fl->elements[i];
278
279         if (i)
280             wrbuf_puts(w, ", ");
281         yaz_attributes_to_wrbuf(w, ff->attributes);
282     }
283 }
284
285 /*
286  * Local variables:
287  * c-basic-offset: 4
288  * c-file-style: "Stroustrup"
289  * indent-tabs-mode: nil
290  * End:
291  * vim: shiftwidth=4 tabstop=8 expandtab
292  */
293