Define new 'pivot-prop-loadable' property
[nautilus-actions.git] / src / io-desktop / nadp-reader.c
blobf2406eb241e50c3d9131f668be15bb1aa753069e
1 /*
2 * Nautilus-Actions
3 * A Nautilus extension which offers configurable context menu actions.
5 * Copyright (C) 2005 The GNOME Foundation
6 * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
7 * Copyright (C) 2009, 2010, 2011 Pierre Wieser and others (see AUTHORS)
9 * This Program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
14 * This Program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public
20 * License along with this Library; see the file COPYING. If not,
21 * write to the Free Software Foundation, Inc., 59 Temple Place,
22 * Suite 330, Boston, MA 02111-1307, USA.
24 * Authors:
25 * Frederic Ruaudel <grumz@grumz.net>
26 * Rodrigo Moya <rodrigo@gnome-db.org>
27 * Pierre Wieser <pwieser@trychlos.org>
28 * ... and many others (see AUTHORS)
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
35 #include <stdlib.h>
36 #include <string.h>
38 #include <api/na-core-utils.h>
39 #include <api/na-data-types.h>
40 #include <api/na-ifactory-object-data.h>
41 #include <api/na-ifactory-provider.h>
42 #include <api/na-object-api.h>
44 #include "nadp-desktop-provider.h"
45 #include "nadp-keys.h"
46 #include "nadp-reader.h"
47 #include "nadp-utils.h"
48 #include "nadp-xdg-dirs.h"
50 typedef struct {
51 gchar *path;
52 gchar *id;
54 DesktopPath;
56 /* the structure passed as reader data to NAIFactoryObject
58 typedef struct {
59 NadpDesktopFile *ndf;
60 NAObjectAction *action;
62 NadpReaderData;
64 static GList *get_list_of_desktop_paths( NadpDesktopProvider *provider, GSList **mesages );
65 static void get_list_of_desktop_files( const NadpDesktopProvider *provider, GList **files, const gchar *dir, GSList **messages );
66 static gboolean is_already_loaded( const NadpDesktopProvider *provider, GList *files, const gchar *desktop_id );
67 static GList *desktop_path_from_id( const NadpDesktopProvider *provider, GList *files, const gchar *dir, const gchar *id );
68 static NAIFactoryObject *item_from_desktop_path( const NadpDesktopProvider *provider, DesktopPath *dps, GSList **messages );
69 static NAIFactoryObject *item_from_desktop_file( const NadpDesktopProvider *provider, NadpDesktopFile *ndf, GSList **messages );
70 static void desktop_weak_notify( NadpDesktopFile *ndf, GObject *item );
71 static void free_desktop_paths( GList *paths );
73 static void read_start_read_subitems_key( const NAIFactoryProvider *provider, NAObjectItem *item, NadpReaderData *reader_data, GSList **messages );
74 static void read_start_profile_attach_profile( const NAIFactoryProvider *provider, NAObjectProfile *profile, NadpReaderData *reader_data, GSList **messages );
76 static gboolean read_done_item_is_writable( const NAIFactoryProvider *provider, NAObjectItem *item, NadpReaderData *reader_data, GSList **messages );
77 static void read_done_action_read_profiles( const NAIFactoryProvider *provider, NAObjectAction *action, NadpReaderData *data, GSList **messages );
78 static void read_done_action_load_profile( const NAIFactoryProvider *provider, NadpReaderData *reader_data, const gchar *profile_id, GSList **messages );
81 * Returns an unordered list of NAIFactoryObject-derived objects
83 * This is implementation of NAIIOProvider::read_items method
85 GList *
86 nadp_iio_provider_read_items( const NAIIOProvider *provider, GSList **messages )
88 static const gchar *thisfn = "nadp_iio_provider_read_items";
89 GList *items;
90 GList *desktop_paths, *ip;
91 NAIFactoryObject *item;
93 g_debug( "%s: provider=%p (%s), messages=%p",
94 thisfn, ( void * ) provider, G_OBJECT_TYPE_NAME( provider ), ( void * ) messages );
96 g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), NULL );
98 items = NULL;
99 nadp_desktop_provider_release_monitors( NADP_DESKTOP_PROVIDER( provider ));
101 desktop_paths = get_list_of_desktop_paths( NADP_DESKTOP_PROVIDER( provider ), messages );
102 for( ip = desktop_paths ; ip ; ip = ip->next ){
104 item = item_from_desktop_path( NADP_DESKTOP_PROVIDER( provider ), ( DesktopPath * ) ip->data, messages );
106 if( item ){
107 items = g_list_prepend( items, item );
111 free_desktop_paths( desktop_paths );
113 g_debug( "%s: count=%d", thisfn, g_list_length( items ));
114 return( items );
118 * returns a list of DesktopPath items
120 * we get the ordered list of XDG_DATA_DIRS, and the ordered list of
121 * subdirs to add; then for each item of each list, we search for
122 * .desktop files in the resulted built path
124 * the returned list is so a list of DesktopPath struct, in
125 * the ordered of preference (most preferred first)
127 static GList *
128 get_list_of_desktop_paths( NadpDesktopProvider *provider, GSList **messages )
130 GList *files;
131 GSList *xdg_dirs, *idir;
132 GSList *subdirs, *isub;
133 gchar *dir;
135 files = NULL;
136 xdg_dirs = nadp_xdg_dirs_get_data_dirs();
137 subdirs = na_core_utils_slist_from_split( NADP_DESKTOP_PROVIDER_SUBDIRS, G_SEARCHPATH_SEPARATOR_S );
139 /* explore each directory from XDG_DATA_DIRS
141 for( idir = xdg_dirs ; idir ; idir = idir->next ){
143 /* explore each N-A candidate subdirectory for each XDG dir
145 for( isub = subdirs ; isub ; isub = isub->next ){
147 dir = g_build_filename(( gchar * ) idir->data, ( gchar * ) isub->data, NULL );
148 nadp_desktop_provider_add_monitor( provider, dir );
149 get_list_of_desktop_files( provider, &files, dir, messages );
150 g_free( dir );
154 na_core_utils_slist_free( subdirs );
155 na_core_utils_slist_free( xdg_dirs );
157 return( files );
161 * scans the directory for .desktop files
162 * only adds to the list those which have not been yet loaded
164 static void
165 get_list_of_desktop_files( const NadpDesktopProvider *provider, GList **files, const gchar *dir, GSList **messages )
167 static const gchar *thisfn = "nadp_reader_get_list_of_desktop_files";
168 GDir *dir_handle;
169 GError *error;
170 const gchar *name;
171 gchar *desktop_id;
173 g_debug( "%s: provider=%p, files=%p (count=%d), dir=%s, messages=%p",
174 thisfn, ( void * ) provider, ( void * ) files, g_list_length( *files ), dir, ( void * ) messages );
176 error = NULL;
177 dir_handle = NULL;
179 /* do not warn when the directory just doesn't exist
181 if( g_file_test( dir, G_FILE_TEST_IS_DIR )){
182 dir_handle = g_dir_open( dir, 0, &error );
183 if( error ){
184 g_warning( "%s: %s: %s", thisfn, dir, error->message );
185 g_error_free( error );
186 goto close_dir_handle;
188 } else {
189 g_debug( "%s: %s: directory doesn't exist", thisfn, dir );
192 if( dir_handle ){
193 while(( name = g_dir_read_name( dir_handle ))){
194 if( g_str_has_suffix( name, NADP_DESKTOP_FILE_SUFFIX )){
195 desktop_id = na_core_utils_str_remove_suffix( name, NADP_DESKTOP_FILE_SUFFIX );
196 if( !is_already_loaded( provider, *files, desktop_id )){
197 *files = desktop_path_from_id( provider, *files, dir, desktop_id );
199 g_free( desktop_id );
204 close_dir_handle:
205 if( dir_handle ){
206 g_dir_close( dir_handle );
210 static gboolean
211 is_already_loaded( const NadpDesktopProvider *provider, GList *files, const gchar *desktop_id )
213 gboolean found;
214 GList *ip;
215 DesktopPath *dps;
217 found = FALSE;
218 for( ip = files ; ip && !found ; ip = ip->next ){
219 dps = ( DesktopPath * ) ip->data;
220 if( !g_ascii_strcasecmp( dps->id, desktop_id )){
221 found = TRUE;
225 return( found );
228 static GList *
229 desktop_path_from_id( const NadpDesktopProvider *provider, GList *files, const gchar *dir, const gchar *id )
231 DesktopPath *dps;
232 gchar *bname;
233 GList *list;
235 dps = g_new0( DesktopPath, 1 );
237 bname = g_strdup_printf( "%s%s", id, NADP_DESKTOP_FILE_SUFFIX );
238 dps->path = g_build_filename( dir, bname, NULL );
239 g_free( bname );
241 dps->id = g_strdup( id );
243 list = g_list_prepend( files, dps );
245 return( list );
249 * Returns a newly allocated NAIFactoryObject-derived object, initialized
250 * from the .desktop file pointed to by DesktopPath struct
252 static NAIFactoryObject *
253 item_from_desktop_path( const NadpDesktopProvider *provider, DesktopPath *dps, GSList **messages )
255 NadpDesktopFile *ndf;
257 ndf = nadp_desktop_file_new_from_path( dps->path );
258 if( !ndf ){
259 return( NULL );
262 return( item_from_desktop_file( provider, ndf, messages ));
266 * Returns a newly allocated NAIFactoryObject-derived object, initialized
267 * from the .desktop file
269 static NAIFactoryObject *
270 item_from_desktop_file( const NadpDesktopProvider *provider, NadpDesktopFile *ndf, GSList **messages )
272 static const gchar *thisfn = "nadp_reader_item_from_desktop_file";
273 NAIFactoryObject *item;
274 gchar *type;
275 NadpReaderData *reader_data;
276 gchar *id;
278 item = NULL;
279 type = nadp_desktop_file_get_file_type( ndf );
281 if( !type || !strlen( type ) || !strcmp( type, NADP_VALUE_TYPE_ACTION )){
282 item = NA_IFACTORY_OBJECT( na_object_action_new());
284 } else if( !strcmp( type, NADP_VALUE_TYPE_MENU )){
285 item = NA_IFACTORY_OBJECT( na_object_menu_new());
287 } else {
288 g_warning( "%s: unknown type=%s", thisfn, type );
291 if( item ){
292 id = nadp_desktop_file_get_id( ndf );
293 na_object_set_id( item, id );
294 g_free( id );
296 reader_data = g_new0( NadpReaderData, 1 );
297 reader_data->ndf = ndf;
299 na_ifactory_provider_read_item( NA_IFACTORY_PROVIDER( provider ), reader_data, item, messages );
301 na_object_set_provider_data( item, ndf );
302 g_object_weak_ref( G_OBJECT( item ), ( GWeakNotify ) desktop_weak_notify, ndf );
304 g_free( reader_data );
307 return( item );
310 static void
311 desktop_weak_notify( NadpDesktopFile *ndf, GObject *item )
313 static const gchar *thisfn = "nadp_reader_desktop_weak_notify";
315 g_debug( "%s: ndf=%p (%s), item=%p (%s)",
316 thisfn, ( void * ) ndf, G_OBJECT_TYPE_NAME( ndf ),
317 ( void * ) item, G_OBJECT_TYPE_NAME( item ));
319 g_object_unref( ndf );
322 static void
323 free_desktop_paths( GList *paths )
325 GList *ip;
326 DesktopPath *dps;
328 for( ip = paths ; ip ; ip = ip->next ){
329 dps = ( DesktopPath * ) ip->data;
330 g_free( dps->path );
331 g_free( dps->id );
332 g_free( dps );
335 g_list_free( paths );
339 * nadp_reader_iimporter_import_from_uri:
340 * @instance: the #NAIImporter provider.
341 * @parms: a #NAIImporterUriParms structure.
343 * Imports an item.
345 * Returns: the import operation code.
347 * As soon as we have a valid .desktop file, we are most probably willing
348 * to successfully import an action or a menu of it.
350 * GLib does not have any primitive to load a key file from an uri.
351 * So we have to load the file into memory, and then try to load the key
352 * file from the memory data.
354 guint
355 nadp_reader_iimporter_import_from_uri( const NAIImporter *instance, NAIImporterImportFromUriParms *parms )
357 static const gchar *thisfn = "nadp_reader_iimporter_import_from_uri";
358 guint code;
359 NadpDesktopFile *ndf;
360 NAIImporterManageImportModeParms manage_parms;
362 g_debug( "%s: instance=%p, parms=%p", thisfn, ( void * ) instance, ( void * ) parms );
364 g_return_val_if_fail( NA_IS_IIMPORTER( instance ), IMPORTER_CODE_PROGRAM_ERROR );
365 g_return_val_if_fail( NADP_IS_DESKTOP_PROVIDER( instance ), IMPORTER_CODE_PROGRAM_ERROR );
367 code = IMPORTER_CODE_NOT_WILLING_TO;
369 ndf = nadp_desktop_file_new_from_uri( parms->uri );
370 if( ndf ){
371 parms->exist = FALSE;
372 parms->import_mode = IMPORTER_MODE_NO_IMPORT;
373 parms->imported = ( NAObjectItem * ) item_from_desktop_file(
374 ( const NadpDesktopProvider * ) NADP_DESKTOP_PROVIDER( instance ),
375 ndf, &parms->messages );
377 if( parms->imported ){
378 code = IMPORTER_CODE_OK;
379 g_return_val_if_fail( NA_IS_OBJECT_ITEM( parms->imported ), IMPORTER_CODE_NOT_WILLING_TO );
381 /* remove the weak reference on desktop file set by 'item_from_desktop_file'
382 * as we must consider this #NAObjectItem as a new one
384 na_object_set_provider_data( parms->imported, NULL );
385 g_object_weak_unref( G_OBJECT( parms->imported ), ( GWeakNotify ) desktop_weak_notify, ndf );
386 g_object_unref( ndf );
388 manage_parms.version = 1;
389 manage_parms.imported = parms->imported;
390 manage_parms.check_fn = parms->check_fn;
391 manage_parms.check_fn_data = parms->check_fn_data;
392 manage_parms.ask_fn = parms->ask_fn;
393 manage_parms.ask_fn_data = parms->ask_fn_data;
394 manage_parms.asked_mode = parms->asked_mode;
395 manage_parms.messages = parms->messages;
397 code = na_iimporter_manage_import_mode( &manage_parms );
399 parms->exist = manage_parms.exist;
400 parms->import_mode = manage_parms.import_mode;
403 if( code != IMPORTER_CODE_OK ){
404 if( parms->imported ){
405 g_object_unref( parms->imported );
406 parms->imported = NULL;
411 return( code );
415 * at this time, the object has been allocated and its id has been set
416 * read here the subitems key, which may be 'Profiles' or 'ItemsList'
417 * depending of the exact class of the NAObjectItem
419 void
420 nadp_reader_ifactory_provider_read_start( const NAIFactoryProvider *reader, void *reader_data, const NAIFactoryObject *serializable, GSList **messages )
422 static const gchar *thisfn = "nadp_reader_ifactory_provider_read_start";
424 g_return_if_fail( NA_IS_IFACTORY_PROVIDER( reader ));
425 g_return_if_fail( NADP_IS_DESKTOP_PROVIDER( reader ));
426 g_return_if_fail( NA_IS_IFACTORY_OBJECT( serializable ));
428 if( !NADP_DESKTOP_PROVIDER( reader )->private->dispose_has_run ){
430 g_debug( "%s: reader=%p (%s), reader_data=%p, serializable=%p (%s), messages=%p",
431 thisfn,
432 ( void * ) reader, G_OBJECT_TYPE_NAME( reader ),
433 ( void * ) reader_data,
434 ( void * ) serializable, G_OBJECT_TYPE_NAME( serializable ),
435 ( void * ) messages );
437 if( NA_IS_OBJECT_ITEM( serializable )){
438 read_start_read_subitems_key( reader, NA_OBJECT_ITEM( serializable ), ( NadpReaderData * ) reader_data, messages );
439 na_object_set_iversion( serializable, 3 );
442 if( NA_IS_OBJECT_PROFILE( serializable )){
443 read_start_profile_attach_profile( reader, NA_OBJECT_PROFILE( serializable ), ( NadpReaderData * ) reader_data, messages );
448 static void
449 read_start_read_subitems_key( const NAIFactoryProvider *provider, NAObjectItem *item, NadpReaderData *reader_data, GSList **messages )
451 GSList *subitems;
452 gboolean key_found;
454 subitems = nadp_desktop_file_get_string_list( reader_data->ndf,
455 NADP_GROUP_DESKTOP,
456 NA_IS_OBJECT_ACTION( item ) ? NADP_KEY_PROFILES : NADP_KEY_ITEMS_LIST,
457 &key_found,
458 NULL );
460 if( key_found ){
461 na_object_set_items_slist( item, subitems );
464 na_core_utils_slist_free( subitems );
467 static void
468 read_start_profile_attach_profile( const NAIFactoryProvider *provider, NAObjectProfile *profile, NadpReaderData *reader_data, GSList **messages )
470 na_object_attach_profile( reader_data->action, profile );
474 * reading any data from a desktop file requires:
475 * - a NadpDesktopFile object which has been initialized with the .desktop file
476 * -> has been attached to the NAObjectItem in get_item() above
477 * - the data type (+ reading default value)
478 * - group and key names
480 * Returns: NULL if the key has not been found
481 * letting the caller deal with default values
483 NADataBoxed *
484 nadp_reader_ifactory_provider_read_data( const NAIFactoryProvider *reader, void *reader_data, const NAIFactoryObject *object, const NADataDef *def, GSList **messages )
486 static const gchar *thisfn = "nadp_reader_ifactory_provider_read_data";
487 NADataBoxed *boxed;
488 gboolean found;
489 NadpReaderData *nrd;
490 gchar *group, *id;
491 gchar *msg;
492 gchar *str_value;
493 gboolean bool_value;
494 GSList *slist_value;
495 guint uint_value;
497 g_return_val_if_fail( NA_IS_IFACTORY_PROVIDER( reader ), NULL );
498 g_return_val_if_fail( NADP_IS_DESKTOP_PROVIDER( reader ), NULL );
499 g_return_val_if_fail( NA_IS_IFACTORY_OBJECT( object ), NULL );
501 boxed = NULL;
503 if( !NADP_DESKTOP_PROVIDER( reader )->private->dispose_has_run ){
505 nrd = ( NadpReaderData * ) reader_data;
506 g_return_val_if_fail( NADP_IS_DESKTOP_FILE( nrd->ndf ), NULL );
508 if( def->desktop_entry ){
510 if( NA_IS_OBJECT_ITEM( object )){
511 group = g_strdup( NADP_GROUP_DESKTOP );
513 } else {
514 g_return_val_if_fail( NA_IS_OBJECT_PROFILE( object ), NULL );
515 id = na_object_get_id( object );
516 group = g_strdup_printf( "%s %s", NADP_GROUP_PROFILE, id );
517 g_free( id );
520 switch( def->type ){
522 case NA_DATA_TYPE_LOCALE_STRING:
523 str_value = nadp_desktop_file_get_locale_string( nrd->ndf, group, def->desktop_entry, &found, def->default_value );
524 if( found ){
525 boxed = na_data_boxed_new( def );
526 na_boxed_set_from_void( NA_BOXED( boxed ), str_value );
528 g_free( str_value );
529 break;
531 case NA_DATA_TYPE_STRING:
532 str_value = nadp_desktop_file_get_string( nrd->ndf, group, def->desktop_entry, &found, def->default_value );
533 if( found ){
534 boxed = na_data_boxed_new( def );
535 na_boxed_set_from_void( NA_BOXED( boxed ), str_value );
537 g_free( str_value );
538 break;
540 case NA_DATA_TYPE_BOOLEAN:
541 bool_value = nadp_desktop_file_get_boolean( nrd->ndf, group, def->desktop_entry, &found, na_core_utils_boolean_from_string( def->default_value ));
542 if( found ){
543 boxed = na_data_boxed_new( def );
544 na_boxed_set_from_void( NA_BOXED( boxed ), GUINT_TO_POINTER( bool_value ));
546 break;
548 case NA_DATA_TYPE_STRING_LIST:
549 slist_value = nadp_desktop_file_get_string_list( nrd->ndf, group, def->desktop_entry, &found, def->default_value );
550 if( found ){
551 boxed = na_data_boxed_new( def );
552 na_boxed_set_from_void( NA_BOXED( boxed ), slist_value );
554 na_core_utils_slist_free( slist_value );
555 break;
557 case NA_DATA_TYPE_UINT:
558 uint_value = nadp_desktop_file_get_uint( nrd->ndf, group, def->desktop_entry, &found, atoi( def->default_value ));
559 if( found ){
560 boxed = na_data_boxed_new( def );
561 na_boxed_set_from_void( NA_BOXED( boxed ), GUINT_TO_POINTER( uint_value ));
563 break;
565 default:
566 msg = g_strdup_printf( "%s: %d: invalid data type.", thisfn, def->type );
567 g_warning( "%s", msg );
568 *messages = g_slist_append( *messages, msg );
571 g_free( group );
575 return( boxed );
579 * called when each NAIFactoryObject object has been read
581 void
582 nadp_reader_ifactory_provider_read_done( const NAIFactoryProvider *reader, void *reader_data, const NAIFactoryObject *serializable, GSList **messages )
584 static const gchar *thisfn = "nadp_reader_ifactory_provider_read_done";
585 gboolean writable;
587 g_return_if_fail( NA_IS_IFACTORY_PROVIDER( reader ));
588 g_return_if_fail( NADP_IS_DESKTOP_PROVIDER( reader ));
589 g_return_if_fail( NA_IS_IFACTORY_OBJECT( serializable ));
591 if( !NADP_DESKTOP_PROVIDER( reader )->private->dispose_has_run ){
593 g_debug( "%s: reader=%p (%s), reader_data=%p, serializable=%p (%s), messages=%p",
594 thisfn,
595 ( void * ) reader, G_OBJECT_TYPE_NAME( reader ),
596 ( void * ) reader_data,
597 ( void * ) serializable, G_OBJECT_TYPE_NAME( serializable ),
598 ( void * ) messages );
600 if( NA_IS_OBJECT_ITEM( serializable )){
601 writable = read_done_item_is_writable( reader, NA_OBJECT_ITEM( serializable ), ( NadpReaderData * ) reader_data, messages );
602 na_object_set_readonly( serializable, !writable );
605 if( NA_IS_OBJECT_ACTION( serializable )){
606 read_done_action_read_profiles( reader, NA_OBJECT_ACTION( serializable ), ( NadpReaderData * ) reader_data, messages );
609 g_debug( "%s: quitting for %s at %p", thisfn, G_OBJECT_TYPE_NAME( serializable ), ( void * ) serializable );
613 static gboolean
614 read_done_item_is_writable( const NAIFactoryProvider *provider, NAObjectItem *item, NadpReaderData *reader_data, GSList **messages )
616 NadpDesktopFile *ndf;
617 gchar *uri;
618 gboolean writable;
620 ndf = reader_data->ndf;
621 uri = nadp_desktop_file_get_key_file_uri( ndf );
622 writable = nadp_utils_uri_is_writable( uri );
623 g_free( uri );
625 return( writable );
629 * read and attach profiles in the specified order
630 * profiles which may exist in .desktop files, but are not referenced
631 * in the 'Profiles' string list are just ignored
633 static void
634 read_done_action_read_profiles( const NAIFactoryProvider *provider, NAObjectAction *action, NadpReaderData *reader_data, GSList **messages )
636 GSList *order;
637 GSList *ip;
638 gchar *profile_id;
639 NAObjectId *found;
641 reader_data->action = action;
642 order = na_object_get_items_slist( action );
644 for( ip = order ; ip ; ip = ip->next ){
645 profile_id = ( gchar * ) ip->data;
646 found = na_object_get_item( action, profile_id );
647 if( !found ){
648 read_done_action_load_profile( provider, reader_data, profile_id, messages );
652 na_core_utils_slist_free( order );
655 static void
656 read_done_action_load_profile( const NAIFactoryProvider *provider, NadpReaderData *reader_data, const gchar *profile_id, GSList **messages )
658 NAObjectProfile *profile;
660 g_debug( "nadp_reader_read_done_action_load_profile: loading profile=%s", profile_id );
662 profile = na_object_profile_new();
663 na_object_set_id( profile, profile_id );
665 na_ifactory_provider_read_item(
666 NA_IFACTORY_PROVIDER( provider ),
667 reader_data,
668 NA_IFACTORY_OBJECT( profile ),
669 messages );