[Gnucash-changes] r13621 - gnucash/trunk - Synchronise with QOF 0.6.3. Correct map handling to allow reverse operations and iteration over hierarchical objects. Improving debug messages and preventing a crash when loading a map directly. Standardise QSF backend on gint and gchar. Add new map file.

Neil Williams codehelp at cvs.gnucash.org
Mon Mar 13 17:52:03 EST 2006


Author: codehelp
Date: 2006-03-13 17:52:02 -0500 (Mon, 13 Mar 2006)
New Revision: 13621
Trac: http://svn.gnucash.org/trac/changeset/13621

Added:
   gnucash/trunk/lib/libqof/backend/file/pilot-qsf-gncCustomer.xml
Modified:
   gnucash/trunk/ChangeLog
   gnucash/trunk/lib/libqof/backend/file/Makefile.am
   gnucash/trunk/lib/libqof/backend/file/qsf-backend.c
   gnucash/trunk/lib/libqof/backend/file/qsf-map.xsd.xml
   gnucash/trunk/lib/libqof/backend/file/qsf-xml-map.c
   gnucash/trunk/lib/libqof/backend/file/qsf-xml.c
   gnucash/trunk/lib/libqof/backend/file/qsf-xml.h
   gnucash/trunk/lib/libqof/qof/deprecated.c
   gnucash/trunk/lib/libqof/qof/deprecated.h
   gnucash/trunk/lib/libqof/qof/gnc-date.c
Log:
Synchronise with QOF 0.6.3. Correct map handling to allow reverse operations and iteration over hierarchical objects. Improving debug messages and preventing a crash when loading a map directly. Standardise QSF backend on gint and gchar. Add new map file.

Modified: gnucash/trunk/ChangeLog
===================================================================
--- gnucash/trunk/ChangeLog	2006-03-13 21:16:29 UTC (rev 13620)
+++ gnucash/trunk/ChangeLog	2006-03-13 22:52:02 UTC (rev 13621)
@@ -1,3 +1,26 @@
+2006-03-13  Neil Williams  <linux at codehelp.co.uk>
+
+	* : Synchronise with external QOF 0.6.3
+
+	* qof/deprecated.c : Tweak.
+	* qof/deprecated.h : Tweak.
+	* qof/gnc-date.c : Use the macro defined in
+	external QOF that avoids a legacy gnucash macro.
+
+	* backend/file/qsf-backend.c : Standardise on gint and gchar.
+	Skip unregistered objects when processing maps.
+	* backend/file/qsf-map.xsd.xml : allow for iteration of hierarchical
+	objects
+	* backend/file/qsf-xml-map.c : Standardise on gint and gchar.
+	Correct map handling to allow reverse operations and iteration
+	over hierarchical objects. Improving debug messages
+	and preventing a crash when loading a map directly.
+	* backend/file/pilot-qsf-gncCustomer.xml : add reverse mapping
+	* backend/file/qsf-xml.c : Standardise on gint and gchar.
+	* backend/file/qsf-xml.h : Standardise on gint and gchar.
+	Support iteration over incoming QSF objects inside map
+	operations. Remove gnucash-specific gettext defines.
+
 2006-03-13  Andreas Köhler  <andi5.py at gmx.net>
 
 	* src/gnome-utils/gnc-plugin-page.c (gnc_plugin_page_add_book):

Modified: gnucash/trunk/lib/libqof/backend/file/Makefile.am
===================================================================
--- gnucash/trunk/lib/libqof/backend/file/Makefile.am	2006-03-13 21:16:29 UTC (rev 13620)
+++ gnucash/trunk/lib/libqof/backend/file/Makefile.am	2006-03-13 22:52:02 UTC (rev 13621)
@@ -23,7 +23,8 @@
 qsfschema_DATA = \
  qsf-object.xsd.xml \
  qsf-map.xsd.xml \
- pilot-qsf-GnuCashInvoice.xml
+ pilot-qsf-GnuCashInvoice.xml \
+ pilot-qsf-gncCustomer.xml
 
 EXTRA_DIST = \
   $(qsfschema_DATA) \

Added: gnucash/trunk/lib/libqof/backend/file/pilot-qsf-gncCustomer.xml
===================================================================
--- gnucash/trunk/lib/libqof/backend/file/pilot-qsf-gncCustomer.xml	2006-03-13 21:16:29 UTC (rev 13620)
+++ gnucash/trunk/lib/libqof/backend/file/pilot-qsf-gncCustomer.xml	2006-03-13 22:52:02 UTC (rev 13621)
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<qsf-map xmlns="http://qof.sourceforge.net/">
+  <definition qof_version="3">
+    <define e_type="pilot_address"/>
+    <define e_type="gncBillTerm"/>
+    <define e_type="gncCustomer"/>
+    <define e_type="gncAddress" foreach="true"/>
+  </definition>
+  <object type="gncCustomer">
+      <calculate type="string" value="id"/>
+      <calculate type="string" value="notes">
+        <set>entryNote</set>
+      </calculate>
+      <calculate type="string" value="name">
+        <set>entryCompany</set>
+      </calculate>
+      <calculate type="guid" value="guid"/>
+      <calculate type="guid" value="addr">
+        <set>guid</set>
+      </calculate>
+      <calculate type="guid" value="customer_terms"/>
+      <calculate type="guid" value="shipaddr"/>
+      <calculate type="boolean" value="active">
+	<set>true</set>
+      </calculate>
+      <calculate type="boolean" value="tax table override"/>
+      <calculate type="numeric" value="amount of discount"/>
+      <calculate type="numeric" value="amount of credit"/>
+  </object>
+  <object type="gncAddress">
+      <calculate type="string" value="city">
+        <set>entryZip</set>
+      </calculate>
+      <calculate type="string" value="street">
+        <set>entryAddress</set>
+      </calculate>
+      <calculate type="string" value="fax">
+        <set>entryPhone2</set>
+      </calculate>
+      <calculate type="string" value="number"/>
+      <calculate type="string" value="name">
+        <set>entryFirstname</set>
+        <set>entryLastname</set>
+      </calculate>
+      <calculate type="string" value="email">
+        <set>entryPhone5</set>
+      </calculate>
+      <calculate type="string" value="locality">
+        <set>entryState</set>
+      </calculate>
+      <calculate type="string" value="phone">
+        <set>entryPhone1</set>
+      </calculate>
+      <calculate type="guid" value="guid"/>
+      <calculate type="guid" value="owner">
+        <set>guid</set>
+      </calculate>
+  </object>
+  <object type="gncBillTerm">
+      <calculate type="string" value="description"/>
+      <calculate type="string" value="name"/>
+      <calculate type="string" value="bill type"/>
+      <calculate type="guid" value="guid"/>
+      <calculate type="numeric" value="amount of discount"/>
+      <calculate type="gint32" value="cut off"/>
+      <calculate type="gint32" value="number of days due"/>
+      <calculate type="gint32" value="number of discounted days"/>
+  </object>
+  <object type="pilot_address">
+      <calculate type="string" value="entryCity">
+        <set object="gncAddress">city</set>
+      </calculate>
+      <calculate type="string" value="entryCustom4"/>
+      <calculate type="string" value="entryPhone1">
+        <set object="gncAddress">phone</set>
+      </calculate>
+      <calculate type="string" value="entryZip"/>
+      <calculate type="string" value="entryLastname">
+        <set object="gncAddress">name</set>
+      </calculate>
+      <calculate type="string" value="entryPhone2"/>
+      <calculate type="string" value="entryNote"/>
+      <calculate type="string" value="category"/>
+      <calculate type="string" value="entryFirstname"/>
+      <calculate type="string" value="entryPhone3"/>
+      <calculate type="string" value="entryTitle"/>
+      <calculate type="string" value="entryPhone4"/>
+      <calculate type="string" value="entryCompany">
+        <set object="gncCustomer">name</set>
+      </calculate>
+      <calculate type="string" value="entryPhone5"/>
+      <calculate type="string" value="entryState">
+        <set object="gncAddress">locality</set>
+      </calculate>
+      <calculate type="string" value="entryCustom1"/>
+      <calculate type="string" value="entryAddress">
+        <set object="gncAddress">number</set>
+      </calculate>
+      <calculate type="string" value="entryCustom2"/>
+      <calculate type="string" value="entryCountry"/>
+      <calculate type="string" valuee="entryCustom3"/>
+  </object>
+</qsf-map>

Modified: gnucash/trunk/lib/libqof/backend/file/qsf-backend.c
===================================================================
--- gnucash/trunk/lib/libqof/backend/file/qsf-backend.c	2006-03-13 21:16:29 UTC (rev 13620)
+++ gnucash/trunk/lib/libqof/backend/file/qsf-backend.c	2006-03-13 22:52:02 UTC (rev 13621)
@@ -2,7 +2,7 @@
  *            qsf-backend.c
  *
  *  Sat Jan  1 15:07:14 2005
