QOF
0.8.7
|
00001 /*************************************************************************** 00002 * qsf-xml-map.c 00003 * 00004 * Sat Jan 1 07:31:55 2005 00005 * Copyright 2005-2006 Neil Williams 00006 * linux@codehelp.co.uk 00007 ****************************************************************************/ 00008 /* 00009 * This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00022 */ 00023 00024 #include "config.h" 00025 #include <glib.h> 00026 #include <libxml/xmlversion.h> 00027 #include <libxml/xmlmemory.h> 00028 #include <libxml/tree.h> 00029 #include <libxml/parser.h> 00030 #include <libxml/xmlschemas.h> 00031 #include "qof.h" 00032 #include "qof-backend-qsf.h" 00033 #include "qsf-xml.h" 00034 00035 static QofLogModule log_module = QOF_MOD_QSF; 00036 00037 static void 00038 qsf_date_default_handler (const gchar * default_name, 00039 GHashTable * qsf_default_hash, 00040 xmlNodePtr parent_tag, xmlNodePtr import_node, xmlNsPtr ns) 00041 { 00042 xmlNodePtr output_parent; 00043 time_t *qsf_time; 00044 gchar date_as_string[QSF_DATE_LENGTH]; 00045 00046 output_parent = xmlAddChild (parent_tag, xmlNewNode (ns, 00047 xmlGetProp (import_node, BAD_CAST QSF_OBJECT_TYPE))); 00048 xmlNewProp (output_parent, BAD_CAST QSF_OBJECT_TYPE, 00049 xmlGetProp (import_node, BAD_CAST MAP_VALUE_ATTR)); 00050 qsf_time = 00051 (time_t *) g_hash_table_lookup (qsf_default_hash, default_name); 00052 strftime (date_as_string, QSF_DATE_LENGTH, QSF_XSD_TIME, 00053 gmtime (qsf_time)); 00054 xmlNodeAddContent (output_parent, BAD_CAST date_as_string); 00055 } 00056 00057 static void 00058 qsf_string_default_handler (const gchar * default_name, 00059 GHashTable * qsf_default_hash, 00060 xmlNodePtr parent_tag, xmlNodePtr import_node, xmlNsPtr ns) 00061 { 00062 xmlNodePtr node; 00063 xmlChar *output; 00064 00065 node = xmlAddChild (parent_tag, 00066 xmlNewNode (ns, 00067 xmlGetProp (import_node, BAD_CAST QSF_OBJECT_TYPE))); 00068 xmlNewProp (node, BAD_CAST QSF_OBJECT_TYPE, 00069 xmlGetProp (import_node, BAD_CAST MAP_VALUE_ATTR)); 00070 output = 00071 (xmlChar *) g_hash_table_lookup (qsf_default_hash, default_name); 00072 xmlNodeAddContent (node, output); 00073 } 00074 00075 static void 00076 qsf_map_validation_handler (xmlNodePtr child, xmlNsPtr ns, 00077 QsfValidator * valid) 00078 { 00079 xmlChar *qof_version, *obj_type; 00080 gboolean is_registered; 00081 gchar *buff; 00082 xmlNodePtr child_node; 00083 QsfStatus type, incoming_type; 00084 00085 buff = NULL; 00086 is_registered = FALSE; 00087 type = QSF_NO_OBJECT; 00088 if (qsf_is_element (child, ns, MAP_DEFINITION_TAG)) 00089 { 00090 qof_version = xmlGetProp (child, BAD_CAST MAP_QOF_VERSION); 00091 buff = g_strdup_printf ("%i", QSF_QOF_VERSION); 00092 if (xmlStrcmp (qof_version, BAD_CAST buff) != 0) 00093 { 00094 PERR (" Wrong QOF_VERSION in map '%s', should be %s", 00095 qof_version, buff); 00096 valid->error_state = QOF_FATAL; 00097 g_free (buff); 00098 return; 00099 } 00100 g_free (buff); 00101 for (child_node = child->children; child_node != NULL; 00102 child_node = child_node->next) 00103 { 00104 if (qsf_is_element (child_node, ns, MAP_DEFINE_TAG)) 00105 { 00106 obj_type = xmlGetProp (child_node, BAD_CAST MAP_E_TYPE); 00107 type = QSF_DEFINED_OBJECT; 00108 is_registered = qof_class_is_registered ((gchar*)obj_type); 00109 if (is_registered) 00110 { 00111 type = QSF_REGISTERED_OBJECT; 00112 } 00113 g_hash_table_insert (valid->map_table, obj_type, 00114 GINT_TO_POINTER (type)); 00115 } 00116 } 00117 } 00118 if (qsf_is_element (child, ns, MAP_OBJECT_TAG)) 00119 { 00120 obj_type = xmlGetProp (child, BAD_CAST MAP_TYPE_ATTR); 00121 /* check each listed object is either registered or calculated. */ 00122 type = 00123 GPOINTER_TO_INT (g_hash_table_lookup 00124 (valid->map_table, obj_type)); 00125 switch (type) 00126 { 00127 case QSF_DEFINED_OBJECT: 00128 /* we have a calculation for an unregistered object. */ 00129 /* Ignore the calculation that exists to support bidirectional maps. */ 00130 /* Check that the incoming QSF contains data for this object */ 00131 { 00132 /* lookup the same object in QSF object_table */ 00133 incoming_type = 00134 GPOINTER_TO_INT (g_hash_table_lookup 00135 (valid->object_table, obj_type)); 00136 switch (incoming_type) 00137 { 00138 case QSF_DEFINED_OBJECT: 00139 { 00140 valid->incoming_count++; 00141 g_hash_table_insert (valid->map_table, obj_type, 00142 GINT_TO_POINTER (type)); 00143 break; /* good, proceed. */ 00144 } 00145 default: 00146 { 00147 PERR (" Missing data: %s", obj_type); 00148 type = QSF_INVALID_OBJECT; 00149 break; 00150 } 00151 } 00152 break; 00153 } 00154 case QSF_REGISTERED_OBJECT: /* use this calculation. */ 00155 { 00156 type = QSF_CALCULATED_OBJECT; 00157 valid->map_calculated_count++; 00158 valid->qof_registered_count++; 00159 /* store the result */ 00160 g_hash_table_insert (valid->map_table, obj_type, 00161 GINT_TO_POINTER (type)); 00162 break; 00163 } 00164 default: 00165 { 00166 type = QSF_INVALID_OBJECT; 00167 break; 00168 } 00169 } 00170 PINFO (" final type=%s result=%d", obj_type, type); 00171 if (type == QSF_INVALID_OBJECT) 00172 { 00173 valid->error_state = QOF_FATAL; 00174 } 00175 } 00176 } 00177 00178 static QofErrorId 00179 check_qsf_object_with_map_internal (xmlDocPtr map_doc, xmlDocPtr doc) 00180 { 00181 xmlNodePtr map_root, object_root; 00182 struct QsfNodeIterate qsfiter; 00183 QsfValidator valid; 00184 xmlNsPtr map_ns; 00185 00186 valid.map_table = g_hash_table_new (g_str_hash, g_str_equal); 00187 valid.object_table = g_hash_table_new (g_str_hash, g_str_equal); 00188 map_root = xmlDocGetRootElement (map_doc); 00189 object_root = xmlDocGetRootElement (doc); 00190 valid.map_calculated_count = 0; 00191 valid.valid_object_count = 0; 00192 valid.qof_registered_count = 0; 00193 valid.incoming_count = 0; 00194 valid.error_state = QOF_SUCCESS; 00195 map_ns = map_root->ns; 00196 qsfiter.ns = object_root->ns; 00197 qsf_valid_foreach (object_root, qsf_object_validation_handler, 00198 &qsfiter, &valid); 00199 qsfiter.ns = map_ns; 00200 qsf_valid_foreach (map_root, qsf_map_validation_handler, &qsfiter, 00201 &valid); 00202 if (valid.error_state != QOF_SUCCESS) 00203 { 00204 PINFO (" Map is wrong. Trying the next map."); 00205 g_hash_table_destroy (valid.object_table); 00206 g_hash_table_destroy (valid.map_table); 00207 return valid.error_state; 00208 } 00209 /* check all counted objects are valid: 00210 Objects to be calculated must also be registered 00211 so that new objects can be created and populated 00212 from the incoming data: qof_registered_count > 0 00213 The incoming data must contain valid objects - 00214 not an empty QofBook: valid_object_count > 0 00215 The map must contain at least some calculations: 00216 map_calculated_count > 0 00217 */ 00218 if ((valid.qof_registered_count < 1) 00219 || (valid.map_calculated_count < 1) 00220 || (valid.valid_object_count < 1) 00221 || (valid.incoming_count < g_hash_table_size (valid.object_table))) 00222 { 00223 PINFO 00224 (" Map is wrong. map:%d object:%d reg:%d incoming:%d size:%d", 00225 valid.map_calculated_count, valid.valid_object_count, 00226 valid.qof_registered_count, valid.incoming_count, 00227 g_hash_table_size (valid.object_table)); 00228 g_hash_table_destroy (valid.object_table); 00229 g_hash_table_destroy (valid.map_table); 00230 return valid.error_state; 00231 } 00232 g_hash_table_destroy (valid.object_table); 00233 g_hash_table_destroy (valid.map_table); 00234 return QOF_SUCCESS; 00235 } 00236 00237 gboolean 00238 is_qsf_object_with_map_be (gchar * map_file, QsfParam * params) 00239 { 00240 xmlDocPtr doc, map_doc; 00241 QofErrorId result; 00242 gchar *path, *map_path; 00243 00244 g_return_val_if_fail ((params != NULL), FALSE); 00245 path = g_strdup (params->filepath); 00246 map_path = g_strdup_printf ("%s/%s", QSF_SCHEMA_DIR, map_file); 00247 PINFO (" checking map file '%s'", map_path); 00248 if (path == NULL) 00249 { 00250 qof_error_set_be (params->be, qof_error_register 00251 (_("The QSF XML file '%s' could not be found."), TRUE)); 00252 return FALSE; 00253 } 00254 doc = xmlParseFile (path); 00255 if (doc == NULL) 00256 { 00257 qof_error_set_be (params->be, qof_error_register 00258 (_("There was an error parsing the file '%s'."), TRUE)); 00259 return FALSE; 00260 } 00261 if (TRUE != qsf_is_valid (QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc)) 00262 { 00263 qof_error_set_be (params->be, qof_error_register 00264 (_("Invalid QSF Object file! The QSF object file '%s' " 00265 " failed to validate against the QSF object schema. " 00266 "The XML structure of the file is either not well-formed " 00267 "or the file contains illegal data."), TRUE)); 00268 return FALSE; 00269 } 00270 if (map_path == NULL) 00271 { 00272 qof_error_set_be (params->be, qof_error_register 00273 (_("The QSF map file '%s' could not be found."), TRUE)); 00274 return FALSE; 00275 } 00276 map_doc = xmlParseFile (map_path); 00277 if (map_doc == NULL) 00278 { 00279 qof_error_set_be (params->be, qof_error_register 00280 (_("There was an error parsing the file '%s'."), TRUE)); 00281 return FALSE; 00282 } 00283 result = check_qsf_object_with_map_internal (map_doc, doc); 00284 return (result == QOF_SUCCESS) ? TRUE : FALSE; 00285 } 00286 00287 gboolean 00288 is_qsf_object_with_map (const gchar * path, gchar * map_file) 00289 { 00290 xmlDocPtr doc, map_doc; 00291 QofErrorId result; 00292 gchar *map_path; 00293 00294 map_path = g_strdup_printf ("%s/%s", QSF_SCHEMA_DIR, map_file); 00295 if (path == NULL) 00296 { 00297 return FALSE; 00298 } 00299 doc = xmlParseFile (path); 00300 if (doc == NULL) 00301 { 00302 return FALSE; 00303 } 00304 if (TRUE != qsf_is_valid (QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc)) 00305 { 00306 return FALSE; 00307 } 00308 if (map_path == NULL) 00309 { 00310 return FALSE; 00311 } 00312 map_doc = xmlParseFile (map_path); 00313 result = check_qsf_object_with_map_internal (map_doc, doc); 00314 return (result == QOF_SUCCESS) ? TRUE : FALSE; 00315 } 00316 00317 gboolean 00318 is_qsf_map_be (QsfParam * params) 00319 { 00320 xmlDocPtr doc; 00321 struct QsfNodeIterate qsfiter; 00322 QsfValidator valid; 00323 xmlNodePtr map_root; 00324 xmlNsPtr map_ns; 00325 gchar *path; 00326 00327 g_return_val_if_fail ((params != NULL), FALSE); 00328 path = g_strdup (params->filepath); 00329 if (path == NULL) 00330 { 00331 qof_error_set_be (params->be, qof_error_register 00332 (_("The QSF XML file '%s' could not be found."), TRUE)); 00333 return FALSE; 00334 } 00335 doc = xmlParseFile (path); 00336 if (doc == NULL) 00337 { 00338 qof_error_set_be (params->be, qof_error_register 00339 (_("There was an error parsing the file '%s'."), TRUE)); 00340 return FALSE; 00341 } 00342 if (TRUE != qsf_is_valid (QSF_SCHEMA_DIR, QSF_MAP_SCHEMA, doc)) 00343 { 00344 qof_error_set_be (params->be, 00345 qof_error_register ( 00346 _("Invalid QSF Map file! The QSF map file " 00347 "failed to validate against the QSF map schema. " 00348 "The XML structure of the file is either not well-formed " 00349 "or the file contains illegal data."), FALSE)); 00350 return FALSE; 00351 } 00352 map_root = xmlDocGetRootElement (doc); 00353 map_ns = map_root->ns; 00354 qsfiter.ns = map_ns; 00355 valid.object_table = g_hash_table_new (g_str_hash, g_str_equal); 00356 valid.map_table = g_hash_table_new (g_str_hash, g_str_equal); 00357 valid.error_state = QOF_SUCCESS; 00358 qsf_valid_foreach (map_root, qsf_map_validation_handler, 00359 &qsfiter, &valid); 00360 if (valid.error_state != QOF_SUCCESS) 00361 { 00362 g_hash_table_destroy (valid.object_table); 00363 return FALSE; 00364 } 00365 g_hash_table_destroy (valid.object_table); 00366 return TRUE; 00367 } 00368 00369 gboolean 00370 is_qsf_map (const gchar * path) 00371 { 00372 xmlDocPtr doc; 00373 struct QsfNodeIterate qsfiter; 00374 QsfValidator valid; 00375 xmlNodePtr map_root; 00376 xmlNsPtr map_ns; 00377 00378 g_return_val_if_fail ((path != NULL), FALSE); 00379 if (path == NULL) 00380 { 00381 return FALSE; 00382 } 00383 doc = xmlParseFile (path); 00384 if (doc == NULL) 00385 { 00386 return FALSE; 00387 } 00388 if (TRUE != qsf_is_valid (QSF_SCHEMA_DIR, QSF_MAP_SCHEMA, doc)) 00389 { 00390 return FALSE; 00391 } 00392 map_root = xmlDocGetRootElement (doc); 00393 map_ns = map_root->ns; 00394 qsfiter.ns = map_ns; 00395 valid.error_state = QOF_SUCCESS; 00396 valid.map_table = g_hash_table_new (g_str_hash, g_str_equal); 00397 qsf_valid_foreach (map_root, qsf_map_validation_handler, 00398 &qsfiter, &valid); 00399 if (valid.error_state != QOF_SUCCESS) 00400 { 00401 g_hash_table_destroy (valid.map_table); 00402 return FALSE; 00403 } 00404 g_hash_table_destroy (valid.map_table); 00405 return TRUE; 00406 } 00407 00408 static void 00409 qsf_map_default_handler (xmlNodePtr child, xmlNsPtr ns, QsfParam * params) 00410 { 00411 xmlChar * G_GNUC_UNUSED qsf_enum; 00412 gchar *iterate; 00413 QofErrorId bad_map; 00414 00415 g_return_if_fail (params->qsf_define_hash != NULL); 00416 iterate = NULL; 00417 bad_map = qof_error_register 00418 (_("The selected QSF map '%s' contains unusable or " 00419 "missing data. This is usually because not all the " 00420 "required parameters for the defined objects have " 00421 "calculations described in the map."), TRUE); 00422 if (qsf_is_element (child, ns, MAP_DEFINE_TAG)) 00423 { 00424 iterate = (gchar*) xmlGetProp (child, BAD_CAST MAP_ITERATE_ATTR); 00425 if ((qof_util_bool_to_int (iterate) == 1) && 00426 (qof_class_is_registered 00427 ((gchar*) xmlGetProp (child, BAD_CAST MAP_E_TYPE)))) 00428 { 00429 params->qof_foreach = (gchar*) xmlGetProp (child, BAD_CAST MAP_E_TYPE); 00430 PINFO (" iterating over '%s' objects", params->qof_foreach); 00431 } 00432 if (NULL == g_hash_table_lookup (params->qsf_define_hash, 00433 xmlGetProp (child, BAD_CAST MAP_E_TYPE))) 00434 { 00435 g_hash_table_insert (params->qsf_define_hash, 00436 xmlGetProp (child, BAD_CAST MAP_E_TYPE), 00437 params->child_node); 00438 } 00439 else 00440 { 00441 qof_error_set_be (params->be, bad_map); 00442 PERR (" ERR_QSF_BAD_MAP set"); 00443 return; 00444 } 00445 } 00446 if (qsf_is_element (child, ns, MAP_DEFAULT_TAG)) 00447 { 00448 if (qsf_strings_equal 00449 (xmlGetProp (child, BAD_CAST MAP_TYPE_ATTR), MAP_ENUM_TYPE)) 00450 { 00451 qsf_enum = xmlNodeGetContent (child); 00453 PERR (" enum todo incomplete"); 00457 if (NULL == g_hash_table_lookup (params->qsf_default_hash, 00458 xmlNodeGetContent (child))) 00459 { 00460 g_hash_table_insert (params->qsf_default_hash, 00461 xmlNodeGetContent (child), child); 00462 } 00463 else 00464 { 00465 qof_error_set_be (params->be, bad_map); 00466 PERR (" ERR_QSF_BAD_MAP set"); 00467 return; 00468 } 00469 } 00471 else 00472 { 00473 if (NULL == g_hash_table_lookup (params->qsf_default_hash, 00474 xmlGetProp (child, BAD_CAST MAP_NAME_ATTR))) 00475 { 00476 g_hash_table_insert (params->qsf_default_hash, 00477 xmlGetProp (child, BAD_CAST MAP_NAME_ATTR), child); 00478 } 00479 else 00480 /* if(0 != xmlHashAddEntry(params->default_map, 00481 xmlGetProp(child_node, MAP_NAME_ATTR), child_node))*/ 00482 { 00483 qof_error_set_be (params->be, bad_map); 00484 PERR (" ERR_QSF_BAD_MAP set"); 00485 return; 00486 } 00487 } 00488 } 00489 } 00490 00491 static void 00492 qsf_map_top_node_handler (xmlNodePtr child, xmlNsPtr ns, 00493 QsfParam * params) 00494 { 00495 xmlChar *qof_version; 00496 gchar *buff; 00497 struct QsfNodeIterate qsfiter; 00498 00499 if (!params->qsf_define_hash) 00500 return; 00501 if (!params->qsf_default_hash) 00502 return; 00503 ENTER (" map top node child=%s", child->name); 00504 buff = NULL; 00505 if (qsf_is_element (child, ns, MAP_DEFINITION_TAG)) 00506 { 00507 qof_version = xmlGetProp (child, BAD_CAST MAP_QOF_VERSION); 00508 buff = g_strdup_printf ("%i", QSF_QOF_VERSION); 00509 if (xmlStrcmp (qof_version, BAD_CAST buff) != 0) 00510 { 00511 qof_error_set_be (params->be, qof_error_register( 00512 _("The QSF Map file '%s' was written for a different " 00513 "version of QOF. It may need to be modified to work with " 00514 "your current QOF installation."), TRUE)); 00515 LEAVE (" BAD QOF VERSION"); 00516 return; 00517 } 00518 qsfiter.ns = ns; 00519 qsf_node_foreach (child, qsf_map_default_handler, &qsfiter, params); 00520 } 00521 LEAVE (" "); 00522 } 00523 00524 static char * 00525 qsf_else_set_value (xmlNodePtr parent, gchar * content, 00526 xmlNsPtr map_ns) 00527 { 00528 xmlNodePtr cur_node; 00529 00530 content = NULL; 00531 for (cur_node = parent->children; cur_node != NULL; 00532 cur_node = cur_node->next) 00533 { 00534 if (qsf_is_element (cur_node, map_ns, QSF_CONDITIONAL_SET)) 00535 { 00536 content = (gchar *) xmlNodeGetContent (cur_node); 00537 return content; 00538 } 00539 } 00540 return NULL; 00541 } 00542 00543 /* Handles the set tag in the map. 00544 This function will be overhauled once inside QOF 00545 QOF hook required for "Lookup in the receiving application" 00546 */ 00547 static gchar * 00548 qsf_set_handler (xmlNodePtr parent, GHashTable * default_hash, 00549 gchar * content, QsfParam * params) 00550 { 00551 xmlNodePtr cur_node, lookup_node; 00552 00553 ENTER (" lookup problem"); 00554 content = NULL; 00555 for (cur_node = parent->children; cur_node != NULL; 00556 cur_node = cur_node->next) 00557 { 00558 if (qsf_is_element (cur_node, params->map_ns, QSF_CONDITIONAL_SET)) 00559 { 00560 content = (gchar *) xmlGetProp (cur_node, BAD_CAST QSF_OPTION); 00561 if (qsf_strings_equal (xmlGetProp (cur_node, 00562 BAD_CAST QSF_OPTION), "qsf_lookup_string")) 00563 { 00564 lookup_node = 00565 (xmlNodePtr) g_hash_table_lookup (default_hash, 00566 xmlNodeGetContent (cur_node)); 00567 content = 00568 (gchar *) xmlGetProp (lookup_node, 00569 BAD_CAST MAP_VALUE_ATTR); 00571 /* Find by name, get GUID, return GUID as string. */ 00572 g_message ("Lookup %s in the receiving application\n", 00573 content); 00574 LEAVE (" todo"); 00575 return content; 00576 } 00577 if (content) 00578 { 00579 lookup_node = 00580 (xmlNodePtr) g_hash_table_lookup (default_hash, 00581 xmlNodeGetContent (cur_node)); 00582 content = 00583 (gchar *) xmlGetProp (lookup_node, BAD_CAST "value"); 00584 return content; 00585 } 00586 content = (gchar *) xmlGetProp (parent, BAD_CAST "boolean"); 00587 if (!content) 00588 { 00590 lookup_node = 00591 (xmlNodePtr) g_hash_table_lookup (params-> 00592 qsf_parameter_hash, 00593 xmlGetProp (parent->parent, BAD_CAST MAP_TYPE_ATTR)); 00594 if (lookup_node) 00595 { 00596 return (gchar *) xmlNodeGetContent (lookup_node); 00597 } 00598 LEAVE (" check arguments"); 00599 return (gchar *) xmlNodeGetContent (cur_node); 00600 } 00601 } 00602 } 00603 LEAVE (" null"); 00604 return NULL; 00605 } 00606 00607 static void 00608 qsf_calculate_else (xmlNodePtr param_node, xmlNodePtr child, 00609 QsfParam * params) 00610 { 00611 xmlNodePtr export_node; 00612 xmlChar *output_content, *object_data; 00613 00614 if (qsf_is_element (param_node, params->map_ns, QSF_CONDITIONAL_ELSE)) 00615 { 00616 if (params->boolean_calculation_done == 0) 00617 { 00618 output_content = object_data = NULL; 00619 output_content = BAD_CAST qsf_set_handler (param_node, 00620 params-> 00621 qsf_default_hash, (gchar *) output_content, params); 00622 if (output_content == NULL) 00623 { 00624 output_content = 00625 xmlGetProp (param_node, BAD_CAST MAP_TYPE_ATTR); 00626 object_data = 00627 BAD_CAST qsf_else_set_value (param_node, 00628 (gchar *) output_content, params->map_ns); 00629 output_content = 00630 BAD_CAST xmlGetProp ((xmlNodePtr) 00631 g_hash_table_lookup (params-> 00632 qsf_default_hash, 00633 object_data), BAD_CAST MAP_VALUE_ATTR); 00634 } 00635 if (object_data != NULL) 00636 { 00637 export_node = 00638 (xmlNodePtr) g_hash_table_lookup (params-> 00639 qsf_parameter_hash, 00640 xmlGetProp (params-> 00641 child_node, BAD_CAST QSF_OBJECT_TYPE)); 00642 object_data = xmlNodeGetContent (export_node); 00643 } 00644 if (output_content != NULL) 00645 { 00646 object_data = output_content; 00647 } 00648 export_node = 00649 xmlAddChild (params->lister, 00650 xmlNewNode (params->qsf_ns, 00651 xmlGetProp (child, BAD_CAST QSF_OBJECT_TYPE))); 00652 xmlNewProp (export_node, BAD_CAST QSF_OBJECT_TYPE, 00653 xmlGetProp (child, BAD_CAST MAP_VALUE_ATTR)); 00654 xmlNodeAddContent (export_node, object_data); 00655 params->boolean_calculation_done = 1; 00656 } 00657 } 00658 } 00659 00660 static void 00661 qsf_set_format_value (xmlChar * format, gchar * qsf_time_now_as_string, 00662 xmlNodePtr cur_node, QsfParam * params) 00663 { 00664 gint result; 00665 xmlChar *content; 00666 time_t *output; 00667 struct tm *tmp; 00668 time_t tester; 00669 xmlNodePtr kl; 00670 regex_t reg; 00671 00674 result = 0; 00675 if (format == NULL) 00676 { 00677 return; 00678 } 00679 ENTER (" "); 00680 content = xmlNodeGetContent (cur_node); 00681 output = 00682 (time_t *) g_hash_table_lookup (params->qsf_default_hash, content); 00683 if (!output) 00684 { 00687 tester = time (NULL); 00688 tmp = gmtime (&tester); 00691 kl = (xmlNodePtr) g_hash_table_lookup (params->qsf_parameter_hash, 00692 content); 00693 if (!kl) 00694 { 00695 LEAVE (" no suitable date set."); 00696 return; 00697 } 00699 strptime ((char *) xmlNodeGetContent (kl), QSF_XSD_TIME, tmp); 00700 if (!tmp) 00701 { 00702 LEAVE (" empty date field in QSF object.\n"); 00703 return; 00704 } 00705 tester = mktime (tmp); 00706 output = &tester; 00707 } 00708 result = regcomp (®, "%[a-zA-Z]", REG_EXTENDED | REG_NOSUB); 00709 result = regexec (®, (gchar *) format, (size_t) 0, NULL, 0); 00710 if (result == REG_NOMATCH) 00711 { 00712 format = BAD_CAST "%F"; 00713 } 00714 regfree (®); 00715 /* QSF_DATE_LENGTH preset for all internal and QSF_XSD_TIME string formats. */ 00716 strftime (qsf_time_now_as_string, QSF_DATE_LENGTH, (char *) format, 00717 gmtime (output)); 00718 LEAVE (" ok"); 00719 } 00720 00721 static void 00722 qsf_boolean_set_value (xmlNodePtr parent, QsfParam * params, 00723 gchar * content, xmlNsPtr map_ns) 00724 { 00725 xmlNodePtr cur_node; 00726 xmlChar *boolean_name; 00727 00728 boolean_name = NULL; 00729 for (cur_node = parent->children; cur_node != NULL; 00730 cur_node = cur_node->next) 00731 { 00732 if (qsf_is_element (cur_node, map_ns, QSF_CONDITIONAL_SET)) 00733 { 00734 boolean_name = 00735 xmlGetProp (cur_node, BAD_CAST QSF_FORMATTING_OPTION); 00736 qsf_set_format_value (boolean_name, content, cur_node, params); 00737 } 00738 } 00739 } 00740 00741 static void 00742 qsf_calculate_conditional (xmlNodePtr param_node, xmlNodePtr child, 00743 QsfParam * params) 00744 { 00745 xmlNodePtr export_node; 00746 xmlChar *output_content; 00747 00748 output_content = NULL; 00749 if (qsf_is_element (param_node, params->map_ns, QSF_CONDITIONAL)) 00750 { 00751 if (params->boolean_calculation_done == 0) 00752 { 00753 /* set handler */ 00754 output_content = 00755 BAD_CAST qsf_set_handler (param_node, 00756 params->qsf_default_hash, 00757 (gchar *) output_content, params); 00758 /* If the 'if' contains a boolean that has a default value */ 00759 if (output_content == NULL) 00760 { 00761 if (NULL != 00762 xmlGetProp (param_node, BAD_CAST QSF_BOOLEAN_DEFAULT)) 00763 { 00764 output_content = 00765 xmlGetProp ((xmlNodePtr) 00766 g_hash_table_lookup (params-> 00767 qsf_default_hash, 00768 xmlGetProp 00769 (param_node, 00770 BAD_CAST 00771 QSF_BOOLEAN_DEFAULT)), 00772 BAD_CAST MAP_VALUE_ATTR); 00773 } 00774 /* Is the default set to true? */ 00775 if (0 == 00776 qsf_compare_tag_strings (output_content, 00777 QSF_XML_BOOLEAN_TEST)) 00778 { 00779 qsf_boolean_set_value (param_node, params, 00780 (gchar *) output_content, params->map_ns); 00781 export_node = 00782 xmlAddChild (params->lister, 00783 xmlNewNode (params->qsf_ns, 00784 xmlGetProp (child, BAD_CAST QSF_OBJECT_TYPE))); 00785 xmlNewProp (export_node, BAD_CAST QSF_OBJECT_TYPE, 00786 xmlGetProp (child, BAD_CAST MAP_VALUE_ATTR)); 00787 xmlNodeAddContent (export_node, output_content); 00788 params->boolean_calculation_done = 1; 00789 } 00790 } 00791 } 00792 } 00793 } 00794 00795 static void 00796 qsf_add_object_tag (QsfParam * params, gint count) 00797 { 00798 xmlNodePtr extra_node; 00799 GString *str; 00800 xmlChar *property; 00801 00802 str = g_string_new (" "); 00803 g_string_printf (str, "%i", count); 00804 extra_node = NULL; 00805 extra_node = xmlAddChild (params->output_node, 00806 xmlNewNode (params->qsf_ns, BAD_CAST QSF_OBJECT_TAG)); 00807 xmlNewProp (extra_node, BAD_CAST QSF_OBJECT_TYPE, 00808 xmlGetProp (params->convert_node, BAD_CAST QSF_OBJECT_TYPE)); 00809 property = xmlCharStrdup (str->str); 00810 xmlNewProp (extra_node, BAD_CAST QSF_OBJECT_COUNT, property); 00811 params->lister = extra_node; 00812 } 00813 00814 static gint 00815 identify_source_func (gconstpointer qsf_object, gconstpointer map) 00816 { 00817 PINFO (" qsf_object=%s, map=%s", 00818 ((QsfObject *) qsf_object)->object_type, (QofIdType) map); 00819 return safe_strcmp (((QsfObject *) qsf_object)->object_type, 00820 (QofIdType) map); 00821 } 00822 00823 static void 00824 qsf_map_calculate_output (xmlNodePtr param_node, xmlNodePtr child, 00825 QsfParam * params) 00826 { 00827 xmlNodePtr export_node; 00828 xmlChar *output_content; 00829 xmlNodePtr input_node; 00830 GList *source; 00831 00832 output_content = xmlNodeGetContent (param_node); 00833 DEBUG (" %s", output_content); 00834 /* source refers to the source object that provides the data */ 00835 source = g_list_find_custom (params->qsf_object_list, 00836 BAD_CAST xmlGetProp (param_node, 00837 BAD_CAST MAP_OBJECT_ATTR), identify_source_func); 00838 PINFO (" checking %s", BAD_CAST xmlGetProp (param_node, 00839 BAD_CAST MAP_OBJECT_ATTR)); 00840 if (!source) 00841 { 00842 DEBUG (" no source found in list."); 00843 return; 00844 } 00845 params->object_set = source->data; 00846 input_node = g_hash_table_lookup (params->object_set->parameters, 00847 output_content); 00848 DEBUG (" node_value=%s, content=%s", 00849 xmlGetProp (child, BAD_CAST MAP_VALUE_ATTR), 00850 xmlNodeGetContent (input_node)); 00851 export_node = xmlAddChild (params->lister, xmlNewNode (params->qsf_ns, 00852 xmlGetProp (child, BAD_CAST QSF_OBJECT_TYPE))); 00853 xmlNewProp (export_node, BAD_CAST QSF_OBJECT_TYPE, 00854 xmlGetProp (child, BAD_CAST MAP_VALUE_ATTR)); 00855 xmlNodeAddContent (export_node, xmlNodeGetContent (input_node)); 00856 } 00857 00858 static void 00859 qsf_map_object_handler (xmlNodePtr child, xmlNsPtr ns, QsfParam * params) 00860 { 00861 xmlNodePtr param_node; 00862 xmlNsPtr map_ns, qsf_ns; 00863 gint G_GNUC_UNUSED result; 00864 00865 map_ns = ns; 00866 qsf_ns = params->qsf_ns; 00867 param_node = NULL; 00868 result = 0; 00869 if (child == NULL) 00870 { 00871 return; 00872 } 00873 if (ns == NULL) 00874 { 00875 return; 00876 } 00877 params->boolean_calculation_done = 0; 00878 00879 if (qsf_is_element (child, map_ns, MAP_CALCULATE_TAG)) 00880 { 00881 params->boolean_calculation_done = 0; 00882 /* read the child nodes to prepare the calculation. */ 00883 for (param_node = child->children; param_node != NULL; 00884 param_node = param_node->next) 00885 { 00886 if (qsf_is_element (param_node, map_ns, QSF_CONDITIONAL_SET)) 00887 { 00888 /* Map the pre-defined defaults */ 00889 if (0 == 00890 qsf_compare_tag_strings (xmlNodeGetContent 00891 (param_node), "qsf_enquiry_date")) 00892 { 00893 qsf_string_default_handler ("qsf_enquiry_date", 00894 params->qsf_default_hash, 00895 params->lister, child, qsf_ns); 00896 } 00897 if (0 == 00898 qsf_compare_tag_strings (xmlNodeGetContent 00899 (param_node), "qsf_time_now")) 00900 { 00901 qsf_date_default_handler ("qsf_time_now", 00902 params->qsf_default_hash, 00903 params->lister, child, qsf_ns); 00904 } 00905 if (0 == 00906 qsf_compare_tag_strings (xmlNodeGetContent 00907 (param_node), "qsf_time_string")) 00908 { 00909 qsf_string_default_handler ("qsf_time_string", 00910 params->qsf_default_hash, 00911 params->lister, child, qsf_ns); 00912 } 00913 qsf_map_calculate_output (param_node, child, params); 00914 } 00915 qsf_calculate_conditional (param_node, child, params); 00916 qsf_calculate_else (param_node, child, params); 00917 } 00918 /* calculate_map currently not in use */ 00919 /* ensure uniqueness of the key before re-instating */ 00920 /* result = xmlHashAddEntry2(calculate_map, 00921 xmlGetProp(child_node, MAP_TYPE_ATTR), 00922 xmlGetProp(child_node, MAP_VALUE_ATTR), child_node); 00923 if(result != 0) { 00924 printf("add entry to calculate hash failed. %s\t%s\t%s.\n", 00925 xmlGetProp(child_node, MAP_TYPE_ATTR), 00926 xmlGetProp(child_node, MAP_VALUE_ATTR), child_node->name); 00927 return; 00928 } 00929 00930 is_qsf_object_with_map(path, map_path); 00931 */ 00932 } 00933 } 00934 00935 static void 00936 iterator_cb (xmlNodePtr child, xmlNsPtr ns, QsfParam * params) 00937 { 00938 gchar *object_name; 00939 00940 /* count the number of iterators in the QSF file */ 00941 if (qsf_is_element (child, ns, QSF_OBJECT_TAG)) 00942 { 00943 object_name = (gchar*) xmlGetProp (child, BAD_CAST QSF_OBJECT_TYPE); 00944 if (0 == safe_strcmp (object_name, params->qof_foreach)) 00945 { 00946 params->foreach_limit++; 00947 } 00948 } 00949 } 00950 00951 xmlDocPtr 00952 qsf_object_convert (xmlDocPtr mapDoc, xmlNodePtr qsf_root, 00953 QsfParam * params) 00954 { 00955 /* mapDoc : map document. qsf_root: incoming QSF root node. */ 00956 struct QsfNodeIterate qsfiter; 00957 xmlDocPtr output_doc; 00958 xmlNode *cur_node; 00959 xmlNode *map_root, *output_root; 00960 00961 g_return_val_if_fail ((mapDoc && qsf_root && params), NULL); 00962 ENTER (" root=%s", qsf_root->name); 00963 /* prepare the intermediary document */ 00964 qsfiter.ns = params->qsf_ns; 00965 output_doc = xmlNewDoc (BAD_CAST QSF_XML_VERSION); 00966 output_root = xmlNewNode (NULL, BAD_CAST QSF_ROOT_TAG); 00967 xmlDocSetRootElement (output_doc, output_root); 00968 xmlSetNs (output_root, params->qsf_ns); 00969 params->output_node = xmlNewChild (output_root, params->qsf_ns, 00970 BAD_CAST QSF_BOOK_TAG, NULL); 00971 xmlNewProp (params->output_node, BAD_CAST QSF_BOOK_COUNT, 00972 BAD_CAST "1"); 00973 /* parse the incoming QSF */ 00974 qsf_book_node_handler (qsf_root->children->next, params->qsf_ns, 00975 params); 00976 /* parse the map and calculate the values */ 00977 map_root = xmlDocGetRootElement (mapDoc); 00978 params->foreach_limit = 0; 00979 qsfiter.ns = params->map_ns; 00980 /* sets qof_foreach iterator, defines and defaults. */ 00981 qsf_node_foreach (map_root, qsf_map_top_node_handler, &qsfiter, params); 00982 /* identify the entities of iterator type. */ 00983 qsfiter.ns = params->qsf_ns; 00984 qsf_node_foreach (qsf_root->children->next, iterator_cb, &qsfiter, 00985 params); 00986 PINFO (" counted %d records", params->foreach_limit); 00987 params->count = 0; 00988 for (cur_node = map_root->children; cur_node != NULL; 00989 cur_node = cur_node->next) 00990 { 00991 params->convert_node = cur_node; 00992 if (qsf_is_element (cur_node, params->map_ns, MAP_OBJECT_TAG)) 00993 { 00994 gint i; 00995 00996 params->lister = NULL; 00997 PINFO (" found an object tag. starting calculation"); 00998 /* cur_node describes the target object */ 00999 if (!qof_class_is_registered ((gchar*) 01000 xmlGetProp (cur_node, BAD_CAST MAP_TYPE_ATTR))) 01001 { 01002 continue; 01003 } 01004 qsf_add_object_tag (params, params->count); 01005 params->count++; 01006 qsfiter.ns = params->map_ns; 01007 PINFO (" params->foreach_limit=%d", params->foreach_limit); 01008 for (i = -1; i < params->foreach_limit; i++) 01009 { 01010 qsf_node_foreach (cur_node, qsf_map_object_handler, 01011 &qsfiter, params); 01012 params->qsf_object_list = 01013 g_list_next (params->qsf_object_list); 01014 params->count++; 01015 } 01016 } 01017 } 01018 params->file_type = OUR_QSF_OBJ; 01019 /* use for debugging */ 01020 xmlSaveFormatFileEnc ("-", output_doc, "UTF-8", 1); 01021 LEAVE (" "); 01022 return output_doc; 01023 }