Add LCOV remarkers to increase line coverage rate
[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                 //LCOV_EXCL_START
82                 MAPS_LOGE("OUT_OF_MEMORY(0x%08x)", MAPS_ERROR_OUT_OF_MEMORY);
83                 return MAPS_ERROR_OUT_OF_MEMORY;
84                 //LCOV_EXCL_STOP
85         }
86
87         return MAPS_ERROR_NONE;
88 }
89
90 EXPORT_API int maps_route_destroy(maps_route_h route)
91 {
92         if (!maps_condition_check_maps_feature())
93                 return MAPS_ERROR_NOT_SUPPORTED;
94         if (!route)
95                 return MAPS_ERROR_INVALID_PARAMETER;
96
97         maps_route_s *p = (maps_route_s *) route;
98
99         if (p->route_id)
100                 g_free(p->route_id);
101         if (p->origin)
102                 maps_coordinates_destroy(p->origin);
103         if (p->destination)
104                 maps_coordinates_destroy(p->destination);
105         if (p->bounding_box)
106                 maps_area_destroy(p->bounding_box);
107         if (p->properties)
108                 maps_item_hashtable_destroy(p->properties);
109
110         if (p->segments) {
111                 maps_item_list_remove_all(p->segments,
112                         maps_route_segment_destroy);
113                 maps_item_list_destroy(p->segments);
114         }
115
116         if (p->path) {
117                 maps_item_list_remove_all(p->path, maps_coordinates_destroy);
118                 maps_item_list_destroy(p->path);
119         }
120
121         if (p->supported_data)
122                 maps_int_hashtable_destroy(p->supported_data);
123
124         g_slice_free(maps_route_s, route);
125         return MAPS_ERROR_NONE;
126 }
127
128 EXPORT_API int maps_route_clone(const maps_route_h origin,
129                                                                 maps_route_h *cloned)
130 {
131         if (!maps_condition_check_maps_feature())
132                 return MAPS_ERROR_NOT_SUPPORTED;
133         if (!cloned || !origin)
134                 return MAPS_ERROR_INVALID_PARAMETER;
135
136         int error = MAPS_ERROR_NONE;
137         do {
138                 error = maps_route_create(cloned);
139                 if (!(*cloned) || (error != MAPS_ERROR_NONE))
140                         break;
141
142                 maps_route_s *r = (maps_route_s *) origin;
143
144                 if (r->route_id) {
145                         error = maps_route_set_route_id(*cloned, r->route_id);
146                         if (error != MAPS_ERROR_NONE)
147                                 break;
148                 }
149
150                 if (r->origin) {
151                         error = maps_route_set_origin(*cloned, r->origin);
152                         if (error != MAPS_ERROR_NONE)
153                                 break;
154                 }
155
156                 if (r->destination) {
157                         error = maps_route_set_destination(*cloned, r->destination);
158                         if (error != MAPS_ERROR_NONE)
159                                 break;
160                 }
161
162                 if (r->bounding_box) {
163                         error = maps_route_set_bounding_box(*cloned, r->bounding_box);
164                         if (error != MAPS_ERROR_NONE)
165                                 break;
166                 }
167
168                 error = maps_route_set_transport_mode(*cloned, r->transport_mode);
169                 if (error != MAPS_ERROR_NONE)
170                         break;
171
172                 error = maps_route_set_total_distance(*cloned, r->total_distance);
173                 if (error != MAPS_ERROR_NONE)
174                         break;
175
176                 error = maps_route_set_total_duration(*cloned, r->total_duration);
177                 if (error != MAPS_ERROR_NONE)
178                         break;
179
180                 error = maps_route_set_distance_unit(*cloned, r->distance_unit);
181                 if (error != MAPS_ERROR_NONE)
182                         break;
183
184                 if (r->segments) {
185                         error = maps_route_set_segments(*cloned, r->segments);
186                         if (error != MAPS_ERROR_NONE)
187                                 break;
188                 }
189
190                 if (r->path) {
191                         error = maps_route_set_path(*cloned, r->path);
192                         if (error != MAPS_ERROR_NONE)
193                                 break;
194                 }
195
196                 if (r->properties) {
197                         error = maps_route_set_properties(*cloned, r->properties);
198                         if (error != MAPS_ERROR_NONE)
199                                 break;
200                 }
201
202                 if (r->supported_data) {
203                         error = _maps_route_set_supported_data(*cloned, r->supported_data);
204                         if (error != MAPS_ERROR_NONE)
205                                 break;
206                 }
207
208                 return MAPS_ERROR_NONE;
209         } while (false);
210
211         //LCOV_EXCL_START
212         maps_route_destroy(*cloned);
213         *cloned = NULL;
214         return error;
215         //LCOV_EXCL_STOP
216 }
217
218 /*----------------------------------------------------------------------------*/
219
220 EXPORT_API int maps_route_get_route_id(const maps_route_h route,
221                                                                 char **route_id)
222 {
223         if (!maps_condition_check_maps_feature())
224                 return MAPS_ERROR_NOT_SUPPORTED;
225         if (!route || !route_id)
226                 return MAPS_ERROR_INVALID_PARAMETER;
227         return maps_get_string(((maps_route_s *) route)->route_id,
228                 _MAPS_ROUTE_ID_MAX_LENGTH, route_id);
229 }
230
231 EXPORT_API int maps_route_get_origin(const maps_route_h route,
232                                                                 maps_coordinates_h *origin)
233 {
234         if (!maps_condition_check_maps_feature())
235                 return MAPS_ERROR_NOT_SUPPORTED;
236         if (!route || !origin)
237                 return MAPS_ERROR_INVALID_PARAMETER;
238         maps_coordinates_clone(((maps_route_s *) route)->origin, origin);
239         return MAPS_ERROR_NONE;
240 }
241
242 EXPORT_API int maps_route_get_destination(const maps_route_h route,
243                                                                 maps_coordinates_h *destination)
244 {
245         if (!maps_condition_check_maps_feature())
246                 return MAPS_ERROR_NOT_SUPPORTED;
247         if (!route || !destination)
248                 return MAPS_ERROR_INVALID_PARAMETER;
249         return maps_coordinates_clone(((maps_route_s *) route)->destination,
250                 destination);
251 }
252
253 EXPORT_API int maps_route_get_bounding_box(const maps_route_h route,
254                                                                 maps_area_h *bounding_box)
255 {
256         if (!maps_condition_check_maps_feature())
257                 return MAPS_ERROR_NOT_SUPPORTED;
258         if (!route || !bounding_box)
259                 return MAPS_ERROR_INVALID_PARAMETER;
260         return maps_area_clone(((maps_route_s *) route)->bounding_box,
261                 bounding_box);
262 }
263
264 EXPORT_API int maps_route_get_transport_mode(const maps_route_h route,
265                                                                 maps_route_transport_mode_e *transport_mode)
266 {
267         if (!maps_condition_check_maps_feature())
268                 return MAPS_ERROR_NOT_SUPPORTED;
269         if (!route || !transport_mode)
270                 return MAPS_ERROR_INVALID_PARAMETER;
271         *transport_mode = ((maps_route_s *) route)->transport_mode;
272         return MAPS_ERROR_NONE;
273 }
274
275 EXPORT_API int maps_route_get_total_distance(const maps_route_h route,
276                                                                 double *total_distance)
277 {
278         if (!maps_condition_check_maps_feature())
279                 return MAPS_ERROR_NOT_SUPPORTED;
280         if (!route || !total_distance)
281                 return MAPS_ERROR_INVALID_PARAMETER;
282         *total_distance = ((maps_route_s *) route)->total_distance;
283         return MAPS_ERROR_NONE;
284 }
285
286 EXPORT_API int maps_route_get_total_duration(const maps_route_h route,
287                                                                 long *total_duration)
288 {
289         if (!maps_condition_check_maps_feature())
290                 return MAPS_ERROR_NOT_SUPPORTED;
291         if (!route || !total_duration)
292                 return MAPS_ERROR_INVALID_PARAMETER;
293         *total_duration = ((maps_route_s *) route)->total_duration;
294         return MAPS_ERROR_NONE;
295 }
296
297 EXPORT_API int maps_route_foreach_path(const maps_route_h route,
298                                                                 maps_route_path_cb callback,
299                                                                 void *user_data)
300 {
301         if (!maps_condition_check_maps_feature())
302                 return MAPS_ERROR_NOT_SUPPORTED;
303         if (!route)
304                 return MAPS_ERROR_INVALID_PARAMETER;
305         if (!__is_supported(route, MAPS_ROUTE_PATH))
306                 return MAPS_ERROR_NOT_SUPPORTED;
307         if (!callback)
308                 return MAPS_ERROR_INVALID_PARAMETER;
309         if (!((maps_route_s *) route)->path)
310                 return MAPS_ERROR_NOT_FOUND;
311
312         return maps_item_list_foreach(((maps_route_s *) route)->path,
313                 maps_coordinates_clone, callback, user_data);
314 }
315
316 EXPORT_API int maps_route_foreach_segment(const maps_route_h route,
317                                                                 maps_route_segment_cb callback,
318                                                                 void *user_data)
319 {
320         if (!maps_condition_check_maps_feature())
321                 return MAPS_ERROR_NOT_SUPPORTED;
322         if (!route)
323                 return MAPS_ERROR_INVALID_PARAMETER;
324         if (!__is_supported(route, MAPS_ROUTE_SEGMENTS_PATH)
325                 && !__is_supported(route, MAPS_ROUTE_SEGMENTS_MANEUVERS))
326                 return MAPS_ERROR_NOT_SUPPORTED;
327         if (!callback)
328                 return MAPS_ERROR_INVALID_PARAMETER;
329         if (!((maps_route_s *) route)->segments)
330                 return MAPS_ERROR_NOT_FOUND;
331
332         return maps_item_list_foreach(((maps_route_s *) route)->segments,
333                 maps_route_segment_clone, callback, user_data);
334 }
335
336 EXPORT_API int maps_route_foreach_property(const maps_route_h route,
337                                                                 maps_route_properties_cb callback,
338                                                                 void *user_data)
339 {
340         if (!maps_condition_check_maps_feature())
341                 return MAPS_ERROR_NOT_SUPPORTED;
342         if (!route || !callback)
343                 return MAPS_ERROR_INVALID_PARAMETER;
344         if (!((maps_route_s *) route)->properties)
345                 return MAPS_ERROR_NOT_FOUND;
346         return maps_item_hashtable_foreach(((maps_route_s *) route)->properties,
347                 callback, user_data);
348 }
349
350 EXPORT_API int maps_route_get_distance_unit(const maps_route_h route,
351                                                                 maps_distance_unit_e *distance_unit)
352 {
353         if (!maps_condition_check_maps_feature())
354                 return MAPS_ERROR_NOT_SUPPORTED;
355         if (!route || !distance_unit)
356                 return MAPS_ERROR_INVALID_PARAMETER;
357         *distance_unit = ((maps_route_s *) route)->distance_unit;
358         return MAPS_ERROR_NONE;
359 }
360
361 int _maps_route_is_data_supported(const maps_route_h route,
362                                                                 maps_service_data_e data, bool *supported)
363 {
364         if (!maps_condition_check_maps_feature())
365                 return MAPS_ERROR_NOT_SUPPORTED;
366         if (!route || !supported)
367                 return MAPS_ERROR_INVALID_PARAMETER;
368
369         maps_route_s *r = (maps_route_s *)route;
370
371         if (!r->supported_data) {
372                 /* This is a case when the "supported" flags are not set yet */
373                 /* No need to limit access to fields */
374                 *supported = true;
375                 return MAPS_ERROR_NONE;
376         }
377
378         *supported = false;
379         return maps_int_hashtable_contains(r->supported_data, data, supported);
380 }
381
382 /*----------------------------------------------------------------------------*/
383
384 EXPORT_API int maps_route_set_route_id(const maps_route_h route,
385                                                                 const char *route_id)
386 {
387         if (!maps_condition_check_maps_feature())
388                 return MAPS_ERROR_NOT_SUPPORTED;
389         if (!route || !route_id)
390                 return MAPS_ERROR_INVALID_PARAMETER;
391         return maps_set_string(route_id, _MAPS_ROUTE_ID_MAX_LENGTH,
392                 &((maps_route_s *) route)->route_id);
393 }
394
395 EXPORT_API int maps_route_set_origin(maps_route_h route,
396                                                                 const maps_coordinates_h origin)
397 {
398         if (!maps_condition_check_maps_feature())
399                 return MAPS_ERROR_NOT_SUPPORTED;
400         if (!route || !origin)
401                 return MAPS_ERROR_INVALID_PARAMETER;
402         maps_route_s *p = (maps_route_s *) route;
403         if (p->origin)
404                 maps_coordinates_destroy(p->origin);
405         return maps_coordinates_clone(origin, &p->origin);
406 }
407
408 EXPORT_API int maps_route_set_destination(maps_route_h route,
409                                                                 const maps_coordinates_h destination)
410 {
411         if (!maps_condition_check_maps_feature())
412                 return MAPS_ERROR_NOT_SUPPORTED;
413         if (!route || !destination)
414                 return MAPS_ERROR_INVALID_PARAMETER;
415         maps_route_s *p = (maps_route_s *) route;
416         if (p->destination)
417                 maps_coordinates_destroy(p->destination);
418         return maps_coordinates_clone(destination, &p->destination);
419 }
420
421 EXPORT_API int maps_route_set_bounding_box(maps_route_h route,
422                                                                 const maps_area_h bounding_box)
423 {
424         if (!maps_condition_check_maps_feature())
425                 return MAPS_ERROR_NOT_SUPPORTED;
426         if (!route || !bounding_box)
427                 return MAPS_ERROR_INVALID_PARAMETER;
428         maps_route_s *p = (maps_route_s *) route;
429         if (p->bounding_box)
430                 maps_area_destroy(p->bounding_box);
431         return maps_area_clone(bounding_box, &p->bounding_box);
432 }
433
434 EXPORT_API int maps_route_set_total_distance(maps_route_h route,
435                                                                 const double total_distance)
436 {
437         if (!maps_condition_check_maps_feature())
438                 return MAPS_ERROR_NOT_SUPPORTED;
439         if (!route || total_distance < 0)
440                 return MAPS_ERROR_INVALID_PARAMETER;
441         ((maps_route_s *) route)->total_distance = total_distance;
442         return MAPS_ERROR_NONE;
443 }
444
445 EXPORT_API int maps_route_set_total_duration(maps_route_h route,
446                                                                 const long total_duration)
447 {
448         if (!maps_condition_check_maps_feature())
449                 return MAPS_ERROR_NOT_SUPPORTED;
450         if (!route || total_duration < 0)
451                 return MAPS_ERROR_INVALID_PARAMETER;
452         ((maps_route_s *) route)->total_duration = total_duration;
453         return MAPS_ERROR_NONE;
454 }
455
456 EXPORT_API int maps_route_set_transport_mode(maps_route_h route,
457                                                                 const maps_route_transport_mode_e transport_mode)
458 {
459         if (!maps_condition_check_maps_feature())
460                 return MAPS_ERROR_NOT_SUPPORTED;
461         if (!route)
462                 return MAPS_ERROR_INVALID_PARAMETER;
463         if ((transport_mode < MAPS_ROUTE_TRANSPORT_MODE_CAR) ||
464                 (transport_mode > MAPS_ROUTE_TRANSPORT_MODE_TRUCK))
465                 return MAPS_ERROR_INVALID_PARAMETER;
466         ((maps_route_s *) route)->transport_mode = transport_mode;
467         return MAPS_ERROR_NONE;
468 }
469
470 EXPORT_API int maps_route_set_path(maps_route_h route,
471                                                                 const maps_item_list_h path)
472 {
473         if (!maps_condition_check_maps_feature())
474                 return MAPS_ERROR_NOT_SUPPORTED;
475         if (!route || !path)
476                 return MAPS_ERROR_INVALID_PARAMETER;
477         maps_route_s *p = (maps_route_s *) route;
478         if (p->path) {
479                 maps_item_list_remove_all(p->path, maps_coordinates_destroy);
480                 maps_item_list_destroy(p->path);
481         }
482         maps_item_list_clone(path, maps_coordinates_clone, &p->path);
483         return MAPS_ERROR_NONE;
484 }
485
486 EXPORT_API int maps_route_set_segments(maps_route_h route,
487                                                                 const maps_item_list_h segments)
488 {
489         if (!maps_condition_check_maps_feature())
490                 return MAPS_ERROR_NOT_SUPPORTED;
491         if (!route || !segments)
492                 return MAPS_ERROR_INVALID_PARAMETER;
493         maps_route_s *p = (maps_route_s *) route;
494         if (p->segments) {
495                 maps_item_list_remove_all(p->segments,
496                         maps_route_segment_destroy);
497                 maps_item_list_destroy(p->segments);
498         }
499         maps_item_list_clone(segments, maps_route_segment_clone, &p->segments);
500         return MAPS_ERROR_NONE;
501 }
502
503 EXPORT_API int maps_route_set_properties(maps_route_h route,
504                                                                 const maps_item_hashtable_h properties)
505 {
506         if (!maps_condition_check_maps_feature())
507                 return MAPS_ERROR_NOT_SUPPORTED;
508         if (!route || !properties)
509                 return MAPS_ERROR_INVALID_PARAMETER;
510         maps_route_s *p = (maps_route_s *) route;
511         if (p->properties)
512                 maps_item_hashtable_destroy(p->properties);
513         return maps_item_hashtable_clone(properties, &p->properties);
514 }
515
516 EXPORT_API int maps_route_set_distance_unit(maps_route_h route,
517                                                                 const maps_distance_unit_e distance_unit)
518 {
519         if (!maps_condition_check_maps_feature())
520                 return MAPS_ERROR_NOT_SUPPORTED;
521         if (!route)
522                 return MAPS_ERROR_INVALID_PARAMETER;
523         if ((distance_unit < MAPS_DISTANCE_UNIT_M) ||
524                 (distance_unit > MAPS_DISTANCE_UNIT_YD))
525                 return MAPS_ERROR_INVALID_PARAMETER;
526         ((maps_route_s *) route)->distance_unit = distance_unit;
527         return MAPS_ERROR_NONE;
528 }
529
530 int _maps_route_set_supported_data(maps_route_h route,
531                                                                 const maps_int_hashtable_h supported_data)
532 {
533         if (!route || !supported_data)
534                 return MAPS_ERROR_INVALID_PARAMETER;
535         maps_route_s *p = (maps_route_s *) route;
536         if (p->supported_data)
537                 maps_int_hashtable_destroy(p->supported_data);
538         int error =
539                 maps_int_hashtable_clone(supported_data, &p->supported_data);
540         if (error != MAPS_ERROR_NONE)
541                 return error;
542
543         if (p->segments)
544                 error = maps_item_list_foreach(p->segments, NULL,
545                         __maps_route_set_supported_data_foreach_cb, supported_data);
546         return error;
547 }