1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2009 Index Data
3 * See the file LICENSE for details.
8 * \brief Implements RPN to CQL conversion
15 #include <yaz/rpn2cql.h>
16 #include <yaz/xmalloc.h>
17 #include <yaz/diagbib1.h>
18 #include <yaz/z-core.h>
19 #include <yaz/wrbuf.h>
21 static const char *lookup_index_from_string_attr(Z_AttributeList *attributes)
24 int server_choice = 1;
25 for (j = 0; j < attributes->num_attributes; j++)
27 Z_AttributeElement *ae = attributes->attributes[j];
28 if (*ae->attributeType == 1) /* use attribute */
30 if (ae->which == Z_AttributeValue_complex)
32 Z_ComplexAttribute *ca = ae->value.complex;
34 for (i = 0; i < ca->num_list; i++)
36 Z_StringOrNumeric *son = ca->list[i];
37 if (son->which == Z_StringOrNumeric_string)
41 server_choice = 0; /* not serverChoice because we have use attr */
45 return "cql.serverChoice";
49 static const char *lookup_relation_index_from_attr(Z_AttributeList *attributes)
52 for (j = 0; j < attributes->num_attributes; j++)
54 Z_AttributeElement *ae = attributes->attributes[j];
55 if (*ae->attributeType == 2) /* relation attribute */
57 if (ae->which == Z_AttributeValue_numeric)
59 /* Only support for numeric relation */
60 Odr_int *relation = ae->value.numeric;
61 /* map this numeric to representation in CQL */
63 /* Unsure on whether this is the relation attribute constants? */
64 case Z_ProximityOperator_Prox_lessThan:
66 case Z_ProximityOperator_Prox_lessThanOrEqual:
68 case Z_ProximityOperator_Prox_equal:
70 case Z_ProximityOperator_Prox_greaterThanOrEqual:
72 case Z_ProximityOperator_Prox_greaterThan:
74 case Z_ProximityOperator_Prox_notEqual:
77 /* phonetic is not supported in CQL */
80 /* stem is not supported in CQL */
83 /* relevance is supported in CQL, but not implemented yet */
86 /* Invalid relation */
91 /* Can we have a complex relation value?
92 Should we implement something?
100 static int rpn2cql_attr(cql_transform_t ct,
101 Z_AttributeList *attributes, WRBUF w)
103 const char *relation = cql_lookup_reverse(ct, "relation.", attributes);
104 const char *index = cql_lookup_reverse(ct, "index.", attributes);
105 const char *structure = cql_lookup_reverse(ct, "structure.", attributes);
107 /* if transform (properties) do not match, we'll just use a USE string attribute (bug #2978) */
109 index = lookup_index_from_string_attr(attributes);
111 /* Attempt to fix bug #2978: Look for a relation attribute */
113 relation = lookup_relation_index_from_attr(attributes);
117 cql_transform_set_error(ct,
118 YAZ_BIB1_UNSUPP_USE_ATTRIBUTE, 0);
121 /* for serverChoice we omit index+relation+structure */
122 if (strcmp(index, "cql.serverChoice"))
124 wrbuf_puts(w, index);
127 if (!strcmp(relation, "exact"))
129 else if (!strcmp(relation, "eq"))
131 else if (!strcmp(relation, "le"))
133 else if (!strcmp(relation, "ge"))
135 /* Missing mapping of not equal, phonetic, stem and relevance */
136 wrbuf_puts(w, relation);
143 if (strcmp(structure, "*"))
146 wrbuf_puts(w, structure);
154 /* Bug 2878: Currently only support left and right truncation. Specific check for this */
155 static int checkForTruncation(int flag, Z_AttributeList *attributes) {
157 int server_choice = 1;
158 for (j = 0; j < attributes->num_attributes; j++)
160 Z_AttributeElement *ae = attributes->attributes[j];
161 if (*ae->attributeType == 5) /* truncation attribute */
163 if (ae->which == Z_AttributeValue_numeric)
165 int truncation = *(ae->value.numeric);
166 /* This logic only works for Left, right and both. eg. 1,2,3 */
168 return (int) (truncation & flag);
170 /* Complex: Shouldn't happen */
173 /* No truncation or unsupported */
177 static int checkForLeftTruncation(Z_AttributeList *attributes) {
178 return checkForTruncation(1, attributes);
181 static int checkForRightTruncation(Z_AttributeList *attributes) {
182 return checkForTruncation(2, attributes);
185 static int rpn2cql_simple(cql_transform_t ct,
186 void (*pr)(const char *buf, void *client_data),
188 Z_Operand *q, WRBUF w)
191 if (q->which != Z_Operand_APT)
194 cql_transform_set_error(ct, YAZ_BIB1_RESULT_SET_UNSUPP_AS_A_SEARCH_TERM, 0);
198 Z_AttributesPlusTerm *apt = q->u.attributesPlusTerm;
199 Z_Term *term = apt->term;
200 const char *sterm = 0;
204 ret = rpn2cql_attr(ct, apt->attributes, w);
209 lterm = term->u.general->len;
210 sterm = (const char *) term->u.general->buf;
213 wrbuf_printf(w, ODR_INT_PRINTF, *term->u.numeric);
215 case Z_Term_characterString:
216 sterm = term->u.characterString;
217 lterm = strlen(sterm);
221 cql_transform_set_error(ct, YAZ_BIB1_TERM_TYPE_UNSUPP, 0);
228 for (i = 0 ; i < lterm; i++)
233 /* Bug 2878: Check and add Truncation */
234 if (checkForLeftTruncation(apt->attributes))
236 wrbuf_write(w, sterm, lterm);
237 /* Bug 2878: Check and add Truncation */
238 if (checkForRightTruncation(apt->attributes))
244 pr(wrbuf_cstr(w), client_data);
250 static int rpn2cql_structure(cql_transform_t ct,
251 void (*pr)(const char *buf, void *client_data),
253 Z_RPNStructure *q, int nested,
256 if (q->which == Z_RPNStructure_simple)
257 return rpn2cql_simple(ct, pr, client_data, q->u.simple, w);
260 Z_Operator *op = q->u.complex->roperator;
264 pr("(", client_data);
266 r = rpn2cql_structure(ct, pr, client_data, q->u.complex->s1, 1, w);
272 pr(" and ", client_data);
275 pr(" or ", client_data);
277 case Z_Operator_and_not:
278 pr(" not ", client_data);
280 case Z_Operator_prox:
281 cql_transform_set_error(ct, YAZ_BIB1_UNSUPP_SEARCH, 0);
284 r = rpn2cql_structure(ct, pr, client_data, q->u.complex->s2, 1, w);
286 pr(")", client_data);
291 int cql_transform_rpn2cql_stream(cql_transform_t ct,
292 void (*pr)(const char *buf, void *client_data),
297 WRBUF w = wrbuf_alloc();
298 cql_transform_set_error(ct, 0, 0);
299 r = rpn2cql_structure(ct, pr, client_data, q->RPNStructure, 0, w);
305 int cql_transform_rpn2cql_wrbuf(cql_transform_t ct,
309 return cql_transform_rpn2cql_stream(ct, wrbuf_vputs, w, q);
315 * c-file-style: "Stroustrup"
316 * indent-tabs-mode: nil
318 * vim: shiftwidth=4 tabstop=8 expandtab