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