- *  Copyright  2005  Neil Williams
+ *  Copyright  2005, 2006  Neil Williams
  *  linux at codehelp.co.uk
  ****************************************************************************/
 /*
@@ -42,7 +42,7 @@
 {
 	QofBackend be;
 	qsf_param *params;
-	char *fullpath;
+	gchar *fullpath;
 };
 
 typedef struct QSFBackend_s QSFBackend;
@@ -110,6 +110,7 @@
 qsf_map_prepare_list(GList **maps)
 {
 	*maps = g_list_prepend(*maps, "pilot-qsf-GnuCashInvoice.xml");
+	*maps = g_list_prepend(*maps, "pilot-qsf-gncCustomer.xml");
 	return maps;
 }
 
@@ -136,6 +137,7 @@
 	params->full_kvp_path = NULL;
 	params->map_ns = NULL;
 	params->map_files = NULL;
+	params->map_path = NULL;
 	params->qsf_object_list = NULL;
 	params->qsf_parameter_hash = g_hash_table_new(g_str_hash, g_str_equal);
 	params->qsf_default_hash = g_hash_table_new(g_str_hash, g_str_equal);
@@ -170,7 +172,7 @@
 }
 
 static gboolean 
-qsf_determine_file_type(const char *path)
+qsf_determine_file_type(const gchar *path)
 {
 	struct stat sbuf;
 
@@ -180,7 +182,7 @@
 	if (sbuf.st_size == 0)       { return TRUE; }
 	if(is_our_qsf_object(path))  { return TRUE; }
 	else if(is_qsf_object(path)) { return TRUE; }
-    else if(is_qsf_map(path))    { return TRUE; }
+	else if(is_qsf_map(path))    { return TRUE; }
 	return FALSE;
 }
 
@@ -188,11 +190,11 @@
 Just strip the file: from the start of the book_path URL. Locks are not implemented.
 */
 static void
