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