fedeba3b950590e988f475fe68dca3e7cb5136b8
[platform/core/api/maps-service.git] / src / api / maps_route.cpp
1 /*
2  * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd All Rights Reserved
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 <glib.h>
18 #include "maps_util.h"
19 #include "maps_route_plugin.h"
20 #include "maps_error.h"
21 #include "maps_preference.h"
22 #include "maps_route_segment_plugin.h"
23 #include "maps_route_private.h"
24 #include "maps_route_segment_private.h"
25 #include "maps_condition.h"
26
27 static bool __is_supported(const maps_route_h route, maps_service_data_e data)
28 {
29         bool supported = false;
30         _maps_route_is_data_supported(route, data, &supported);
31         return supported;
32 }
33
34 static bool __maps_route_set_supported_data_foreach_cb(int index, int total,
35                                                        void *data,
36                                                        void *user_data)
37 {
38         _maps_route_segment_set_supported_data(data, user_data);
39         return true;
40 }
41
42 /*----------------------------------------------------------------------------*/
43
44 /*
45  * maps_route_s module
46  */
47 typedef struct _maps_route_s
48 {
49         char *route_id;                 /*< route_id */
50         maps_coordinates_h origin;      /*< Coordinate StartCoord */
51         maps_coordinates_h destination; /*< Coordinates destCoord */
52         maps_area_h bounding_box;       /*< A rectangular geographical area */
53         maps_route_transport_mode_e transport_mode;     /*< The transport mode
54                                                           for the route */
55         double total_distance;          /*< Total distance */
56         long total_duration;            /*< Total duration */
57         maps_distance_unit_e distance_unit;     /*< Distance units */
58         maps_item_list_h segments;      /*< List of segments,
59                                                   maps_route_segment_h */
60         maps_item_list_h path;          /*< Path, list of maps_coordinates_h */
61         maps_item_hashtable_h properties;       /*< Key/Value> */
62
63         /* The table of available data features */
64         maps_int_hashtable_h supported_data;
65         /* TODO: implement hashtable<int, int> */
66 } maps_route_s;
67
68 const gsize _MAPS_ROUTE_ID_MAX_LENGTH = MAPS_BASE_ID_MAX_LEN;
69
70 /*----------------------------------------------------------------------------*/
71
72 EXPORT_API int maps_route_create(maps_route_h *route)
73 {
74         if (!maps_condition_check_maps_feature())
75                 return MAPS_ERROR_NOT_SUPPORTED;
76         if (!route)
77                 return MAPS_ERROR_INVALID_PARAMETER;
78         *route = (maps_route_h) g_slice_new0(maps_route_s);
79
80         if (*route == NULL) {
81                 MAPS_LOGE("OUT_OF_MEMORY(0x%08x)", MAPS_ERROR_OUT_OF_MEMORY);
82                 return MAPS_ERROR_OUT_OF_MEMORY;
83         }
84
85         return MAPS_ERROR_NONE;
86 }
87
88 EXPORT_API int maps_route_destroy(maps_route_h route)
89 {
90         if (!maps_condition_check_maps_feature())
91                 return MAPS_ERROR_NOT_SUPPORTED;
92         if (!route)
93                 return MAPS_ERROR_INVALID_PARAMETER;
94
95         maps_route_s *p = (maps_route_s *) route;
96
97         if (p->route_id)
98                 g_free(p->route_id);
99         if (p->origin)
100                 maps_coordinates_destroy(p->origin);
101         if (p->destination)
102                 maps_coordinates_destroy(p->destination);
103         if (p->bounding_box)
104                 maps_area_destroy(p->bounding_box);
105         if (p->properties)
106                 maps_item_hashtable_destroy(p->properties);
107
108         if (p->segments) {
109                 maps_item_list_remove_all(p->segments,
110                         maps_route_segment_destroy);
111                 maps_item_list_destroy(p->segments);
112         }
113
114         if (p->path) {
115                 maps_item_list_remove_all(p->path, maps_coordinates_destroy);
116                 maps_item_list_destroy(p->path);
117         }
118
119         if (p->supported_data)
120                 maps_int_hashtable_destroy(p->supported_data);
121
122         g_slice_free(maps_route_s, route);
123         return MAPS_ERROR_NONE;
124 }
125
126 EXPORT_API int maps_route_clone(const maps_route_h origin,
127                                                                 maps_route_h *cloned)
128 {
129         if (!maps_condition_check_maps_feature())
130                 return MAPS_ERROR_NOT_SUPPORTED;
131         if (!cloned || !origin)
132                 return MAPS_ERROR_INVALID_PARAMETER;
133
134         int error = MAPS_ERROR_NONE;
135         do {
136                 error = maps_route_create(cloned);
137                 if (!(*cloned) || (error != MAPS_ERROR_NONE))
138                         break;
139
140                 maps_route_s *r = (maps_route_s *) origin;
141
142                 if (r->route_id) {
143                         error = maps_route_set_route_id(*cloned, r->route_id);
144                         if (error != MAPS_ERROR_NONE)
145                                 break;
146                 }
147
148                 if (r->origin) {
149                         error = maps_route_set_origin(*cloned, r->origin);
150                         if (error != MAPS_ERROR_NONE)
151                                 break;
152                 }
153
154                 if (r->destination) {
155                         error = maps_route_set_destination(*cloned, r->destination);
156                         if (error != MAPS_ERROR_NONE)
157                                 break;
158                 }
159
160                 if (r->bounding_box) {
161                         error = maps_route_set_bounding_box(*cloned, r->bounding_box);
162                         if (error != MAPS_ERROR_NONE)
163                                 break;
164                 }
165
166                 error = maps_route_set_transport_mode(*cloned, r->transport_mode);
167                 if (error != MAPS_ERROR_NONE)
168                         break;
169
170                 error = maps_route_set_total_distance(*cloned, r->total_distance);
171                 if (error != MAPS_ERROR_NONE)
172                         break;
173
174                 error = maps_route_set_total_duration(*cloned, r->total_duration);
175                 if (error != MAPS_ERROR_NONE)
176                         break;
177
178                 error = maps_route_set_distance_unit(*cloned, r->distance_unit);
179                 if (error != MAPS_ERROR_NONE)
180                         break;
181
182                 if (r->segments) {
183                         error = maps_route_set_segments(*cloned, r->segments);
184                         if (error != MAPS_ERROR_NONE)
185                                 break;
186                 }
187
188                 if (r->path) {
189                         error = maps_route_set_path(*cloned, r->path);
190                         if (error != MAPS_ERROR_NONE)
191                                 break;
192                 }
193
194                 if (r->properties) {
195                         error = maps_route_set_properties(*cloned, r->properties);
196                         if (error != MAPS_ERROR_NONE)
197                                 break;
198                 }
199
200                 if (r->supported_data) {
201                         error = _maps_route_set_supported_data(*cloned, r->supported_data);
202                         if (error != MAPS_ERROR_NONE)
203                                 break;
204                 }
205
206                 return MAPS_ERROR_NONE;
207         } while (false);
208
209         maps_route_destroy(*cloned);
210         *cloned = NULL;
211         return error;
212 }
213
214 /*----------------------------------------------------------------------------*/
215
216 EXPORT_API int maps_route_get_route_id(const maps_route_h route,
217                                                                 char **route_id)
218 {
219         if (!maps_condition_check_maps_feature())
220                 return MAPS_ERROR_NOT_SUPPORTED;
221         if (!route || !route_id)
222                 return MAPS_ERROR_INVALID_PARAMETER;
223         return maps_get_string(((maps_route_s *) route)->route_id,
224                 _MAPS_ROUTE_ID_MAX_LENGTH, route_id);
225 }
226
227 EXPORT_API int maps_route_get_origin(const maps_route_h route,
228                                                                 maps_coordinates_h *origin)
229 {
230         if (!maps_condition_check_maps_feature())
231                 return MAPS_ERROR_NOT_SUPPORTED;
232         if (!route || !origin)
233                 return MAPS_ERROR_INVALID_PARAMETER;
234         maps_coordinates_clone(((maps_route_s *) route)->origin, origin);
235         return MAPS_ERROR_NONE;
236 }
237
238 EXPORT_API int maps_route_get_destination(const maps_route_h route,
239                                                                 maps_coordinates_h *destination)
240 {
241         if (!maps_condition_check_maps_feature())
242                 return MAPS_ERROR_NOT_SUPPORTED;
243         if (!route || !destination)
244                 return MAPS_ERROR_INVALID_PARAMETER;
245         return maps_coordinates_clone(((maps_route_s *) route)->destination,
246                 destination);
247 }
248
249 EXPORT_API int maps_route_get_bounding_box(const maps_route_h route,
250                                                                 maps_area_h *bounding_box)
251 {
252         if (!maps_condition_check_maps_feature())
253                 return MAPS_ERROR_NOT_SUPPORTED;
254         if (!route || !bounding_box)
255                 return MAPS_ERROR_INVALID_PARAMETER;
256         return maps_area_clone(((maps_route_s *) route)->bounding_box,
257                 bounding_box);
258 }
259
260 EXPORT_API int maps_route_get_transport_mode(const maps_route_h route,
261                                                                 maps_route_transport_mode_e *transport_mode)
262 {
263         if (!maps_condition_check_maps_feature())
264                 return MAPS_ERROR_NOT_SUPPORTED;
265         if (!route || !transport_mode)
266                 return MAPS_ERROR_INVALID_PARAMETER;
267         *transport_mode = ((maps_route_s *) route)->transport_mode;
268         return MAPS_ERROR_NONE;
269 }
270
271 EXPORT_API int maps_route_get_total_distance(const maps_route_h route,
272                                                                 double *total_distance)
273 {
274         if (!maps_condition_check_maps_feature())
275                 return MAPS_ERROR_NOT_SUPPORTED;
276         if (!route || !total_distance)
277                 return MAPS_ERROR_INVALID_PARAMETER;
278         *total_distance = ((maps_route_s *) route)->total_distance;
279         return MAPS_ERROR_NONE;
280 }
281
282 EXPORT_API int maps_route_get_total_duration(const maps_route_h route,
283                                                                 long *total_duration)
284 {
285         if (!maps_condition_check_maps_feature())
286                 return MAPS_ERROR_NOT_SUPPORTED;
287         if (!route || !total_duration)
288                 return MAPS_ERROR_INVALID_PARAMETER;
289         *total_duration = ((maps_route_s *) route)->total_duration;
290         return MAPS_ERROR_NONE;
291 }
292
293 EXPORT_API int maps_route_foreach_path(const maps_route_h route,
294                                                                 maps_route_path_cb callback,
295                                                                 void *user_data)
296 {
297         if (!maps_condition_check_maps_feature())
298                 return MAPS_ERROR_NOT_SUPPORTED;
299         if (!route)
300                 return MAPS_ERROR_INVALID_PARAMETER;
301         if (!__is_supported(route, MAPS_ROUTE_PATH))
302                 return MAPS_ERROR_NOT_SUPPORTED;
303         if (!callback)
304                 return MAPS_ERROR_INVALID_PARAMETER;
305         if (!((maps_route_s *) route)->path)
306                 return MAPS_ERROR_NOT_FOUND;
307
308         return maps_item_list_foreach(((maps_route_s *) route)->path,
309                 maps_coordinates_clone, callback, user_data);
310 }
311
312 EXPORT_API int maps_route_foreach_segment(const maps_route_h route,
313                                                                 maps_route_segment_cb callback,
314                                                                 void *user_data)
315 {
316         if (!maps_condition_check_maps_feature())
317                 return MAPS_ERROR_NOT_SUPPORTED;
318         if (!route)
319                 return MAPS_ERROR_INVALID_PARAMETER;
320         if (!__is_supported(route, MAPS_ROUTE_SEGMENTS_PATH)
321                 && !__is_supported(route, MAPS_ROUTE_SEGMENTS_MANEUVERS))
322                 return MAPS_ERROR_NOT_SUPPORTED;
323         if (!callback)
324                 return MAPS_ERROR_INVALID_PARAMETER;
325         if (!((maps_route_s *) route)->segments)
326                 return MAPS_ERROR_NOT_FOUND;
327
328         return maps_item_list_foreach(((maps_route_s *) route)->segments,
329                 maps_route_segment_clone, callback, user_data);
330 }
331
332 EXPORT_API int maps_route_foreach_property(const maps_route_h route,
333                                                                 maps_route_properties_cb callback,
334                                                                 void *user_data)
335 {
336         if (!maps_condition_check_maps_feature())
337                 return MAPS_ERROR_NOT_SUPPORTED;
338         if (!route || !callback)
339                 return MAPS_ERROR_INVALID_PARAMETER;
340         if (!((maps_route_s *) route)->properties)
341                 return MAPS_ERROR_NOT_FOUND;
342         return maps_item_hashtable_foreach(((maps_route_s *) route)->properties,
343                 callback, user_data);
344 }
345
346 EXPORT_API int maps_route_get_distance_unit(const maps_route_h route,
347                                                                 maps_distance_unit_e *distance_unit)
348 {
349         if (!maps_condition_check_maps_feature())
350                 return MAPS_ERROR_NOT_SUPPORTED;
351         if (!route || !distance_unit)
352                 return MAPS_ERROR_INVALID_PARAMETER;
353         *distance_unit = ((maps_route_s *) route)->distance_unit;
354         return MAPS_ERROR_NONE;
355 }
356
357 int _maps_route_is_data_supported(const maps_route_h route,
358                                                                 maps_service_data_e data, bool *supported)
359 {
360         if (!maps_condition_check_maps_feature())
361                 return MAPS_ERROR_NOT_SUPPORTED;
362         if (!route || !supported)
363                 return MAPS_ERROR_INVALID_PARAMETER;
364
365         maps_route_s *r = (maps_route_s *)route;
366
367         if (!r->supported_data) {
368                 /* This is a case when the "supported" flags are not set yet */
369                 /* No need to limit access to fields */
370                 *supported = true;
371                 return MAPS_ERROR_NONE;
372         }
373
374         *supported = false;
375         return maps_int_hashtable_contains(r->supported_data, data, supported);
376 }
377
378 /*----------------------------------------------------------------------------*/
379
380 EXPORT_API int maps_route_set_route_id(const maps_route_h route,
381                                                                 const char *route_id)
382 {
383         if (!maps_condition_check_maps_feature())
384                 return MAPS_ERROR_NOT_SUPPORTED;
385         if (!route || !route_id)
386                 return MAPS_ERROR_INVALID_PARAMETER;
387         return maps_set_string(route_id, _MAPS_ROUTE_ID_MAX_LENGTH,
388                 &((maps_route_s *) route)->route_id);
389 }
390
391 EXPORT_API int maps_route_set_origin(maps_route_h route,
392                                                                 const maps_coordinates_h origin)
393 {
394         if (!maps_condition_check_maps_feature())
395                 return MAPS_ERROR_NOT_SUPPORTED;
396         if (!route || !origin)
397                 return MAPS_ERROR_INVALID_PARAMETER;
398         maps_route_s *p = (maps_route_s *) route;
399         if (p->origin)
400                 maps_coordinates_destroy(p->origin);
401         return maps_coordinates_clone(origin, &p->origin);
402 }
403
404 EXPORT_API int maps_route_set_destination(maps_route_h route,
405                                                                 const maps_coordinates_h destination)
406 {
407         if (!maps_condition_check_maps_feature())
408                 return MAPS_ERROR_NOT_SUPPORTED;
409         if (!route || !destination)
410                 return MAPS_ERROR_INVALID_PARAMETER;
411         maps_route_s *p = (maps_route_s *) route;
412         if (p->destination)
413                 maps_coordinates_destroy(p->destination);
414         return maps_coordinates_clone(destination, &p->destination);
415 }
416
417 EXPORT_API int maps_route_set_bounding_box(maps_route_h route,
418                                                                 const maps_area_h bounding_box)
419 {
420         if (!maps_condition_check_maps_feature())
421                 return MAPS_ERROR_NOT_SUPPORTED;
422         if (!route || !bounding_box)
423                 return MAPS_ERROR_INVALID_PARAMETER;
424         maps_route_s *p = (maps_route_s *) route;
425         if (p->bounding_box)
426                 maps_area_destroy(p->bounding_box);
427         return maps_area_clone(bounding_box, &p->bounding_box);
428 }
429
430 EXPORT_API int maps_route_set_total_distance(maps_route_h route,
431                                                                 const double total_distance)
432 {
433         if (!maps_condition_check_maps_feature())
434                 return MAPS_ERROR_NOT_SUPPORTED;
435         if (!route || total_distance < 0)
436                 return MAPS_ERROR_INVALID_PARAMETER;
437         ((maps_route_s *) route)->total_distance = total_distance;
438         return MAPS_ERROR_NONE;
439 }
440
441 EXPORT_API int maps_route_set_total_duration(maps_route_h route,
442                                                                 const long total_duration)
443 {
444         if (!maps_condition_check_maps_feature())
445                 return MAPS_ERROR_NOT_SUPPORTED;
446         if (!route || total_duration < 0)
447                 return MAPS_ERROR_INVALID_PARAMETER;
448         ((maps_route_s *) route)->total_duration = total_duration;
449         return MAPS_ERROR_NONE;
450 }
451
452 EXPORT_API int maps_route_set_transport_mode(maps_route_h route,
453                                                                 const maps_route_transport_mode_e transport_mode)
454 {
455         if (!maps_condition_check_maps_feature())
456                 return MAPS_ERROR_NOT_SUPPORTED;
457         if (!route)
458                 return MAPS_ERROR_INVALID_PARAMETER;
459         if ((transport_mode < MAPS_ROUTE_TRANSPORT_MODE_CAR) ||
460                 (transport_mode > MAPS_ROUTE_TRANSPORT_MODE_TRUCK))
461                 return MAPS_ERROR_INVALID_PARAMETER;
462         ((maps_route_s *) route)->transport_mode = transport_mode;
463         return MAPS_ERROR_NONE;
464 }
465
466 EXPORT_API int maps_route_set_path(maps_route_h route,
467                                                                 const maps_item_list_h path)
468 {
469         if (!maps_condition_check_maps_feature())
470                 return MAPS_ERROR_NOT_SUPPORTED;
471         if (!route || !path)
472                 return MAPS_ERROR_INVALID_PARAMETER;
473         maps_route_s *p = (maps_route_s *) route;
474         if (p->path) {
475                 maps_item_list_remove_all(p->path, maps_coordinates_destroy);
476                 maps_item_list_destroy(p->path);
477         }
478         maps_item_list_clone(path, maps_coordinates_clone, &p->path);
479         return MAPS_ERROR_NONE;
480 }
481
482 EXPORT_API int maps_route_set_segments(maps_route_h route,
483                                                                 const maps_item_list_h segments)
484 {
485         if (!maps_condition_check_maps_feature())
486                 return MAPS_ERROR_NOT_SUPPORTED;
487         if (!route || !segments)
488                 return MAPS_ERROR_INVALID_PARAMETER;
489         maps_route_s *p = (maps_route_s *) route;
490         if (p->segments) {
491                 maps_item_list_remove_all(p->segments,
492                         maps_route_segment_destroy);
493                 maps_item_list_destroy(p->segments);
494         }
495         maps_item_list_clone(segments, maps_route_segment_clone, &p->segments);
496         return MAPS_ERROR_NONE;
497 }
498
499 EXPORT_API int maps_route_set_properties(maps_route_h route,
500                                                                 const maps_item_hashtable_h properties)
501 {
502         if (!maps_condition_check_maps_feature())
503                 return MAPS_ERROR_NOT_SUPPORTED;
504         if (!route || !properties)
505                 return MAPS_ERROR_INVALID_PARAMETER;
506         maps_route_s *p = (maps_route_s *) route;
507         if (p->properties)
508                 maps_item_hashtable_destroy(p->properties);
509         return maps_item_hashtable_clone(properties, &p->properties);
510 }
511
512 EXPORT_API int maps_route_set_distance_unit(maps_route_h route,
513                                                                 const maps_distance_unit_e distance_unit)
514 {
515         if (!maps_condition_check_maps_feature())
516                 return MAPS_ERROR_NOT_SUPPORTED;
517         if (!route)
518                 return MAPS_ERROR_INVALID_PARAMETER;
519         if ((distance_unit < MAPS_DISTANCE_UNIT_M) ||
520                 (distance_unit > MAPS_DISTANCE_UNIT_YD))
521                 return MAPS_ERROR_INVALID_PARAMETER;
522         ((maps_route_s *) route)->distance_unit = distance_unit;
523         return MAPS_ERROR_NONE;
524 }
525
526 int _maps_route_set_supported_data(maps_route_h route,
527                                                                 const maps_int_hashtable_h supported_data)
528 {
529         if (!route || !supported_data)
530                 return MAPS_ERROR_INVALID_PARAMETER;
531         maps_route_s *p = (maps_route_s *) route;
532         if (p->supported_data)
533                 maps_int_hashtable_destroy(p->supported_data);
534         int error =
535                 maps_int_hashtable_clone(supported_data, &p->supported_data);
536         if (error != MAPS_ERROR_NONE)
537                 return error;
538
539         if (p->segments)
540                 error = maps_item_list_foreach(p->segments, NULL,
541                         __maps_route_set_supported_data_foreach_cb, supported_data);
542         return error;
543 }