a7cdb524fd3c5db7aeb6131362df4c730f8ab8c4
[yaz-moved-to-github.git] / src / solr.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2010 Index Data
3  * See the file LICENSE for details.
4  */
5 /**
6  * \file srwutil.c
7  * \brief Implements SRW/SRU utilities.
8  */
9
10 #include <stdlib.h>
11 #include <assert.h>
12 #include <yaz/srw.h>
13 #include <yaz/matchstr.h>
14 #include <yaz/yaz-iconv.h>
15 #include <yaz/log.h>
16
17 #include "sru-p.h"
18
19 #if YAZ_HAVE_XML2
20 #include <libxml/parser.h>
21 #include <libxml/tree.h>
22 #endif
23
24 int yaz_solr_decode_response(ODR o, Z_HTTP_Response *hres, Z_SRW_PDU **pdup)
25 {
26 #if YAZ_HAVE_XML2
27     const char *content_buf = hres->content_buf;
28     int content_len = hres->content_len;
29     xmlDocPtr doc = xmlParseMemory(content_buf, content_len);
30     int ret = 0;
31     xmlNodePtr ptr = 0;
32     Odr_int start = 0;
33     Z_SRW_PDU *pdu = yaz_srw_get(o, Z_SRW_searchRetrieve_response);
34     Z_SRW_searchRetrieveResponse *sr = pdu->u.response;
35
36     if (!doc)
37     {
38         ret = -1;
39     }
40     if (doc)
41     {
42         xmlNodePtr root = xmlDocGetRootElement(doc);
43         if (!root)
44         {
45             ret = -1;
46         }
47         else if (strcmp((const char *) root->name, "response"))
48         {
49             ret = -1;
50         }
51         else
52         {
53             /** look for result node */
54             for (ptr = root->children; ptr; ptr = ptr->next)
55             {
56                 if (ptr->type == XML_ELEMENT_NODE &&
57                     !strcmp((const char *) ptr->name, "result"))
58                     break;
59             }
60             if (!ptr)
61             {
62                 ret = -1;
63             }
64         }
65     }
66     if (ptr)
67     {   /* got result node */
68         struct _xmlAttr *attr;
69
70         for (attr = ptr->properties; attr; attr = attr->next)
71             if (attr->children && attr->children->type == XML_TEXT_NODE)
72             {
73                 if (!strcmp((const char *) attr->name, "numFound"))
74                 {
75                     sr->numberOfRecords =
76                         odr_intdup(o, 
77                                    odr_atoi(
78                                        (const char *) attr->children->content));
79                 }
80                 else if (!strcmp((const char *) attr->name, "start"))
81                 {
82                     start = odr_atoi((const char *) attr->children->content);
83                 }
84             }
85     }
86     if (ptr)
87     {
88         xmlNodePtr node;
89         int offset = 0;
90         int i = 0;
91
92         sr->num_records = 0;
93         for (node = ptr->children; node; node = node->next)
94             if (node->type == XML_ELEMENT_NODE)
95                 sr->num_records++;
96
97         sr->records = odr_malloc(o, sizeof(*sr->records) * sr->num_records);
98
99         for (node = ptr->children; node; node = node->next)
100         {
101             if (node->type == XML_ELEMENT_NODE)
102             {
103                 Z_SRW_record *record = sr->records + i;
104                 xmlBufferPtr buf = xmlBufferCreate();
105                 xmlNode *tmp = xmlCopyNode(node, 1);
106
107                 xmlNodeDump(buf, tmp->doc, tmp, 0, 0);
108
109                 xmlFreeNode(tmp);
110
111                 record->recordSchema = 0;
112                 record->recordPacking = Z_SRW_recordPacking_XML;
113                 record->recordData_len = buf->use;
114                 record->recordData_buf = odr_malloc(o, buf->use + 1);
115                 memcpy(record->recordData_buf, buf->content, buf->use);
116                 record->recordData_buf[buf->use] = '\0';
117                 // TODO Solve the real problem: Making the recordPosition 1-based due to "funny" code in zoom-sru
118                 record->recordPosition = odr_intdup(o, start + offset + 1);
119
120                 xmlBufferFree(buf);
121
122                 offset++;
123                 i++;
124             }
125         }
126     }
127     if (doc)
128         xmlFreeDoc(doc);
129     if (ret == 0)
130         *pdup = pdu;
131     return ret;
132 #else
133     return -1;
134 #endif
135 }
136
137 int yaz_solr_encode_request(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
138                             ODR encode, const char *charset)
139 {
140     const char *solr_op = 0;
141     char *name[30], *value[30];
142     char *uri_args;
143     char *path;
144     int i = 0;
145
146     z_HTTP_header_add_basic_auth(encode, &hreq->headers, 
147                                  srw_pdu->username, srw_pdu->password);
148
149     switch (srw_pdu->which)
150     {
151     case Z_SRW_searchRetrieve_request:
152         solr_op = "select";
153         
154         switch(srw_pdu->u.request->query_type)
155         {
156         case Z_SRW_query_type_pqf:
157             yaz_add_name_value_str(encode, name, value, &i,
158                                    "q", srw_pdu->u.request->query.pqf);
159             break;
160         case Z_SRW_query_type_cql:
161             yaz_add_name_value_str(encode, name, value, &i,
162                                    "q", srw_pdu->u.request->query.cql);
163             break;
164         default:
165             return -1;
166         }
167         if (srw_pdu->u.request->startRecord)
168         {
169             Odr_int start = *srw_pdu->u.request->startRecord - 1;
170             yaz_add_name_value_int(encode, name, value, &i,
171                                    "start", &start);
172         }
173         yaz_add_name_value_int(encode, name, value, &i,
174                                "rows", srw_pdu->u.request->maximumRecords);
175         yaz_add_name_value_str(encode, name, value, &i,
176                                "fl", srw_pdu->u.request->recordSchema);
177         break;
178     default:
179         return -1;
180     }
181     name[i] = 0;
182     yaz_array_to_uri(&uri_args, encode, name, value);
183     
184     hreq->method = "GET";
185     
186     path = (char *)
187         odr_malloc(encode, strlen(hreq->path) +
188                    strlen(uri_args) + strlen(solr_op) + 4);
189
190     sprintf(path, "%s/%s?%s", hreq->path, solr_op, uri_args);
191     hreq->path = path;
192
193     z_HTTP_header_add_content_type(encode, &hreq->headers,
194                                    "text/xml", charset);
195     return 0;
196 }
197
198
199 /*
200  * Local variables:
201  * c-basic-offset: 4
202  * c-file-style: "Stroustrup"
203  * indent-tabs-mode: nil
204  * End:
205  * vim: shiftwidth=4 tabstop=8 expandtab
206  */
207