Fix a crash
[framework/location/libdecarta.git] / decarta / decarta_xml_directory.c
1 /*
2  * libdecarta
3  *
4  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Youngae Kang <youngae.kang@samsung.com>, Yunhan Kim <yhan.kim@samsung.com>,
7  *          Genie Kim <daejins.kim@samsung.com>, Minjune Kim <sena06.kim@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21
22 #include <glib.h>
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 #include "decarta_log.h"
27 #include "xml_wrapper.h"
28 #include "decarta_xml.h"
29 #include "decarta_xml_internal.h"
30
31 #define POI_CONTEXT             "//"NS_XLS":POIContext[%d]"
32
33 #define POI                     POI_CONTEXT"/"NS_XLS":POI"
34 #define POI_NAME                POI"/@POIName"
35 #define POI_ID                  POI"/@ID"
36 #define POI_PHONENUMBER         POI"/@phoneNumber"
37
38 #define POI_INFO                POI"/"NS_XLS":POIAttributeList/"NS_XLS":POIInfoList/"NS_XLS":POIInfo[%d]"
39 #define POI_INFO_NAME           POI_INFO"/@name"
40 #define POI_INFO_VALUE          POI_INFO"/@value"
41
42 #define POI_DISTANCE            POI_CONTEXT"/"NS_XLS":Distance"
43
44
45 static gboolean
46 make_xml_poi_location (XmlWriterHandler handle,
47         const DecartaDirectoryRequest *request)
48 {
49         if (!xml_writer_all_start(handle, NS_XLS":POILocation", NULL, NULL)) return FALSE;
50
51         if (request->search_type == DECARTA_DIRECTORY_SEARCH_TYPE_NEAREST){
52                 if (!xml_writer_all_start(handle, NS_XLS":Nearest", NULL, NULL)) return FALSE;
53         } else if (request->search_type == DECARTA_DIRECTORY_SEARCH_TYPE_WITHIN_DISTANCE){
54                 if (!xml_writer_all_start(handle, NS_XLS":WithinDistance", NULL, NULL)) return FALSE;
55         } else if (request->search_type == DECARTA_DIRECTORY_SEARCH_TYPE_ADDRESS){
56                 // Address type added, needn't the NS_XLS":Address" keyword
57         } else if (request->search_type == DECARTA_DIRECTORY_SEARCH_TYPE_WITHIN_BOUNDARY){
58                 if (!xml_writer_all_start(handle, NS_XLS":WithinBoundary", NULL, NULL)) return FALSE;
59         } else {
60                 DECARTA_LOGW("Invalid DecartaDirectorySearchType");
61                 return FALSE;
62         }
63
64         if (request->type == DECARTA_DIRECTORY_TYPE_POS){
65                 if (!xml_writer_all_start(handle, NS_XLS":POI", NULL, "ID", "1", NULL)) return FALSE;
66                 if (!xml_writer_all_start(handle, NS_GML":Point", NULL, NULL)) return FALSE;
67                 if (!make_xml_position(handle, request->pos)) return FALSE;
68                 if (!xml_writer_end(handle)) return FALSE;
69                 if (!xml_writer_end(handle)) return FALSE;
70         } else if(request->type == DECARTA_DIRECTORY_TYPE_ADDRESS){
71                 if (request->search_type == DECARTA_DIRECTORY_SEARCH_TYPE_ADDRESS) {
72                         // Directory ADDRESS mode's address different with others, NOT "place"
73                         if (!make_directory_addr_mode_xml_address(handle, request->addr)) return FALSE;
74                 } else {
75                         if (!make_xml_address(handle, request->addr)) return FALSE;
76                 }
77         } else if(request->type == DECARTA_DIRECTORY_TYPE_BOUNDARY){
78                 if (!make_xml_boundary(handle, request->boundary)) return FALSE;
79         } else {
80                 DECARTA_LOGW("Invalid DecartaDirectoryType");
81                 return FALSE;
82         }
83         if (request->search_type == DECARTA_DIRECTORY_SEARCH_TYPE_WITHIN_DISTANCE){
84                 char max_dist[256];
85                 g_snprintf(max_dist, 256, "%f", request->distance);
86                 if(!xml_writer_all_start(handle, NS_XLS":MaximumDistance", NULL, "value", max_dist, "uom", DISTANCE_UINT, NULL))  return FALSE;
87                 if (!xml_writer_end(handle)) return FALSE;      }
88         if (!xml_writer_end(handle)) return FALSE;
89
90         if (request->search_type != DECARTA_DIRECTORY_SEARCH_TYPE_ADDRESS) {
91                 // in directory ADDRESS mode, No this end toker
92                 if (!xml_writer_end(handle)) return FALSE;
93         }
94
95         if (request->property) {
96                 if(!xml_writer_all_start(handle, NS_XLS":POIProperties", NULL, NULL))  return FALSE;
97
98                 if (!xml_writer_element_start(handle, NS_XLS":POIProperty")) return FALSE;
99                 if (request->property->poi_name) {
100                         if (!xml_writer_attribute_write(handle, "name", "POIName")) return FALSE;
101                         if (!xml_writer_attribute_write(handle, "value", request->property->poi_name)) return FALSE;
102                 }
103                 if (request->property->keyword) {
104                         if (!xml_writer_attribute_write(handle, "name", "Keyword")) return FALSE;
105                         if (!xml_writer_attribute_write(handle, "value", request->property->keyword)) return FALSE;
106                 }
107                 if (request->property->brand) {
108                         if (!xml_writer_attribute_write(handle, "name", "Brand")) return FALSE;
109                         if (!xml_writer_attribute_write(handle, "value", request->property->brand)) return FALSE;
110                 }
111                 if (request->property->type) {
112                         if (!xml_writer_attribute_write(handle, "name", "Type")) return FALSE;
113                         if (!xml_writer_attribute_write(handle, "value", request->property->type)) return FALSE;
114                 }
115                 if (request->property->description) {
116                         if (!xml_writer_attribute_write(handle, "name", "description")) return FALSE;
117                         if (!xml_writer_attribute_write(handle, "value", request->property->description)) return FALSE;
118                 }
119                 if (request->property->URL) {
120                         if (!xml_writer_attribute_write(handle, "name", "URL")) return FALSE;
121                         if (!xml_writer_attribute_write(handle, "value", request->property->URL)) return FALSE;
122                 }
123             if( !xml_writer_end(handle)) return FALSE;
124             if( !xml_writer_end(handle)) return FALSE;
125         }
126     return TRUE;
127 }
128
129 gboolean
130 xml_directory_request_get (const DecartaDirectoryRequest *request,
131         char **xml_request,
132         unsigned int *size)
133 {
134         if (!request || !request->pref || !request->pref->item ||
135                         !xml_request || !size) {
136                 DECARTA_LOGW ("request or xml_request or size is NULL");
137                 return FALSE;
138         }
139
140         char max_responses[32];
141         if (g_snprintf (max_responses, 32, "%d", request->pref->max_result_cnt) < 0) return FALSE;
142         char request_id[32];
143         // pass the  request_id from the caller
144         if (g_snprintf (request_id, 32, "%d", request->request_id) < 0) return FALSE;
145
146         if ((g_strcmp0(request->pref->item, "Name") != 0) && (g_strcmp0(request->pref->item, "Type") != 0) &&
147                         (g_strcmp0(request->pref->item, "Distance") != 0)) {
148                 DECARTA_LOGW ("directory request's sort criteria string is wrong");
149                 return FALSE;
150         }
151
152         gchar *sortDirection = NULL;
153         if (request->pref->sort_order == DECARTA_POI_PREF_SO_ASC) {
154                 sortDirection = g_strdup("Ascending");
155         } else if (request->pref->sort_order == DECARTA_POI_PREF_SO_DESC) {
156                 sortDirection = g_strdup("Descending");
157         } else {
158                 DECARTA_LOGW ("set directory request's sort direction to ascending");
159                 sortDirection = g_strdup("Ascending");
160         }
161
162         gboolean ret = FALSE;
163         XmlWriterHandler handle = xml_writer_open("UTF-8");
164         if (!handle) {
165                 g_free(sortDirection);
166                 sortDirection = NULL;
167                 return FALSE;
168         }
169         if (make_xml_header(handle, "DirectoryRequest", max_responses, request_id) &&
170                 xml_writer_all_start(handle, NS_XLS":DirectoryRequest", NULL, "sortCriteria", request->pref->item, "sortDirection", sortDirection, NULL) &&
171                 make_xml_poi_location(handle, request) &&
172                 xml_writer_end(handle)) ret = TRUE;
173         else ret = FALSE;
174         if (!xml_writer_close(handle, xml_request, size)) ret = FALSE;
175
176         if (sortDirection) {
177                 g_free(sortDirection);
178                 sortDirection = NULL;
179         }
180         return ret;
181 }
182
183 gboolean
184 xml_directory_parse (const char* xml_response,
185         GList** poi_list,
186         char **req_id,
187         char **error_code,
188         char **message)
189 {
190         DECARTA_LOGD ("xml_directory_parse");
191         if (!xml_response || !poi_list || !req_id || !error_code || !message) {
192                 DECARTA_LOGW ("xml_response or response is NULL");
193                 return FALSE;
194         }
195         XmlReaderHandler handle = xml_reader_open (xml_response, NS_XLS, NS_XLS_URI, NS_GML, NS_GML_URI, NULL);
196         if (!handle) return FALSE;
197
198         int idx = 1;
199         *poi_list = NULL;
200
201         if (parse_xml_request_id(handle, req_id)) {
202                 DECARTA_LOGD ("xml_directory_parse req_id: [%s]", *req_id);
203         }
204
205         char *severity = NULL;
206         if (parse_xml_error (handle, error_code, message, &severity)) {
207                 DECARTA_LOGD ("xml_directory_parse %s: %s [%s]", *error_code, *message, severity);
208                 g_free(severity);
209                 xml_reader_close (handle);
210                 return FALSE;
211         }
212
213         while (1) {
214                 char *name = NULL;
215                 char *id = NULL;
216                 char* phone_number = NULL;
217                 DecartaPOIInfoTable *info_list = NULL;
218                 DecartaPosition *pos = NULL;
219                 DecartaAddress *addr = NULL;
220                 double distance = 0;
221
222                 if (!xml_reader_is_valid (handle, POI_CONTEXT, idx)) break;
223                 xml_reader_get_string(handle, &name, POI_NAME, idx);
224                 xml_reader_get_string(handle, &id, POI_ID, idx);
225                 xml_reader_get_string(handle, &phone_number, POI_PHONENUMBER, idx);
226                 int idx2 = 1;
227                 while (xml_reader_is_valid (handle, POI_INFO, idx, idx2)) {
228                         info_list = decarta_poi_info_table_new ();
229                         char *info_name = NULL;
230                         char *info_val = NULL;
231                         xml_reader_get_string(handle, &info_name, POI_INFO_NAME, idx, idx2);
232                         xml_reader_get_string(handle, &info_val, POI_INFO_VALUE, idx, idx2);
233                         decarta_poi_info_table_insert (info_list, info_name, info_val);
234                         g_free(info_name);
235                         g_free(info_val);
236                         idx2++;
237                 }
238                 char *poi_prefix = g_strdup_printf(POI, idx);
239                 pos = parse_xml_position(handle, poi_prefix, 1);
240                 addr = parse_xml_address(handle, poi_prefix);
241                 g_free(poi_prefix);
242
243                 char* distance_str = NULL;
244                 xml_reader_get_string(handle, &distance_str, POI_DISTANCE, idx);
245                 if (distance_str) {
246                         distance = g_strtod (distance_str, NULL);
247                         g_free (distance_str);
248                 }
249                 DecartaPOI *poi = decarta_poi_new (name, id, phone_number, info_list, pos, addr, distance);
250                 g_free (name);
251                 g_free (id);
252                 g_free (phone_number);
253                 decarta_poi_info_table_free (info_list);
254                 decarta_position_free (pos);
255                 decarta_address_free (addr);
256                 *poi_list = decarta_poi_list_append (*poi_list, poi);
257                 idx++;
258         }
259         xml_reader_close(handle);
260         return TRUE;
261 }