Release Tizen2.0 beta
[framework/location/libslp-location.git] / location / map-service / location-route.c
1 /*
2  * libslp-location
3  *
4  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Youngae Kang <youngae.kang@samsung.com>, Yunhan Kim <yhan.kim@samsung.com>,
7  *          Genie Kim <daejins.kim@samsung.com>, Minjune Kim <sena06.kim@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "location-types.h"
27 #include "location-route.h"
28 #include "location-route-ext.h"
29 #include "location-boundary.h"
30 #include "map-service.h"
31
32
33 struct _LocationRoute {
34 //      gint req_id;                            //< Request id : for expandability
35         LocationPosition *origin;               //< Coordinate StartCoord
36         LocationPosition *destination;          //< Coordinates destCoord
37         LocationBoundary *bbox;                 //< a rectangular geographical area
38         gdouble total_distance;                 //< Total distance
39         gchar *distance_unit;                   //< Distance Unit
40         glong total_duration;                   //< Total duration
41         GHashTable *properties;                 //<Key/Value>
42         GList *segment;
43 };
44
45 //Waypoints
46 struct _LocationRouteSegment {
47         LocationPosition *start;        //< Coordinate StartCoord;
48         LocationPosition *end;          //< Coordinates destCoord;
49         LocationBoundary *bbox;         //< a rectangular geographical area
50         gdouble distance;
51         glong duration;
52         GHashTable *properties;         //<Key/Value>
53         GList *step;
54 };
55
56 // Each instruction
57 struct _LocationRouteStep {
58         LocationPosition *start;        //< Coordinate StartCoord;
59         LocationPosition *end;          //< Coordinates destCoord;
60         LocationBoundary *bbox;         //< a rectangular geographical area
61         gdouble distance;
62         glong duration;
63         gchar *transport_mode;
64         gchar *instruction;
65         GList *geometry;
66
67         GHashTable *properties;
68 };
69
70 struct _LocationRoutePreference {
71         GList* addr_to_avoid;
72         GList* area_to_avoid;
73         GList* feature_to_avoid;
74         GList* freeformed_addr_to_avoid;
75         LocationBoundary* bbox;
76         guint max_matches_count;
77         gchar *distance_unit;
78
79         gchar *route_type;
80         gchar *transport_mode;
81         gboolean is_geometry_used;
82         gboolean is_instruction_bounding_box_used;
83         gboolean is_instruction_geometry_used;
84         gboolean is_instruction_used;
85         gboolean is_traffic_data_used;
86
87         // AvoidFreeways, Easy, Fastest, MoreFreeways, NoFreeways, Pedestrian, Shortest
88         GHashTable *properties;
89
90 };
91
92 static void route_pref_addr_to_avoid_copy_cb (gpointer data, gpointer user_data)
93 {
94         g_return_if_fail(data);
95         g_return_if_fail(user_data);
96
97         LocationAddress *address = (LocationAddress *)data;
98         LocationRoutePreference *pref = (LocationRoutePreference *)user_data;
99
100         pref->addr_to_avoid = g_list_append (pref->addr_to_avoid, location_address_copy(address));
101 }
102
103 static void addr_to_avoid_free_cb (gpointer data)
104 {
105         g_return_if_fail (data);
106
107         LocationAddress *addr = (LocationAddress *)data;
108
109         location_address_free (addr);
110 }
111
112 EXPORT_API gboolean
113 location_route_pref_set_addr_to_avoid (LocationRoutePreference *pref, GList *addr)
114 {
115         g_return_val_if_fail(pref, FALSE);
116
117         if (pref->addr_to_avoid) {
118                 g_list_free_full (pref->addr_to_avoid, addr_to_avoid_free_cb);
119                 pref->addr_to_avoid = NULL;
120         }
121
122         if (addr) g_list_foreach (addr, route_pref_addr_to_avoid_copy_cb, pref);
123
124         return TRUE;
125 }
126
127 static void route_pref_area_to_avoid_copy_cb (gpointer data, gpointer user_data)
128 {
129         g_return_if_fail(data);
130         g_return_if_fail(user_data);
131
132         LocationBoundary *area = (LocationBoundary *)data;
133         LocationRoutePreference *pref = (LocationRoutePreference *)user_data;
134
135         pref->area_to_avoid = g_list_append (pref->area_to_avoid, location_boundary_copy((const LocationBoundary *)area));
136 }
137
138 static void route_pref_area_to_avoid_free_cb (gpointer data)
139 {
140         g_return_if_fail (data);
141
142         LocationBoundary *boundary = (LocationBoundary *)data;
143
144         location_boundary_free (boundary);
145 }
146
147 EXPORT_API gboolean
148 location_route_pref_set_area_to_avoid (LocationRoutePreference *pref, GList *area)
149 {
150         g_return_val_if_fail(pref, FALSE);
151
152         if (pref->area_to_avoid) {
153                 g_list_free_full (pref->area_to_avoid, route_pref_area_to_avoid_free_cb);
154                 pref->area_to_avoid = NULL;
155         }
156
157         if (area) g_list_foreach (area, route_pref_area_to_avoid_copy_cb, pref);
158
159         return TRUE;
160 }
161
162 static void route_pref_feature_to_avoid_copy_cb (gpointer data, gpointer user_data)
163 {
164         g_return_if_fail (data);
165         g_return_if_fail (user_data);
166
167         gchar *feature = (gchar *)data;
168         LocationRoutePreference *pref = (LocationRoutePreference *) user_data;
169
170         pref->feature_to_avoid = g_list_append (pref->feature_to_avoid, g_strdup (feature));
171 }
172
173 EXPORT_API gboolean
174 location_route_pref_set_feature_to_avoid (LocationRoutePreference *pref, GList * feature)
175 {
176         g_return_val_if_fail(pref, FALSE);
177
178         if (pref->feature_to_avoid) {
179                 g_list_free_full (pref->feature_to_avoid, g_free);
180                 pref->feature_to_avoid = NULL;
181         }
182
183         g_list_foreach (feature, route_pref_feature_to_avoid_copy_cb, pref);
184
185         return TRUE;
186 }
187
188 static void route_pref_freeforemd_addr_to_avoid_foreach_copy (gpointer data, gpointer user_data)
189 {
190         g_return_if_fail(data);
191         g_return_if_fail(user_data);
192
193         gchar *freeformed_addr = (gchar *)data;
194         LocationRoutePreference *pref = (LocationRoutePreference *)user_data;
195
196         pref->freeformed_addr_to_avoid = g_list_append (pref->freeformed_addr_to_avoid, g_strdup(freeformed_addr));
197 }
198
199 EXPORT_API gboolean
200 location_route_pref_set_freeformed_addr_to_avoid (LocationRoutePreference *pref, GList *freeformed_addr)
201 {
202         g_return_val_if_fail(pref, FALSE);
203
204         if (pref->freeformed_addr_to_avoid) {
205                 g_list_free_full (pref->freeformed_addr_to_avoid, g_free);
206                 pref->freeformed_addr_to_avoid = NULL;
207         }
208
209         if (freeformed_addr) g_list_foreach (freeformed_addr, route_pref_freeforemd_addr_to_avoid_foreach_copy, pref);
210
211         return TRUE;
212 }
213
214 EXPORT_API gboolean
215 location_route_pref_set_bounding_box (LocationRoutePreference *pref, const LocationBoundary *bbox)
216 {
217         g_return_val_if_fail(pref, FALSE);
218
219         if (pref->bbox) {
220                 location_boundary_free (pref->bbox);
221                 pref->bbox = NULL;
222         }
223
224         if (bbox) pref->bbox = location_boundary_copy (bbox);
225
226         return TRUE;
227 }
228
229 EXPORT_API gboolean
230 location_route_pref_set_max_result (LocationRoutePreference *pref, guint max_num)
231 {
232         g_return_val_if_fail(pref, FALSE);
233         g_return_val_if_fail(max_num > 0, FALSE);
234
235         pref->max_matches_count = max_num;
236
237         return TRUE;
238 }
239
240 EXPORT_API gboolean
241 location_route_pref_set_route_type (LocationRoutePreference *pref, const gchar *type)
242 {
243         g_return_val_if_fail(pref, FALSE);
244
245         if (pref->route_type) {
246                 g_free(pref->route_type);
247                 pref->route_type = NULL;
248         }
249
250         if (type) pref->route_type = g_strdup (type);
251
252         return TRUE;
253 }
254
255 EXPORT_API gboolean
256 location_route_pref_set_transport_mode (LocationRoutePreference *pref, const gchar *mode)
257 {
258         g_return_val_if_fail(pref, FALSE);
259
260         if (pref->transport_mode) {
261                 g_free(pref->transport_mode);
262                 pref->transport_mode = NULL;
263         }
264
265         if (mode) pref->transport_mode = g_strdup (mode);
266
267         return TRUE;
268 }
269
270 EXPORT_API gboolean
271 location_route_pref_set_geometry_used (LocationRoutePreference *pref, gboolean is_used)
272 {
273         g_return_val_if_fail(pref, FALSE);
274
275         pref->is_geometry_used = is_used;
276
277         return TRUE;
278 }
279
280 EXPORT_API gboolean
281 location_route_pref_set_instruction_bounding_box_used (LocationRoutePreference *pref, gboolean is_used)
282 {
283         g_return_val_if_fail(pref, FALSE);
284
285         pref->is_instruction_bounding_box_used = is_used;
286
287         return TRUE;
288 }
289
290 EXPORT_API gboolean
291 location_route_pref_set_instruction_geometry_used (LocationRoutePreference *pref, gboolean is_used)
292 {
293         g_return_val_if_fail(pref, FALSE);
294
295         pref->is_instruction_geometry_used = is_used;
296
297         return TRUE;
298 }
299
300 EXPORT_API gboolean
301 location_route_pref_set_instruction_used (LocationRoutePreference *pref, gboolean is_used)
302 {
303         g_return_val_if_fail(pref, FALSE);
304
305         pref->is_instruction_used = is_used;
306
307         return TRUE;
308 }
309
310 EXPORT_API gboolean
311 location_route_pref_set_traffic_data_used (LocationRoutePreference *pref, gboolean is_used)
312 {
313         g_return_val_if_fail(pref, FALSE);
314
315         pref->is_traffic_data_used = is_used;
316
317         return TRUE;
318 }
319
320 EXPORT_API gboolean
321 location_route_pref_set_property (LocationRoutePreference *pref, gconstpointer key, gconstpointer value)
322 {
323         g_return_val_if_fail(pref, FALSE);
324         g_return_val_if_fail(key, FALSE);
325
326         if (value) {
327                 gchar *re_key = g_strdup(key);
328                 gchar *re_val = g_strdup(value);
329                 g_hash_table_insert (pref->properties, re_key, re_val);
330         } else g_hash_table_remove (pref->properties, key);
331
332         return TRUE;
333 }
334
335 EXPORT_API GList *
336 location_route_pref_get_addr_to_avoid (const LocationRoutePreference *pref)
337 {
338         g_return_val_if_fail(pref, NULL);
339
340         return pref->addr_to_avoid;
341 }
342
343 EXPORT_API GList *
344 location_route_pref_get_area_to_avoid (const LocationRoutePreference *pref)
345 {
346         g_return_val_if_fail(pref, NULL);
347
348         return pref->area_to_avoid;
349 }
350
351 EXPORT_API GList *
352 location_route_pref_get_feature_to_avoid (const LocationRoutePreference *pref)
353 {
354         g_return_val_if_fail(pref, NULL);
355
356         return pref->feature_to_avoid;
357 }
358
359 EXPORT_API GList *
360 location_route_pref_get_freeformed_addr_to_avoid (const LocationRoutePreference *pref)
361 {
362         g_return_val_if_fail(pref, NULL);
363
364         return pref->freeformed_addr_to_avoid;
365 }
366
367 EXPORT_API LocationBoundary *
368 location_route_pref_get_bounding_box (const LocationRoutePreference *pref)
369 {
370         g_return_val_if_fail(pref, NULL);
371
372         return pref->bbox;
373 }
374
375 EXPORT_API guint
376 location_route_pref_get_max_result (const LocationRoutePreference *pref)
377 {
378         g_return_val_if_fail(pref, 0);
379
380         return pref->max_matches_count;
381 }
382
383 EXPORT_API gchar *
384 location_route_pref_get_route_type (const LocationRoutePreference *pref)
385 {
386         g_return_val_if_fail(pref, NULL);
387
388         return pref->route_type;
389 }
390
391 EXPORT_API gchar *
392 location_route_pref_get_transport_mode (const LocationRoutePreference *pref)
393 {
394         g_return_val_if_fail(pref, NULL);
395
396         return pref->transport_mode;
397 }
398
399 EXPORT_API gboolean
400 location_route_pref_get_geometry_used (const LocationRoutePreference *pref)
401 {
402         g_return_val_if_fail(pref, FALSE);
403
404         return pref->is_geometry_used;
405 }
406
407 EXPORT_API gboolean
408 location_route_pref_get_instruction_bounding_box_used (const LocationRoutePreference *pref)
409 {
410         g_return_val_if_fail(pref, FALSE);
411
412         return pref->is_instruction_bounding_box_used;
413 }
414
415 EXPORT_API gboolean
416 location_route_pref_get_instruction_geometry_used (const LocationRoutePreference *pref)
417 {
418         g_return_val_if_fail(pref, FALSE);
419
420         return pref->is_instruction_geometry_used;
421 }
422
423 EXPORT_API gboolean
424 location_route_pref_get_instruction_used (const LocationRoutePreference *pref)
425 {
426         g_return_val_if_fail(pref, FALSE);
427
428         return pref->is_instruction_used;
429 }
430
431 EXPORT_API gboolean
432 location_route_pref_get_traffic_data_used (const LocationRoutePreference *pref)
433 {
434         g_return_val_if_fail(pref, FALSE);
435
436         return pref->is_traffic_data_used;
437 }
438
439 EXPORT_API GList*
440 location_route_pref_get_property_key (const LocationRoutePreference *pref)
441 {
442         g_return_val_if_fail(pref, NULL);
443
444         return g_hash_table_get_keys(pref->properties);
445 }
446
447 EXPORT_API gpointer
448 location_route_pref_get_property (const LocationRoutePreference *pref, gconstpointer key)
449 {
450         g_return_val_if_fail(pref, NULL);
451         g_return_val_if_fail(key, NULL);
452
453         return g_hash_table_lookup(pref->properties, key);
454 }
455
456 EXPORT_API LocationRoutePreference *
457 location_route_pref_new (void)
458 {
459         LocationRoutePreference *pref = g_slice_new0(LocationRoutePreference);
460         g_return_val_if_fail (pref, NULL);
461
462         pref->properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
463         return pref;
464 }
465
466 static void route_pref_property_copy_cb (gpointer key, gpointer value, gpointer user_data)
467 {
468         g_return_if_fail(key);
469         g_return_if_fail(value);
470         g_return_if_fail(user_data);
471
472         LocationRoutePreference *pref = (LocationRoutePreference *)user_data;
473
474         if (pref->properties) {
475                 gchar *re_key = g_strdup (key);
476                 gchar *re_val = g_strdup (value);
477                 g_hash_table_insert (pref->properties, re_key, re_val);
478         }
479 }
480
481 EXPORT_API LocationRoutePreference *
482 location_route_pref_copy (const LocationRoutePreference *pref)
483 {
484         g_return_val_if_fail(pref, NULL);
485
486         LocationRoutePreference *new_pref = location_route_pref_new();
487         g_return_val_if_fail (pref, NULL);
488
489         location_route_pref_set_addr_to_avoid(new_pref, location_route_pref_get_addr_to_avoid (pref));
490         location_route_pref_set_area_to_avoid(new_pref, location_route_pref_get_area_to_avoid (pref));
491         location_route_pref_set_feature_to_avoid(new_pref, location_route_pref_get_feature_to_avoid (pref));
492         location_route_pref_set_freeformed_addr_to_avoid(new_pref, location_route_pref_get_freeformed_addr_to_avoid (pref));
493         location_route_pref_set_bounding_box(new_pref, location_route_pref_get_bounding_box (pref));
494         location_route_pref_set_max_result(new_pref, location_route_pref_get_max_result (pref));
495         location_route_pref_set_route_type(new_pref, location_route_pref_get_route_type (pref));
496         location_route_pref_set_transport_mode(new_pref, location_route_pref_get_transport_mode (pref));
497         location_route_pref_set_geometry_used(new_pref, location_route_pref_get_geometry_used (pref));
498         location_route_pref_set_instruction_bounding_box_used(new_pref, location_route_pref_get_instruction_bounding_box_used (pref));
499         location_route_pref_set_instruction_geometry_used(new_pref, location_route_pref_get_instruction_geometry_used (pref));
500         location_route_pref_set_instruction_used(new_pref, location_route_pref_get_instruction_used (pref));
501         location_route_pref_set_traffic_data_used(new_pref, location_route_pref_get_traffic_data_used (pref));
502         location_route_pref_set_traffic_data_used(new_pref, location_route_pref_get_traffic_data_used (pref));
503
504         if (new_pref->properties) g_hash_table_foreach (pref->properties, route_pref_property_copy_cb, new_pref);
505
506         return new_pref;
507 }
508
509
510 EXPORT_API void
511 location_route_pref_free (LocationRoutePreference *pref)
512 {
513         g_return_if_fail(pref);
514
515         location_route_pref_set_addr_to_avoid(pref, NULL);
516         location_route_pref_set_area_to_avoid(pref, NULL);
517         location_route_pref_set_feature_to_avoid(pref, NULL);
518         location_route_pref_set_freeformed_addr_to_avoid(pref, NULL);
519         location_route_pref_set_bounding_box(pref, NULL);
520         location_route_pref_set_route_type(pref, NULL);
521         location_route_pref_set_transport_mode(pref, NULL);
522
523         if (pref->properties) {
524                 g_hash_table_destroy (pref->properties);
525                 pref->properties = NULL;
526         }
527
528         g_slice_free (LocationRoutePreference, pref);
529 }
530
531 /* for expandability
532 EXPORT_API gint
533 location_route_get_req_id (const LocationRoute *route)
534 {
535         g_return_val_if_fail(route, 0);
536
537         return route->req_id;
538 }
539 */
540
541 EXPORT_API LocationPosition *
542 location_route_get_origin (const LocationRoute *route)
543 {
544         g_return_val_if_fail(route, NULL);
545
546         return route->origin;
547 }
548
549 EXPORT_API LocationPosition *
550 location_route_get_destination (const LocationRoute *route)
551 {
552         g_return_val_if_fail(route, NULL);
553
554         return route->destination;
555 }
556
557 EXPORT_API LocationBoundary *
558 location_route_get_bounding_box (const LocationRoute *route)
559 {
560         g_return_val_if_fail(route, NULL);
561
562         return route->bbox;
563 }
564
565 EXPORT_API gdouble
566 location_route_get_total_distance (const LocationRoute *route)
567 {
568         g_return_val_if_fail(route, 0.0);
569
570         return route->total_distance;
571 }
572
573 EXPORT_API gchar *
574 location_route_get_distance_unit (const LocationRoute *route)
575 {
576         g_return_val_if_fail(route, NULL);
577
578         return route->distance_unit;
579 }
580
581 EXPORT_API glong
582 location_route_get_total_duration (const LocationRoute *route)
583 {
584         g_return_val_if_fail(route, 0);
585
586         return route->total_duration;
587 }
588
589 EXPORT_API GList *
590 location_route_get_property_key (const LocationRoute *route)
591 {
592         g_return_val_if_fail(route, NULL);
593
594         return g_hash_table_get_keys(route->properties);
595 }
596
597 EXPORT_API gpointer
598 location_route_get_property (const LocationRoute *route, gconstpointer key)
599 {
600         g_return_val_if_fail(route, NULL);
601         g_return_val_if_fail(key, NULL);
602
603         return g_hash_table_lookup(route->properties, key);
604 }
605
606 EXPORT_API GList *
607 location_route_get_route_segment (const LocationRoute *route)
608 {
609         g_return_val_if_fail(route, NULL);
610
611         return route->segment;
612 }
613
614 /* for expandability
615 EXPORT_API gboolean
616 location_route_set_req_id (LocationRoute *route, gint req_id)
617 {
618         g_return_val_if_fail(route, FALSE);
619
620         route->req_id = req_id;
621
622         return TRUE;
623 }
624 */
625
626 EXPORT_API gboolean
627 location_route_set_origin (LocationRoute *route, const LocationPosition* origin)
628 {
629         g_return_val_if_fail(route, FALSE);
630
631         if (route->origin) {
632                 location_position_free(route->origin);
633                 route->origin = NULL;
634         }
635
636         if (origin) route->origin = location_position_copy(origin);
637
638         return TRUE;
639 }
640
641 EXPORT_API gboolean
642 location_route_set_destination (LocationRoute *route, const LocationPosition* destination)
643 {
644         g_return_val_if_fail(route, FALSE);
645
646         if (route->destination) {
647                 location_position_free(route->destination);
648                 route->destination = NULL;
649         }
650
651         if (destination) route->destination = location_position_copy(destination);
652
653         return TRUE;
654 }
655
656 EXPORT_API gboolean
657 location_route_set_bounding_box (LocationRoute *route, const LocationBoundary* bbox)
658 {
659         g_return_val_if_fail(route, FALSE);
660
661         if (route->bbox) {
662                 location_boundary_free(route->bbox);
663                 route->bbox = NULL;
664         }
665
666         if (bbox) route->bbox = location_boundary_copy(bbox);
667
668         return TRUE;
669 }
670
671 EXPORT_API
672 gboolean location_route_set_total_distance (LocationRoute *route, gdouble total_distance)
673 {
674         g_return_val_if_fail(route, FALSE);
675
676         route->total_distance = total_distance;
677
678         return TRUE;
679 }
680
681 EXPORT_API
682 gboolean location_route_set_distance_unit (LocationRoute *route, const gchar* distance_unit)
683 {
684         g_return_val_if_fail(route, FALSE);
685
686         if (route->distance_unit) {
687                 g_free(route->distance_unit);
688                 route->distance_unit = NULL;
689         }
690
691         if (distance_unit) route->distance_unit = g_strdup(distance_unit);
692
693         return TRUE;
694 }
695
696 EXPORT_API gboolean
697 location_route_set_total_duration (LocationRoute *route, glong total_duration)
698 {
699         g_return_val_if_fail(route, FALSE);
700
701         route->total_duration = total_duration;
702
703         return TRUE;
704 }
705
706 EXPORT_API gboolean
707 location_route_set_property (LocationRoute *route, gconstpointer key, gconstpointer value)
708 {
709         g_return_val_if_fail(route, FALSE);
710         g_return_val_if_fail(key, FALSE);
711         if (!route->properties) return FALSE;
712
713         if (value) {
714                 gchar *re_key = g_strdup (key);
715                 gchar *re_val = g_strdup (value);
716                 g_hash_table_insert(route->properties, re_key, re_val);
717         } else g_hash_table_remove (route->properties, key);
718
719         return TRUE;
720 }
721
722 static void route_segment_foreach_copy (gpointer data, gpointer user_data)
723 {
724         g_return_if_fail (data);
725
726         LocationRouteSegment *segment = (LocationRouteSegment *) data;
727         LocationRoute *route = (LocationRoute *) user_data;
728
729         route->segment = g_list_append (route->segment, location_route_segment_copy (segment));
730 }
731
732 static void route_segment_foreach_free (gpointer data)
733 {
734         g_return_if_fail (data);
735
736         LocationRouteSegment *segment = (LocationRouteSegment *)data;
737
738         location_route_segment_free(segment);
739 }
740
741
742 EXPORT_API gboolean
743 location_route_set_route_segment (LocationRoute *route, GList* segment)
744 {
745         g_return_val_if_fail(route, FALSE);
746
747         if (route->segment) {
748                 g_list_free_full (route->segment, route_segment_foreach_free);
749                 route->segment = NULL;
750         }
751
752         if (segment) g_list_foreach (segment, route_segment_foreach_copy, route);
753
754         return TRUE;
755 }
756
757 EXPORT_API LocationRoute *
758 location_route_new (void)
759 {
760         LocationRoute *route = g_slice_new0(LocationRoute);
761         g_return_val_if_fail (route, NULL);
762
763         route->properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
764
765         return route;
766 }
767
768 static void route_property_copy_cb (gpointer key, gpointer value, gpointer user_data)
769 {
770         g_return_if_fail (key);
771         g_return_if_fail (value);
772         g_return_if_fail (user_data);
773
774         LocationRoute *route = (LocationRoute *)user_data;
775
776         if (route->properties) {
777                 gchar *re_key = g_strdup (key);
778                 gchar *re_val = g_strdup (value);
779                 g_hash_table_insert (route->properties, re_key, re_val);
780         }
781 }
782
783 EXPORT_API LocationRoute *
784 location_route_copy (const LocationRoute *route)
785 {
786         g_return_val_if_fail(route, NULL);
787         LocationRoute *new_route = location_route_new();
788         g_return_val_if_fail(new_route, NULL);
789
790         location_route_set_origin (new_route, location_route_get_origin(route));
791         location_route_set_destination (new_route, location_route_get_destination(route));
792         location_route_set_bounding_box (new_route, location_route_get_bounding_box(route));
793         location_route_set_total_distance (new_route, location_route_get_total_distance(route));
794         location_route_set_distance_unit (new_route, location_route_get_distance_unit(route));
795         location_route_set_total_duration (new_route, location_route_get_total_duration(route));
796
797         g_list_foreach(route->segment, route_segment_foreach_copy, new_route);
798
799         if (route->properties) g_hash_table_foreach (route->properties, route_property_copy_cb, new_route);
800
801         return new_route;
802 }
803
804 EXPORT_API void
805 location_route_free (LocationRoute *route)
806 {
807         g_return_if_fail (route);
808
809         location_route_set_origin (route, NULL);
810         location_route_set_destination (route, NULL);
811         location_route_set_bounding_box (route, NULL);
812         location_route_set_distance_unit (route, NULL);
813         location_route_set_route_segment (route, NULL);
814
815         if (route->properties) {
816                 g_hash_table_destroy (route->properties);
817                 route->properties = NULL;
818         }
819
820         g_slice_free (LocationRoute, route);
821 }
822
823 EXPORT_API LocationPosition *
824 location_route_segment_get_start_point (const LocationRouteSegment *segment)
825 {
826         g_return_val_if_fail(segment, NULL);
827
828         return segment->start;
829 }
830
831 EXPORT_API LocationPosition *
832 location_route_segment_get_end_point (const LocationRouteSegment *segment)
833 {
834         g_return_val_if_fail(segment, NULL);
835
836         return segment->end;
837 }
838
839 EXPORT_API LocationBoundary *
840 location_route_segment_get_bounding_box (const LocationRouteSegment *segment)
841 {
842         g_return_val_if_fail(segment, NULL);
843
844         return segment->bbox;
845 }
846
847 EXPORT_API gdouble
848 location_route_segment_get_distance (const LocationRouteSegment *segment)
849 {
850         g_return_val_if_fail(segment, 0.0);
851
852         return segment->distance;
853 }
854
855 EXPORT_API glong
856 location_route_segment_get_duration (const LocationRouteSegment *segment)
857 {
858         g_return_val_if_fail(segment, 0);
859
860         return segment->duration;
861 }
862
863 EXPORT_API GList*
864 location_route_segment_get_property_key (const LocationRouteSegment *segment)
865 {
866         g_return_val_if_fail(segment, NULL);
867
868         return g_hash_table_get_keys(segment->properties);
869 }
870
871 EXPORT_API gpointer
872 location_route_segment_get_property (const LocationRouteSegment *segment, gconstpointer key)
873 {
874         g_return_val_if_fail(segment, NULL);
875         g_return_val_if_fail(key, NULL);
876
877         return g_hash_table_lookup(segment->properties, (gpointer) key);
878 }
879
880 EXPORT_API GList*
881 location_route_segment_get_route_step (const LocationRouteSegment *segment)
882 {
883         g_return_val_if_fail(segment, NULL);
884
885         return segment->step;
886 }
887
888 EXPORT_API gboolean
889 location_route_segment_set_start_point (LocationRouteSegment *segment, const LocationPosition *start)
890 {
891         g_return_val_if_fail (segment, FALSE);
892
893         if (segment->start) {
894                 location_position_free(segment->start);
895                 segment->start = NULL;
896         }
897
898         if (start) segment->start = location_position_copy (start);
899
900         return TRUE;
901 }
902
903 EXPORT_API gboolean
904 location_route_segment_set_end_point (LocationRouteSegment *segment, const LocationPosition *end)
905 {
906         g_return_val_if_fail (segment, FALSE);
907
908         if (segment->end) {
909                 location_position_free(segment->end);
910                 segment->end = NULL;
911         }
912
913         if (end) segment->end = location_position_copy (end);
914
915         return TRUE;
916
917 }
918
919 EXPORT_API gboolean
920 location_route_segment_set_bounding_box (LocationRouteSegment *segment, const LocationBoundary *bbox)
921 {
922         g_return_val_if_fail (segment, FALSE);
923
924         if (segment->bbox) {
925                 location_boundary_free(segment->bbox);
926                 segment->bbox = NULL;
927         }
928
929         if (bbox) segment->bbox = location_boundary_copy (bbox);
930
931         return TRUE;
932 }
933
934 EXPORT_API gboolean
935 location_route_segment_set_distance (LocationRouteSegment *segment, gdouble distance)
936 {
937         g_return_val_if_fail (segment, FALSE);
938
939         segment->distance = distance;
940
941         return TRUE;
942 }
943
944 EXPORT_API gboolean
945 location_route_segment_set_duration (LocationRouteSegment *segment, glong duration)
946 {
947         g_return_val_if_fail (segment, FALSE);
948
949         segment->duration = duration;
950
951         return TRUE;
952 }
953
954 EXPORT_API gboolean
955 location_route_segment_set_property (LocationRouteSegment *segment, gconstpointer key, gconstpointer value)
956 {
957         g_return_val_if_fail (segment, FALSE);
958         g_return_val_if_fail (key, FALSE);
959         if (!segment->properties) return FALSE;
960
961         if (value) {
962                 gchar *re_key = g_strdup (key);
963                 gchar *re_val = g_strdup (value);
964                 g_hash_table_insert(segment->properties, re_key, re_val);
965         } else g_hash_table_remove (segment->properties, key);
966
967         return TRUE;
968 }
969
970 static void route_step_foreach_free (gpointer data)
971 {
972         g_return_if_fail (data);
973
974         LocationRouteStep *step = (LocationRouteStep *) data;
975
976         location_route_step_free(step);
977 }
978
979 static void route_step_foreach_copy (gpointer data, gpointer user_data)
980 {
981         g_return_if_fail (data);
982         g_return_if_fail (user_data);
983
984         LocationRouteStep *step = (LocationRouteStep *) data;
985         LocationRouteSegment *segment = (LocationRouteSegment *) user_data;
986
987         LocationRouteStep *step_new = location_route_step_copy(step);
988         segment->step = g_list_append(segment->step, step_new);
989
990 }
991
992 EXPORT_API gboolean
993 location_route_segment_set_route_step (LocationRouteSegment *segment, GList* step)
994 {
995         g_return_val_if_fail (segment, FALSE);
996
997         if (segment->step) {
998                 g_list_free_full (segment->step, route_step_foreach_free);
999                 segment->step = NULL;
1000         }
1001
1002         if (step) g_list_foreach (step, route_step_foreach_copy, segment);
1003
1004         return TRUE;
1005
1006 }
1007
1008 EXPORT_API LocationRouteSegment *
1009 location_route_segment_new (void)
1010 {
1011         LocationRouteSegment *segment = g_slice_new0 (LocationRouteSegment);
1012         g_return_val_if_fail (segment, NULL);
1013
1014         segment->properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1015
1016         return segment;
1017 }
1018
1019 static void segment_property_copy_cb (gpointer key, gpointer value, gpointer user_data)
1020 {
1021         g_return_if_fail (key);
1022         g_return_if_fail (value);
1023         g_return_if_fail (user_data);
1024
1025         LocationRouteSegment *segment = (LocationRouteSegment *)user_data;
1026
1027         if (segment->properties) {
1028                 gchar *re_key = g_strdup (key);
1029                 gchar *re_val = g_strdup (value);
1030                 g_hash_table_insert (segment->properties, re_key, re_val);
1031         }
1032 }
1033
1034 EXPORT_API LocationRouteSegment *
1035 location_route_segment_copy (LocationRouteSegment *segment)
1036 {
1037         g_return_val_if_fail(segment, NULL);
1038
1039         LocationRouteSegment *new_segment = location_route_segment_new();
1040         g_return_val_if_fail(new_segment, NULL);
1041
1042         location_route_segment_set_start_point(new_segment, location_route_segment_get_start_point(segment));
1043         location_route_segment_set_end_point(new_segment, location_route_segment_get_end_point(segment));
1044         location_route_segment_set_bounding_box(new_segment, location_route_segment_get_bounding_box(segment));
1045         location_route_segment_set_distance(new_segment, location_route_segment_get_distance(segment));
1046         location_route_segment_set_duration(new_segment, location_route_segment_get_duration(segment));
1047         location_route_segment_set_route_step(new_segment, location_route_segment_get_route_step(segment));
1048
1049         if (segment->properties) g_hash_table_foreach (segment->properties, segment_property_copy_cb, new_segment);
1050
1051         return new_segment;
1052 }
1053
1054 EXPORT_API void
1055 location_route_segment_free (LocationRouteSegment *segment)
1056 {
1057         g_return_if_fail(segment);
1058
1059         location_route_segment_set_start_point(segment, NULL);
1060         location_route_segment_set_end_point(segment, NULL);
1061         location_route_segment_set_bounding_box(segment, NULL);
1062         location_route_segment_set_distance(segment, 0.0);
1063         location_route_segment_set_duration(segment, 0);
1064         location_route_segment_set_route_step(segment, NULL);
1065
1066         if (segment->properties) {
1067                 g_hash_table_destroy (segment->properties);
1068                 segment->properties = NULL;
1069         }
1070
1071         g_slice_free(LocationRouteSegment, segment);
1072 }
1073
1074 EXPORT_API LocationPosition*
1075 location_route_step_get_start_point (const LocationRouteStep *step)
1076 {
1077         g_return_val_if_fail(step, NULL);
1078
1079         return step->start;
1080 }
1081
1082 EXPORT_API LocationPosition*
1083 location_route_step_get_end_point (const LocationRouteStep *step)
1084 {
1085         g_return_val_if_fail(step, NULL);
1086
1087         return step->end;
1088 }
1089
1090 EXPORT_API LocationBoundary*
1091 location_route_step_get_bounding_box (const LocationRouteStep *step)
1092 {
1093         g_return_val_if_fail(step, NULL);
1094
1095         return step->bbox;
1096 }
1097
1098 EXPORT_API gdouble
1099 location_route_step_get_distance (const LocationRouteStep *step)
1100 {
1101         g_return_val_if_fail(step, 0.0);
1102
1103         return step->distance;
1104 }
1105
1106 EXPORT_API glong
1107 location_route_step_get_duration (const LocationRouteStep *step)
1108 {
1109         g_return_val_if_fail(step, 0);
1110
1111         return step->duration;
1112 }
1113
1114 EXPORT_API gchar*
1115 location_route_step_get_transport_mode (const LocationRouteStep *step)
1116 {
1117         g_return_val_if_fail(step, NULL);
1118
1119         return step->transport_mode;
1120 }
1121
1122 EXPORT_API gchar*
1123 location_route_step_get_instruction (const LocationRouteStep *step)
1124 {
1125         g_return_val_if_fail(step, NULL);
1126
1127         return step->instruction;
1128 }
1129
1130 EXPORT_API GList *
1131 location_route_step_get_geometry (const LocationRouteStep *step)
1132 {
1133         g_return_val_if_fail(step, NULL);
1134
1135         return step->geometry;
1136 }
1137
1138 EXPORT_API GList*
1139 location_route_step_get_property_key (const LocationRouteStep *step)
1140 {
1141         g_return_val_if_fail(step, NULL);
1142
1143         return g_hash_table_get_keys (step->properties);
1144 }
1145
1146 EXPORT_API gpointer
1147 location_route_step_get_property (const LocationRouteStep *step, gconstpointer key)
1148 {
1149         g_return_val_if_fail(step, NULL);
1150         g_return_val_if_fail(key, NULL);
1151
1152         return g_hash_table_lookup (step->properties, key);
1153 }
1154
1155 EXPORT_API gboolean
1156 location_route_step_set_start_point (LocationRouteStep *step, const LocationPosition *start)
1157 {
1158         g_return_val_if_fail (step, FALSE);
1159
1160         if (step->start) {
1161                 location_position_free (step->start);
1162                 step->start = NULL;
1163         }
1164
1165         if (start) step->start = location_position_copy (start);
1166
1167         return TRUE;
1168 }
1169
1170 EXPORT_API gboolean
1171 location_route_step_set_end_point (LocationRouteStep *step, const LocationPosition *end)
1172 {
1173         g_return_val_if_fail (step, FALSE);
1174
1175         if (step->end) {
1176                 location_position_free (step->end);
1177                 step->end = NULL;
1178         }
1179
1180         if (end) step->end = location_position_copy (end);
1181
1182         return TRUE;
1183 }
1184
1185 EXPORT_API gboolean
1186 location_route_step_set_bounding_box (LocationRouteStep *step, const LocationBoundary *bbox)
1187 {
1188         g_return_val_if_fail (step, FALSE);
1189
1190         if (step->bbox) {
1191                 location_boundary_free (step->bbox);
1192                 step->bbox = NULL;
1193         }
1194
1195         if (bbox) step->bbox = location_boundary_copy (bbox);
1196
1197         return TRUE;
1198 }
1199
1200 EXPORT_API gboolean
1201 location_route_step_set_distance (LocationRouteStep *step, gdouble distance)
1202 {
1203         g_return_val_if_fail (step, FALSE);
1204
1205         step->distance = distance;
1206
1207         return TRUE;
1208
1209 }
1210
1211 EXPORT_API gboolean
1212 location_route_step_set_duration (LocationRouteStep *step, glong duration)
1213 {
1214         g_return_val_if_fail (step, FALSE);
1215
1216         step->duration = duration;
1217
1218         return TRUE;
1219 }
1220
1221 EXPORT_API gboolean
1222 location_route_step_set_transport_mode (LocationRouteStep *step, const gchar *transport_mode)
1223 {
1224         g_return_val_if_fail (step, FALSE);
1225
1226         if (step->transport_mode) {
1227                 g_free(step->transport_mode);
1228                 step->transport_mode = NULL;
1229         }
1230
1231         if (transport_mode) step->transport_mode = g_strdup(transport_mode);
1232
1233         return TRUE;
1234
1235 }
1236
1237 EXPORT_API gboolean
1238 location_route_step_set_instruction (LocationRouteStep *step, const gchar *instruction)
1239 {
1240         g_return_val_if_fail (step, FALSE);
1241
1242         if (step->instruction) {
1243                 g_free(step->instruction);
1244                 step->instruction = NULL;
1245         }
1246
1247         if (instruction) step->instruction = g_strdup(instruction);
1248
1249         return TRUE;
1250
1251 }
1252
1253 static void route_step_geometry_foreach_copy (gpointer data, gpointer user_data)
1254 {
1255         g_return_if_fail (data);
1256         g_return_if_fail (user_data);
1257
1258         LocationPosition *pos = (LocationPosition *)data;
1259         LocationRouteStep *step = (LocationRouteStep *)user_data;
1260
1261         step->geometry = g_list_append (step->geometry, location_position_copy (pos));
1262 }
1263
1264 static void route_step_geometry_free (gpointer data)
1265 {
1266         g_return_if_fail (data);
1267
1268         LocationPosition *pos = (LocationPosition *)data;
1269
1270         location_position_free(pos);
1271 }
1272
1273 EXPORT_API gboolean
1274 location_route_step_set_geometry (LocationRouteStep *step, GList *geometry)
1275 {
1276         g_return_val_if_fail (step, FALSE);
1277
1278         if (step->geometry) {
1279                 g_list_free_full (step->geometry, route_step_geometry_free);
1280                 step->geometry = NULL;
1281         }
1282
1283         if (geometry) g_list_foreach (geometry, route_step_geometry_foreach_copy, step);
1284
1285         return TRUE;
1286
1287 }
1288
1289 EXPORT_API gboolean
1290 location_route_step_set_property (LocationRouteStep *step, gconstpointer key, gconstpointer value)
1291 {
1292         g_return_val_if_fail(step, FALSE);
1293         g_return_val_if_fail(key, FALSE);
1294
1295         if (!step->properties) return FALSE;
1296
1297         if (value) {
1298                 gchar *re_key = g_strdup (key);
1299                 gchar *re_val = g_strdup (value);
1300                 g_hash_table_insert (step->properties, re_key, re_val);
1301         }
1302         else g_hash_table_remove (step->properties, key);
1303
1304         return TRUE;
1305 }
1306
1307 EXPORT_API LocationRouteStep *
1308 location_route_step_new (void)
1309 {
1310         LocationRouteStep *step = g_slice_new0 (LocationRouteStep);
1311         g_return_val_if_fail(step, NULL);
1312
1313         step->properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1314
1315         return step;
1316 }
1317
1318 static void step_property_copy_cb (gpointer key, gpointer value, gpointer user_data)
1319 {
1320         g_return_if_fail (key);
1321         g_return_if_fail (value);
1322         g_return_if_fail (user_data);
1323
1324         LocationRouteStep *step = (LocationRouteStep *) user_data;
1325
1326         if (step->properties) {
1327                 gchar *re_key = g_strdup (key);
1328                 gchar *re_val = g_strdup (value);
1329                 g_hash_table_insert (step->properties, re_key, re_val);
1330         }
1331 }
1332
1333
1334 EXPORT_API LocationRouteStep *
1335 location_route_step_copy (LocationRouteStep *step)
1336 {
1337         g_return_val_if_fail(step, NULL);
1338
1339         LocationRouteStep *new_step = location_route_step_new ();
1340         g_return_val_if_fail (new_step, NULL);
1341
1342         location_route_step_set_start_point (new_step, location_route_step_get_start_point(step));
1343         location_route_step_set_end_point (new_step, location_route_step_get_end_point(step));
1344         location_route_step_set_bounding_box (new_step, location_route_step_get_bounding_box(step));
1345         location_route_step_set_distance (new_step, location_route_step_get_distance(step));
1346         location_route_step_set_duration (new_step, location_route_step_get_duration(step));
1347         location_route_step_set_instruction (new_step, location_route_step_get_instruction(step));
1348         location_route_step_set_geometry (new_step, location_route_step_get_geometry(step));
1349
1350         if (step->properties) g_hash_table_foreach (step->properties, step_property_copy_cb, new_step);
1351         return new_step;
1352 }
1353
1354 EXPORT_API void
1355 location_route_step_free (LocationRouteStep *step)
1356 {
1357         g_return_if_fail(step);
1358
1359         location_route_step_set_start_point (step, NULL);
1360         location_route_step_set_end_point (step, NULL);
1361         location_route_step_set_bounding_box (step, NULL);
1362         location_route_step_set_distance (step, 0.0);
1363         location_route_step_set_duration (step, 0);
1364         location_route_step_set_instruction (step, NULL);
1365         location_route_step_set_geometry (step, NULL);
1366
1367         if (step->properties) {
1368                 g_hash_table_destroy (step->properties);
1369                 step->properties = NULL;
1370         }
1371         g_slice_free(LocationRouteStep, step);
1372 }