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