81d49aee78c2fecbfe691335d0195a150a3714c8
[framework/location/maps-service.git] / src / session / commands.cpp
1 /* Copyright (c) 2010-2014 Samsung Electronics Co., Ltd. All rights reserved.
2  *
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "commands.h"
18 #include "maps_util.h"
19 #include "maps_place_private.h"
20 #include "maps_route_private.h"
21 #include "empty_module.h"
22
23 static int __put_to_hashtable(session::command_handler *ch,
24                               maps_service_data_e feature,
25                               const char *feature_str,
26                               maps_string_hashtable_h t)
27 {
28         if (!ch || !feature_str || !t)
29                 return MAPS_ERROR_INVALID_PARAMETER;
30         bool supported = false;
31         ch->plugin()->interface.maps_plugin_is_data_supported(feature,
32                 &supported);
33         return (supported) ? maps_string_hashtable_set(t, feature_str,
34                 feature_str) : MAPS_ERROR_NONE;
35 }
36
37 /*----------------------------------------------------------------------------*/
38 /*typedef int (*maps_plugin_geocode_f)(maps_service_h maps, const char *address,
39 * maps_service_geocode_cb callback, void *user_data, int *request_id); */
40 session::command_geocode::command_geocode(maps_service_h ms, const string a,
41                                           const maps_item_hashtable_h pref,
42                                           maps_service_geocode_cb cb,
43                                           void *ud, int *request_id)
44  : command(ms)
45  , address(a)
46  , preference(NULL)
47  , callback(cb)
48  , user_data(ud)
49  , error(0)
50 {
51         *request_id = command::command_request_id++;
52         my_req_id = *request_id;
53
54         if (pref &&
55             (maps_item_hashtable_clone(pref, &preference) != MAPS_ERROR_NONE))
56                 error = MAPS_ERROR_INVALID_PARAMETER;
57 }
58
59 session::command_geocode::~command_geocode()
60 {
61         maps_item_hashtable_destroy(preference);
62 }
63
64 int session::command_geocode::run()
65 {
66
67         if (error != MAPS_ERROR_NONE)
68                 return error;
69
70         pending_request pr(plugin());
71
72         /* Get the plugin interface function */
73         maps_plugin_geocode_f func = interface()->maps_plugin_geocode;
74         command_geocode_handler *handler = NULL;
75         if (func) {
76                 /*  need to create the handler when the function is NULL */
77                 pr.add(my_req_id);
78                 handler = new command_geocode_handler(plugin(),
79                                              callback,
80                                              user_data,
81                                              my_req_id);
82
83                 if (handler) {
84                         /* Run the plugin interface function */
85                         error = func(address.c_str(), preference,
86                                          command_geocode_handler::foreach_geocode_cb, handler,
87                                          &handler->plg_req_id);
88
89                         pr.update(my_req_id, handler);
90
91                         MAPS_LOGD("session::command_geocode::run: %d", my_req_id);
92                 }
93                 else {
94                         error = MAPS_ERROR_OUT_OF_MEMORY;
95                 }
96         }
97         else {
98                 /* Plugin Function is NULL: use default empty function */
99                 /*
100                 func = plugin::get_empty_interface().maps_plugin_geocode;
101                 */
102                 MAPS_LOGE("MAPS_ERROR_NOT_SUPPORTED: Can't get any plugin");
103                 error = MAPS_ERROR_NOT_SUPPORTED;
104         }
105
106         const int ret = error;
107         destroy();
108         return ret;
109 }
110
111 session::command_geocode_handler::command_geocode_handler(plugin::plugin_s *p,
112                                                 maps_service_geocode_cb cb,
113                                                 void *ud, int urid)
114  : command_handler(p, ud, urid)
115  , callback(cb)
116 {
117 }
118
119 bool session::command_geocode_handler::foreach_geocode_cb(maps_error_e error,
120                                                           int request_id,
121                                                           int index,
122                                                           int total_count,
123                                                           maps_coordinates_h
124                                                           coordinates,
125                                                           void *user_data)
126 {
127
128         command_geocode_handler *handler =
129                 (command_geocode_handler *) user_data;
130
131         if (request_id != handler->plg_req_id) {
132                 MAPS_LOGE(
133 "\n\nERROR! Incorrect request id [%d] come from the plugin; expected [%d]\n\n",
134                         request_id, handler->plg_req_id);
135         }
136
137         /* Make a user's copy of result data */
138         maps_coordinates_h cloned_result = NULL;
139         if (error == MAPS_ERROR_NONE)
140                 error = (maps_error_e) maps_coordinates_clone(coordinates,
141                         &cloned_result);
142         maps_coordinates_destroy(coordinates);
143
144         /* Send data to user */
145         const bool b =
146                 handler->callback(error, handler->user_req_id, index,
147                 total_count, cloned_result, handler->user_data);
148         if (!b || (index >= (total_count - 1))) {
149                 pending_request pr(handler->plugin());
150                 pr.remove(handler->user_req_id);
151         }
152
153         return b;
154 }
155
156 /*----------------------------------------------------------------------------*/
157 /*typedef int (*maps_plugin_geocode_inside_area_f)(maps_service_h maps, const
158 * char *address, maps_area_h bounds, maps_service_geocode_cb callback,
159 * void *user_data, int *request_id); */
160 session::command_geocode_inside_bounds::command_geocode_inside_bounds(
161                                         maps_service_h ms,
162                                         const char *a,
163                                         const maps_area_h b,
164                                         const maps_item_hashtable_h pref,
165                                         maps_service_geocode_cb cb,
166                                         void *ud, int *request_id)
167  : command(ms)
168  , address(a)
169  , bounds(NULL)
170  , preference(NULL)
171  , callback(cb)
172  , user_data(ud)
173  , error(0)
174 {
175         *request_id = command::command_request_id++;
176         my_req_id = *request_id;
177
178         if (maps_area_clone(b, &bounds) != MAPS_ERROR_NONE)
179                 error = MAPS_ERROR_INVALID_PARAMETER;
180
181         if (pref &&
182             (maps_item_hashtable_clone(pref, &preference) != MAPS_ERROR_NONE))
183                 error = MAPS_ERROR_INVALID_PARAMETER;
184 }
185
186 session::command_geocode_inside_bounds::~command_geocode_inside_bounds()
187 {
188         maps_area_destroy(bounds);
189         maps_item_hashtable_destroy(preference);
190 }
191
192 int session::command_geocode_inside_bounds::run()
193 {
194         if (error != MAPS_ERROR_NONE)
195                 return error;
196
197         pending_request pr(plugin());
198
199         /* Get the plugin interface function */
200         maps_plugin_geocode_inside_area_f func =
201                 interface()->maps_plugin_geocode_inside_area;
202         command_geocode_handler *handler = NULL;
203         if (func) {
204                 /* No need to create the handler when the function is NULL */
205                 pr.add(my_req_id);
206                 handler = new command_geocode_handler(plugin(),
207                                                       callback,
208                                                       user_data,
209                                                       my_req_id);
210
211                 if (handler) {
212                         /* Run the plugin interface function */
213                         error = func(address.c_str(), bounds, preference,
214                                      command_geocode_handler::foreach_geocode_cb,
215                                      handler, &handler->plg_req_id);
216
217                         pr.update(my_req_id, handler);
218
219                         MAPS_LOGD("session::command_geocode_inside_bounds::run: %d", my_req_id);
220                 }
221                 else {
222                         error = MAPS_ERROR_OUT_OF_MEMORY;
223                 }
224         }
225         else {
226                 /* Plugin Function is NULL: use default empty function */
227                 /*
228                 func = plugin::get_empty_interface().
229                         maps_plugin_geocode_inside_area;
230                 */
231                 MAPS_LOGE("MAPS_ERROR_NOT_SUPPORTED: Can't get any plugin");
232                 error = MAPS_ERROR_NOT_SUPPORTED;
233         }
234
235         const int ret = error;
236         destroy();
237         return ret;
238 }
239
240 /*----------------------------------------------------------------------------*/
241 /*typedef int (*maps_plugin_geocode_by_structured_address_f)(
242 * maps_service_h maps, maps_address_h address, maps_preference_h preference,
243 * maps_service_geocode_cb callback, void *user_data, int *request_id); */
244 session::command_geocode_by_structured_address::
245         command_geocode_by_structured_address(maps_service_h ms,
246                                               const maps_address_h a,
247                                               const maps_item_hashtable_h pref,
248                                               maps_service_geocode_cb cb,
249                                               void *ud, int *request_id)
250  : command(ms)
251  , address(NULL)
252  , preference(NULL)
253  , callback(cb)
254  , user_data(ud)
255  , error(0)
256 {
257         *request_id = command::command_request_id++;
258         my_req_id = *request_id;
259
260         if (maps_address_clone(a, &address) != MAPS_ERROR_NONE)
261                 error = MAPS_ERROR_INVALID_PARAMETER;
262
263         if (pref &&
264             (maps_item_hashtable_clone(pref, &preference) != MAPS_ERROR_NONE))
265                 error = MAPS_ERROR_INVALID_PARAMETER;
266 }
267
268 session::command_geocode_by_structured_address::
269         ~command_geocode_by_structured_address()
270 {
271         maps_address_destroy(address);
272         maps_item_hashtable_destroy(preference);
273 }
274
275 int session::command_geocode_by_structured_address::run()
276 {
277         if (error != MAPS_ERROR_NONE)
278                 return error;
279
280         pending_request pr(plugin());
281
282         /* Get the plugin interface function */
283         maps_plugin_geocode_by_structured_address_f func =
284                 interface()->maps_plugin_geocode_by_structured_address;
285         command_geocode_handler *handler = NULL;
286         if (func) {
287                 /* No need to create the handler when the function is NULL */
288                 pr.add(my_req_id);
289                 handler = new command_geocode_handler(plugin(),
290                                                       callback,
291                                                       user_data,
292                                                       my_req_id);
293
294                 if (handler) {
295                         /* Run the plugin interface function */
296                         error = func(address,
297                                                  preference, command_geocode_handler::foreach_geocode_cb,
298                                                  handler, &handler->plg_req_id);
299
300                         pr.update(my_req_id, handler);
301                 }
302                 else {
303                         error = MAPS_ERROR_OUT_OF_MEMORY;
304                 }
305         }
306         else {
307                 /* Plugin Function is NULL: use default empty function */
308                 /*
309                 func = plugin::get_empty_interface().
310                         maps_plugin_geocode_by_structured_address;
311                 */
312                 MAPS_LOGE("MAPS_ERROR_NOT_SUPPORTED: Can't get any plugin");
313                 error = MAPS_ERROR_NOT_SUPPORTED;
314         }
315
316         const int ret = error;
317         destroy();
318         return ret;
319 }
320
321 /*----------------------------------------------------------------------------*/
322 /*typedef int (*maps_plugin_reverse_geocode_f)(maps_service_h maps,
323 * double latitude, double longitude, maps_service_reverse_geocode_cb callback,
324 * void *user_data, int *request_id); */
325 session::command_reverse_geocode::command_reverse_geocode(maps_service_h ms,
326                                         double lat, double lon,
327                                         const maps_item_hashtable_h pref,
328                                         maps_service_reverse_geocode_cb cb,
329                                         void *ud, int *request_id)
330  : command(ms)
331  , latitude(lat)
332  , longitude(lon)
333  , preference(NULL)
334  , callback(cb)
335  , user_data(ud)
336  , error(0)
337 {
338         *request_id = command::command_request_id++;
339         my_req_id = *request_id;
340
341         if (pref &&
342             (maps_item_hashtable_clone(pref, &preference) != MAPS_ERROR_NONE))
343                 error = MAPS_ERROR_INVALID_PARAMETER;
344 }
345
346 session::command_reverse_geocode::~command_reverse_geocode()
347 {
348         maps_item_hashtable_destroy(preference);
349 }
350
351 int session::command_reverse_geocode::run()
352 {
353
354         if (error != MAPS_ERROR_NONE)
355                 return error;
356
357         pending_request pr(plugin());
358
359         /* Get the plugin interface function */
360         maps_plugin_reverse_geocode_f func =
361                 interface()->maps_plugin_reverse_geocode;
362         command_reverse_geocode_handler *handler = NULL;
363         if (func) {
364                 /* No need to create the handler when the function is NULL */
365                 pr.add(my_req_id);
366                 handler = new command_reverse_geocode_handler(plugin(),
367                                                               callback,
368                                                               user_data,
369                                                               my_req_id);
370
371                 if (handler) {
372                         /* Run the plugin interface function */
373                         error = func(latitude, longitude, preference,
374                                                 command_reverse_geocode_handler::foreach_reverse_geocode_cb,
375                                         handler, &handler->plg_req_id);
376
377                         pr.update(my_req_id, handler);
378
379                         MAPS_LOGD("session::command_reverse_geocode::run: %d", my_req_id);
380                 }
381                 else {
382                         error = MAPS_ERROR_OUT_OF_MEMORY;
383                 }
384         }
385         else {
386                 /* Plugin Function is NULL: use default empty function */
387                 /*
388                 func = plugin::get_empty_interface().
389                         maps_plugin_reverse_geocode;
390                 */
391                 MAPS_LOGE("MAPS_ERROR_NOT_SUPPORTED: Can't get any plugin");
392                 error = MAPS_ERROR_NOT_SUPPORTED;
393         }
394
395         const int ret = error;
396         destroy();
397         return ret;
398 }
399
400 session::command_reverse_geocode_handler::command_reverse_geocode_handler(
401                                         plugin::plugin_s *p,
402                                         maps_service_reverse_geocode_cb cb,
403                                         void *ud, int urid)
404  : command_handler(p, ud, urid)
405  , callback(cb)
406 {
407 }
408
409 void session::command_reverse_geocode_handler::foreach_reverse_geocode_cb(
410                                                 maps_error_e error,
411                                                 int request_id, int index,
412                                                 int total,
413                                                 maps_address_h address,
414                                                 void *user_data)
415 {
416
417         command_reverse_geocode_handler *handler =
418                 (command_reverse_geocode_handler *) user_data;
419
420         if (request_id != handler->plg_req_id) {
421                 MAPS_LOGE(
422 "\n\nERROR! Incorrect request id [%d] come from the plugin; expected [%d]\n\n",
423                         request_id, handler->plg_req_id);
424         }
425
426         /* Make a user's copy of result data */
427         maps_address_h cloned_result = NULL;
428         if (error == MAPS_ERROR_NONE)
429                 error = (maps_error_e) maps_address_clone(address,
430                         &cloned_result);
431         maps_address_destroy(address);
432
433         /* Send data to user */
434         handler->callback(error, handler->user_req_id, index, total,
435                 cloned_result, handler->user_data);
436         /*if(index>=(total-1)) */
437
438         pending_request pr(handler->plugin());
439         pr.remove(handler->user_req_id);
440 }
441
442 /*----------------------------------------------------------------------------*/
443 /*typedef int (*maps_plugin_search_place_f)(maps_service_h maps,
444 * maps_coordinates_h position, int distance, maps_item_hashtable_h preference,
445 * maps_place_filter_h filter, maps_service_search_place_cb callback,
446 * void* user_data, int* request_id); */
447 session::command_search_place::command_search_place(maps_service_h ms,
448                                         const maps_coordinates_h pos,
449                                         int dst,
450                                         const maps_item_hashtable_h pref,
451                                         const maps_place_filter_h flt,
452                                         maps_service_search_place_cb cb,
453                                         void *ud, int *request_id)
454  : command(ms)
455  , position(NULL)
456  , distance(dst)
457  , preference(NULL)
458  , filter(NULL)
459  , callback(cb)
460  , user_data(ud)
461  , error(MAPS_ERROR_NONE)
462 {
463         *request_id = command::command_request_id++;
464         my_req_id = *request_id;
465
466         if (maps_coordinates_clone(pos, &position) != MAPS_ERROR_NONE)
467                 error = MAPS_ERROR_INVALID_PARAMETER;
468
469         if (pref &&
470             (maps_item_hashtable_clone(pref, &preference) != MAPS_ERROR_NONE))
471                 error = MAPS_ERROR_INVALID_PARAMETER;
472
473         if (maps_place_filter_clone(flt, &filter) != MAPS_ERROR_NONE)
474                 error = MAPS_ERROR_INVALID_PARAMETER;
475 }
476
477 session::command_search_place::~command_search_place()
478 {
479         maps_coordinates_destroy(position);
480         maps_item_hashtable_destroy(preference);
481         maps_place_filter_destroy(filter);
482 }
483
484 int session::command_search_place::run()
485 {
486
487         if (error != MAPS_ERROR_NONE)
488                 return error;
489
490         pending_request pr(plugin());
491
492         /* Get the plugin interface function */
493         maps_plugin_search_place_f func = interface()->maps_plugin_search_place;
494         command_search_place_handler *handler = NULL;
495         if (func) {
496                 /* No need to create the handler when the function is NULL */
497                 pr.add(my_req_id);
498                 handler = new command_search_place_handler(plugin(),
499                                                            callback,
500                                                            user_data,
501                                                            my_req_id);
502                 if (handler) {
503                         /* Run the plugin interface function */
504                         error = func(position, distance, filter, preference,
505                                          command_search_place_handler::foreach_place_cb, handler,
506                                          &handler->plg_req_id);
507
508                         pr.update(my_req_id, handler);
509
510                         MAPS_LOGD("session::command_search_place::run: %d", my_req_id);
511                 }
512                 else {
513                         error = MAPS_ERROR_OUT_OF_MEMORY;
514                 }
515         }
516         else {
517                 /* Plugin Function is NULL: use default empty function */
518                 /*
519                 func = plugin::get_empty_interface().maps_plugin_search_place;
520                 */
521                 MAPS_LOGE("MAPS_ERROR_NOT_SUPPORTED: Can't get any plugin");
522                 error = MAPS_ERROR_NOT_SUPPORTED;
523         }
524
525         const int ret = error;
526         destroy();
527         return ret;
528 }
529
530 session::command_search_place_handler::command_search_place_handler(
531                                                 plugin::plugin_s* p,
532                                                 maps_service_search_place_cb cb,
533                                                 void *ud, int urid)
534  : command_handler(p, ud, urid)
535  , callback(cb)
536 {
537 }
538
539 void session::command_search_place_handler::set_supported_data(maps_place_h
540                                                                place)
541 {
542         if (!place || !plugin())
543                 return;
544
545         maps_string_hashtable_h data_supported = NULL;
546         if (maps_string_hashtable_create(&data_supported) != MAPS_ERROR_NONE)
547                 return;
548
549         __put_to_hashtable(this, MAPS_PLACE_ADDRESS, _S(MAPS_PLACE_ADDRESS),
550                 data_supported);
551         __put_to_hashtable(this, MAPS_PLACE_RATING, _S(MAPS_PLACE_RATING),
552                 data_supported);
553         __put_to_hashtable(this, MAPS_PLACE_CATEGORIES,
554                 _S(MAPS_PLACE_CATEGORIES), data_supported);
555         __put_to_hashtable(this, MAPS_PLACE_ATTRIBUTES,
556                 _S(MAPS_PLACE_ATTRIBUTES), data_supported);
557         __put_to_hashtable(this, MAPS_PLACE_CONTACTS, _S(MAPS_PLACE_CONTACTS),
558                 data_supported);
559         __put_to_hashtable(this, MAPS_PLACE_EDITORIALS,
560                 _S(MAPS_PLACE_EDITORIALS), data_supported);
561         __put_to_hashtable(this, MAPS_PLACE_REVIEWS, _S(MAPS_PLACE_REVIEWS),
562                 data_supported);
563         __put_to_hashtable(this, MAPS_PLACE_IMAGE, _S(MAPS_PLACE_IMAGE),
564                 data_supported);
565         __put_to_hashtable(this, MAPS_PLACE_SUPPLIER, _S(MAPS_PLACE_SUPPLIER),
566                 data_supported);
567         __put_to_hashtable(this, MAPS_PLACE_RELATED, _S(MAPS_PLACE_RELATED),
568                 data_supported);
569
570         _maps_place_set_supported_data(place, data_supported);
571         maps_string_hashtable_destroy(data_supported);
572 }
573
574 bool session::command_search_place_handler::foreach_place_cb(maps_error_e error,
575                                                              int request_id,
576                                                              int index,
577                                                              int length,
578                                                              maps_place_h place,
579                                                              void *user_data)
580 {
581
582         command_search_place_handler *handler =
583                 (command_search_place_handler *) user_data;
584
585         if (request_id != handler->plg_req_id) {
586                 MAPS_LOGE(
587 "\n\nERROR! Incorrect request id [%d] come from the plugin; expected [%d]\n\n",
588                         request_id, handler->plg_req_id);
589         }
590
591         /* Make a user's copy of result data */
592         maps_place_h cloned_result = NULL;
593         if (error == MAPS_ERROR_NONE)
594                 error = (maps_error_e) maps_place_clone(place, &cloned_result);
595         maps_place_destroy(place);
596
597         /* Check which data features are supported */
598         if (cloned_result)
599                 handler->set_supported_data(cloned_result);
600
601         /* Send data to user */
602         const bool b =
603                 handler->callback(error, handler->user_req_id, index, length,
604                 cloned_result, handler->user_data);
605         if (!b || (index >= (length - 1))) {
606                 pending_request pr(handler->plugin());
607                 pr.remove(handler->user_req_id);
608         }
609
610         return b;
611 }
612
613 /*----------------------------------------------------------------------------*/
614 /*typedef int (*maps_plugin_search_place_by_area_f)(maps_service_h maps,
615 * maps_area_h boundary , maps_item_hashtable_h preference,
616 * maps_place_filter_h filter, maps_service_search_place_cb callback,
617 * void *user_data, int *request_id); */
618 session::command_search_by_area_place::command_search_by_area_place(
619                                         maps_service_h ms, const maps_area_h b,
620                                         const maps_item_hashtable_h pref,
621                                         const maps_place_filter_h flt,
622                                         maps_service_search_place_cb cb,
623                                         void *ud, int *request_id)
624  : command(ms)
625  , boundary(NULL)
626  , preference(NULL)
627  , filter(NULL)
628  , callback(cb)
629  , user_data(ud)
630  , error(MAPS_ERROR_NONE)
631 {
632         *request_id = command::command_request_id++;
633         my_req_id = *request_id;
634
635         if (maps_area_clone(b, &boundary) != MAPS_ERROR_NONE)
636                 error = MAPS_ERROR_INVALID_PARAMETER;
637
638         if (pref &&
639             (maps_item_hashtable_clone(pref, &preference) != MAPS_ERROR_NONE))
640                 error = MAPS_ERROR_INVALID_PARAMETER;
641
642         if (maps_place_filter_clone(flt, &filter) != MAPS_ERROR_NONE)
643                 error = MAPS_ERROR_INVALID_PARAMETER;
644 }
645
646 session::command_search_by_area_place::~command_search_by_area_place()
647 {
648         maps_area_destroy(boundary);
649         maps_item_hashtable_destroy(preference);
650         maps_place_filter_destroy(filter);
651 }
652
653 int session::command_search_by_area_place::run()
654 {
655
656         if (error != MAPS_ERROR_NONE)
657                 return error;
658
659         pending_request pr(plugin());
660
661         /* Get the plugin interface function */
662         maps_plugin_search_place_by_area_f func =
663                 interface()->maps_plugin_search_place_by_area;
664         command_search_place_handler *handler = NULL;
665         if (func) {
666                 /* No need to create the handler when the function is NULL */
667                 pr.add(my_req_id);
668                 handler = new command_search_place_handler(plugin(),
669                                                            callback,
670                                                            user_data,
671                                                            my_req_id);
672                 if (handler) {
673
674                         /* Run the plugin interface function */
675                         error = func(boundary, filter,
676                                 preference, command_search_place_handler::foreach_place_cb,
677                                 handler, &handler->plg_req_id);
678
679                         pr.update(my_req_id, handler);
680
681                         MAPS_LOGD("session::command_search_by_area_place::run: %d", my_req_id);
682                 }
683                 else {
684                         error = MAPS_ERROR_OUT_OF_MEMORY;
685                 }
686         }
687         else {
688                 /* Plugin Function is NULL: use default empty function */
689                 /*
690                 func = plugin::get_empty_interface().
691                         maps_plugin_search_place_by_area;
692                 */
693
694                 MAPS_LOGE("MAPS_ERROR_NOT_SUPPORTED: Can't get any plugin");
695                 error = MAPS_ERROR_NOT_SUPPORTED;
696         }
697
698         const int ret = error;
699         destroy();
700         return ret;
701 }
702
703 /*----------------------------------------------------------------------------*/
704 /*typedef int (*maps_plugin_search_place_by_address_f)(maps_service_h maps,
705 * const char *address, maps_area_h boundary, maps_item_hashtable_h preference,
706 * maps_place_filter_h filter, maps_service_search_place_cb callback,
707 * void *user_data, int *request_id); */
708 session::command_search_by_address_place::command_search_by_address_place(
709                                         maps_service_h ms, const char *a,
710                                         const maps_area_h b,
711                                         const maps_item_hashtable_h pref,
712                                         const maps_place_filter_h flt,
713                                         maps_service_search_place_cb cb,
714                                         void *ud, int *request_id)
715  : command(ms)
716  , address(a)
717  , boundary(NULL)
718  , preference(NULL)
719  , filter(NULL)
720  , callback(cb)
721  , user_data(ud)
722  , error(MAPS_ERROR_NONE)
723 {
724         *request_id = command::command_request_id++;
725         my_req_id = *request_id;
726
727         if (maps_area_clone(b, &boundary) != MAPS_ERROR_NONE)
728                 error = MAPS_ERROR_INVALID_PARAMETER;
729
730         if (pref &&
731             (maps_item_hashtable_clone(pref, &preference) != MAPS_ERROR_NONE))
732                 error = MAPS_ERROR_INVALID_PARAMETER;
733
734         if (maps_place_filter_clone(flt, &filter) != MAPS_ERROR_NONE)
735                 error = MAPS_ERROR_INVALID_PARAMETER;
736 }
737
738 session::command_search_by_address_place::~command_search_by_address_place()
739 {
740         maps_area_destroy(boundary);
741         maps_item_hashtable_destroy(preference);
742         maps_place_filter_destroy(filter);
743 }
744
745 int session::command_search_by_address_place::run()
746 {
747         if (error != MAPS_ERROR_NONE)
748                 return error;
749
750         pending_request pr(plugin());
751
752         /* Get the plugin interface function */
753         maps_plugin_search_place_by_address_f func =
754                 interface()->maps_plugin_search_place_by_address;
755         command_search_place_handler *handler = NULL;
756         if (func) {
757                 /* No need to create the handler when the function is NULL */
758                 pr.add(my_req_id);
759                 handler = new command_search_place_handler(plugin(),
760                                                            callback,
761                                                            user_data,
762                                                            my_req_id);
763                 if (handler) {
764                         /* Run the plugin interface function */
765                         error = func(address.c_str(), boundary, filter, preference,
766                                          command_search_place_handler::foreach_place_cb, handler,
767                                          &handler->plg_req_id);
768
769                         pr.update(my_req_id, handler);
770
771                         MAPS_LOGD("session::command_search_by_address_place::run: %d",
772                                 my_req_id);
773
774                 }
775                 else {
776                         error = MAPS_ERROR_OUT_OF_MEMORY;
777                 }
778         }
779         else {
780                 /* Plugin Function is NULL: use default empty function */
781                 /*
782                 func = plugin::get_empty_interface().
783                         maps_plugin_search_place_by_address;
784                 */
785                 MAPS_LOGE("MAPS_ERROR_NOT_SUPPORTED: Can't get any plugin");
786                 error = MAPS_ERROR_NOT_SUPPORTED;
787         }
788
789         const int ret = error;
790         destroy();
791         return ret;
792 }
793
794 /*----------------------------------------------------------------------------*/
795 /*typedef int (*maps_plugin_search_route_f)(maps_service_h maps,
796 * maps_item_hashtable_h preference, maps_coordinates_h origin,
797 * maps_coordinates_h destination, maps_service_search_route_cb callback,
798 * void *user_data, int *request_id); */
799 session::command_search_route::command_search_route(maps_service_h ms,
800                                         const maps_item_hashtable_h pref,
801                                         const maps_coordinates_h orig,
802                                         const maps_coordinates_h dest,
803                                         maps_service_search_route_cb cb,
804                                         void *ud, int *request_id)
805  : command(ms)
806  , preference(NULL)
807  , origin(NULL)
808  , destination(NULL)
809  , callback(cb)
810  , user_data(ud)
811  , error(MAPS_ERROR_NONE)
812 {
813         *request_id = command::command_request_id++;
814         my_req_id = *request_id;
815
816         if (pref &&
817             (maps_item_hashtable_clone(pref, &preference) != MAPS_ERROR_NONE))
818                 error = MAPS_ERROR_INVALID_PARAMETER;
819
820         if (maps_coordinates_clone(orig, &origin) != MAPS_ERROR_NONE)
821                 error = MAPS_ERROR_INVALID_PARAMETER;
822
823         if (maps_coordinates_clone(dest, &destination) != MAPS_ERROR_NONE)
824                 error = MAPS_ERROR_INVALID_PARAMETER;
825
826 }
827
828 session::command_search_route::~command_search_route()
829 {
830         maps_item_hashtable_destroy(preference);
831         maps_coordinates_destroy(origin);
832         maps_coordinates_destroy(destination);
833 }
834
835 int session::command_search_route::run()
836 {
837
838         if (error != MAPS_ERROR_NONE)
839                 return error;
840
841         pending_request pr(plugin());
842
843         /* Get the plugin interface function */
844         maps_plugin_search_route_f func = interface()->maps_plugin_search_route;
845         command_search_route_handler *handler = NULL;
846         if (func) {
847                 /* No need to create the handler when the function is NULL */
848                 pr.add(my_req_id);
849                 handler = new command_search_route_handler(plugin(),
850                                                            callback,
851                                                            user_data,
852                                                            my_req_id);
853
854                 if (handler) {
855                         /* Run the plugin interface function */
856                         error = func(origin, destination, preference,
857                      command_search_route_handler::foreach_route_cb,
858                      handler, &handler->plg_req_id);
859
860                         pr.update(my_req_id, handler);
861
862                         MAPS_LOGD("session::command_search_route::run: %d", my_req_id);
863                 }
864                 else {
865                         error = MAPS_ERROR_OUT_OF_MEMORY;
866                 }
867         }
868         else {
869                 /* Plugin Function is NULL: use default empty function */
870                 /*
871                 func = plugin::get_empty_interface().maps_plugin_search_route;
872                 */
873                 MAPS_LOGE("MAPS_ERROR_NOT_SUPPORTED: Can't get any plugin");
874                 error = MAPS_ERROR_NOT_SUPPORTED;
875         }
876
877         const int ret = error;
878         destroy();
879         return ret;
880 }
881
882 /*----------------------------------------------------------------------------*/
883 /*typedef int (*maps_plugin_search_route_waypoints_f)(maps_service_h maps,
884 * maps_item_hashtable_h preference, maps_coordinates_h *waypoint_list,
885 * int waypoint_num, maps_service_search_route_cb callback, void *user_data,
886 * int *request_id); */
887 session::command_search_route_waypoints::command_search_route_waypoints(
888                                 maps_service_h ms,
889                                 const maps_item_hashtable_h pref,
890                                 const maps_coordinates_h *list,
891                                 int num, maps_service_search_route_cb cb,
892                                 void *ud, int *request_id)
893  : command(ms)
894  , preference(NULL)
895  , waypoint_list(NULL)
896  , waypoint_num(num)
897  , callback(cb)
898  , user_data(ud)
899  , error(MAPS_ERROR_NONE)
900 {
901         *request_id = command::command_request_id++;
902         my_req_id = *request_id;
903
904         if (pref &&
905             (maps_item_hashtable_clone(pref, &preference) != MAPS_ERROR_NONE))
906                 error = MAPS_ERROR_INVALID_PARAMETER;
907
908         waypoint_list = new maps_coordinates_h[num];
909         for (int index = 0; index < num; index++) {
910                 if (list[index] != NULL) {
911                         maps_coordinates_clone(list[index],
912                                 &waypoint_list[index]);
913                 }
914         }
915 }
916
917 session::command_search_route_waypoints::~command_search_route_waypoints()
918 {
919         maps_item_hashtable_destroy(preference);
920
921         for (int index = 0; index < waypoint_num; index++) {
922                 if (waypoint_list[index] != NULL) {
923                         maps_coordinates_destroy(waypoint_list[index]);
924                 }
925         }
926         delete [] waypoint_list;
927 }
928
929 int session::command_search_route_waypoints::run()
930 {
931
932         if (error != MAPS_ERROR_NONE)
933                 return error;
934
935         pending_request pr(plugin());
936
937         /* Get the plugin interface function */
938         maps_plugin_search_route_waypoints_f func =
939                 interface()->maps_plugin_search_route_waypoints;
940
941         command_search_route_handler *handler = NULL;
942         if (func) {
943                 /* No need to create the handler when the function is NULL */
944                 pr.add(my_req_id);
945                 handler = new command_search_route_handler(plugin(),
946                                                  callback,
947                                                  user_data,
948                                                  my_req_id);
949                 if (handler) {
950                         /* Run the plugin interface function */
951                         error = func(waypoint_list, waypoint_num, preference,
952                                          command_search_route_handler::foreach_route_cb, handler,
953                                          &handler->plg_req_id);
954
955                         pr.update(my_req_id, handler);
956
957                         MAPS_LOGD("session::command_search_place::run: %d", my_req_id);
958                 }
959                 else {
960                         error = MAPS_ERROR_OUT_OF_MEMORY;
961                 }
962         }
963         else {
964                 /* Plugin Function is NULL: use default empty function */
965                 /*
966                 func = plugin::get_empty_interface().
967                         maps_plugin_search_route_waypoints;
968                 */
969                 MAPS_LOGE("MAPS_ERROR_NOT_SUPPORTED: Can't get any plugin");
970                 error = MAPS_ERROR_NOT_SUPPORTED;
971         }
972
973         const int ret = error;
974         destroy();
975         return ret;
976 }
977
978 session::command_search_route_handler::command_search_route_handler(
979                                                 plugin::plugin_s *p,
980                                                 maps_service_search_route_cb cb,
981                                                 void *ud, int urid)
982  : command_handler(p, ud, urid)
983  , callback(cb)
984 {
985 }
986
987 void session::command_search_route_handler::set_supported_data(maps_route_h
988                                                                route)
989 {
990         if (!route || !plugin())
991                 return;
992
993         maps_string_hashtable_h data_supported = NULL;
994         if (maps_string_hashtable_create(&data_supported) != MAPS_ERROR_NONE)
995                 return;
996
997         __put_to_hashtable(this, MAPS_ROUTE_PATH, _S(MAPS_ROUTE_PATH),
998                 data_supported);
999         __put_to_hashtable(this, MAPS_ROUTE_SEGMENTS_PATH,
1000                 _S(MAPS_ROUTE_SEGMENTS_PATH), data_supported);
1001         __put_to_hashtable(this, MAPS_ROUTE_SEGMENTS_MANEUVERS,
1002                 _S(MAPS_ROUTE_SEGMENTS_MANEUVERS), data_supported);
1003
1004         _maps_route_set_supported_data(route, data_supported);
1005         maps_string_hashtable_destroy(data_supported);
1006 }
1007
1008 bool session::command_search_route_handler::foreach_route_cb(maps_error_e error,
1009                                                              int request_id,
1010                                                              int index,
1011                                                              int length,
1012                                                              maps_route_h route,
1013                                                              void *user_data)
1014 {
1015         command_search_route_handler *handler =
1016                 (command_search_route_handler *) user_data;
1017
1018         if (request_id != handler->plg_req_id) {
1019                 MAPS_LOGE(
1020 "\n\nERROR! Incorrect request id [%d] come from the plugin; expected [%d]\n\n",
1021                         request_id, handler->plg_req_id);
1022         }
1023
1024         /* Make a user's copy of result data */
1025         maps_route_h cloned_result = NULL;
1026         if (error == MAPS_ERROR_NONE)
1027                 error = (maps_error_e) maps_route_clone(route, &cloned_result);
1028         maps_route_destroy(route);
1029
1030         /* Check which data features are supported */
1031         if (cloned_result)
1032                 handler->set_supported_data(cloned_result);
1033
1034         /* Send data to user */
1035         const bool b =
1036                 handler->callback(error, handler->user_req_id, index, length,
1037                 cloned_result, handler->user_data);
1038         if (!b || (index >= (length - 1))) {
1039                 pending_request pr(handler->plugin());
1040                 pr.remove(handler->user_req_id);
1041         }
1042
1043         return b;
1044 }
1045
1046 /*----------------------------------------------------------------------------*/
1047 /*typedef int (*maps_plugin_cancel_request_f)(maps_service_h maps,
1048 * int request_id); */
1049 int session::command_cancel_request::run()
1050 {
1051         pending_request pr(plugin());
1052         MAPS_LOGD("session::command_cancel_request::run: %d, %d", request_id,
1053                 pr.look_up(request_id));
1054         const int error =
1055                 (pr.contains(request_id)) ? interface()->
1056                 maps_plugin_cancel_request(pr.
1057                 extract_plg_id(request_id)) : MAPS_ERROR_NOT_FOUND;
1058
1059         const int ret = error;
1060         destroy();
1061         return ret;
1062 }