Fixed bug in yaz_srw_get: case Z_SRW_scan_response missed a break.
[yaz-moved-to-github.git] / src / querytowrbuf.c
1 /*
2  * Copyright (C) 1995-2005, Index Data ApS
3  * All rights reserved.
4  *
5  * $Id: querytowrbuf.c,v 1.4 2006-04-19 10:05:03 adam Exp $
6  */
7
8 /** \file querytowrbuf.c
9     \brief Query to WRBUF (to strings)
10  */
11
12 #include <stdio.h>
13 #include <assert.h>
14
15 #include <yaz/logrpn.h>
16 #include <yaz/querytowrbuf.h>
17
18 static void yaz_term_to_wrbuf(WRBUF b, const char *term, int len)
19 {
20     int i;
21     for (i = 0; i < len; i++)
22         if (strchr(" \"{", term[i]))
23             break;
24     if (i == len && i)
25         wrbuf_printf(b, "%.*s ", len, term);
26     else
27     {
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         wrbuf_printf(b, "\" ");
36     }
37 }
38
39 static void yaz_attribute_element_to_wrbuf(WRBUF b,
40                                            const Z_AttributeElement *element)
41 {
42     int i;
43     char *setname="";
44     char *sep = ""; /* optional space after attrset name */
45     if (element->attributeSet)
46     {
47         oident *attrset;
48         attrset = oid_getentbyoid (element->attributeSet);
49         setname = attrset->desc;
50         sep = " ";
51     }
52     switch (element->which) 
53     {
54     case Z_AttributeValue_numeric:
55         wrbuf_printf(b,"@attr %s%s%d=%d ", setname, sep,
56                      *element->attributeType, *element->value.numeric);
57         break;
58     case Z_AttributeValue_complex:
59         wrbuf_printf(b,"@attr %s%s\"%d=", setname, sep,
60                      *element->attributeType);
61         for (i = 0; i<element->value.complex->num_list; i++)
62         {
63             if (i)
64                 wrbuf_printf(b,",");
65             if (element->value.complex->list[i]->which ==
66                 Z_StringOrNumeric_string)
67                 wrbuf_printf (b, "%s",
68                               element->value.complex->list[i]->u.string);
69             else if (element->value.complex->list[i]->which ==
70                      Z_StringOrNumeric_numeric)
71                 wrbuf_printf (b, "%d", 
72                               *element->value.complex->list[i]->u.numeric);
73         }
74         wrbuf_printf(b, "\" ");
75         break;
76     default:
77         wrbuf_printf (b, "@attr 1=unknown ");
78     }
79 }
80
81 static const char *complex_op_name(const Z_Operator *op)
82 {
83     switch (op->which)
84     {
85     case Z_Operator_and:
86         return "and";
87     case Z_Operator_or:
88         return "or";
89     case Z_Operator_and_not:
90         return "not";
91     case Z_Operator_prox:
92         return "prox";
93     default:
94         return "unknown complex operator";
95     }
96 }
97
98 static void yaz_apt_to_wrbuf(WRBUF b, const Z_AttributesPlusTerm *zapt)
99 {
100     int num_attributes = zapt->attributes->num_attributes;
101     int i;
102     for (i = 0; i<num_attributes; i++)
103         yaz_attribute_element_to_wrbuf(b,zapt->attributes->attributes[i]);
104     
105     switch (zapt->term->which)
106     {
107     case Z_Term_general:
108         yaz_term_to_wrbuf(b, (const char *)zapt->term->u.general->buf,
109                           zapt->term->u.general->len);
110         break;
111     case Z_Term_characterString:
112         wrbuf_printf(b, "@term string ");
113         yaz_term_to_wrbuf(b, zapt->term->u.characterString,
114                           strlen(zapt->term->u.characterString));
115         break;
116     case Z_Term_numeric:
117         wrbuf_printf(b, "@term numeric %d ", *zapt->term->u.numeric);
118         break;
119     case Z_Term_null:
120         wrbuf_printf(b, "@term null x");
121         break;
122     default:
123         wrbuf_printf(b, "@term null unknown%d ", zapt->term->which);
124     }
125 }
126
127 static void yaz_rpnstructure_to_wrbuf(WRBUF b, const Z_RPNStructure *zs)
128 {
129     if (zs->which == Z_RPNStructure_complex)
130     {
131         Z_Operator *op = zs->u.complex->roperator;
132         wrbuf_printf(b, "@%s ", complex_op_name(op) );
133         if (op->which== Z_Operator_prox)
134         {
135             if (!op->u.prox->exclusion)
136                 wrbuf_putc(b, 'n');
137             else if (*op->u.prox->exclusion)
138                 wrbuf_putc(b, '1');
139             else
140                 wrbuf_putc(b, '0');
141
142             wrbuf_printf(b, " %d %d %d ", *op->u.prox->distance,
143                          *op->u.prox->ordered,
144                          *op->u.prox->relationType);
145
146             switch(op->u.prox->which)
147             {
148             case Z_ProximityOperator_known:
149                 wrbuf_putc(b, 'k');
150                 break;
151             case Z_ProximityOperator_private:
152                 wrbuf_putc(b, 'p');
153                 break;
154             default:
155                 wrbuf_printf(b, "%d", op->u.prox->which);
156             }
157             if (op->u.prox->u.known)
158                 wrbuf_printf(b, " %d ", *op->u.prox->u.known);
159             else
160                 wrbuf_printf(b, " 0 ");
161         }
162         yaz_rpnstructure_to_wrbuf(b,zs->u.complex->s1);
163         yaz_rpnstructure_to_wrbuf(b,zs->u.complex->s2);
164     }
165     else if (zs->which == Z_RPNStructure_simple)
166     {
167         if (zs->u.simple->which == Z_Operand_APT)
168             yaz_apt_to_wrbuf(b, zs->u.simple->u.attributesPlusTerm);
169         else if (zs->u.simple->which == Z_Operand_resultSetId)
170         {
171             wrbuf_printf(b, "@set ");
172             yaz_term_to_wrbuf(b, zs->u.simple->u.resultSetId,
173                               strlen(zs->u.simple->u.resultSetId));
174         }
175         else
176             wrbuf_printf (b, "(unknown simple structure)");
177     }
178     else
179         wrbuf_puts(b, "(unknown structure)");
180 }
181
182 void yaz_rpnquery_to_wrbuf(WRBUF b, const Z_RPNQuery *rpn)
183 {
184     oident *attrset;
185     enum oid_value ast;
186     
187     attrset = oid_getentbyoid (rpn->attributeSetId);
188     if (attrset)
189     {
190         ast = attrset->value;
191         wrbuf_printf(b, "@attrset %s ", attrset->desc);
192     } 
193     yaz_rpnstructure_to_wrbuf(b, rpn->RPNStructure);
194     wrbuf_chop_right(b);
195 }
196
197 void yaz_query_to_wrbuf(WRBUF b, const Z_Query *q)
198 {
199     assert(q);
200     assert(b);
201     switch (q->which)
202     {
203     case Z_Query_type_1: 
204     case Z_Query_type_101:
205         wrbuf_printf(b,"RPN: ");
206         yaz_rpnquery_to_wrbuf(b, q->u.type_1);
207         break;
208     case Z_Query_type_2:
209         wrbuf_printf(b, "CCL: %.*s", q->u.type_2->len, q->u.type_2->buf);
210         break;
211     case Z_Query_type_100:
212         wrbuf_printf(b, "Z39.58: %.*s", q->u.type_100->len,
213                      q->u.type_100->buf);
214         break;
215     case Z_Query_type_104:
216         if (q->u.type_104->which == Z_External_CQL)
217             wrbuf_printf(b, "CQL: %s", q->u.type_104->u.cql);
218         else
219             wrbuf_printf(b,"Unknown type 104 query %d", q->u.type_104->which);
220     }
221 }
222
223 void yaz_scan_to_wrbuf(WRBUF b, const Z_AttributesPlusTerm *zapt,
224                        oid_value ast)
225 {
226     /* should print attr set here */
227     yaz_apt_to_wrbuf(b, zapt);
228 }
229
230 /* obsolete */
231 void wrbuf_scan_term(WRBUF b, const Z_AttributesPlusTerm *zapt, oid_value ast)
232 {
233     yaz_apt_to_wrbuf(b, zapt);
234 }
235
236 /* obsolete */
237 void wrbuf_put_zquery(WRBUF b, const Z_Query *q)
238 {
239     yaz_query_to_wrbuf(b, q);
240 }
241
242
243 /*
244  * Local variables:
245  * c-basic-offset: 4
246  * indent-tabs-mode: nil
247  * End:
248  * vim: shiftwidth=4 tabstop=8 expandtab
249  */
250