26 #include <libxml/xmlversion.h> 27 #include <libxml/xmlmemory.h> 28 #include <libxml/tree.h> 29 #include <libxml/parser.h> 30 #include <libxml/xmlschemas.h> 38 qsf_date_default_handler (
const gchar * default_name,
39 GHashTable * qsf_default_hash,
40 xmlNodePtr parent_tag, xmlNodePtr import_node, xmlNsPtr ns)
42 xmlNodePtr output_parent;
46 output_parent = xmlAddChild (parent_tag, xmlNewNode (ns,
51 (time_t *) g_hash_table_lookup (qsf_default_hash, default_name);
54 xmlNodeAddContent (output_parent, BAD_CAST date_as_string);
58 qsf_string_default_handler (
const gchar * default_name,
59 GHashTable * qsf_default_hash,
60 xmlNodePtr parent_tag, xmlNodePtr import_node, xmlNsPtr ns)
65 node = xmlAddChild (parent_tag,
67 xmlGetProp (import_node, BAD_CAST QSF_OBJECT_TYPE)));
68 xmlNewProp (node, BAD_CAST QSF_OBJECT_TYPE,
71 (xmlChar *) g_hash_table_lookup (qsf_default_hash, default_name);
72 xmlNodeAddContent (node, output);
76 qsf_map_validation_handler (xmlNodePtr child, xmlNsPtr ns,
79 xmlChar *qof_version, *obj_type;
80 gboolean is_registered;
82 xmlNodePtr child_node;
86 is_registered = FALSE;
92 if (xmlStrcmp (qof_version, BAD_CAST buff) != 0)
94 PERR (
" Wrong QOF_VERSION in map '%s', should be %s",
101 for (child_node = child->children; child_node != NULL;
102 child_node = child_node->next)
106 obj_type = xmlGetProp (child_node, BAD_CAST
MAP_E_TYPE);
113 g_hash_table_insert (valid->
map_table, obj_type,
114 GINT_TO_POINTER (type));
123 GPOINTER_TO_INT (g_hash_table_lookup
134 GPOINTER_TO_INT (g_hash_table_lookup
136 switch (incoming_type)
141 g_hash_table_insert (valid->
map_table, obj_type,
142 GINT_TO_POINTER (type));
147 PERR (
" Missing data: %s", obj_type);
160 g_hash_table_insert (valid->
map_table, obj_type,
161 GINT_TO_POINTER (type));
170 PINFO (
" final type=%s result=%d", obj_type, type);
179 check_qsf_object_with_map_internal (xmlDocPtr map_doc, xmlDocPtr doc)
181 xmlNodePtr map_root, object_root;
186 valid.
map_table = g_hash_table_new (g_str_hash, g_str_equal);
187 valid.object_table = g_hash_table_new (g_str_hash, g_str_equal);
188 map_root = xmlDocGetRootElement (map_doc);
189 object_root = xmlDocGetRootElement (doc);
190 valid.map_calculated_count = 0;
191 valid.valid_object_count = 0;
192 valid.qof_registered_count = 0;
193 valid.incoming_count = 0;
195 map_ns = map_root->ns;
196 qsfiter.ns = object_root->ns;
204 PINFO (
" Map is wrong. Trying the next map.");
205 g_hash_table_destroy (valid.object_table);
206 g_hash_table_destroy (valid.map_table);
207 return valid.error_state;
218 if ((valid.qof_registered_count < 1)
219 || (valid.map_calculated_count < 1)
220 || (valid.valid_object_count < 1)
221 || (valid.incoming_count < g_hash_table_size (valid.object_table)))
224 (
" Map is wrong. map:%d object:%d reg:%d incoming:%d size:%d",
225 valid.map_calculated_count, valid.valid_object_count,
226 valid.qof_registered_count, valid.incoming_count,
227 g_hash_table_size (valid.object_table));
228 g_hash_table_destroy (valid.object_table);
229 g_hash_table_destroy (valid.map_table);
230 return valid.error_state;
232 g_hash_table_destroy (valid.object_table);
233 g_hash_table_destroy (valid.map_table);
240 xmlDocPtr doc, map_doc;
242 gchar *path, *map_path;
244 g_return_val_if_fail ((params != NULL), FALSE);
246 map_path = g_strdup_printf (
"%s/%s", QSF_SCHEMA_DIR, map_file);
247 PINFO (
" checking map file '%s'", map_path);
251 (_(
"The QSF XML file '%s' could not be found."), TRUE));
254 doc = xmlParseFile (path);
258 (_(
"There was an error parsing the file '%s'."), TRUE));
264 (_(
"Invalid QSF Object file! The QSF object file '%s' " 265 " failed to validate against the QSF object schema. " 266 "The XML structure of the file is either not well-formed " 267 "or the file contains illegal data."), TRUE));
270 if (map_path == NULL)
273 (_(
"The QSF map file '%s' could not be found."), TRUE));
276 map_doc = xmlParseFile (map_path);
280 (_(
"There was an error parsing the file '%s'."), TRUE));
283 result = check_qsf_object_with_map_internal (map_doc, doc);
290 xmlDocPtr doc, map_doc;
294 map_path = g_strdup_printf (
"%s/%s", QSF_SCHEMA_DIR, map_file);
299 doc = xmlParseFile (path);
308 if (map_path == NULL)
312 map_doc = xmlParseFile (map_path);
313 result = check_qsf_object_with_map_internal (map_doc, doc);
327 g_return_val_if_fail ((params != NULL), FALSE);
332 (_(
"The QSF XML file '%s' could not be found."), TRUE));
335 doc = xmlParseFile (path);
339 (_(
"There was an error parsing the file '%s'."), TRUE));
344 qof_error_set_be (params->
be,
346 _(
"Invalid QSF Map file! The QSF map file " 347 "failed to validate against the QSF map schema. " 348 "The XML structure of the file is either not well-formed " 349 "or the file contains illegal data."), FALSE));
352 map_root = xmlDocGetRootElement (doc);
353 map_ns = map_root->ns;
355 valid.object_table = g_hash_table_new (g_str_hash, g_str_equal);
356 valid.map_table = g_hash_table_new (g_str_hash, g_str_equal);
362 g_hash_table_destroy (valid.object_table);
365 g_hash_table_destroy (valid.object_table);
378 g_return_val_if_fail ((path != NULL), FALSE);
383 doc = xmlParseFile (path);
392 map_root = xmlDocGetRootElement (doc);
393 map_ns = map_root->ns;
396 valid.map_table = g_hash_table_new (g_str_hash, g_str_equal);
401 g_hash_table_destroy (valid.map_table);
404 g_hash_table_destroy (valid.map_table);
409 qsf_map_default_handler (xmlNodePtr child, xmlNsPtr ns,
QsfParam * params)
411 xmlChar * G_GNUC_UNUSED qsf_enum;
415 g_return_if_fail (params->qsf_define_hash != NULL);
418 (_(
"The selected QSF map '%s' contains unusable or " 419 "missing data. This is usually because not all the " 420 "required parameters for the defined objects have " 421 "calculations described in the map."), TRUE);
427 ((gchar*) xmlGetProp (child, BAD_CAST
MAP_E_TYPE))))
429 params->
qof_foreach = (gchar*) xmlGetProp (child, BAD_CAST MAP_E_TYPE);
432 if (NULL == g_hash_table_lookup (params->qsf_define_hash,
433 xmlGetProp (child, BAD_CAST MAP_E_TYPE)))
435 g_hash_table_insert (params->qsf_define_hash,
436 xmlGetProp (child, BAD_CAST MAP_E_TYPE),
441 qof_error_set_be (params->
be, bad_map);
442 PERR (
" ERR_QSF_BAD_MAP set");
451 qsf_enum = xmlNodeGetContent (child);
453 PERR (
" enum todo incomplete");
457 if (NULL == g_hash_table_lookup (params->qsf_default_hash,
458 xmlNodeGetContent (child)))
460 g_hash_table_insert (params->qsf_default_hash,
461 xmlNodeGetContent (child), child);
465 qof_error_set_be (params->
be, bad_map);
466 PERR (
" ERR_QSF_BAD_MAP set");
473 if (NULL == g_hash_table_lookup (params->qsf_default_hash,
476 g_hash_table_insert (params->qsf_default_hash,
477 xmlGetProp (child, BAD_CAST MAP_NAME_ATTR), child);
483 qof_error_set_be (params->
be, bad_map);
484 PERR (
" ERR_QSF_BAD_MAP set");
492 qsf_map_top_node_handler (xmlNodePtr child, xmlNsPtr ns,
495 xmlChar *qof_version;
499 if (!params->qsf_define_hash)
501 if (!params->qsf_default_hash)
503 ENTER (
" map top node child=%s", child->name);
509 if (xmlStrcmp (qof_version, BAD_CAST buff) != 0)
512 _(
"The QSF Map file '%s' was written for a different " 513 "version of QOF. It may need to be modified to work with " 514 "your current QOF installation."), TRUE));
515 LEAVE (
" BAD QOF VERSION");
525 qsf_else_set_value (xmlNodePtr parent, gchar * content,
531 for (cur_node = parent->children; cur_node != NULL;
532 cur_node = cur_node->next)
536 content = (gchar *) xmlNodeGetContent (cur_node);
548 qsf_set_handler (xmlNodePtr parent, GHashTable * default_hash,
551 xmlNodePtr cur_node, lookup_node;
553 ENTER (
" lookup problem");
555 for (cur_node = parent->children; cur_node != NULL;
556 cur_node = cur_node->next)
560 content = (gchar *) xmlGetProp (cur_node, BAD_CAST
QSF_OPTION);
562 BAD_CAST QSF_OPTION),
"qsf_lookup_string"))
565 (xmlNodePtr) g_hash_table_lookup (default_hash,
566 xmlNodeGetContent (cur_node));
568 (gchar *) xmlGetProp (lookup_node,
572 g_message (
"Lookup %s in the receiving application\n",
580 (xmlNodePtr) g_hash_table_lookup (default_hash,
581 xmlNodeGetContent (cur_node));
583 (gchar *) xmlGetProp (lookup_node, BAD_CAST
"value");
586 content = (gchar *) xmlGetProp (parent, BAD_CAST
"boolean");
591 (xmlNodePtr) g_hash_table_lookup (params->
596 return (gchar *) xmlNodeGetContent (lookup_node);
598 LEAVE (
" check arguments");
599 return (gchar *) xmlNodeGetContent (cur_node);
608 qsf_calculate_else (xmlNodePtr param_node, xmlNodePtr child,
611 xmlNodePtr export_node;
612 xmlChar *output_content, *object_data;
618 output_content = object_data = NULL;
619 output_content = BAD_CAST qsf_set_handler (param_node,
621 qsf_default_hash, (gchar *) output_content, params);
622 if (output_content == NULL)
627 BAD_CAST qsf_else_set_value (param_node,
628 (gchar *) output_content, params->map_ns);
630 BAD_CAST xmlGetProp ((xmlNodePtr)
631 g_hash_table_lookup (params->
635 if (object_data != NULL)
638 (xmlNodePtr) g_hash_table_lookup (params->
641 child_node, BAD_CAST QSF_OBJECT_TYPE));
642 object_data = xmlNodeGetContent (export_node);
644 if (output_content != NULL)
646 object_data = output_content;
649 xmlAddChild (params->
lister,
650 xmlNewNode (params->
qsf_ns,
651 xmlGetProp (child, BAD_CAST QSF_OBJECT_TYPE)));
652 xmlNewProp (export_node, BAD_CAST QSF_OBJECT_TYPE,
654 xmlNodeAddContent (export_node, object_data);
661 qsf_set_format_value (xmlChar * format, gchar * qsf_time_now_as_string,
662 xmlNodePtr cur_node,
QsfParam * params)
680 content = xmlNodeGetContent (cur_node);
682 (time_t *) g_hash_table_lookup (params->qsf_default_hash, content);
687 tester = time (NULL);
688 tmp = gmtime (&tester);
695 LEAVE (
" no suitable date set.");
699 strptime ((
char *) xmlNodeGetContent (kl),
QSF_XSD_TIME, tmp);
702 LEAVE (
" empty date field in QSF object.\n");
705 tester = mktime (tmp);
708 result = regcomp (®,
"%[a-zA-Z]", REG_EXTENDED | REG_NOSUB);
709 result = regexec (®, (gchar *) format, (
size_t) 0, NULL, 0);
710 if (result == REG_NOMATCH)
712 format = BAD_CAST
"%F";
722 qsf_boolean_set_value (xmlNodePtr parent,
QsfParam * params,
723 gchar * content, xmlNsPtr map_ns)
726 xmlChar *boolean_name;
729 for (cur_node = parent->children; cur_node != NULL;
730 cur_node = cur_node->next)
736 qsf_set_format_value (boolean_name, content, cur_node, params);
742 qsf_calculate_conditional (xmlNodePtr param_node, xmlNodePtr child,
745 xmlNodePtr export_node;
746 xmlChar *output_content;
748 output_content = NULL;
755 BAD_CAST qsf_set_handler (param_node,
756 params->qsf_default_hash,
757 (gchar *) output_content, params);
759 if (output_content == NULL)
765 xmlGetProp ((xmlNodePtr)
766 g_hash_table_lookup (params->
771 QSF_BOOLEAN_DEFAULT)),
779 qsf_boolean_set_value (param_node, params,
780 (gchar *) output_content, params->map_ns);
782 xmlAddChild (params->
lister,
783 xmlNewNode (params->
qsf_ns,
784 xmlGetProp (child, BAD_CAST QSF_OBJECT_TYPE)));
785 xmlNewProp (export_node, BAD_CAST QSF_OBJECT_TYPE,
787 xmlNodeAddContent (export_node, output_content);
796 qsf_add_object_tag (
QsfParam * params, gint count)
798 xmlNodePtr extra_node;
802 str = g_string_new (
" ");
803 g_string_printf (str,
"%i", count);
807 xmlNewProp (extra_node, BAD_CAST QSF_OBJECT_TYPE,
808 xmlGetProp (params->
convert_node, BAD_CAST QSF_OBJECT_TYPE));
809 property = xmlCharStrdup (str->str);
811 params->
lister = extra_node;
815 identify_source_func (gconstpointer qsf_object, gconstpointer map)
817 PINFO (
" qsf_object=%s, map=%s",
824 qsf_map_calculate_output (xmlNodePtr param_node, xmlNodePtr child,
827 xmlNodePtr export_node;
828 xmlChar *output_content;
829 xmlNodePtr input_node;
832 output_content = xmlNodeGetContent (param_node);
833 DEBUG (
" %s", output_content);
836 BAD_CAST xmlGetProp (param_node,
838 PINFO (
" checking %s", BAD_CAST xmlGetProp (param_node,
839 BAD_CAST MAP_OBJECT_ATTR));
842 DEBUG (
" no source found in list.");
846 input_node = g_hash_table_lookup (params->
object_set->parameters,
848 DEBUG (
" node_value=%s, content=%s",
850 xmlNodeGetContent (input_node));
851 export_node = xmlAddChild (params->
lister, xmlNewNode (params->
qsf_ns,
852 xmlGetProp (child, BAD_CAST QSF_OBJECT_TYPE)));
853 xmlNewProp (export_node, BAD_CAST QSF_OBJECT_TYPE,
854 xmlGetProp (child, BAD_CAST MAP_VALUE_ATTR));
855 xmlNodeAddContent (export_node, xmlNodeGetContent (input_node));
859 qsf_map_object_handler (xmlNodePtr child, xmlNsPtr ns,
QsfParam * params)
861 xmlNodePtr param_node;
862 xmlNsPtr map_ns, qsf_ns;
863 gint G_GNUC_UNUSED result;
883 for (param_node = child->children; param_node != NULL;
884 param_node = param_node->next)
891 (param_node),
"qsf_enquiry_date"))
893 qsf_string_default_handler (
"qsf_enquiry_date",
894 params->qsf_default_hash,
895 params->
lister, child, qsf_ns);
899 (param_node),
"qsf_time_now"))
901 qsf_date_default_handler (
"qsf_time_now",
902 params->qsf_default_hash,
903 params->
lister, child, qsf_ns);
907 (param_node),
"qsf_time_string"))
909 qsf_string_default_handler (
"qsf_time_string",
910 params->qsf_default_hash,
911 params->
lister, child, qsf_ns);
913 qsf_map_calculate_output (param_node, child, params);
915 qsf_calculate_conditional (param_node, child, params);
916 qsf_calculate_else (param_node, child, params);
936 iterator_cb (xmlNodePtr child, xmlNsPtr ns,
QsfParam * params)
943 object_name = (gchar*) xmlGetProp (child, BAD_CAST QSF_OBJECT_TYPE);
957 xmlDocPtr output_doc;
959 xmlNode *map_root, *output_root;
961 g_return_val_if_fail ((mapDoc && qsf_root && params), NULL);
962 ENTER (
" root=%s", qsf_root->name);
964 qsfiter.ns = params->
qsf_ns;
967 xmlDocSetRootElement (output_doc, output_root);
968 xmlSetNs (output_root, params->
qsf_ns);
977 map_root = xmlDocGetRootElement (mapDoc);
979 qsfiter.ns = params->map_ns;
983 qsfiter.ns = params->
qsf_ns;
988 for (cur_node = map_root->children; cur_node != NULL;
989 cur_node = cur_node->next)
997 PINFO (
" found an object tag. starting calculation");
1004 qsf_add_object_tag (params, params->
count);
1006 qsfiter.ns = params->map_ns;
1020 xmlSaveFormatFileEnc (
"-", output_doc,
"UTF-8", 1);
gint map_calculated_count
QofErrorId qof_error_register(const gchar *err_message, gboolean use_file)
Generate and register a new error.
#define PERR(format, args...)
void qsf_object_validation_handler(xmlNodePtr child, xmlNsPtr ns, QsfValidator *valid)
Checks all incoming objects for QOF registration.
#define PINFO(format, args...)
gboolean qof_class_is_registered(QofIdTypeConst obj_name)
gboolean is_qsf_object_with_map(const gchar *path, gchar *map_file)
Validate a QSF file and a selected QSF map.
void qsf_valid_foreach(xmlNodePtr parent, QsfValidCB cb, struct QsfNodeIterate *qsfiter, QsfValidator *valid)
gboolean qsf_is_valid(const gchar *schema_dir, const gchar *schema_filename, xmlDocPtr doc)
Compares an xmlDoc in memory against the schema file.
gint32 QofErrorId
The ID of this error.
#define MAP_DEFINITION_TAG
Private QSF header - not for use by applications.
gint qof_util_bool_to_int(const gchar *val)
gint qsf_strings_equal(const xmlChar *node_name, gchar *tag_name)
shorthand function
#define LEAVE(format, args...)
gint qsf_compare_tag_strings(const xmlChar *node_name, gchar *tag_name)
shorthand function
#define QSF_CONDITIONAL_SET
One iterator, two typedefs.
#define QSF_FORMATTING_OPTION
#define QSF_XML_BOOLEAN_TEST
#define QSF_BOOLEAN_DEFAULT
A specific boolean default for this map.
gint qof_registered_count
QsfStatus
Status of various object during mapping.
void qsf_node_foreach(xmlNodePtr parent, QsfNodeCB cb, struct QsfNodeIterate *qsfiter, QsfParam *params)
#define DEBUG(format, args...)
QSF API - Backend, maps, objects and configuration.
#define MAP_CALCULATE_TAG
gboolean is_qsf_object_with_map_be(gchar *map_path, QsfParam *params)
Validate a QSF file and a selected QSF map.
gboolean is_qsf_map_be(QsfParam *params)
Validate a QSF map file.
gboolean is_qsf_map(const gchar *path)
Validate a QSF map file.
#define QSF_CONDITIONAL_ELSE
#define QSF_OBJECT_SCHEMA
gint qsf_is_element(xmlNodePtr a, xmlNsPtr ns, gchar *c)
shorthand function
Holds a description of the QofObject.
#define QOF_FATAL
general error value
gint safe_strcmp(const gchar *da, const gchar *db)
xmlDocPtr qsf_object_convert(xmlDocPtr mapDoc, xmlNodePtr qsf_root, QsfParam *params)
Convert between QSF objects.
void qsf_book_node_handler(xmlNodePtr child, xmlNsPtr qsf_ns, QsfParam *params)
Book and book-guid node handler.
GHashTable * object_table
#define ENTER(format, args...)
const gchar * QofLogModule