-qsf_session_begin(QofBackend *be, QofSession *session, const char *book_path,
+qsf_session_begin(QofBackend *be, QofSession *session, const gchar *book_path,
                    gboolean ignore_lock, gboolean create_if_nonexistent)
 {
 	QSFBackend *qsf_be;
-	char *p, *path;
+	gchar *p, *path;
 
 	PINFO (" ignore_lock=%d create_if_nonexistent=%d", ignore_lock, create_if_nonexistent);
 	g_return_if_fail(be != NULL);
@@ -209,7 +211,7 @@
 	if (p) {
 		path = g_strdup (book_path);
 		if (!g_ascii_strncasecmp(path, "file:", 5)) {
-			p = g_new(char, strlen(path) - 5 + 1);
+			p = g_new(gchar, strlen(path) - 5 + 1);
 			strcpy(p, path + 5);
 		}
 		qsf_be->fullpath = g_strdup(p);
@@ -335,14 +337,15 @@
 	while(object_list != NULL)
 	{
 		params->object_set = object_list->data;
+		object_list = g_list_next(object_list);
 		params->qsf_parameter_hash = params->object_set->parameters;
+		if(!qof_class_is_registered(params->object_set->object_type)) { continue; }
 		inst = (QofInstance*)qof_object_new_instance(params->object_set->object_type, book);
 		g_return_val_if_fail(inst != NULL, FALSE);
 		params->qsf_ent = &inst->entity;
 		qof_begin_edit(inst);
 		g_hash_table_foreach(params->qsf_parameter_hash, qsf_object_commitCB, params);
 		qof_commit_edit(inst);
-		object_list = g_list_next(object_list);
 	}
 	qof_object_foreach_type(insert_ref_cb, params);
 	qof_book_set_data(book, ENTITYREFERENCE, params->referenceList);
@@ -352,22 +355,19 @@
 /* QofBackend routine to load from file - needs a map.
 */
 static gboolean
-load_qsf_object(QofBook *book, const char *fullpath, qsf_param *params)
+load_qsf_object(QofBook *book, const gchar *fullpath, qsf_param *params)
 {
 	xmlNodePtr qsf_root, map_root;
 	xmlDocPtr mapDoc, foreign_doc;
 	gchar *map_path, *map_file;
-	GList *maps;
 
-	maps = params->map_files;
-	map_path = NULL;
+	map_file = params->map_path;
 	mapDoc = NULL;
-	if(!maps) {
+	/* use selected map */
+	if(!map_file) {
 		qof_backend_set_error(params->be, ERR_QSF_NO_MAP);
-		return FALSE;
+		return FALSE; 
 	}
-	/* use default maps */
-	map_file = g_strdup(maps->data);
 	foreign_doc = xmlParseFile(fullpath);
 	if (foreign_doc == NULL) {
 		qof_backend_set_error(params->be, ERR_FILEIO_PARSE_ERROR);
@@ -391,12 +391,11 @@
 	params->map_ns = map_root->ns;
 	params->input_doc = qsf_object_convert(mapDoc, qsf_root, params);
 	qsfdoc_to_qofbook(params->input_doc, params);
-	g_free(map_file);
 	return TRUE;
 }
 
 static gboolean
-load_our_qsf_object(QofBook *book, const char *fullpath, qsf_param *params)
+load_our_qsf_object(QofBook *book, const gchar *fullpath, qsf_param *params)
 {
 	xmlNodePtr qsf_root;
 
@@ -434,7 +433,7 @@
 	QSFBackend *qsf_be;
 	qsf_param *params;
 	FILE *f;
-	char *path;
+	gchar *path;
 	gboolean result;
 
 	g_return_if_fail(be != NULL);
@@ -462,6 +461,7 @@
 		params->file_type = IS_QSF_OBJ;
 		result = load_qsf_object(book, path, params);
 		if(!result) { qof_backend_set_error(be, ERR_FILEIO_PARSE_ERROR); }
+		return;
 	}
 	if(result == FALSE) {
 		if(is_qsf_map_be(params)) {
@@ -556,7 +556,7 @@
 
 
 static void
-qsf_from_kvp_helper(const char *path, KvpValue *content, gpointer data)
+qsf_from_kvp_helper(const gchar *path, KvpValue *content, gpointer data)
 {
 	qsf_param *params;
 	QofParam *qof_param;
@@ -741,10 +741,10 @@
 	QofEntity  *choice_ent;
 	KvpFrame   *qsf_kvp;
 	QofCollection *qsf_coll;
-	int        param_count;
+	gint        param_count;
 	gboolean   own_guid;
 	const GUID *cm_guid;
-	char       cm_sa[GUID_ENCODING_LENGTH + 1];
+	gchar       cm_sa[GUID_ENCODING_LENGTH + 1];
 
 	g_return_if_fail(data != NULL);
 	params = (qsf_param*)data;
@@ -828,7 +828,7 @@
 			for( supported = g_slist_copy(params->supported_types);
 				supported != NULL; supported = g_slist_next(supported))
 			{
-				if(0 == safe_strcmp((const char*)supported->data, (const char*)qof_param->param_type))
+				if(0 == safe_strcmp((const gchar*)supported->data, (const gchar*)qof_param->param_type))
 				{
 					node = xmlAddChild(object_node, xmlNewNode(ns, BAD_CAST qof_param->param_type));
 					string_buffer = g_strdup(qof_book_merge_param_as_string(qof_param, ent));
@@ -954,9 +954,9 @@
 }
 
 KvpValue*
-string_to_kvp_value(const char *content, KvpValueType type)
+string_to_kvp_value(const gchar *content, KvpValueType type)
 {
-	char        *tail;
+	gchar        *tail;
 	gint64      cm_i64;
 	double      cm_double;
 	gnc_numeric cm_numeric;
@@ -1030,7 +1030,7 @@
 	QofIdType          obj_type, reference_type;
 	struct tm          qsf_time;
 	time_t             qsf_time_t;
-	char               *tail;
+	gchar              *tail;
 	/* cm_ prefix used for variables that hold the data to commit */
 	gnc_numeric    cm_numeric;
 	double         cm_double;
@@ -1038,40 +1038,40 @@
 	gint32         cm_i32;
 	gint64         cm_i64;
 	Timespec       cm_date;
-	char           cm_char,    (*char_getter)  (xmlNodePtr);
+	gchar          cm_char,    (*char_getter)  (xmlNodePtr);
 	GUID           *cm_guid;
 	KvpFrame       *cm_kvp;
 	KvpValue       *cm_value;
 	KvpValueType   cm_type;
 	QofSetterFunc  cm_setter;
 	const QofParam *cm_param;
-	void (*string_setter)    (QofEntity*, const char*);
+	void (*string_setter)    (QofEntity*, const gchar*);
 	void (*date_setter)      (QofEntity*, Timespec);
 	void (*numeric_setter)   (QofEntity*, gnc_numeric);
 	void (*double_setter)    (QofEntity*, double);
 	void (*boolean_setter)   (QofEntity*, gboolean);
 	void (*i32_setter)       (QofEntity*, gint32);
 	void (*i64_setter)       (QofEntity*, gint64);
-	void (*char_setter)      (QofEntity*, char);
+	void (*char_setter)      (QofEntity*, gchar);
 
 	g_return_if_fail(data && value && key);
 	params = (qsf_param*)data;
 	node = (xmlNodePtr)value;
-	parameter_name = (const char*)key;
-	qof_type = (char*)node->name;
+	parameter_name = (const gchar*)key;
+	qof_type = (gchar*)node->name;
 	qsf_ent = params->qsf_ent;
 	targetBook = params->book;
 	memset (&qsf_time, '\0', sizeof(qsf_time));
 	cm_date.tv_nsec = 0;
 	cm_date.tv_sec = 0;
-	obj_type = (char*)xmlGetProp(node->parent, BAD_CAST QSF_OBJECT_TYPE);
+	obj_type = (gchar*)xmlGetProp(node->parent, BAD_CAST QSF_OBJECT_TYPE);
 	if(0 == safe_strcasecmp(obj_type, parameter_name)) { return; }
 	cm_setter = qof_class_get_parameter_setter(obj_type, parameter_name);
 	cm_param = qof_class_get_parameter(obj_type, parameter_name);
 	object_set = params->object_set;
 	if(safe_strcmp(qof_type, QOF_TYPE_STRING) == 0)  {
-		string_setter = (void(*)(QofEntity*, const char*))cm_setter;
-		if(string_setter != NULL) { string_setter(qsf_ent, (char*)xmlNodeGetContent(node)); }
+		string_setter = (void(*)(QofEntity*, const gchar*))cm_setter;
+		if(string_setter != NULL) { string_setter(qsf_ent, (gchar*)xmlNodeGetContent(node)); }
 	}
 	if(safe_strcmp(qof_type, QOF_TYPE_DATE) == 0) {
 		date_setter = (void(*)(QofEntity*, Timespec))cm_setter;
@@ -1123,7 +1123,7 @@
 	}
 	if(safe_strcmp(qof_type, QOF_TYPE_INT64) == 0) {
 		errno = 0;
-		cm_i64 = strtoll((char*)xmlNodeGetContent(node), &tail, 0);
+		cm_i64 = strtoll((gchar*)xmlNodeGetContent(node), &tail, 0);
 		if(errno == 0) {
 			i64_setter = (void(*)(QofEntity*, gint64))cm_setter;
 			if(i64_setter != NULL) { i64_setter(qsf_ent, cm_i64); }
@@ -1132,14 +1132,14 @@
 	}
 	if(safe_strcmp(qof_type, QOF_TYPE_DOUBLE) == 0) {
 		errno = 0;
-		cm_double = strtod((char*)xmlNodeGetContent(node), &tail);
+		cm_double = strtod((gchar*)xmlNodeGetContent(node), &tail);
 		if(errno == 0) {
 			double_setter = (void(*)(QofEntity*, double))cm_setter;
 			if(double_setter != NULL) { double_setter(qsf_ent, cm_double); }
 		}
 	}
 	if(safe_strcmp(qof_type, QOF_TYPE_BOOLEAN) == 0){
-		if(0 == safe_strcasecmp((char*)xmlNodeGetContent(node), 
+		if(0 == safe_strcasecmp((gchar*)xmlNodeGetContent(node), 
 				QSF_XML_BOOLEAN_TEST)) {
 			cm_boolean = TRUE;
 		}
@@ -1148,11 +1148,11 @@
 		if(boolean_setter != NULL) { boolean_setter(qsf_ent, cm_boolean); }
 	}
 	if(safe_strcmp(qof_type, QOF_TYPE_KVP) == 0) {
-		cm_type = qsf_to_kvp_helper((char*)xmlGetProp(node, BAD_CAST QSF_OBJECT_VALUE));
+		cm_type = qsf_to_kvp_helper((gchar*)xmlGetProp(node, BAD_CAST QSF_OBJECT_VALUE));
 		if(!cm_type) { return; }
-		cm_value = string_to_kvp_value((char*)xmlNodeGetContent(node), cm_type);
+		cm_value = string_to_kvp_value((gchar*)xmlNodeGetContent(node), cm_type);
 		cm_kvp = (KvpFrame*)cm_param->param_getfcn(qsf_ent, cm_param);
-		cm_kvp = kvp_frame_set_value(cm_kvp, (char*)xmlGetProp(node, 
+		cm_kvp = kvp_frame_set_value(cm_kvp, (gchar*)xmlGetProp(node, 
 			BAD_CAST QSF_OBJECT_KVP), cm_value);
 	}
 	if(safe_strcmp(qof_type, QOF_TYPE_COLLECT) == 0) {
@@ -1164,7 +1164,7 @@
 		qsf_coll = cm_param->param_getfcn(qsf_ent, cm_param);
 		type = qof_collection_get_type(qsf_coll);
 		cm_guid = g_new(GUID, 1);
-		if(TRUE != string_to_guid((char*)xmlNodeGetContent(node), cm_guid))
+		if(TRUE != string_to_guid((gchar*)xmlNodeGetContent(node), cm_guid))
 		{
 			qof_backend_set_error(params->be, ERR_QSF_BAD_OBJ_GUID);
 			PINFO (" string to guid collect failed for %s", xmlNodeGetContent(node));
@@ -1185,9 +1185,9 @@
 		params->referenceList = g_list_append(params->referenceList, reference);
 	}
 	if(safe_strcmp(qof_type, QOF_TYPE_CHAR) == 0) {
-		char_getter = (char (*)(xmlNodePtr))xmlNodeGetContent;
+		char_getter = (gchar (*)(xmlNodePtr))xmlNodeGetContent;
 		cm_char = char_getter(node);
-		char_setter = (void(*)(QofEntity*, char))cm_setter;
+		char_setter = (void(*)(QofEntity*, gchar))cm_setter;
 		if(char_setter != NULL) { char_setter(qsf_ent, cm_char); }
 	}
 }

Modified: gnucash/trunk/lib/libqof/backend/file/qsf-map.xsd.xml
===================================================================
--- gnucash/trunk/lib/libqof/backend/file/qsf-map.xsd.xml	2006-03-13 21:16:29 UTC (rev 13620)
+++ gnucash/trunk/lib/libqof/backend/file/qsf-map.xsd.xml	2006-03-13 22:52:02 UTC (rev 13621)
@@ -38,6 +38,7 @@
  <xsd:simpleContent>
    <xsd:extension base="xsd:string">
      <xsd:attribute name="e_type" type="xsd:string"/>
+     <xsd:attribute name="foreach" type="xsd:string" use="optional"/>
    </xsd:extension>
  </xsd:simpleContent>
 </xsd:complexType>

Modified: gnucash/trunk/lib/libqof/backend/file/qsf-xml-map.c
===================================================================
--- gnucash/trunk/lib/libqof/backend/file/qsf-xml-map.c	2006-03-13 21:16:29 UTC (rev 13620)
+++ gnucash/trunk/lib/libqof/backend/file/qsf-xml-map.c	2006-03-13 22:52:02 UTC (rev 13621)
@@ -38,12 +38,12 @@
 static QofLogModule log_module = QOF_MOD_QSF;
 
 static void
-qsf_date_default_handler(const char *default_name, GHashTable *qsf_default_hash,
+qsf_date_default_handler(const gchar *default_name, GHashTable *qsf_default_hash,
 	xmlNodePtr parent_tag, xmlNodePtr import_node, xmlNsPtr ns)
 {
 	xmlNodePtr output_parent;
 	time_t *qsf_time;
-	char date_as_string[QSF_DATE_LENGTH];
+	gchar date_as_string[QSF_DATE_LENGTH];
 
 	output_parent = xmlAddChild(parent_tag, xmlNewNode(ns,
 		xmlGetProp(import_node, BAD_CAST QSF_OBJECT_TYPE)));
@@ -55,7 +55,7 @@
 }
 
 static void
-qsf_string_default_handler(const char *default_name, GHashTable *qsf_default_hash,
+qsf_string_default_handler(const gchar *default_name, GHashTable *qsf_default_hash,
 	xmlNodePtr parent_tag, xmlNodePtr import_node, xmlNsPtr ns)
 {
 	xmlNodePtr node;
@@ -75,6 +75,7 @@
 	xmlChar *qof_version, *match;
 	GString *buff;
 	xmlNodePtr child_node;
+	QofIdType obj_type;
 
 	if (qsf_is_element(child, ns, MAP_DEFINITION_TAG)) {
 		qof_version = xmlGetProp(child, BAD_CAST MAP_QOF_VERSION);
@@ -97,26 +98,33 @@
 	}
 	if(qsf_is_element(child, ns, MAP_OBJECT_TAG)) {
 		match = NULL;
-		match = BAD_CAST  g_hash_table_lookup( valid->validation_table,
-			xmlGetProp(child, BAD_CAST MAP_TYPE_ATTR));
+		obj_type = xmlGetProp(child, BAD_CAST MAP_TYPE_ATTR);
+		match = BAD_CAST g_hash_table_lookup( valid->validation_table, obj_type);
 		if(match) {
 			valid->map_calculated_count++;
+			if(TRUE == qof_class_is_registered((QofIdTypeConst) obj_type))
+			{
+				valid->qof_registered_count++;
+				PINFO (" %s is to be calculated", obj_type);
+			}
+			else { PINFO (" %s to be mapped", obj_type); }
 		}
 	}
 }
 
-gboolean is_qsf_object_with_map_be(char *map_file, qsf_param *params)
+gboolean is_qsf_object_with_map_be(gchar *map_file, qsf_param *params)
 {
 	xmlDocPtr doc, map_doc;
-	int valid_count;
+	gint valid_count, calc_count;
 	struct qsf_node_iterate iter;
 	xmlNodePtr map_root, object_root;
 	xmlNsPtr map_ns;
 	qsf_validator valid;
-	char *path;
+	gchar *path;
 	gchar *map_path;
 
 	g_return_val_if_fail((params != NULL),FALSE);
+	PINFO (" mapfile=%s", map_file);
 	path = g_strdup(params->filepath);
 	map_path = g_strdup_printf("%s/%s", QSF_SCHEMA_DIR, map_file);
 	if(path == NULL) {
@@ -162,23 +170,39 @@
 		g_hash_table_destroy(valid.validation_table);
 		return FALSE;
 	}
-	valid_count = 0 - g_hash_table_size(valid.validation_table);
-	valid_count += valid.map_calculated_count;
-	valid_count += valid.valid_object_count;
-	g_hash_table_destroy(valid.validation_table);
-	if(valid_count == 0) {
+	/* check all counted objects are valid */
+	/* Should be: 
+	the same number of valid object calculations as there are defined in the map.
+	And the number of calculations must match the number of unregistered
+	objects plus the number of registered objects defined. */
+	valid_count = g_hash_table_size(valid.validation_table) - valid.map_calculated_count;
+	calc_count  = valid.map_calculated_count - 
+        (valid.valid_object_count + valid.qof_registered_count);
+	if(valid_count == 0 && calc_count == 0) {
+        g_hash_table_destroy(valid.validation_table);
 		qof_backend_get_error(params->be);
 		return TRUE;
 	}
 	qof_backend_set_error(params->be, ERR_QSF_WRONG_MAP);
 	/* the object is OK, only the map is wrong. */
+	PINFO (" Map is wrong. map:%d object:%d reg:%d size:%d result:%d",
+        valid.map_calculated_count, valid.valid_object_count, 
+        valid.qof_registered_count,
+        g_hash_table_size(valid.validation_table), valid_count);
+	if(valid_count != 0) {
+		PINFO (" size - map != 0. actual: %d.", valid_count);
+	}
+		if(calc_count != 0) {
+		PINFO (" map - (object + registered) != 0. Actual: %d.", calc_count);
+	}
+	g_hash_table_destroy(valid.validation_table);
 	return TRUE;
 }
 
-gboolean is_qsf_object_with_map(const char *path, char *map_file)
+gboolean is_qsf_object_with_map(const gchar *path, gchar *map_file)
 {
 	xmlDocPtr doc, map_doc;
-	int valid_count;
+	gint valid_count;
 	struct qsf_node_iterate iter;
 	xmlNodePtr map_root, object_root;
 	xmlNsPtr map_ns;
@@ -238,7 +262,7 @@
 	qsf_validator valid;
 	xmlNodePtr map_root;
 	xmlNsPtr map_ns;
-	char *path;
+	gchar *path;
 
 	g_return_val_if_fail((params != NULL),FALSE);
 	qof_backend_get_error(params->be);
@@ -259,6 +283,7 @@
 	map_root = xmlDocGetRootElement(doc);
 	map_ns = map_root->ns;
 	iter.ns = map_ns;
+	valid.validation_table = g_hash_table_new(g_str_hash, g_str_equal);
 	valid.error_state = ERR_BACKEND_NO_ERR;
 	qsf_valid_foreach(map_root, qsf_map_validation_handler, &iter, &valid);
 	if (valid.error_state != ERR_BACKEND_NO_ERR) {
@@ -271,7 +296,7 @@
 	return TRUE;
 }
 
-gboolean is_qsf_map(const char *path)
+gboolean is_qsf_map(const gchar *path)
 {
 	xmlDocPtr doc;
 	struct qsf_node_iterate iter;
@@ -290,6 +315,7 @@
 	map_ns = map_root->ns;
 	iter.ns = map_ns;
 	valid.error_state = ERR_BACKEND_NO_ERR;
+	valid.validation_table = g_hash_table_new(g_str_hash, g_str_equal);
 	qsf_valid_foreach(map_root, qsf_map_validation_handler, &iter, &valid);
 	if (valid.error_state != ERR_BACKEND_NO_ERR) {
 		g_hash_table_destroy(valid.validation_table);
@@ -304,9 +330,16 @@
 qsf_map_default_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params )
 {
 	xmlChar *qsf_enum;
+	gchar* iterate;
 
 	g_return_if_fail(params->qsf_define_hash != NULL);
+	iterate = NULL;
 	if (qsf_is_element(child, ns, MAP_DEFINE_TAG)) {
+        iterate = xmlGetProp(child, MAP_ITERATE_ATTR);
+        if(qof_util_bool_to_int(iterate) == 1) 
+        {
+            params->qof_foreach = xmlGetProp(child, BAD_CAST MAP_E_TYPE);
+        }
 		if(NULL == g_hash_table_lookup(params->qsf_define_hash,
 			xmlGetProp(child, BAD_CAST MAP_E_TYPE)))
 		{
@@ -354,7 +387,7 @@
 				xmlGetProp(child_node, MAP_NAME_ATTR), child_node))*/
 			{
 				qof_backend_set_error(params->be, ERR_QSF_BAD_MAP);
-				LEAVE (" ");
+				PERR (" ERR_QSF_BAD_MAP set");
 				return;
 			}
 		}
@@ -370,23 +403,25 @@
 
 	if(!params->qsf_define_hash) return;
 	if(!params->qsf_default_hash) return;
+	ENTER (" child=%s", child->name);
 	if(qsf_is_element(child, ns, MAP_DEFINITION_TAG)) {
 		qof_version = xmlGetProp(child, BAD_CAST MAP_QOF_VERSION);
 		buff = g_string_new(" ");
 		g_string_printf(buff, "%i", QSF_QOF_VERSION);
 		if(xmlStrcmp(qof_version, BAD_CAST buff->str) != 0) {
 			qof_backend_set_error(params->be, ERR_QSF_BAD_QOF_VERSION);
-			PERR (" ERR_QSF_BAD_QOF_VERSION set");
+			LEAVE (" ERR_QSF_BAD_QOF_VERSION set");
 			return;
 		}
 		iter.ns = ns;
 		qsf_node_foreach(child, qsf_map_default_handler, &iter, params);
 	}
+	LEAVE (" ");
 }
 
 static char*
 qsf_else_set_value(xmlNodePtr parent, GHashTable *default_hash,
-		char *content, xmlNsPtr map_ns)
+		gchar *content, xmlNsPtr map_ns)
 {
 	xmlNodePtr cur_node;
 
@@ -394,7 +429,7 @@
 	for(cur_node = parent->children; cur_node != NULL; cur_node = cur_node->next)
 	{
 		if(qsf_is_element(cur_node, map_ns, QSF_CONDITIONAL_SET)) {
-			content = (char*)xmlNodeGetContent(cur_node);
+			content = (gchar*)xmlNodeGetContent(cur_node);
 			return content;
 		}
 	}
@@ -405,9 +440,9 @@
 This function will be overhauled once inside QOF
 QOF hook required for "Lookup in the receiving application"
 */
-static char*
+static gchar*
 qsf_set_handler(xmlNodePtr parent, GHashTable *default_hash,
-	char *content, qsf_param *params)
+	gchar *content, qsf_param *params)
 {
 	xmlNodePtr cur_node, lookup_node;
 
@@ -417,12 +452,12 @@
 	{
 		if(qsf_is_element(cur_node, params->map_ns, QSF_CONDITIONAL_SET))
 		{
-			content = (char*)xmlGetProp(cur_node, BAD_CAST QSF_OPTION);
+			content = (gchar*)xmlGetProp(cur_node, BAD_CAST QSF_OPTION);
 			if(qsf_strings_equal(xmlGetProp(cur_node, BAD_CAST QSF_OPTION), "qsf_lookup_string"))
 			{
 				lookup_node = (xmlNodePtr) g_hash_table_lookup(default_hash,
 					xmlNodeGetContent(cur_node));
-				content = (char*)xmlGetProp(lookup_node, BAD_CAST MAP_VALUE_ATTR);
+				content = (gchar*)xmlGetProp(lookup_node, BAD_CAST MAP_VALUE_ATTR);
 				/** \todo FIXME: do the lookup. type is defined by output object. */
 				/* Find by name, get GUID, return GUID as string. */
 				g_message("Lookup %s in the receiving application\n", content );
@@ -433,17 +468,17 @@
 			{
 				lookup_node = (xmlNodePtr) g_hash_table_lookup(default_hash,
 					xmlNodeGetContent(cur_node));
-				content = (char*)xmlGetProp(lookup_node, BAD_CAST "value");
+				content = (gchar*)xmlGetProp(lookup_node, BAD_CAST "value");
 				return content;
 			}
-			content = (char*)xmlGetProp(parent, BAD_CAST "boolean");
+			content = (gchar*)xmlGetProp(parent, BAD_CAST "boolean");
 			if(!content) {
 				/** \todo Check qsf_parameter_hash arguments */
 				lookup_node = (xmlNodePtr) g_hash_table_lookup(params->qsf_parameter_hash,
 					xmlGetProp(parent->parent, BAD_CAST MAP_TYPE_ATTR));
-				if(lookup_node) { return (char*)xmlNodeGetContent(lookup_node); }
+				if(lookup_node) { return (gchar*)xmlNodeGetContent(lookup_node); }
 				LEAVE (" check arguments");
-				return (char*)xmlNodeGetContent(cur_node);
+				return (gchar*)xmlNodeGetContent(cur_node);
 			}
 		}
 	}
@@ -461,11 +496,11 @@
 		if(params->boolean_calculation_done == 0) {
 			output_content = object_data = NULL;
 			output_content = BAD_CAST qsf_set_handler(param_node,
-				params->qsf_default_hash, (char*)output_content, params);
+				params->qsf_default_hash, (gchar*)output_content, params);
 			if(output_content == NULL) {
 				output_content = xmlGetProp(param_node, BAD_CAST MAP_TYPE_ATTR);
 				object_data = BAD_CAST qsf_else_set_value(param_node, params->qsf_default_hash,
-					(char*)output_content, params->map_ns);
+					(gchar*)output_content, params->map_ns);
 				output_content = BAD_CAST xmlGetProp( (xmlNodePtr) g_hash_table_lookup(
 					params->qsf_default_hash, object_data), BAD_CAST MAP_VALUE_ATTR);
 			}
@@ -487,10 +522,10 @@
 }
 
 static void
-qsf_set_format_value(xmlChar *format, char *qsf_time_now_as_string,
+qsf_set_format_value(xmlChar *format, gchar *qsf_time_now_as_string,
 	xmlNodePtr cur_node, qsf_param *params)
 {
-	int result;
+	gint result;
 	xmlChar *content;
 	time_t *output;
 	struct tm *tmp;
@@ -527,7 +562,7 @@
 		output = &tester;
 	}
 	result = regcomp(&reg, "%[a-zA-Z]", REG_EXTENDED|REG_NOSUB);
-	result = regexec(&reg, (char*)format,(size_t)0,NULL,0);
+	result = regexec(&reg, (gchar*)format,(size_t)0,NULL,0);
 	if(result == REG_NOMATCH) { format = BAD_CAST "%F"; }
 	regfree(&reg);
 	/** QSF_DATE_LENGTH preset for all internal and QSF_XSD_TIME string formats.
@@ -538,7 +573,7 @@
 
 static void
 qsf_boolean_set_value(xmlNodePtr parent, qsf_param *params,
-		char *content, xmlNsPtr map_ns)
+		gchar *content, xmlNsPtr map_ns)
 {
 	xmlNodePtr cur_node;
 	xmlChar *boolean_name;
@@ -563,7 +598,7 @@
 		if(params->boolean_calculation_done == 0) {
 		/* set handler */
 		output_content = BAD_CAST qsf_set_handler(param_node, params->qsf_default_hash,
-				(char*)output_content, params);
+				(gchar*)output_content, params);
 		/* If the 'if' contains a boolean that has a default value */
 		if(output_content == NULL) {
 			if(NULL != xmlGetProp(param_node, BAD_CAST QSF_BOOLEAN_DEFAULT)) {
@@ -574,7 +609,7 @@
 			/* Is the default set to true? */
 			if( 0 == qsf_compare_tag_strings(output_content, QSF_XML_BOOLEAN_TEST))
 			{
-				qsf_boolean_set_value(param_node, params, (char*)output_content, params->map_ns);
+				qsf_boolean_set_value(param_node, params, (gchar*)output_content, params->map_ns);
 				export_node = xmlAddChild(params->lister, xmlNewNode(params->qsf_ns,
 					xmlGetProp(child, BAD_CAST QSF_OBJECT_TYPE)));
 				xmlNewProp(export_node, BAD_CAST QSF_OBJECT_TYPE,
@@ -587,8 +622,8 @@
 	}
 }
 
-static xmlNodePtr
-qsf_add_object_tag(qsf_param *params, int count)
+static void
+qsf_add_object_tag(qsf_param *params, gint count)
 {
 	xmlNodePtr extra_node;
 	GString *str;
@@ -603,35 +638,60 @@
 		xmlGetProp(params->convert_node, BAD_CAST QSF_OBJECT_TYPE));
 	property = xmlCharStrdup(str->str);
 	xmlNewProp(extra_node, BAD_CAST QSF_OBJECT_COUNT, property);
-	return extra_node;
+	params->lister = extra_node;
 }
 
+static gint
+identify_source_func(gconstpointer qsf_object, gconstpointer map)
+{
+	return safe_strcmp(((qsf_objects*)qsf_object)->object_type, (QofIdType)map);
+}
+
 static void
+qsf_map_calculate_output(xmlNodePtr param_node, xmlNodePtr child, qsf_param *params)
+{
+	xmlNodePtr export_node;
+	xmlChar *output_content;
+	xmlNodePtr node;
+	GList *source;
+
+	DEBUG (" %s", xmlNodeGetContent(param_node));
+	output_content = xmlNodeGetContent(param_node);
+	/* source refers to the source object that provides the data */
+	source = g_list_find_custom(params->qsf_object_list, 
+		BAD_CAST xmlGetProp(param_node, MAP_OBJECT_ATTR), identify_source_func);
+	if(!source) return;
+	params->object_set = source->data;
+	node = g_hash_table_lookup(params->object_set->parameters, output_content);
+	export_node = xmlAddChild(params->lister, xmlNewNode(params->qsf_ns,
+		xmlGetProp(child, BAD_CAST QSF_OBJECT_TYPE)));
+	xmlNewProp(export_node, BAD_CAST QSF_OBJECT_TYPE,
+		xmlGetProp(child, BAD_CAST MAP_VALUE_ATTR));
+	if(node) { xmlNodeAddContent(export_node, xmlNodeGetContent(node)); }
+}
+
+static void
 qsf_map_object_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params)
 {
-	xmlNodePtr param_node, export_node;
+	xmlNodePtr param_node;
 	xmlNsPtr map_ns, qsf_ns;
-	xmlChar *output_content;
-	int result, count;
+	gint result;
 
 	map_ns = ns;
 	qsf_ns = params->qsf_ns;
 	param_node = NULL;
 	result = 0;
-	count = params->count;
 	if(child == NULL) { return; }
 	if(ns == NULL) { return; }
 	params->boolean_calculation_done = 0;
 
 	if(qsf_is_element(child, map_ns, MAP_CALCULATE_TAG)) {
 		params->boolean_calculation_done = 0;
+        /* read the child nodes to prepare the calculation. */
 		for(param_node = child->children; param_node != NULL;
 			param_node = param_node->next)
 		{
-			output_content = NULL;
-			export_node = NULL;
-			if(!params->lister) { params->lister = qsf_add_object_tag(params, count); }
-			if(qsf_is_element(param_node, map_ns, "set"))
+			if(qsf_is_element(param_node, map_ns, QSF_CONDITIONAL_SET))
 			{
 				/* Map the pre-defined defaults */
 				if(0 == qsf_compare_tag_strings(
@@ -652,25 +712,11 @@
 					qsf_string_default_handler("qsf_time_string",
 						params->qsf_default_hash, params->lister, child, qsf_ns);
 				}
-				output_content = xmlNodeGetContent(param_node);
-				if(output_content != NULL) {
-					output_content = xmlNodeGetContent((xmlNodePtr) g_hash_table_lookup(
-						params->qsf_parameter_hash, xmlGetProp(child, BAD_CAST MAP_TYPE_ATTR)));
-					if(output_content != NULL) {
-						export_node = xmlAddChild(params->lister, xmlNewNode(qsf_ns,
-							xmlGetProp(child, BAD_CAST QSF_OBJECT_TYPE)));
-						xmlNewProp(export_node, BAD_CAST QSF_OBJECT_TYPE,
-							xmlGetProp(child, BAD_CAST MAP_VALUE_ATTR));
-						xmlNodeAddContent(export_node, output_content);
-						xmlFree(output_content);
-					}
-				}
+                qsf_map_calculate_output(param_node, child, params);
 			}
-
 			qsf_calculate_conditional( param_node, child, params);
 			qsf_calculate_else(param_node, child, params);
 		}
-
 		/* calculate_map currently not in use */
 		/* ensure uniqueness of the key before re-instating */
 /*		result = xmlHashAddEntry2(calculate_map,
@@ -688,39 +734,80 @@
 	}
 }
 
+static void
+iterator_cb(xmlNodePtr child, xmlNsPtr ns, qsf_param *params)
+{
+	gchar *object_name;
+
+	/* count the number of iterators in the QSF file */
+	if(qsf_is_element(child, ns, QSF_OBJECT_TAG))
+	{
+		object_name = xmlGetProp(child, QSF_OBJECT_TYPE);
+		if(0 == safe_strcmp(object_name, params->qof_foreach))
+		{
+			params->foreach_limit++;
+		}
+	}
+}
+
 xmlDocPtr
 qsf_object_convert(xmlDocPtr mapDoc, xmlNodePtr qsf_root, qsf_param *params)
 {
+	/* mapDoc : map document. qsf_root: incoming QSF root node. */
 	struct qsf_node_iterate iter;
 	xmlDocPtr output_doc;
 	xmlNode *cur_node;
-	xmlNode *map_root, *output_root, *output_node;
+	xmlNode *map_root, *output_root;
 
-	ENTER (" ");
+	g_return_val_if_fail((mapDoc && qsf_root && params), NULL);
+	ENTER (" root=%s", qsf_root->name);
+	/* prepare the intermediary document */
+	iter.ns = params->qsf_ns;
 	output_doc = xmlNewDoc(BAD_CAST QSF_XML_VERSION);
-	output_root = xmlDocCopyNode(qsf_root,output_doc,2);
+	output_root = xmlNewNode(NULL, BAD_CAST QSF_ROOT_TAG);
+	xmlDocSetRootElement(output_doc, output_root);
 	xmlSetNs(output_root, params->qsf_ns);
-	output_node = NULL;
-
-	qsf_node_foreach(qsf_root, qsf_object_node_handler, &iter, params);
+	params->output_node = xmlNewChild(output_root, params->qsf_ns, 
+        BAD_CAST QSF_BOOK_TAG, NULL);
+	xmlNewProp(params->output_node, BAD_CAST QSF_BOOK_COUNT, BAD_CAST "1");
+	/* parse the incoming QSF */
+	qsf_book_node_handler(qsf_root->children->next, params->qsf_ns, params);
+	/* parse the map and calculate the values */
 	map_root = xmlDocGetRootElement(mapDoc);
-
+	params->foreach_limit = 0;
 	iter.ns = params->map_ns;
 	qsf_node_foreach(map_root, qsf_map_top_node_handler, &iter, params);
+	/* identify the entities of iterator type. */
+	iter.ns = params->qsf_ns;
+	qsf_node_foreach(qsf_root->children->next, iterator_cb, &iter, params);
 
+	params->count = 0;
 	for(cur_node = map_root->children; cur_node != NULL; cur_node = cur_node->next)
 	{
 		params->convert_node = cur_node;
-		params->count = 0;
 		if(qsf_is_element(cur_node, params->map_ns, MAP_OBJECT_TAG))
 		{
+			gint i;
+
 			params->lister = NULL;
+			/* cur_node describes the target object */
+			if(!qof_class_is_registered(BAD_CAST 
+				xmlGetProp(cur_node, MAP_TYPE_ATTR))) { continue; }
+			qsf_add_object_tag(params, params->count);
 			params->count++;
 			iter.ns = params->map_ns;
-			qsf_node_foreach(cur_node, qsf_map_object_handler, &iter, params);
+			for(i = 0; i < params->foreach_limit; i++) 
+			{
+				qsf_node_foreach(cur_node, qsf_map_object_handler, &iter, params);
+				params->qsf_object_list = g_list_next(params->qsf_object_list);
+				qsf_add_object_tag(params, params->count);
+				params->count++;
+			}
 		}
 	}
 	params->file_type = OUR_QSF_OBJ;
+	/* use for debugging */
+	/*    xmlSaveFormatFileEnc("-", output_doc, "UTF-8", 1);*/
 	LEAVE (" ");
 	return output_doc;
 }

Modified: gnucash/trunk/lib/libqof/backend/file/qsf-xml.c
===================================================================
--- gnucash/trunk/lib/libqof/backend/file/qsf-xml.c	2006-03-13 21:16:29 UTC (rev 13620)
+++ gnucash/trunk/lib/libqof/backend/file/qsf-xml.c	2006-03-13 22:52:02 UTC (rev 13621)
@@ -2,7 +2,7 @@
  *            qsf-xml.c
  *
  *  Fri Nov 26 19:29:47 2004
- *  Copyright  2004-2005  Neil Williams  <linux at codehelp.co.uk>
+ *  Copyright  2004,2005,2006  Neil Williams  <linux at codehelp.co.uk>
  *
  ****************************************************************************/
 /*
@@ -33,21 +33,21 @@
 
 static QofLogModule log_module = QOF_MOD_QSF;
 
-int
-qsf_compare_tag_strings(const xmlChar *node_name, char *tag_name)
+gint
+qsf_compare_tag_strings(const xmlChar *node_name, gchar *tag_name)
 {
 	return xmlStrcmp(node_name, (const xmlChar *)tag_name);
 }
 
-int
-qsf_strings_equal(const xmlChar *node_name, char *tag_name)
+gint
+qsf_strings_equal(const xmlChar *node_name, gchar *tag_name)
 {
 	if(0 == qsf_compare_tag_strings(node_name, tag_name)) { return 1; }
 	return 0;
 }
 
-int
-qsf_is_element(xmlNodePtr a, xmlNsPtr ns, char *c)
+gint
+qsf_is_element(xmlNodePtr a, xmlNsPtr ns, gchar *c)
 {
 	g_return_val_if_fail(a != NULL, 0);
 	g_return_val_if_fail(ns != NULL, 0);
@@ -57,14 +57,14 @@
 	return 0;
 }
 
-int
-qsf_check_tag(qsf_param *params, char *qof_type)
+gint
+qsf_check_tag(qsf_param *params, gchar *qof_type)
 {
 	return qsf_is_element(params->child_node, params->qsf_ns, qof_type);
 }
 
 gboolean
-qsf_is_valid(const char *schema_dir, const char* schema_filename, xmlDocPtr doc)
+qsf_is_valid(const gchar *schema_dir, const gchar* schema_filename, xmlDocPtr doc)
 {
 	xmlSchemaParserCtxtPtr qsf_schema_file;
 	xmlSchemaPtr qsf_schema;
@@ -104,6 +104,7 @@
 {
 	xmlNodePtr cur_node;
 
+	g_return_if_fail(iter->ns);
 	iter->fcn = &cb;
 	for(cur_node = parent->children; cur_node != NULL; cur_node = cur_node->next)
 	{
@@ -138,7 +139,7 @@
 	}
 }
 
-gboolean is_our_qsf_object(const char *path)
+gboolean is_our_qsf_object(const gchar *path)
 {
 	xmlDocPtr doc;
 	struct qsf_node_iterate iter;
@@ -167,7 +168,7 @@
 	return FALSE;
 }
 
-gboolean is_qsf_object(const char *path)
+gboolean is_qsf_object(const gchar *path)
 {
 	xmlDocPtr doc;
 
@@ -188,7 +189,7 @@
 	xmlNodePtr object_root;
 	qsf_validator valid;
 	gint table_count;
-	char *path;
+	gchar *path;
 
 	g_return_val_if_fail((params != NULL),FALSE);
 	path = g_strdup(params->filepath);
@@ -230,7 +231,7 @@
 	gboolean result;
 	xmlDocPtr doc;
 	GList *maps;
-	char *path;
+	gchar *path;
 
 	g_return_val_if_fail((params != NULL),FALSE);
 	path = g_strdup(params->filepath);
@@ -257,8 +258,17 @@
 	/* retrieve list of maps from config frame. */
 	for(maps = params->map_files; maps; maps=maps->next)
 	{
+        QofBackendError err;
 		result = is_qsf_object_with_map_be(maps->data, params);
-		if(result) { break;}
+        err = qof_backend_get_error(params->be);
+        if((err == ERR_BACKEND_NO_ERR) && result) 
+        {
+            params->map_path = maps->data;
+            PINFO ("map chosen = %s", params->map_path);
+            break;
+        }
+        /* pop the error back on the stack. */
+        else { qof_backend_set_error(params->be, err); }
 	}
 	return result;
 }
@@ -271,7 +281,7 @@
 	g_return_if_fail(user_data != NULL);
 	g_return_if_fail(type != NULL);
 	params = (qsf_param*) user_data;
-	if(qsf_is_element(params->param_node, params->qsf_ns, (char*)type))
+	if(qsf_is_element(params->param_node, params->qsf_ns, (gchar*)type))
 	{
 		g_hash_table_insert(params->qsf_parameter_hash,
 			xmlGetProp(params->param_node, BAD_CAST QSF_OBJECT_TYPE), params->param_node);
@@ -285,27 +295,30 @@
 	g_slist_foreach(params->supported_types, qsf_supported_data_types, params);
 }
 
-/* Despite the name, this function handles the QSF object book tag
-AND the object tags. */
 void
 qsf_object_node_handler(xmlNodePtr child, xmlNsPtr qsf_ns, qsf_param *params)
 {
 	struct qsf_node_iterate iter;
 	qsf_objects *object_set;
-	char *tail, *object_count_s;
-	int c;
+	gchar *tail, *object_count_s;
+	gint64 c;
 
 	g_return_if_fail(child != NULL);
 	g_return_if_fail(qsf_ns != NULL);
 	params->qsf_ns = qsf_ns;
 	if(qsf_is_element(child, qsf_ns, QSF_OBJECT_TAG)) {
 		params->qsf_parameter_hash = NULL;
+		c = 0;
 		object_set = g_new(qsf_objects, 1);
 		params->object_set = object_set;
+		object_set->object_count = 0;
 		object_set->parameters = g_hash_table_new(g_str_hash, g_str_equal);
-		object_set->object_type = g_strdup((char*)xmlGetProp(child, BAD_CAST QSF_OBJECT_TYPE));
-		object_count_s = g_strdup((char*)xmlGetProp(child, BAD_CAST QSF_OBJECT_COUNT));
-		c = (int)strtol(object_count_s, &tail, 0);
+		object_set->object_type = g_strdup((gchar*)xmlGetProp(child, 
+			BAD_CAST QSF_OBJECT_TYPE));
+		object_count_s = g_strdup((gchar*)xmlGetProp(child, 
+			BAD_CAST QSF_OBJECT_COUNT));
+		c = (gint64)strtol(object_count_s, &tail, 0);
+		object_set->object_count = (gint)c;
 		g_free(object_count_s);
 		params->qsf_object_list = g_list_prepend(params->qsf_object_list, object_set);
 		iter.ns = qsf_ns;
@@ -317,35 +330,35 @@
 void
 qsf_book_node_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params)
 {
-	char *book_count_s, *tail;
-	int book_count;
+	gchar *book_count_s, *tail;
+	gint book_count;
 	xmlNodePtr child_node;
 	struct qsf_node_iterate iter;
 	gchar *buffer;
 	GUID book_guid;
 
+	g_return_if_fail(child);
+	g_return_if_fail(params);
+	ENTER (" child=%s", child->name);
 	if(qsf_is_element(child, ns, QSF_BOOK_TAG)) {
-		book_count_s = (char*)xmlGetProp(child, BAD_CAST QSF_BOOK_COUNT);
+		book_count_s = (gchar*)xmlGetProp(child, BAD_CAST QSF_BOOK_COUNT);
 		if(book_count_s) {
-			book_count = (int)strtol(book_count_s, &tail, 0);
+			book_count = (gint)strtol(book_count_s, &tail, 0);
 			/* More than one book not currently supported. */
 			g_return_if_fail(book_count == 1);
 		}
 		iter.ns = ns;
-		qsf_node_foreach(child, qsf_object_node_handler, &iter, params);
-	}
-	for(child_node = child->children; child_node != NULL;
-		child_node = child_node->next)
-		{
+		child_node = child->children->next;
 		if(qsf_is_element(child_node, ns, QSF_BOOK_GUID)) {
-			buffer = g_strdup((char*)xmlNodeGetContent(child_node));
+			DEBUG (" trying to set book GUID");
+			buffer = g_strdup((gchar*)xmlNodeGetContent(child_node));
 			g_return_if_fail(TRUE == string_to_guid(buffer, &book_guid));
 			qof_entity_set_guid((QofEntity*)params->book, &book_guid);
+			xmlNewChild(params->output_node, params->qsf_ns, 
+			BAD_CAST QSF_BOOK_GUID, BAD_CAST buffer);
 			g_free(buffer);
 		}
-		if(qsf_is_element(child_node, ns, QSF_OBJECT_TAG)) {
-			iter.ns = ns;
-			qsf_node_foreach(child_node, qsf_object_node_handler, &iter, params);
-		}
+		qsf_node_foreach(child, qsf_object_node_handler, &iter, params);
 	}
+    LEAVE (" ");
 }

Modified: gnucash/trunk/lib/libqof/backend/file/qsf-xml.h
===================================================================
--- gnucash/trunk/lib/libqof/backend/file/qsf-xml.h	2006-03-13 21:16:29 UTC (rev 13620)
+++ gnucash/trunk/lib/libqof/backend/file/qsf-xml.h	2006-03-13 22:52:02 UTC (rev 13621)
@@ -2,7 +2,7 @@
  *            qsf-xml.h
  *
  *  Fri Nov 26 19:29:47 2004
- *  Copyright  2004-2005  Neil Williams  <linux at codehelp.co.uk>
+ *  Copyright  2004,2005,2006  Neil Williams  <linux at codehelp.co.uk>
  *
  ****************************************************************************/
 /*
@@ -40,40 +40,9 @@
 #include <libxml/xmlschemas.h>
 #include "qof.h"
 
-#if defined(HAVE_GETTEXT)             /* HAVE_GETTEXT */
-
 #include <libintl.h>
-#include <locale.h>
+#define _(String) gettext (String)
 
-#undef _
-#undef Q_
-
-#ifdef DISABLE_GETTEXT_UNDERSCORE
-#define _(String) (String)
-#define Q_(String) gnc_qualifier_prefix_noop(String)
-#else                                 /* ENABLE_GETTEXT_UNDERSCORE */
-#define _(String) gettext(String)
-#define Q_(String) gnc_qualifier_prefix_gettext(String)
-#endif                                /* End ENABLE_GETTEXT_UNDERSCORE */
-
-#else                                 /* Not HAVE_GETTEXT */
-#if !defined(__USE_GNU_GETTEXT)
-
-#undef _
-#undef Q_
-#define _(String)       (String)
-#define Q_(String) gnc_qualifier_prefix_noop(String)
-#define gettext(String) (String)
-#define ngettext(msgid, msgid_plural, n) (((n)==1) ? \
-                                            (msgid) : (msgid_plural))
-
-#endif                                /* End not__USE_GNU_GETTEXT */
-#endif                                /* End Not HAVE_GETTEXT */
-
-#undef  N_
-#define N_(String) (String)
-
-
 typedef enum  {
 	QSF_UNDEF = 0, /**< Initial undefined value. */
 	IS_QSF_MAP,   /**< A QSF map */
@@ -94,7 +63,7 @@
 {
 	GHashTable *parameters;
 	QofIdType object_type;
-	int object_count;
+	gint object_count;
 }qsf_objects;
 
 #define QSF_QOF_VERSION QOF_OBJECT_VERSION /**< QOF Version check.
@@ -156,6 +125,8 @@
 Attributes: e_type Copied directly from the QofObject definition.
 Content: The full QofObject description for the defined QOF object.
 */
+#define MAP_ITERATE_ATTR "foreach" /**< Dictate which object type is the basis
+for iteration in a hierarchical object set. */
 #define MAP_DEFAULT_TAG	"default"  /**< User editable defaults for data not
 available within the available QSF objects.
 
@@ -260,6 +231,8 @@
 The value of a calculation is the name of the parameter that will be set by that
 calculation.
 */
+#define MAP_OBJECT_ATTR "object" /**< The object to use to provide the data
+being set using the map.*/
 #define MAP_E_TYPE	"e_type" /**< Validates the objects defined in the map 
 
 The e_type will be used to match incoming QSF objects with the relevant QSF map.
@@ -373,7 +346,7 @@
 {
 	qsf_type file_type;          /**< what type of file is being handled */
 	qsf_objects *object_set;     /**< current object set for qsf_object_list. */
-	int count;                   /**< sequential counter for each object in the book */
+	gint count;                  /**< sequential counter for each object in the book */
 	GList *qsf_object_list;      /**< list of qsf_objects */
 	GSList *qsf_sequence;        /**< Parameter list sorted into QSF order */
 	GList *referenceList;        /**< Table of references, ::QofEntityReference. */
@@ -390,8 +363,10 @@
 	xmlNodePtr book_node;        /**< Node for the book. */
 	xmlNodePtr lister;           /**< Comparison node for map defaults. */
 	xmlNsPtr qsf_ns, map_ns;     /**< Separate namespaces for QSF objects and QSF maps. */
-	const char *qof_type;        /**< Holds details of the QOF_TYPE */
+	const gchar *qof_type;       /**< Holds details of the QOF_TYPE */
 	QofIdType qof_obj_type;	     /**< current QofObject type (e_type) for the parameters. */
+	QofIdType qof_foreach;       /**< How to iterate over hierarchical entities. */
+	gint foreach_limit;          /**< How many iterations are found in the QSF */
 	QofEntity *qsf_ent;          /**< Current entity in the book. */
 	QofBackend *be;              /**< the current QofBackend for this operation. */
 	gboolean knowntype;          /**< detect references by comparing with known QOF types. */
@@ -400,8 +375,9 @@
 
 		Theoretically, QSF can handle multiple QofBooks - currently limited to 1.
 	*/
-	int boolean_calculation_done; /**< simple trip once this boolean is complete. */
-	char *filepath;               /**< Path to the QSF file. */
+	gint boolean_calculation_done; /**< simple trip once this boolean is complete. */
+	gchar *filepath;              /**< Path to the QSF file. */
+	gchar *map_path;              /**< Path to best match map, if any. */
 	gchar* full_kvp_path;         /**< Full path for each KvpValue written out. */
 	gint use_gz_level;            /**< Default compression level. */
 	GList *map_files;             /**< List of selected map files for this session.
@@ -418,12 +394,12 @@
 typedef struct qsf_validates
 {
 	QofBackendError error_state;
-	const char *object_path;
-	const char *map_path;
+	const gchar *object_path;
+	const gchar *map_path;
 	GHashTable *validation_table;
-	int valid_object_count;
-	int map_calculated_count;
-	int qof_registered_count;
+	gint valid_object_count;
+	gint map_calculated_count;
+	gint qof_registered_count;
 }qsf_validator;
 
 /** \brief shorthand function
@@ -431,32 +407,32 @@
 This may look repetitive but each one is used separately
 as well as in a block.
 */
-int
-qsf_compare_tag_strings(const xmlChar *node_name, char *tag_name);
+gint
+qsf_compare_tag_strings(const xmlChar *node_name, gchar *tag_name);
 
 /** \brief shorthand function
 
 This may look repetitive but each one is used separately
 as well as in a block.
 */
-int
-qsf_strings_equal(const xmlChar *node_name, char *tag_name);
+gint
+qsf_strings_equal(const xmlChar *node_name, gchar *tag_name);
 
 /** \brief shorthand function
 
 This may look repetitive but each one is used separately
 as well as in a block.
 */
-int
-qsf_is_element(xmlNodePtr a, xmlNsPtr ns, char *c);
+gint
+qsf_is_element(xmlNodePtr a, xmlNsPtr ns, gchar *c);
 
 /** \brief shorthand function
 
 This may look repetitive but each one is used separately
 as well as in a block.
 */
-int
-qsf_check_tag(qsf_param *params, char *qof_type);
+gint
+qsf_check_tag(qsf_param *params, gchar *qof_type);
 
 /** \brief Checks all incoming objects for QOF registration.
 
@@ -479,7 +455,7 @@
 @return TRUE if the doc validates against the assigned schema, otherwise FALSE.
 */
 gboolean
-qsf_is_valid(const char *schema_dir, const char* schema_filename, xmlDocPtr doc);
+qsf_is_valid(const gchar *schema_dir, const gchar* schema_filename, xmlDocPtr doc);
 
 /** \brief Prepare the default list of maps.
 
@@ -562,7 +538,7 @@
 @return TRUE if the file validates and a QSF map can be found,
 otherwise FALSE.
 */
-gboolean is_qsf_object(const char *path);
+gboolean is_qsf_object(const gchar *path);
 /** \brief Validate a QSF file and determine type.
 
 @param	params	Pointer to qsf_param context
@@ -592,7 +568,7 @@
 @return TRUE if the file validates and all objects pass,
 otherwise FALSE.
 */
-gboolean is_our_qsf_object(const char *path);
+gboolean is_our_qsf_object(const gchar *path);
 /** \brief Validate a QSF map file.
 
 @param	params	Pointer to qsf_param context
@@ -621,7 +597,7 @@
 
 @return TRUE if the map validates, otherwise FALSE.
 */
-gboolean is_qsf_map(const char *path);
+gboolean is_qsf_map(const gchar *path);
 /** \brief Validate a QSF file and a selected QSF map
 
 @param	map_path	Absolute or relative path to the selected QSF map file
@@ -637,7 +613,7 @@
 @return TRUE if the file validates and the supplied QSF map is usable,
 otherwise FALSE.
 */
-gboolean is_qsf_object_with_map_be(char *map_path, qsf_param *params);
+gboolean is_qsf_object_with_map_be(gchar *map_path, qsf_param *params);
 /** \brief Validate a QSF file and a selected QSF map
 
 @param	map_path	Absolute or relative path to the selected QSF map file
@@ -651,7 +627,7 @@
 @return TRUE if the file validates and the supplied QSF map is usable,
 otherwise FALSE.
 */
-gboolean is_qsf_object_with_map(const char *path, char *map_file);
+gboolean is_qsf_object_with_map(const gchar *path, gchar *map_file);
 
 /** @} */
 
@@ -676,7 +652,7 @@
 @return KvpValue* or NULL on failure.
 */
 KvpValue*
-string_to_kvp_value(const char *content, KvpValueType type);
+string_to_kvp_value(const gchar *content, KvpValueType type);
 
 /** Validate the children of the parent node.
 

Modified: gnucash/trunk/lib/libqof/qof/deprecated.c
===================================================================
--- gnucash/trunk/lib/libqof/qof/deprecated.c	2006-03-13 21:16:29 UTC (rev 13620)
+++ gnucash/trunk/lib/libqof/qof/deprecated.c	2006-03-13 22:52:02 UTC (rev 13621)
@@ -103,4 +103,6 @@
 {
     qof_book_merge_rule_foreach(mergeData, cb, mergeResult);
 }
+
+/* ==================================================================== */
 #endif /* QOF_DISABLE_DEPRECATED */

Modified: gnucash/trunk/lib/libqof/qof/deprecated.h
===================================================================
--- gnucash/trunk/lib/libqof/qof/deprecated.h	2006-03-13 21:16:29 UTC (rev 13620)
+++ gnucash/trunk/lib/libqof/qof/deprecated.h	2006-03-13 22:52:02 UTC (rev 13621)
@@ -20,9 +20,8 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02110-1301, USA.
  */
+#ifndef QOF_DISABLE_DEPRECATED 
  
-#ifndef QOF_DISABLE_DEPRECATED
-
 #ifndef _DEPRECATED_H
 #define _DEPRECATED_H
 #include "qof.h"

Modified: gnucash/trunk/lib/libqof/qof/gnc-date.c
===================================================================
--- gnucash/trunk/lib/libqof/qof/gnc-date.c	2006-03-13 21:16:29 UTC (rev 13620)
+++ gnucash/trunk/lib/libqof/qof/gnc-date.c	2006-03-13 22:52:02 UTC (rev 13621)
@@ -31,6 +31,10 @@
 /* to be renamed qofdate.c */
 #include <ctype.h>
 
+#ifdef HAVE_LANGINFO_H
+#define HAVE_LANGINFO_D_FMT 1
+#endif
+
 #ifdef HAVE_LANGINFO_D_FMT
 #include <langinfo.h>
 #endif



More information about the gnucash-changes mailing list