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