upload tizen1.0 source
[framework/api/poi.git] / src / poi.c
1 /*
2 * Copyright (c) 2011 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
18 #include <location/location.h>
19 #include <poi.h>
20 #include <poi_private.h>
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <dlog.h>
26
27 #ifdef LOG_TAG
28 #undef LOG_TAG
29 #endif
30 #define LOG_TAG "TIZEN_N_POI"
31
32 #define POI_CHECK_CONDITION(condition,error,msg)        \
33                 do{ \
34                         if( !(condition) ){     \
35                                 LOGE("[%s] %s(0x%08x)",__FUNCTION__, msg,error); return error;  \
36                         } \
37                 }while(0)
38
39 #define POI_PRINT_ERROR_CODE_RETURN(code) \
40         do{\
41                 LOGE("[%s] %s(0x%08x)",__FUNCTION__, #code,code); return code;  \
42         }while(0)
43
44
45 #define POI_NULL_ARG_CHECK(arg) \
46         POI_CHECK_CONDITION( (arg !=NULL),POI_ERROR_INVALID_PARAMETER,"POI_ERROR_INVALID_PARAMETER")
47
48
49 typedef struct {
50         void *data;
51         poi_service_search_cb callback;
52 }__callback_data;
53
54 /*
55 * Internal Implementation
56 */
57 static int _convert_error_code(int code, const char* func_name)
58 {
59         int ret;
60         char* msg = "POI_ERROR_NONE";
61         switch(code)
62         {
63                 case LOCATION_ERROR_NONE:
64                         ret = POI_ERROR_NONE;
65                         msg = "POI_ERROR_NONE";
66                         break;
67                 case LOCATION_ERROR_NETWORK_FAILED:
68                 case LOCATION_ERROR_NETWORK_NOT_CONNECTED:
69                         ret = POI_ERROR_NETWORK_FAILED;
70                         msg = "POI_ERROR_NETWORK_FAILED";
71                         break;
72                 case LOCATION_ERROR_PARAMETER:
73                         ret = POI_ERROR_INVALID_PARAMETER;
74                         msg = "POI_ERROR_INVALID_PARAMETER";
75                         break;
76                 case LOCATION_ERROR_NOT_FOUND:
77                         ret = POI_ERROR_RESULT_NOT_FOUND;
78                         msg = "POI_ERROR_RESULT_NOT_FOUND";
79                         break;                  
80                 case LOCATION_ERROR_NOT_ALLOWED:
81                 case LOCATION_ERROR_NOT_AVAILABLE:
82                 case LOCATION_ERROR_CONFIGURATION:
83                 case LOCATION_ERROR_UNKNOWN:
84                 default:
85                         msg = "POI_ERROR_SERVICE_NOT_AVAILABLE";
86                         ret = POI_ERROR_SERVICE_NOT_AVAILABLE;  
87         }
88         LOGE("[%s] %s(0x%08x) : core fw error(0x%x)",func_name,msg, ret, code);
89         return ret;     
90 }
91
92 static void __LocationPOICB(LocationError error, guint req_id, GList * landmark_list, gchar * error_code, gchar * error_msg, gpointer userdata)
93 {
94         __callback_data * callback = (__callback_data*)userdata;
95         if( callback == NULL || callback->callback == NULL)
96                 return ;
97         
98         int ret = _convert_error_code(error,"search_callback");
99         GList *mark_list = landmark_list;
100         int length = 0;
101         int index = 0;
102         
103         if( mark_list == NULL || ret != 0){
104                 callback->callback(ret , req_id, index, length, NULL, callback->data);
105                 free(callback);
106                 return;
107         }
108         
109         length = g_list_length(mark_list);
110         while( mark_list) {
111                 LocationLandmark *mark = mark_list->data;
112                 if( callback->callback(ret, req_id, index++, length, mark, callback->data) == false )
113                         break;
114                 mark_list = mark_list->next;
115         }
116
117         free(callback);
118                 
119 }
120
121
122
123 int poi_service_create( poi_service_h *poi)
124 {
125         if( poi == NULL)
126                 POI_PRINT_ERROR_CODE_RETURN(POI_ERROR_INVALID_PARAMETER);
127
128         if( location_init() != LOCATION_ERROR_NONE )
129         {
130                 LOGE("[%s] POI_ERROR_SERVICE_NOT_AVAILABLE(0x%08x) : fail to location_init", __FUNCTION__, POI_ERROR_SERVICE_NOT_AVAILABLE);
131                 return POI_ERROR_SERVICE_NOT_AVAILABLE;
132         }
133         
134         poi_service_s *handle = (poi_service_s*)malloc(sizeof(poi_service_s));
135         if( handle == NULL)
136                 POI_PRINT_ERROR_CODE_RETURN(POI_ERROR_OUT_OF_MEMORY);
137
138         memset(handle, 0 , sizeof(poi_service_s));
139
140         if( POI_ERROR_NONE != poi_preference_create(&handle->preference ) ){
141                 free(handle);
142                 POI_PRINT_ERROR_CODE_RETURN(POI_ERROR_OUT_OF_MEMORY);
143         }
144
145         handle->object = location_new(LOCATION_METHOD_HYBRID);
146         if(handle->object  == NULL)
147         {
148                 free(handle);
149                 LOGE("[%s] POI_ERROR_SERVICE_NOT_AVAILABLE(0x%08x) : fail to location_new", __FUNCTION__, POI_ERROR_SERVICE_NOT_AVAILABLE);
150                 return POI_ERROR_SERVICE_NOT_AVAILABLE;
151         }       
152
153         *poi = (poi_service_h)handle;
154         return POI_ERROR_NONE;
155 }
156
157
158 int poi_service_destroy(poi_service_h poi)
159 {
160         if( poi == NULL)
161                 POI_PRINT_ERROR_CODE_RETURN(POI_ERROR_INVALID_PARAMETER);
162
163         poi_service_s *handle = (poi_service_s*)poi;
164
165         if( handle->preference ){
166                 poi_preference_destroy(handle->preference);
167                 handle->preference = NULL;
168         }
169
170         int ret = location_free(handle->object);
171         if(ret!= POI_ERROR_NONE)
172         {
173                 return _convert_error_code(ret,__FUNCTION__);
174         }
175         free(handle);
176         return POI_ERROR_NONE;
177
178 }
179
180 int poi_service_set_preference(poi_service_h poi , poi_preference_h preference)
181 {
182         POI_NULL_ARG_CHECK(poi);
183         POI_NULL_ARG_CHECK(preference); 
184         
185         poi_service_s *handle = (poi_service_s*)poi;
186
187         if( handle->preference ){
188                 poi_preference_destroy(handle->preference);
189                 handle->preference = (poi_preference_h)location_poi_pref_copy((LocationPOIPreference*)preference);
190         }
191         return POI_ERROR_NONE;
192 }
193
194 int poi_service_get_preference(poi_service_h poi , poi_preference_h *preference)
195 {
196         POI_NULL_ARG_CHECK(poi);
197         POI_NULL_ARG_CHECK(preference); 
198         poi_service_s *handle = (poi_service_s*)poi;
199
200         if( handle->preference == NULL ){
201                 poi_preference_create(&handle->preference );
202         }       
203         *preference = (poi_preference_h)location_poi_pref_copy((LocationPOIPreference*)handle->preference);
204         return POI_ERROR_NONE;
205 }
206
207 int poi_service_search(poi_service_h poi, location_coords_s position, int distance , poi_filter_h filter, poi_service_search_cb callback, void * user_data, int * request_id)
208 {
209         POI_NULL_ARG_CHECK(poi);
210         POI_NULL_ARG_CHECK(callback);
211         POI_CHECK_CONDITION(distance >= 0 , POI_ERROR_INVALID_PARAMETER, "distance value is negative");
212         POI_CHECK_CONDITION(position.latitude>=-90 && position.latitude<=90 ,POI_ERROR_INVALID_PARAMETER,"latitude should be -90 <= latitude <= 90");
213         POI_CHECK_CONDITION(position.longitude>=-180 && position.longitude<=180,POI_ERROR_INVALID_PARAMETER,"longitude should be -180 <= latitude <= 180");
214
215
216         LocationPosition pos;
217         unsigned int reqid;     
218         int ret;
219
220         poi_service_s *handle = (poi_service_s*)poi;
221         pos.latitude = position.latitude;
222         pos.longitude = position.longitude;
223         pos.altitude = 0;
224         pos.status = LOCATION_STATUS_2D_FIX;
225
226
227         __callback_data * calldata = (__callback_data *)malloc(sizeof(__callback_data));
228         if( calldata == NULL)
229                 POI_PRINT_ERROR_CODE_RETURN(POI_ERROR_OUT_OF_MEMORY);
230
231         calldata->callback = callback;
232         calldata->data = user_data;
233
234         if( distance != 0 ){
235                 char distance_str[255];
236                 snprintf(distance_str, 255, "%d", distance);
237                 poi_preference_set(handle->preference, "Distance", distance_str);
238         }else{
239                 poi_preference_set(handle->preference, "Distance", NULL);
240         }
241
242
243         ret = location_search_poi (handle->object , (LocationPOIFilter*)filter , &pos, (LocationPOIPreference *)handle->preference, __LocationPOICB, calldata, &reqid);
244         if( ret != 0 ){
245                 free(calldata);
246                 return _convert_error_code(ret, __func__);
247         }
248
249         if( request_id )
250                 *request_id = reqid;    
251         return POI_ERROR_NONE;
252
253 }
254
255
256 int poi_service_search_by_area (poi_service_h poi, location_bounds_h boundary , poi_filter_h filter, poi_service_search_cb callback, void * user_data, int * request_id)
257 {
258         POI_NULL_ARG_CHECK(poi);
259         POI_NULL_ARG_CHECK(callback);
260         POI_NULL_ARG_CHECK(boundary);
261         
262         unsigned int reqid;     
263         int ret;
264         poi_service_s *handle = (poi_service_s*)poi;
265         location_bounds_type_e bound_type;
266         location_bounds_get_type(boundary, &bound_type);
267         
268         if( bound_type == LOCATION_BOUNDS_RECT ){
269                 if( !location_is_supported_map_provider_capability(handle->object , MAP_SERVICE_POI_SEARCH_BY_RECT_BOUNDARY) )
270                         return POI_ERROR_SERVICE_NOT_AVAILABLE;
271         }else if(bound_type == LOCATION_BOUNDS_CIRCLE){
272                 if( !location_is_supported_map_provider_capability(handle->object , MAP_SERVICE_POI_SEARCH_BY_CIRCLE_BOUNDARY) )
273                         return POI_ERROR_SERVICE_NOT_AVAILABLE; 
274         }else if(bound_type == LOCATION_BOUNDS_CIRCLE){
275                 if( !location_is_supported_map_provider_capability(handle->object , MAP_SERVICE_POI_SEARCH_BY_POLYGON_BOUNDARY) )
276                         return POI_ERROR_SERVICE_NOT_AVAILABLE;         
277         }
278         
279         __callback_data * calldata = (__callback_data *)malloc(sizeof(__callback_data));
280         if( calldata == NULL)
281                 POI_PRINT_ERROR_CODE_RETURN(POI_ERROR_OUT_OF_MEMORY);
282
283         calldata->callback = callback;
284         calldata->data = user_data;
285
286         poi_preference_set(handle->preference, "Distance", NULL);
287
288         ret = location_search_poi_by_area (handle->object , (LocationPOIFilter*)filter , (LocationBoundary *)boundary, (LocationPOIPreference *)handle->preference, __LocationPOICB, calldata, &reqid);
289         if( ret != 0 ){
290                 free(calldata);
291                 return _convert_error_code(ret, __func__);
292         }
293         
294         if( request_id )
295                 *request_id = reqid;    
296         return POI_ERROR_NONE;
297
298 }
299
300 int poi_service_search_by_address(poi_service_h poi, const char* address, int distance, poi_filter_h filter, poi_service_search_cb callback, void * user_data, int * request_id)
301 {
302         POI_NULL_ARG_CHECK(poi);
303         POI_NULL_ARG_CHECK(callback);
304         POI_CHECK_CONDITION(distance >= 0 , POI_ERROR_INVALID_PARAMETER, "distance value is negative");
305
306         
307         unsigned int reqid;     
308         int ret;
309         poi_service_s *handle = (poi_service_s*)poi;
310
311                 __callback_data * calldata = (__callback_data *)malloc(sizeof(__callback_data));
312         if( calldata == NULL)
313                 POI_PRINT_ERROR_CODE_RETURN(POI_ERROR_OUT_OF_MEMORY);
314
315         calldata->callback = callback;
316         calldata->data = user_data;
317
318         if( distance != 0 ){
319                 char distance_str[255];
320                 snprintf(distance_str, 255, "%d", distance);
321                 poi_preference_set(handle->preference, "Distance", distance_str);
322         }else{
323                 poi_preference_set(handle->preference, "Distance", NULL);
324         }       
325
326         ret = location_search_poi_by_freeformed_address (handle->object , (LocationPOIFilter*)filter , address, (LocationPOIPreference *)handle->preference, __LocationPOICB, calldata, &reqid);
327
328         if( ret != 0 ){
329                 free(calldata);
330                 return _convert_error_code(ret, __func__);
331         }
332         
333         if( request_id )
334                 *request_id = reqid;    
335         return POI_ERROR_NONE;
336
337 }
338
339 int poi_service_cancel(poi_service_h service, int request_id)
340 {
341         POI_NULL_ARG_CHECK(service);
342
343         poi_service_s *handle = (poi_service_s*)service;
344         return _convert_error_code(location_cancel_poi_request(handle->object, request_id), __func__);
345 }
346
347 int poi_filter_create(poi_filter_h *filter)
348 {
349         POI_NULL_ARG_CHECK(filter);
350         
351         LocationPOIFilter *native_filter = location_poi_filter_new();
352         POI_CHECK_CONDITION( (native_filter != NULL) , POI_ERROR_OUT_OF_MEMORY, "POI_ERROR_OUT_OF_MEMORY");
353         *filter = (void*)native_filter;
354         return POI_ERROR_NONE;  
355 }
356 int poi_filter_destroy(poi_filter_h filter)
357 {
358         POI_NULL_ARG_CHECK(filter);
359         location_poi_filter_free((LocationPOIFilter*)filter);
360         return POI_ERROR_NONE;
361 }
362 int poi_filter_set(poi_filter_h filter, const char* key, const char* value)
363 {
364         POI_NULL_ARG_CHECK(filter);
365         POI_NULL_ARG_CHECK(key);
366         int ret = location_poi_filter_set((LocationPOIFilter*)filter , key, value);
367         if( !ret )
368                 return POI_ERROR_INVALID_KEY;
369         return POI_ERROR_NONE;  
370 }
371 int poi_filter_get(poi_filter_h filter, const char* key, char** value)
372 {
373         POI_NULL_ARG_CHECK(filter);
374         POI_NULL_ARG_CHECK(key);
375         POI_NULL_ARG_CHECK(value);
376         char *v = (char*)location_poi_filter_get((LocationPOIFilter*)filter, key);
377         if ( v  == NULL )
378                 POI_PRINT_ERROR_CODE_RETURN(POI_ERROR_INVALID_KEY);
379
380         *value = strdup(v);
381         return POI_ERROR_NONE;
382 }
383
384 int poi_filter_foreach_properties(poi_filter_h filter, poi_filter_properties_cb callback , void * user_data)
385 {
386         POI_NULL_ARG_CHECK(filter);
387         POI_NULL_ARG_CHECK(callback);
388
389         GList *keys = location_poi_filter_get_key((LocationPOIFilter*)filter);
390         while(keys){
391                 char *key = keys->data;
392                 char *value = location_poi_filter_get((LocationPOIFilter*)filter, key);
393                 if(!callback(key,value, user_data))
394                         break;
395                 keys = keys->next;
396         }
397          g_list_free(keys);
398         return POI_ERROR_NONE;  
399 }
400
401 int poi_filter_foreach_available_keys( poi_service_h poi, poi_filter_available_key_cb callback , void * user_data)
402 {
403         POI_NULL_ARG_CHECK(poi);
404         POI_NULL_ARG_CHECK(callback);
405
406         GList *keys=NULL;
407         location_get_map_provider_capability_key((LocationObject*)poi, MAP_SERVICE_POI_FILTER, &keys);
408         if( keys == NULL )
409                 return POI_ERROR_RESULT_NOT_FOUND;
410
411         while(keys){
412                 char *key = keys->data;
413                 if( !callback(key,user_data) )
414                         break;
415                 keys = keys->next;
416         }
417         g_list_free_full (keys, g_free);        
418         return POI_ERROR_NONE;
419 }
420
421 int poi_filter_foreach_available_values( poi_service_h poi, const char *key, poi_filter_available_value_cb callback , void * user_data)
422 {
423         //TODO. 
424         // Available category
425         return POI_ERROR_RESULT_NOT_FOUND;
426 }
427
428 int poi_preference_create(poi_preference_h *preference )
429 {
430         POI_NULL_ARG_CHECK(preference);
431         LocationPOIPreference *pref;
432         pref =  location_poi_pref_new();
433         if( pref == NULL)
434                 POI_PRINT_ERROR_CODE_RETURN(POI_ERROR_OUT_OF_MEMORY);
435         *preference = pref;
436
437         return POI_ERROR_NONE;
438 }
439
440 int poi_preference_destroy(poi_preference_h preference )
441 {
442         POI_NULL_ARG_CHECK(preference);
443         location_poi_pref_free((LocationPOIPreference*)preference);
444         return POI_ERROR_NONE;
445 }
446
447 int poi_preference_foreach_properties( poi_preference_h preference, poi_preference_properties_cb callback , void * user_data)
448 {
449         POI_NULL_ARG_CHECK(preference);
450         POI_NULL_ARG_CHECK(callback);
451
452         GList *keys = location_poi_pref_get_property_key((LocationPOIPreference*)preference);
453         while(keys){
454                 char *key = keys->data;
455                 char *value = location_poi_pref_get_property((LocationPOIPreference*)preference, key);
456                 if(!callback(key,value, user_data))
457                         break;
458                 keys = keys->next;
459         }
460          g_list_free(keys);
461         return POI_ERROR_NONE;  
462 }
463
464 int poi_preference_foreach_available_keys( poi_service_h poi,  poi_preference_available_key_cb callback , void * user_data)
465 {
466         POI_NULL_ARG_CHECK(poi);
467         POI_NULL_ARG_CHECK(callback);
468
469         GList *keys=NULL;
470         location_get_map_provider_capability_key((LocationObject*)poi, MAP_SERVICE_POI_PREF_PROPERTY, &keys);
471         if( keys == NULL )
472                 return POI_ERROR_RESULT_NOT_FOUND;
473
474         while(keys){
475                 char *key = keys->data;
476                 if( !callback(key,user_data) )
477                         break;
478                 keys = keys->next;
479         }
480         g_list_free_full (keys, g_free);        
481         return POI_ERROR_NONE;
482 }
483
484 int poi_preference_foreach_available_values( poi_service_h poi, const char *key,  poi_preference_available_value_cb callback , void * user_data)
485 {
486         //TODO. impl..
487         // Availiable LandmarkType 
488         // Availiable LandmarkName      
489         return POI_ERROR_RESULT_NOT_FOUND;
490 }
491
492 int poi_preference_get(poi_preference_h preference, const char *key, char **value)
493 {
494         POI_NULL_ARG_CHECK(preference);
495         POI_NULL_ARG_CHECK(key);
496         POI_NULL_ARG_CHECK(value);
497         char *v = (char*)location_poi_pref_get_property((LocationPOIPreference*)preference, key);
498         if( v == NULL )
499                 POI_PRINT_ERROR_CODE_RETURN(POI_ERROR_INVALID_KEY);
500         *value = strdup(v);
501         return POI_ERROR_NONE;
502 }
503
504 int poi_preference_set(poi_preference_h preference, const char *key, const char *value)
505 {
506         POI_NULL_ARG_CHECK(preference);
507         POI_NULL_ARG_CHECK(key);
508
509         int ret = location_poi_pref_set_property((LocationPOIPreference*)preference,key, value);
510         if( !ret )
511                 POI_PRINT_ERROR_CODE_RETURN(POI_ERROR_INVALID_KEY);
512         return POI_ERROR_NONE;
513 }
514
515 int poi_preference_set_max_result(poi_preference_h preference, int max_result)
516 {
517         POI_NULL_ARG_CHECK(preference);
518         int ret = location_poi_pref_set_max_result((LocationPOIPreference*)preference, max_result);
519         if( !ret )
520                 POI_PRINT_ERROR_CODE_RETURN(POI_ERROR_INVALID_PARAMETER);
521         return POI_ERROR_NONE;  
522 }
523
524 int poi_preference_get_max_result(poi_preference_h preference, int* max_result)
525 {
526         POI_NULL_ARG_CHECK(preference);
527         POI_NULL_ARG_CHECK(max_result);
528         int ret = location_poi_pref_get_max_result((LocationPOIPreference*)preference );
529         if( ret == 0 )
530                 POI_PRINT_ERROR_CODE_RETURN(POI_ERROR_INVALID_PARAMETER);
531         *max_result = ret;
532         return POI_ERROR_NONE;  
533 }
534
535
536 int poi_preference_foreach_sortable_field( poi_service_h poi, poi_preference_sortable_field_cb callback , void * user_data)
537 {
538         POI_NULL_ARG_CHECK(poi);
539         POI_NULL_ARG_CHECK(callback);
540
541         GList *keys=NULL;
542         location_get_map_provider_capability_key((LocationObject*)poi, MAP_SERVICE_POI_PREF_SORT_BY, &keys);
543         if( keys == NULL )
544                 return POI_ERROR_RESULT_NOT_FOUND;
545
546         while(keys){
547                 char *key = keys->data;
548                 if( !callback(key,user_data) )
549                         break;
550                 keys = keys->next;
551         }
552         g_list_free_full (keys, g_free);        
553         return POI_ERROR_NONE;
554 }
555
556 int poi_preference_set_sort(poi_preference_h preference , const char* field , poi_sort_order_e order)
557 {
558         POI_NULL_ARG_CHECK(preference);
559         POI_NULL_ARG_CHECK(field);
560         int ret = location_poi_pref_set_sort_by((LocationPOIPreference*)preference, field);
561         if( !ret )
562                 POI_PRINT_ERROR_CODE_RETURN(POI_ERROR_INVALID_PARAMETER);
563         ret = location_poi_pref_set_sort_order ((LocationPOIPreference*)preference , order);
564         if( !ret )
565                 POI_PRINT_ERROR_CODE_RETURN(POI_ERROR_INVALID_PARAMETER);
566
567         return POI_ERROR_NONE;
568 }
569
570 int poi_preference_get_sort(poi_preference_h preference , char** field,  poi_sort_order_e *order)
571 {
572         POI_NULL_ARG_CHECK(preference);
573         POI_NULL_ARG_CHECK(field);
574         POI_NULL_ARG_CHECK(order);
575         char *sort_by = (char*)location_poi_pref_get_sort_by((LocationPOIPreference*)preference);
576         if( sort_by )
577                 *field = strdup(sort_by);
578         else
579                 *field = NULL;
580         
581         *order  = location_poi_pref_get_sort_order((LocationPOIPreference*)preference);
582         return POI_ERROR_NONE;
583 }
584
585 int poi_create(poi_h *poi)
586 {
587         POI_NULL_ARG_CHECK(poi);
588         LocationLandmark* landmark = location_landmark_new();
589         if( landmark == NULL)
590                 POI_PRINT_ERROR_CODE_RETURN(POI_ERROR_OUT_OF_MEMORY);
591
592         *poi = landmark;
593         return POI_ERROR_NONE;
594 }
595
596 int poi_destroy(poi_h poi)
597 {
598         POI_NULL_ARG_CHECK(poi);
599         location_landmark_free((LocationLandmark*)poi);
600         return POI_ERROR_NONE;
601 }
602
603 int poi_clone(poi_h* cloned, poi_h origin)
604 {
605         POI_NULL_ARG_CHECK(cloned);
606         POI_NULL_ARG_CHECK(origin);
607         
608         LocationLandmark * landmark = location_landmark_copy ((LocationLandmark*)origin);
609         if( landmark == NULL)
610                 POI_PRINT_ERROR_CODE_RETURN(POI_ERROR_OUT_OF_MEMORY);
611         *cloned = landmark;
612         return POI_ERROR_NONE;  
613 }
614
615 int poi_get_id(poi_h poi, int *id)
616 {
617         POI_NULL_ARG_CHECK(poi);
618         POI_NULL_ARG_CHECK(id);
619         *id = location_landmark_get_id((LocationLandmark*)poi);
620         return POI_ERROR_NONE;
621 }
622
623 int poi_get_name(poi_h poi, char **name)
624 {
625         POI_NULL_ARG_CHECK(poi);
626         POI_NULL_ARG_CHECK(name);
627         char *poi_name = (char*)location_landmark_get_name((LocationLandmark*)poi);
628         if( poi_name == NULL)
629                 *name = NULL;
630         else
631                 *name = strdup(poi_name);
632         return POI_ERROR_NONE;  
633 }
634
635 int poi_get_position(poi_h poi, location_coords_s *position)
636 {
637         POI_NULL_ARG_CHECK(poi);
638         POI_NULL_ARG_CHECK(position);
639         const LocationPosition *pos = location_landmark_get_position((LocationLandmark*)poi);
640         if( pos == NULL)
641                 POI_PRINT_ERROR_CODE_RETURN(POI_ERROR_INVALID_PARAMETER);
642
643         position->latitude = pos->latitude;
644         position->longitude = pos->longitude;
645         return POI_ERROR_NONE;  
646 }
647
648 int poi_get_address(poi_h poi, char **building_number, char **postal_code, char **street, char **city, char **district, char **state, char **country_code)
649 {
650         POI_NULL_ARG_CHECK(poi);
651         const LocationAddress * addr = location_landmark_get_address((LocationLandmark*)poi);
652         if( addr == NULL )
653                 return POI_ERROR_RESULT_NOT_FOUND;
654         if( building_number && addr->building_number)
655                 *building_number = strdup(addr->building_number);
656
657         if( postal_code && addr->postal_code)
658                 *postal_code = strdup(addr->postal_code);
659
660         if( street && addr->street)
661                 *street = strdup(addr->street);
662
663         if( city && addr->city)
664                 *city = strdup(addr->city);
665
666         if( district && addr->district)
667                 *district = strdup(addr->district);
668
669         if( state && addr->state)
670                 *state = strdup(addr->state);
671         
672         if( country_code && addr->country_code)
673                 *country_code = strdup(addr->country_code);
674
675         return POI_ERROR_NONE;
676         
677 }
678
679 int poi_get_description(poi_h poi, char** description)
680 {
681         POI_NULL_ARG_CHECK(poi);
682         POI_NULL_ARG_CHECK(description);
683         
684         char * desc = (char*)location_landmark_get_description((LocationLandmark*)poi);
685         if( desc  == NULL)
686                 *description = NULL;
687         else
688                 *description = strdup(desc);
689         return POI_ERROR_NONE;
690 }
691
692 int poi_get_timestamp(poi_h poi , time_t *timestamp)
693 {
694         POI_NULL_ARG_CHECK(poi);
695         POI_NULL_ARG_CHECK(timestamp);
696         *timestamp = location_landmark_get_timestamp((LocationLandmark*)poi);
697         return POI_ERROR_NONE;
698 }
699
700 int poi_get_bounding_rect(poi_h poi , location_coords_s *top_left, location_coords_s *bottom_right)
701 {
702         POI_NULL_ARG_CHECK(poi);
703         POI_NULL_ARG_CHECK(top_left);
704         POI_NULL_ARG_CHECK(bottom_right);       
705
706         const LocationBoundary *bound = location_landmark_get_bounding_box((LocationLandmark*)poi);
707         if( bound == NULL )
708                 return POI_ERROR_RESULT_NOT_FOUND;
709         top_left->latitude = bound->rect.left_top->latitude;
710         top_left->longitude = bound->rect.left_top->longitude;  
711         bottom_right->latitude = bound->rect.right_bottom->latitude;
712         bottom_right->longitude = bound->rect.right_bottom->longitude;
713         
714         return POI_ERROR_NONE;
715 }
716
717 int poi_get_author(poi_h poi , char** author)
718 {
719         POI_NULL_ARG_CHECK(poi);
720         POI_NULL_ARG_CHECK(author);
721         char *auth = (char*)location_landmark_get_author((LocationLandmark*)poi);
722         if( auth == NULL )
723                 *author = NULL;
724         else
725                 *author = strdup(auth);
726         return POI_ERROR_NONE;
727 }
728
729 int poi_get_phone_number(poi_h poi , char** phone_number)
730 {
731         POI_NULL_ARG_CHECK(poi);
732         POI_NULL_ARG_CHECK(phone_number);
733         char *number = (char*)location_landmark_get_phone_number((LocationLandmark*)poi);
734         if( number == NULL )
735                 *phone_number = NULL;
736         else
737                 *phone_number = strdup(number);
738         return POI_ERROR_NONE;
739 }
740
741 int poi_foreach_urls(poi_h poi, poi_urls_cb callback , void * user_data)
742 {
743         POI_NULL_ARG_CHECK(poi);
744         POI_NULL_ARG_CHECK(callback);
745
746         GList *url_list = (GList*)location_landmark_get_url((LocationLandmark*)poi);
747
748         while( url_list ){
749                 LocationLandmarkUrl *url = url_list->data;
750                 if(url != NULL && !callback(location_landmark_url_get_url_path(url), location_landmark_url_get_description(url), user_data) )
751                         break;
752                 url_list = url_list->next;      
753         }
754         return POI_ERROR_NONE;  
755 }
756
757 int poi_foreach_properties(poi_h poi, poi_properties_cb callback, void * user_data)
758 {
759         POI_NULL_ARG_CHECK(poi);
760         POI_NULL_ARG_CHECK(callback);
761         GList *key_list = (GList*)location_landmark_get_property_key((LocationLandmark*)poi);
762         
763         while( key_list ){
764                 char *key = key_list->data;
765                 char *value = NULL;             
766                 if( key != NULL && (value = (char*)location_landmark_get_property((LocationLandmark*)poi, key)) != NULL){
767                         if( callback(key, value, user_data) == false)
768                                 break;                  
769                 }
770                 key_list = key_list->next;      
771         }
772         return POI_ERROR_NONE;  
773 }
774
775 int poi_foreach_categories(poi_h poi , poi_categories_cb callback , void * user_data)
776 {
777         POI_NULL_ARG_CHECK(poi);
778         POI_NULL_ARG_CHECK(callback);
779         GList *category_list = (GList*)location_landmark_get_category((LocationLandmark*)poi);
780         
781         while( category_list ){
782                 char *category = category_list->data;
783                 if( false == callback(category, user_data) )
784                         break;
785                 category_list = category_list->next;    
786         }
787         return POI_ERROR_NONE;
788 }