• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List

opensync/opensync_convert.c

00001 /*
00002  * libopensync - A synchronization framework
00003  * Copyright (C) 2004-2005  Armin Bauer <armin.bauer@opensync.org>
00004  * 
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  * 
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  * 
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00018  * 
00019  */
00020  
00021 #include "opensync.h"
00022 #include "opensync_internals.h"
00023 
00028 
00029 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00030 typedef struct conv_tree {
00031         OSyncFormatEnv *env;
00032         OSyncObjType *type;
00033 
00034         /* The converters that weren't reached yet */
00035         GList *unused;
00036         /* The search queue for the Breadth-first search */
00037         GList *search;
00038 } conv_tree;
00039 
00040 typedef struct vertice {
00041         OSyncObjFormat *format;
00042         
00043         /* The invoke_decap will return a new change everytime
00044          * we run it so that the original change does not get
00045          * changed. We also need to track if the data of this change
00046          * should be freed or if it contains a reference into data of
00047          * a previous change */
00048         OSyncChange *change;
00049         osync_bool free_change_data;
00050         osync_bool free_change;
00051 
00057         size_t references;
00058 
00060         GList *path;
00061 
00062         unsigned losses;
00063         unsigned objtype_changes;
00064         unsigned conversions;
00065 
00066 } vertice;
00067 #endif
00068 
00069 static OSyncFormatConverter *osync_conv_find_converter_objformat(OSyncFormatEnv *env, OSyncObjFormat *fmt_src, OSyncObjFormat *fmt_trg)
00070 {
00071         GList *element = NULL;
00072         for (element = env->converters; element; element = element->next) {
00073                 OSyncFormatConverter *converter = element->data;
00074                 if (fmt_src == converter->source_format && fmt_trg == converter->target_format)
00075                         return converter;
00076         }
00077         return NULL;
00078 }
00079 
00080 osync_bool osync_converter_invoke(OSyncFormatConverter *converter, OSyncChange *change, void *converter_data, OSyncError **error)
00081 {
00082         osync_trace(TRACE_ENTRY, "osync_converter_invoke(%p, %p, %p)", converter, change, error);
00083         osync_trace(TRACE_INTERNAL, "converter: Type: %i, source: %s, target %s", converter->type, converter->source_format->name, converter->target_format->name);
00084         char *data = NULL;
00085         int datasize = 0;
00086         osync_bool ret = TRUE;
00087         if (converter->type == CONVERTER_DETECTOR && !converter->convert_func) {
00088                 change->format = converter->target_format;
00089                 change->objtype = osync_change_get_objformat(change)->objtype;
00090                 osync_trace(TRACE_EXIT, "osync_converter_invoke: TRUE: Detector path");
00091                 return TRUE;
00092         }
00093         
00094         if (!converter->convert_func) {
00095                 osync_error_set(error, OSYNC_ERROR_GENERIC, "Invalid converter");
00096                 osync_trace(TRACE_EXIT_ERROR, "osync_converter_invoke: %s", osync_error_print(error));
00097                 return FALSE;
00098         }
00099         
00100         if (change->data) {
00101                 //Invoke the converter and all extensions
00102                 //osync_conv_invoke_extensions(converter->source_format, FALSE, change);
00103                 osync_bool free_input = FALSE;
00104                 if ((ret = converter->convert_func(converter_data, change->data, change->size, &data, &datasize, &free_input, error))) {
00105                 
00106                         if (converter->type == CONVERTER_DECAP) {
00107                                 if (!free_input) {
00108                                         /* Duplicate the returned data, as the original data will be destroyed */
00109                                         if (!converter->target_format->copy_func) {
00110                                                 /* There is nothing we can do, here. The returned data is a reference, but
00111                                                  * we can't copy the data before destroying it
00112                                                  */
00113                                                 osync_debug("OSYNC", 0, "Format %s don't have a copy function, but a no-copy converter was registered", converter->target_format->name);
00114                                                 osync_error_set(error, OSYNC_ERROR_GENERIC, "Format %s don't have a copy function, but a no-copy converter was registered", converter->target_format->name);
00115                                                 osync_trace(TRACE_EXIT_ERROR, "osync_converter_invoke: %s", osync_error_print(error));
00116                                                 return FALSE;
00117                                         }
00118                                         converter->target_format->copy_func(data, datasize, &data, &datasize);
00119                                 }
00120                         }
00121                         /* Free the data, unless the converter took the ownership of the data */
00122                         if (free_input) {
00123                                 if (converter->source_format->destroy_func) {
00124                                         converter->source_format->destroy_func(change->data, change->size);
00125                                 } else
00126                                         osync_debug("OSYNC", 1, "Format %s don't have a destroy function. Possible memory leak", converter->source_format->name);
00127                         }
00128                         change->data = data;
00129                         change->size = datasize;
00130                         
00131                         //osync_conv_invoke_extensions(converter->target_format, TRUE, change);
00132                 }
00133         }
00134         
00135         if (ret) {
00136                 osync_debug("OSYNC", 3, "Converting! replacing format %s with %s", converter->source_format->name, converter->target_format->name);
00137                 change->format = converter->target_format;
00138                 change->objtype = osync_change_get_objformat(change)->objtype;
00139                 osync_trace(TRACE_EXIT, "osync_converter_invoke: TRUE");
00140         } else
00141                 osync_trace(TRACE_EXIT_ERROR, "osync_converter_invoke: %s", osync_error_print(error));
00142         return ret;
00143 }
00144 
00145 OSyncChange *osync_converter_invoke_decap(OSyncFormatConverter *converter, OSyncChange *change, osync_bool *free_output)
00146 {
00147         osync_trace(TRACE_ENTRY, "osync_converter_invoke_decap(%p, %p, %p)", converter, change, free_output);
00148         
00149         *free_output = FALSE;
00150         
00151         if (!converter->convert_func) {
00152                 osync_trace(TRACE_EXIT_ERROR, "osync_converter_invoke_decap: No convert function");
00153                 return NULL;
00154         }
00155         
00156         if (converter->type != CONVERTER_DECAP) {
00157                 osync_trace(TRACE_EXIT_ERROR, "osync_converter_invoke_decap: Not a decap");
00158                 return NULL;
00159         }
00160         
00161         OSyncChange *new_change = osync_change_new();
00162         
00163         
00164         if (change->changetype != CHANGE_DELETED && change->data) {
00165                 //Invoke the converter and all extensions
00166                 OSyncError *error = NULL;
00167                 if (!converter->convert_func(NULL, change->data, change->size, &(new_change->data), &(new_change->size), free_output, &error)) {
00168                         osync_trace(TRACE_EXIT_ERROR, "osync_converter_invoke_decap: %s", osync_error_print(&error));
00169                         osync_error_free(&error);
00170                         return NULL;
00171                 }
00172                 new_change->has_data = change->has_data;
00173         }
00174         osync_debug("OSYNC", 3, "Converting! replacing format %s with %s", converter->source_format->name, converter->target_format->name);
00175         new_change->format = converter->target_format;
00176         new_change->objtype = osync_change_get_objformat(new_change)->objtype;
00177         new_change->changetype = change->changetype;
00178         osync_trace(TRACE_EXIT, "osync_converter_invoke_decap: %p", new_change);
00179         return new_change;
00180 }
00181 
00189 int compare_vertice_distance(const void *a, const void *b)
00190 {
00191         const vertice *va = a;
00192         const vertice *vb = b;
00193         if (va->losses < vb->losses)
00194                 return -1;
00195         else if (va->losses > vb->losses)
00196                 return 1;
00197         else if (va->objtype_changes < vb->objtype_changes)
00198                 return -1;
00199         else if (va->objtype_changes > vb->objtype_changes)
00200                 return 1;
00201         else if (va->conversions < vb->conversions)
00202                 return -1;
00203         else if (va->conversions > vb->conversions)
00204                 return 1;
00205         else
00206                 return 0;
00207 }
00208 
00210 /*static void ref_vertice(vertice *v)
00211 {
00212         v->references++;
00213 }*/
00214 
00217 static void deref_vertice(vertice *vertice)
00218 {
00219         /* Decrement the reference count,
00220          * and just return if we still
00221          * have a reference
00222          */
00223         if (--vertice->references > 0)
00224                 return;
00225 
00226         g_list_free(vertice->path);
00227         if (vertice->change && vertice->free_change) {
00228                 if (vertice->free_change_data)
00229                         osync_change_free_data(vertice->change);
00230                 osync_change_free(vertice->change);
00231         }
00232 
00233         g_free(vertice);
00234 }
00235 
00241 vertice *get_next_vertice_neighbour(OSyncFormatEnv *env, conv_tree *tree, vertice *ve)
00242 {
00243         GList *c = NULL;
00244         osync_trace(TRACE_ENTRY, "get_next_vertice_neighbour(%p, %p, %p:%s)", env, tree, ve, ve->format ? ve->format->name : "None");
00245                 
00246         for (c = tree->unused; c; c = c->next) {
00247                 OSyncFormatConverter *converter = c->data;
00248                 OSyncObjFormat *fmt_target = converter->target_format;
00249                 
00250                 /* Check only valid converters, from the right format */
00251                 if (strcmp(converter->source_format->name, ve->format->name))
00252                         continue;
00253 
00254                 // If the converter type is a detector we need to know wether the input is correct
00255                 if (converter->detect_func) {
00256                         if (!ve->change) {
00257                                 osync_trace(TRACE_INTERNAL,
00258                                                 "We would call a converter to %s, but there is no change data on vertice", fmt_target->name);
00259                                 continue;
00260                         }
00261                         
00262                         if (ve->change->changetype != CHANGE_DELETED) {
00263                                 if (!converter->detect_func(env, ve->change->data, ve->change->size)) {
00264                                         osync_trace(TRACE_INTERNAL, "Invoked detector for converter from %s to %s: FALSE", converter->source_format->name, converter->target_format->name);
00265                                         continue;
00266                                 }
00267                         }
00268                         
00269                         osync_trace(TRACE_INTERNAL, "Invoked detector for converter from %s to %s: TRUE", converter->source_format->name, converter->target_format->name);
00270                 }
00271 
00272                 OSyncChange *new_change = NULL;
00273                 osync_bool free_output = TRUE;
00274                 if (converter->type == CONVERTER_DECAP) {
00275                         if (!ve->change) {
00276                                 osync_trace(TRACE_INTERNAL, "A desencapsulator to %s would be called, but we can't because the data on this vertice wasn't converted", fmt_target->name);
00277                                 continue;
00278                         }
00279                         
00280                         if (!(new_change = osync_converter_invoke_decap(converter, ve->change, &free_output)))
00281                                 continue;
00282                 }
00283 
00284                 /* From this point, we already found an edge (i.e. a converter) that may
00285                  * be used
00286                  */
00287 
00288                 /* Remove the converter from the unused list */
00289                 tree->unused = g_list_remove(tree->unused, converter);
00290 
00291                 /* Allocate the new neighbour */
00292                 vertice *neigh = g_malloc0(sizeof(vertice));
00293                 /* Start with a reference count = 1 */
00294                 neigh->references = 1;
00295                 neigh->format = fmt_target;
00296                 neigh->path = g_list_copy(ve->path);
00297                 neigh->path = g_list_append(neigh->path, converter);
00298 
00299                 if (new_change) {
00300                         neigh->change = new_change;
00301                         neigh->free_change = TRUE;
00302                         neigh->free_change_data = free_output;
00303                 } else {
00304                         neigh->change = NULL;
00305                         neigh->free_change = FALSE;
00306                         neigh->free_change_data = FALSE;
00307                 }
00308                 
00309                 /* Distance calculation */
00310                 neigh->conversions = ve->conversions + 1;
00311                 neigh->losses = ve->losses;
00312                 if (converter->type == CONVERTER_DECAP)
00313                         neigh->losses++;
00314                 neigh->objtype_changes = ve->objtype_changes;
00315                 if (converter->source_format->objtype != converter->target_format->objtype)
00316                         neigh->objtype_changes++;
00317 
00318                 osync_trace(TRACE_EXIT, "get_next_vertice_neighbour: %p:%s", neigh, neigh->format ? neigh->format->name : "None");
00319                 return neigh;
00320         }
00321         osync_trace(TRACE_EXIT, "get_next_vertice_neighbour: None found");
00322         return NULL;
00323 }
00324 
00348 static osync_bool osync_conv_find_path_fn(OSyncFormatEnv *env, OSyncChange *start, OSyncPathTargetFn target_fn, const void *fndata, GList/* OSyncConverter * */ **path_edges)
00349 {
00350         osync_trace(TRACE_ENTRY, "osync_conv_find_path_fn(%p, %p(%s, %s), %p, %p, %p)", env, start, start ? start->uid : "None", start ? start->format->name : "None", target_fn, fndata, path_edges);
00351         
00352         g_assert(start->format);
00353 
00354         *path_edges = NULL;
00355         osync_bool ret = FALSE;
00356         vertice *result = NULL;
00357 
00358         //Vertice = Spitze = Format
00359         //edge = Kante = Converter
00360 
00361         //Make a new search tree
00362         conv_tree *tree = g_malloc0(sizeof(conv_tree));
00363         tree->unused = g_list_copy(env->converters);
00364         
00365         //We make our starting point (which is the current format of the
00366         //change of course
00367         vertice *begin = g_malloc0(sizeof(vertice));
00368         begin->format = start->format;
00369         begin->path = NULL;
00370         begin->references = 1;
00371         begin->change = start;
00372         begin->free_change_data = FALSE;
00373         begin->free_change = FALSE;
00374         
00375         tree->search = g_list_append(NULL, begin);
00376         
00377         while (g_list_length(tree->search)) {
00378                 vertice *neighbour = NULL;
00379 
00380                 //Get the first vertice and remove it from the queue
00381                 vertice *current = tree->search->data;
00382                 tree->search = g_list_remove(tree->search, current);
00383                 
00384                 osync_debug("OSCONV", 4, "Next vertice: %s.", current->format->name);
00385                 /* Check if we have reached a target format */
00386                 if (target_fn(fndata, current->format)) {
00387                         /* Done. return the result */
00388                         result = current;
00389                         break;
00390                 }
00391                 osync_debug("OSCONV", 4, "Looking at %s's neighbours.", current->format->name);
00392                 while ((neighbour = get_next_vertice_neighbour(env, tree, current))) {
00393                         osync_debug("OSCONV", 4, "%s's neighbour: %s", current->format->name, neighbour->format->name);
00394                         tree->search = g_list_insert_sorted(tree->search, neighbour, compare_vertice_distance);
00395                 }
00396                 /* Done, drop the reference to the vertice */
00397                 deref_vertice(current);
00398         }
00399         /* Remove the references on the search queue */
00400         g_list_foreach(tree->search, (GFunc)deref_vertice, NULL);
00401         
00402         if (result) {
00403                 /* Found it. Copy the conversion path */
00404                 *path_edges = g_list_copy(result->path);
00405                 /* Drop the reference to the result vertice */
00406                 deref_vertice(result);
00407                 ret = TRUE;
00408                 goto free_tree;
00409         }
00410         
00411 free_tree:
00412         g_list_free(tree->unused);
00413         g_list_free(tree->search);
00414         g_free(tree);
00415         if (ret)
00416                 osync_trace(TRACE_EXIT, "osync_conv_find_path_fn: TRUE");
00417         else
00418                 osync_trace(TRACE_EXIT_ERROR, "osync_conv_find_path_fn: FALSE");
00419         return ret;
00420 }
00421 
00422 osync_bool osync_conv_convert_fn(OSyncFormatEnv *env, OSyncChange *change, OSyncPathTargetFn target_fn, const void *fndata, const char *extension_name, OSyncError **error)
00423 {
00424         osync_trace(TRACE_ENTRY, "osync_conv_convert_fn(%p, %p, %p, %p, %p)", env, change, target_fn, fndata, error);
00425         g_assert(change);
00426         g_assert(target_fn);
00427         OSyncObjFormat *source = osync_change_get_objformat(change);
00428         osync_assert_msg(source, "Cannot convert! change has no objformat!");
00429         GList *path = NULL;
00430         osync_bool ret = TRUE;
00431 
00432         /* Optimization: check if the format is already valid */
00433         if (target_fn(fndata, source)) {
00434                 osync_trace(TRACE_EXIT, "osync_conv_convert_fn: Target already valid");
00435                 return TRUE;
00436         }
00437 
00438         //We can convert the deleted change directly since it has no data
00439         /*if (change->changetype == CHANGE_DELETED) {
00440                 change->format = osync_change_get_initial_objformat(change);
00441                 change->objtype = osync_change_get_objformat(change)->objtype;
00442                 if (!target_fn(fndata, source)) {
00443                         osync_error_set(error, OSYNC_ERROR_GENERIC, "converted delete target would not be valid");
00444                         osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
00445                         return FALSE;
00446                 }
00447                 osync_trace(TRACE_EXIT, "osync_conv_convert_fn: converted deleted change");
00448                 return TRUE;
00449         }*/
00450         
00451         ret = FALSE;
00452         if (!osync_conv_find_path_fn(env, change, target_fn, fndata, &path)) {
00453                 osync_error_set(error, OSYNC_ERROR_GENERIC, "Unable to find a conversion path to the format requested");
00454                 osync_trace(TRACE_EXIT_ERROR, "osync_conv_convert_fn: %s", osync_error_print(error));
00455                 goto out;
00456         }
00457         
00458         if (change->changetype == CHANGE_DELETED) {
00459                 OSyncFormatConverter *converter = g_list_last(path)->data;
00460                 change->format = converter->target_format;
00461                 change->objtype = osync_change_get_objformat(change)->objtype;
00462         } else {
00463                 for (; path; path = path->next) {
00464                         OSyncFormatConverter *converter = path->data;
00465         
00466                         osync_trace(TRACE_INTERNAL, "initialize converter: %p", converter->init_func);
00467                         
00468                         //Initialize the converter
00469                         void *converter_data = NULL;
00470                         if (converter->init_func)
00471                                 converter_data = converter->init_func();
00472                         
00473                         if (extension_name) {
00474                                 osync_trace(TRACE_INTERNAL, "initialize extension: %s", extension_name);
00475                                 
00476                                 //Initialize the requested extension
00477                                 OSyncFormatExtension *extension = osync_conv_find_extension(env, converter->source_format, converter->target_format, extension_name);
00478                                 osync_trace(TRACE_INTERNAL, "extension: %p", extension);
00479                                 if (extension)
00480                                         extension->init_func(converter_data);
00481                         } else {
00482                                 
00483                                 osync_trace(TRACE_INTERNAL, "initialize all extensions");
00484                                 //Initialize all available from extensions
00485                                 GList *e;
00486                                 for (e = env->extensions; e; e = e->next) {
00487                                         OSyncFormatExtension *extension = e->data;
00488                                         osync_trace(TRACE_INTERNAL, "extension: %s", extension->name);
00489                                         osync_trace(TRACE_INTERNAL, "%p:%p %p:%p", extension->from_format, converter->source_format, extension->to_format, converter->target_format);
00490                                         if (extension->from_format == converter->source_format && extension->to_format == converter->target_format)
00491                                                 extension->init_func(converter_data);
00492                                 }
00493                         }
00494                         
00495                         if (!osync_converter_invoke(converter, change, converter_data, error)) {
00496                                 osync_trace(TRACE_EXIT_ERROR, "osync_conv_convert_fn: %s", osync_error_print(error));
00497                                 goto out_free_path;
00498                         }
00499                         
00500                         //Finalize the converter data
00501                         if (converter->fin_func)
00502                                 converter->fin_func(converter_data);
00503                         
00504                 }
00505         }
00506         ret = TRUE;
00507 
00508         osync_trace(TRACE_EXIT, "osync_conv_convert_fn: TRUE");
00509 out_free_path:
00510         g_list_free(path);
00511 out:
00512         return ret;
00513 }
00514 
00519 static osync_bool target_fn_fmtlist(const void *data, OSyncObjFormat *fmt)
00520 {
00521         const GList/*OSyncObjFormat * */ *l = data;
00522         const GList *i;
00523         for (i = l; i; i = i->next) {
00524                 OSyncObjFormat *f = i->data;
00525                 if (!strcmp(fmt->name, f->name))
00526                         return TRUE;
00527         }
00528         /* else */
00529         return FALSE;
00530 }
00531 
00534 osync_bool osync_conv_convert_fmtlist(OSyncFormatEnv *env, OSyncChange *change, GList/*OSyncObjFormat * */ *targets)
00535 {
00536         return osync_conv_convert_fn(env, change, target_fn_fmtlist, targets, NULL, NULL);
00537 }
00538 
00539 osync_bool osync_conv_find_path_fmtlist(OSyncFormatEnv *env, OSyncChange *start, GList/*OSyncObjFormat * */ *targets, GList **retlist)
00540 {
00541         return osync_conv_find_path_fn(env, start, target_fn_fmtlist, targets, retlist);
00542 }
00543 
00544 osync_bool osync_conv_objtype_is_any(const char *objstr)
00545 {
00546         if (!strcmp(objstr, "data"))
00547                 return TRUE;
00548         return FALSE;
00549 }
00550 
00560 
00568 OSyncFormatEnv *osync_conv_env_new(OSyncEnv *env)
00569 {
00570         osync_trace(TRACE_ENTRY, "%s(%p)", __func__, env);
00571         OSyncFormatEnv *conv_env = g_malloc0(sizeof(OSyncFormatEnv));
00572         GList *o;
00573         
00574         //Now we resolve all format plugin stuff for the conv env
00575         //First the objecttypes
00576         OSyncObjType *type = NULL;
00577         for (o = env->objtype_templates; o; o = o->next) {
00578                 OSyncObjTypeTemplate *otempl = o->data;
00579                 type = g_malloc0(sizeof(OSyncObjType));
00580                 type->name = g_strdup(otempl->name);
00581                 type->env = conv_env;
00582                 conv_env->objtypes = g_list_append(conv_env->objtypes, type);
00583         }
00584         
00585         //The formats
00586         GList *f = NULL;
00587         for (f = env->format_templates; f; f = f->next) {
00588                 OSyncObjFormatTemplate *ftempl = f->data;
00589                 OSyncObjType *type = osync_conv_find_objtype(conv_env, ftempl->objtype);
00590                 g_assert(type);
00591                 OSyncObjFormat *format = g_malloc0(sizeof(OSyncObjFormat));
00592                 format->env = conv_env;
00593                 format->name = g_strdup(ftempl->name);
00594                 format->objtype = type;
00595                 
00596                 format->cmp_func = ftempl->cmp_func;
00597                 format->merge_func = ftempl->merge_func;
00598                 format->duplicate_func = ftempl->duplicate_func;
00599                 format->copy_func = ftempl->copy_func;
00600                 format->create_func = ftempl->create_func;
00601                 format->destroy_func = ftempl->destroy_func;
00602                 format->print_func = ftempl->print_func;
00603                 format->revision_func = ftempl->revision_func;
00604                 format->marshall_func = ftempl->marshall_func;
00605                 format->demarshall_func = ftempl->demarshall_func;
00606                 type->formats = g_list_append(type->formats, format);
00607                 conv_env->objformats = g_list_append(conv_env->objformats, format);
00608         }
00609         
00610         //The extension
00611         GList *i;
00612         for (i = env->extension_templates; i; i = i->next) {
00613                 OSyncFormatExtensionTemplate *extension_template = i->data;
00614                 OSyncObjFormat *from_format = osync_conv_find_objformat(conv_env, extension_template->from_formatname);
00615                 OSyncObjFormat *to_format = osync_conv_find_objformat(conv_env, extension_template->to_formatname);
00616                 if (!from_format || !to_format)
00617                         continue;
00618 
00619                 OSyncFormatExtension *extension = g_malloc0(sizeof(OSyncFormatExtension));
00620                 extension->name = g_strdup(extension_template->name);
00621                 extension->init_func = extension_template->init_func;
00622                 extension->from_format = from_format;
00623                 extension->to_format = to_format;
00624                 
00625                 conv_env->extensions = g_list_append(conv_env->extensions, extension);
00626         }
00627         
00628         //Converter templates
00629         for (i = env->converter_templates; i; i = i->next) {
00630                 OSyncConverterTemplate *convtmpl = i->data;
00631 
00632                 osync_trace(TRACE_INTERNAL, "New converter from %s to %s", convtmpl->source_format, convtmpl->target_format);
00633 
00634                 OSyncObjFormat *fmt_src = osync_conv_find_objformat(conv_env, convtmpl->source_format);
00635                 OSyncObjFormat *fmt_trg = osync_conv_find_objformat(conv_env, convtmpl->target_format);
00636                 if (!fmt_src || !fmt_trg)
00637                         continue;
00638                 OSyncFormatConverter *converter = g_malloc0(sizeof(OSyncFormatConverter));
00639                 converter->source_format = fmt_src;
00640                 converter->target_format = fmt_trg;
00641                 converter->convert_func = convtmpl->convert_func;
00642                 converter->type = convtmpl->type;
00643                 converter->init_func = convtmpl->init_func;
00644                 
00645                 conv_env->converters = g_list_append(conv_env->converters, converter);
00646         }
00647         
00648         //The detectors
00649         for (i = env->data_detectors; i; i = i->next) {
00650                 OSyncDataDetector *detector = i->data;
00651                 OSyncFormatConverter *converter = osync_conv_find_converter(conv_env, detector->sourceformat, detector->targetformat);
00652                 if (!converter) {
00653                         OSyncObjFormat *fmt_src = osync_conv_find_objformat(conv_env, detector->sourceformat);
00654                         OSyncObjFormat *fmt_trg = osync_conv_find_objformat(conv_env, detector->targetformat);
00655                         if (!fmt_src || !fmt_trg)
00656                                 continue;
00657                         converter = g_malloc0(sizeof(OSyncFormatConverter));
00658                         converter->source_format = fmt_src;
00659                         converter->target_format = fmt_trg;
00660                         converter->type = CONVERTER_DETECTOR;
00661                 }
00662                 converter->detect_func = detector->detect_func;
00663                 conv_env->converters = g_list_append(conv_env->converters, converter);
00664         }
00665                 
00666         //The filters
00667         conv_env->filter_functions = g_list_copy(env->filter_functions);
00668 
00669         osync_conv_set_common_format(conv_env, "contact", "xml-contact", NULL);
00670         osync_conv_set_common_format(conv_env, "event", "xml-event", NULL);
00671         osync_conv_set_common_format(conv_env, "todo", "xml-todo", NULL);
00672         osync_conv_set_common_format(conv_env, "note", "xml-note", NULL);
00673         
00674         osync_trace(TRACE_EXIT, "%s: %p", __func__, conv_env);
00675         return conv_env;
00676 }
00677 
00685 void osync_conv_env_free(OSyncFormatEnv *env)
00686 {
00687         g_assert(env);
00688 
00689         //We need to go through the loaded objtypes and free them.
00690 
00691         g_free(env);
00692 }
00693 
00703 osync_bool osync_conv_set_common_format(OSyncFormatEnv *env, const char *objtypestr, const char *formatname, OSyncError **error)
00704 {
00705         OSyncObjType *type = osync_conv_find_objtype(env, objtypestr);
00706         if (!type) {
00707                 osync_error_set(error, OSYNC_ERROR_GENERIC, "Unable to set a common format: Unable to find the object-type \"%s\"", objtypestr);
00708                 return FALSE;
00709         }
00710         OSyncObjFormat *format = osync_conv_find_objformat(env, formatname);
00711         if (!format) {
00712                 osync_error_set(error, OSYNC_ERROR_GENERIC, "Unable to set a common format: Unable to find the format \"%s\"", formatname);
00713                 return FALSE;
00714         }
00715         type->common_format = format;
00716         return TRUE;
00717 }
00718 
00726 OSyncObjType *osync_conv_find_objtype(OSyncFormatEnv *env, const char *name)
00727 {
00728         g_assert(env);
00729         g_assert(name);
00730         
00731         GList *element = NULL;
00732         for (element = env->objtypes; element; element = element->next) {
00733                 OSyncObjType *type = element->data;
00734                 if (!strcmp(type->name, name))
00735                         return type;
00736         }
00737         osync_debug("CONV", 1, "Unable to find the requested objtype \"%s\"", name);
00738         return NULL;
00739 }
00740 
00747 int osync_conv_num_objtypes(OSyncFormatEnv *env)
00748 {
00749         g_assert(env);
00750         return g_list_length(env->objtypes);
00751 }
00752 
00760 OSyncObjType *osync_conv_nth_objtype(OSyncFormatEnv *env, int nth)
00761 {
00762         g_assert(env);
00763         return g_list_nth_data(env->objtypes, nth);
00764 }
00765 
00773 OSyncObjFormat *osync_conv_find_objformat(OSyncFormatEnv *env, const char *name)
00774 {
00775         g_assert(env);
00776         g_assert(name);
00777         
00778         GList *element = NULL;
00779         for (element = env->objformats; element; element = element->next) {
00780                 OSyncObjFormat *format = element->data;
00781                 if (!strcmp(format->name, name))
00782                         return format;
00783         }
00784         return NULL;
00785 }
00786 
00793 int osync_conv_num_objformats(OSyncObjType *type)
00794 {
00795         g_assert(type);
00796         return g_list_length(type->formats);
00797 }
00798 
00806 OSyncObjFormat *osync_conv_nth_objformat(OSyncObjType *type, int nth)
00807 {
00808         g_assert(type);
00809         return g_list_nth_data(type->formats, nth);
00810 }
00811 
00820 OSyncFormatConverter *osync_conv_find_converter(OSyncFormatEnv *env, const char *sourcename, const char *targetname)
00821 {
00822         g_assert(env);
00823         g_assert(sourcename);
00824         g_assert(targetname);
00825 
00826         OSyncObjFormat *fmt_src = osync_conv_find_objformat(env, sourcename);
00827         if (!fmt_src)
00828                 return NULL;
00829         OSyncObjFormat *fmt_trg = osync_conv_find_objformat(env, targetname);
00830         if (!fmt_trg)
00831                 return NULL;
00832         
00833         return osync_conv_find_converter_objformat(env, fmt_src, fmt_trg);
00834 }
00835 
00845 OSyncFormatExtension *osync_conv_find_extension(OSyncFormatEnv *env, OSyncObjFormat *from_format, OSyncObjFormat *to_format, const char *extension_name)
00846 {
00847         g_assert(env);
00848         g_assert(extension_name);
00849 
00850         GList *i = NULL;
00851         for (i = env->extensions; i; i = i->next) {
00852                 OSyncFormatExtension *extension = i->data;
00853                 osync_trace(TRACE_INTERNAL, "comparing format %p:%p %p:%p name %s:%s", extension->from_format, from_format, extension->to_format, to_format, extension->name, extension_name);
00854                 if ((extension->from_format == from_format || !from_format) && (extension->to_format == to_format || !to_format) && !strcmp(extension->name, extension_name))
00855                         return extension;
00856         }
00857         return NULL;
00858 }
00859 
00866 const char *osync_objtype_get_name(OSyncObjType *type)
00867 {
00868         g_assert(type);
00869         return type->name;
00870 }
00871 
00878 const char *osync_objformat_get_name(OSyncObjFormat *format)
00879 {
00880         g_assert(format);
00881         return format->name;
00882 }
00883 
00890 OSyncObjType *osync_objformat_get_objtype(OSyncObjFormat *format)
00891 {
00892         g_assert(format);
00893         return format->objtype;
00894 }
00895 

Generated on Fri Sep 17 2010 for OpenSync by  doxygen 1.7.1