[Gnucash-changes] r13797 - gnucash/trunk - Final changes for QOF
0.6.4 - Improvements in map handling.
Neil Williams
codehelp at cvs.gnucash.org
Mon Apr 17 09:06:35 EDT 2006
Author: codehelp
Date: 2006-04-17 09:06:33 -0400 (Mon, 17 Apr 2006)
New Revision: 13797
Trac: http://svn.gnucash.org/trac/changeset/13797
Modified:
gnucash/trunk/ChangeLog
gnucash/trunk/configure.in
gnucash/trunk/lib/libqof/backend/file/pilot-qsf-gncCustomer.xml
gnucash/trunk/lib/libqof/backend/file/qof-backend-qsf.h
gnucash/trunk/lib/libqof/backend/file/qsf-backend.c
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.h
gnucash/trunk/lib/libqof/qof/kvp_frame.c
gnucash/trunk/lib/libqof/qof/kvp_frame.h
gnucash/trunk/lib/libqof/qof/qofbookmerge.c
gnucash/trunk/lib/libqof/qof/qofchoice.c
gnucash/trunk/lib/libqof/qof/qofutil.c
gnucash/trunk/lib/libqof/qof/qofutil.h
Log:
Final changes for QOF 0.6.4 - Improvements in map handling.
Modified: gnucash/trunk/ChangeLog
===================================================================
--- gnucash/trunk/ChangeLog 2006-04-17 09:05:19 UTC (rev 13796)
+++ gnucash/trunk/ChangeLog 2006-04-17 13:06:33 UTC (rev 13797)
@@ -1,3 +1,23 @@
+2006-04-17 Neil Williams <linux at codehelp.co.uk>
+
+ * configure.in : Bump versions of QOF libraries.
+
+ * lib/libqof/backend/file/qsf-xml-map.c : Refactoring common
+ code and fixing QOF_VERSION check.
+
+ * lib/libqof/backend/file/pilot-qsf-gncCustomer.xml :
+ remove gncBillTerm - isn't possible to create from
+ pilot data.
+ * lib/libqof/backend/file/qsf-backend.c :
+ * lib/libqof/backend/file/qsf-xml-map.c :
+ * lib/libqof/backend/file/qsf-xml.c :
+ * lib/libqof/backend/file/qsf-xml.h : Add control over status of
+ various objects during mapping.
+
+ * lib/libqof/qof/test/Makefile.am : Remove unwanted include.
+ * lib/libqof/qof/deprecated.h : Retain glib.h in QOF, not
+ deprecated.
+
2006-04-16 Chris Lyttle <chris at wilddev.net>
* NEWS: Added some text about the release.
Modified: gnucash/trunk/configure.in
===================================================================
--- gnucash/trunk/configure.in 2006-04-17 09:05:19 UTC (rev 13796)
+++ gnucash/trunk/configure.in 2006-04-17 13:06:33 UTC (rev 13797)
@@ -472,8 +472,8 @@
QOF_VERSION="internal"
QOF_PREFIX="internal"
QOF_XML_DIR='${datadir}/xml/qsf'
- LIBQOF_LIBRARY_VERSION=1:4:0
- LIBQOF_BACKEND_QSF_LIBRARY_VERSION=0:3:0
+ LIBQOF_LIBRARY_VERSION=1:5:0
+ LIBQOF_BACKEND_QSF_LIBRARY_VERSION=0:4:0
AC_SUBST(LIBQOF_LIBRARY_VERSION)
AC_SUBST(LIBQOF_BACKEND_QSF_LIBRARY_VERSION)
AC_DEFINE(HAVE_LIBQOF,,[We will use the internal QOF code])
Modified: gnucash/trunk/lib/libqof/backend/file/pilot-qsf-gncCustomer.xml
===================================================================
--- gnucash/trunk/lib/libqof/backend/file/pilot-qsf-gncCustomer.xml 2006-04-17 09:05:19 UTC (rev 13796)
+++ gnucash/trunk/lib/libqof/backend/file/pilot-qsf-gncCustomer.xml 2006-04-17 13:06:33 UTC (rev 13797)
@@ -1,71 +1,58 @@
<?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="pilot_address" foreach="true"/>
<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>
+ <set object="pilot_address">entryNote</set>
</calculate>
<calculate type="string" value="name">
- <set>entryCompany</set>
+ <set object="pilot_address">entryCompany</set>
</calculate>
<calculate type="guid" value="guid"/>
<calculate type="guid" value="addr">
- <set>guid</set>
+ <set object="pilot_address">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="active"/>
<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>
+ <set object="pilot_address">entryCity</set>
</calculate>
<calculate type="string" value="street">
- <set>entryAddress</set>
+ <set object="pilot_address">entryAddress</set>
</calculate>
<calculate type="string" value="fax">
- <set>entryPhone2</set>
+ <set object="pilot_address">entryPhone2</set>
</calculate>
<calculate type="string" value="number"/>
<calculate type="string" value="name">
- <set>entryFirstname</set>
- <set>entryLastname</set>
+ <set object="pilot_address">entryFirstname</set>
+ <set object="pilot_address">entryLastname</set>
</calculate>
<calculate type="string" value="email">
- <set>entryPhone5</set>
+ <set object="pilot_address">entryPhone5</set>
</calculate>
<calculate type="string" value="locality">
- <set>entryState</set>
+ <set object="pilot_address">entryState</set>
</calculate>
<calculate type="string" value="phone">
- <set>entryPhone1</set>
+ <set object="pilot_address">entryPhone1</set>
</calculate>
<calculate type="guid" value="guid"/>
<calculate type="guid" value="owner">
- <set>guid</set>
+ <set object="pilot_address">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>
Modified: gnucash/trunk/lib/libqof/backend/file/qof-backend-qsf.h
===================================================================
--- gnucash/trunk/lib/libqof/backend/file/qof-backend-qsf.h 2006-04-17 09:05:19 UTC (rev 13796)
+++ gnucash/trunk/lib/libqof/backend/file/qof-backend-qsf.h 2006-04-17 13:06:33 UTC (rev 13797)
@@ -14,7 +14,7 @@
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
+ * GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
Modified: gnucash/trunk/lib/libqof/backend/file/qsf-backend.c
===================================================================
--- gnucash/trunk/lib/libqof/backend/file/qsf-backend.c 2006-04-17 09:05:19 UTC (rev 13796)
+++ gnucash/trunk/lib/libqof/backend/file/qsf-backend.c 2006-04-17 13:06:33 UTC (rev 13797)
@@ -14,7 +14,7 @@
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
+ * GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
@@ -24,23 +24,24 @@
#define _GNU_SOURCE
#include "config.h"
+#include <errno.h>
+#include <sys/stat.h>
#include <glib.h>
-#include "qof.h"
-#include "qof-backend-qsf.h"
#include <libxml/xmlmemory.h>
#include <libxml/tree.h>
#include <libxml/parser.h>
#include <libxml/xmlschemas.h>
+#include "qof.h"
+#include "qof-backend-qsf.h"
#include "qsf-xml.h"
#include "qsf-dir.h"
-#include <errno.h>
-#include <sys/stat.h>
#define QSF_TYPE_BINARY "binary"
#define QSF_TYPE_GLIST "glist"
#define QSF_TYPE_FRAME "frame"
static QofLogModule log_module = QOF_MOD_QSF;
+
static void qsf_object_commitCB(gpointer key, gpointer value, gpointer data);
struct QSFBackend_s
@@ -60,14 +61,14 @@
g_return_if_fail(params);
if(0 == safe_strcmp(QSF_COMPRESS, option->option_name)) {
params->use_gz_level = (*(gint64*)option->value);
- DEBUG (" gz=%" G_GINT64_FORMAT,params->use_gz_level);
+ PINFO (" compression=%" G_GINT64_FORMAT,params->use_gz_level);
}
if (0 == safe_strcmp(QSF_MAP_FILES, option->option_name)) {
params->map_files = g_list_copy((GList*)option->value);
}
if (0 == safe_strcmp(QSF_ENCODING, option->option_name)) {
params->encoding = g_strdup(option->value);
- DEBUG (" encoding=%s", params->encoding);
+ PINFO (" encoding=%s", params->encoding);
}
}
@@ -104,6 +105,7 @@
option->tooltip = _("QOF can compress QSF XML files using gzip. "
"Note that compression is not used when outputting to STDOUT.");
option->type = KVP_TYPE_GINT64;
+ /* GINT_TO_POINTER can only be used for 32bit values. */
option->value = (gpointer)¶ms->use_gz_level;
qof_backend_prepare_option(be, option);
g_free(option);
@@ -132,6 +134,8 @@
GList**
qsf_map_prepare_list(GList **maps)
{
+ /* Add new map filenames here. */
+ /** \todo Automate this once map support is stable */
*maps = g_list_prepend(*maps, "pilot-qsf-GnuCashInvoice.xml");
*maps = g_list_prepend(*maps, "pilot-qsf-gncCustomer.xml");
return maps;
@@ -246,10 +250,10 @@
}
if(create_if_nonexistent)
{
- FILE *f;
-
- f = fopen(qsf_be->fullpath, "a+");
- if(f) {fclose(f); }
+ FILE *f;
+
+ f = fopen(qsf_be->fullpath, "a+");
+ if(f) {fclose(f); }
else
{
qof_backend_set_error(be, ERR_BACKEND_READONLY);
@@ -364,11 +368,13 @@
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);
+ 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);
+ g_hash_table_foreach(params->qsf_parameter_hash, qsf_object_commitCB,
+ params);
qof_commit_edit(inst);
}
qof_object_foreach_type(insert_ref_cb, params);
@@ -437,24 +443,25 @@
/* Determine the type of QSF and load it into the QofBook
- is_our_qsf_object, OUR_QSF_OBJ, QSF object file using only QOF objects known
- to the calling process. No map is required.
+ to the calling process. No map is required.
- is_qsf_object, IS_QSF_OBJ, QSF object file that may or may not have a QSF map
to convert external objects. This temporary type will be set to HAVE_QSF_MAP
if a suitable map exists, or an error value returned: ERR_QSF_NO_MAP,
ERR_QSF_BAD_MAP or ERR_QSF_WRONG_MAP. This allows the calling process to inform
the user that the QSF itself is valid but a suitable map cannot be found.
- is_qsf_map, IS_QSF_MAP, QSF map file. In the backend, this generates
- ERR_QSF_MAP_NOT_OBJ but it can be used internally when processing maps to
+ ERR_QSF_MAP_NOT_OBJ but it can be used internally when processing maps to
match a QSF object.
returns NULL on error, otherwise a pointer to the QofBook. Use
- the qof_book_merge API to merge the new data into the current
- QofBook.
+the qof_book_merge API to merge the new data into the current
+QofBook.
*/
static void
qsf_file_type(QofBackend *be, QofBook *book)
{
QSFBackend *qsf_be;
+ QofBackendError err;
qsf_param *params;
FILE *f;
gchar *path;
@@ -487,7 +494,16 @@
if(!result) { qof_backend_set_error(be, ERR_FILEIO_PARSE_ERROR); }
return;
}
- if(result == FALSE) {
+ err = qof_backend_get_error(be);
+ if(err == ERR_QSF_WRONG_MAP)
+ {
+ /* usable QSF object but no map available */
+ params->file_type = IS_QSF_OBJ;
+ result = TRUE;
+ }
+ /* pop the error back on the stack. */
+ qof_backend_set_error(params->be, err);
+ if(result == FALSE){
if(is_qsf_map_be(params)) {
params->file_type = IS_QSF_MAP;
qof_backend_set_error(be, ERR_QSF_MAP_NOT_OBJ);
@@ -608,7 +624,8 @@
node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns,
BAD_CAST qof_param->param_type));
xmlNodeAddContent(node, BAD_CAST kvp_value_to_bare_string(content));
- xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
+ xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST
+ qof_param->param_name);
full_path = g_strconcat(params->full_kvp_path, "/", path, NULL);
xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, BAD_CAST full_path);
xmlNewProp(node, BAD_CAST QSF_OBJECT_VALUE,
@@ -792,11 +809,13 @@
if(!own_guid)
{
cm_guid = qof_entity_get_guid(ent);
- node = xmlAddChild(object_node, xmlNewNode(ns, BAD_CAST QOF_TYPE_GUID));
+ node = xmlAddChild(object_node, xmlNewNode(ns, BAD_CAST
+ QOF_TYPE_GUID));
guid_to_string_buff(cm_guid, cm_sa);
string_buffer = g_strdup(cm_sa);
xmlNodeAddContent(node, BAD_CAST string_buffer);
- xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE , BAD_CAST QOF_PARAM_GUID);
+ xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE , BAD_CAST
+ QOF_PARAM_GUID);
g_free(string_buffer);
own_guid = TRUE;
}
@@ -828,12 +847,14 @@
param_list = g_slist_next(param_list);
continue;
}
- node = xmlAddChild(object_node, xmlNewNode(ns, BAD_CAST qof_param->param_type));
+ node = xmlAddChild(object_node, xmlNewNode(ns, BAD_CAST
+ qof_param->param_type));
cm_guid = qof_entity_get_guid(choice_ent);
guid_to_string_buff(cm_guid, cm_sa);
string_buffer = g_strdup(cm_sa);
xmlNodeAddContent(node, BAD_CAST string_buffer);
- xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
+ xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST
+ qof_param->param_name);
xmlNewProp(node, BAD_CAST "name", BAD_CAST choice_ent->e_type);
g_free(string_buffer);
param_list = g_slist_next(param_list);
@@ -852,12 +873,16 @@
for( supported = g_slist_copy(params->supported_types);
supported != NULL; supported = g_slist_next(supported))
{
- if(0 == safe_strcmp((const gchar*)supported->data, (const gchar*)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));
+ 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));
xmlNodeAddContent(node, BAD_CAST string_buffer);
- xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
+ xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST
+ qof_param->param_name);
g_free(string_buffer);
}
}
@@ -932,13 +957,14 @@
be = qof_book_get_backend(book);
qsf_doc = qofbook_to_qsf(book, params);
write_result = 0;
- DEBUG (" use_gz_level=%" G_GINT64_FORMAT " encoding=%s",
+ PINFO (" use_gz_level=%" G_GINT64_FORMAT " encoding=%s",
params->use_gz_level, params->encoding);
if((params->use_gz_level > 0) && (params->use_gz_level <= 9))
{
xmlSetDocCompressMode(qsf_doc, params->use_gz_level);
}
- g_return_if_fail(qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, qsf_doc) == TRUE);
+ g_return_if_fail(
+ qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, qsf_doc) == TRUE);
write_result = xmlSaveFormatFileEnc(path, qsf_doc, params->encoding, 1);
if(write_result < 0)
{
@@ -954,8 +980,9 @@
xmlDocPtr qsf_doc;
qsf_doc = qofbook_to_qsf(book, params);
- g_return_if_fail(qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, qsf_doc) == TRUE);
- DEBUG (" use_gz_level=%" G_GINT64_FORMAT " encoding=%s",
+ g_return_if_fail(
+ qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, qsf_doc) == TRUE);
+ PINFO (" use_gz_level=%" G_GINT64_FORMAT " encoding=%s",
params->use_gz_level, params->encoding);
xmlSaveFormatFileEnc("-", qsf_doc, params->encoding, 1);
fprintf(stdout, "\n");
@@ -993,49 +1020,62 @@
time_t kvp_time_t;
Timespec cm_date;
- switch(type) {
- case KVP_TYPE_GINT64:
- errno = 0;
- cm_i64 = strtoll(content, &tail, 0);
- if(errno == 0) {
- return kvp_value_new_gint64(cm_i64);
+ switch(type)
+ {
+ case KVP_TYPE_GINT64:
+ {
+ errno = 0;
+ cm_i64 = strtoll(content, &tail, 0);
+ if(errno == 0) {
+ return kvp_value_new_gint64(cm_i64);
+ }
+ break;
}
- break;
- case KVP_TYPE_DOUBLE:
- errno = 0;
- cm_double = strtod(content, &tail);
- if(errno == 0) {
- return kvp_value_new_double(cm_double);
+ case KVP_TYPE_DOUBLE:
+ {
+ errno = 0;
+ cm_double = strtod(content, &tail);
+ if(errno == 0) {
+ return kvp_value_new_double(cm_double);
+ }
+ break;
}
- break;
- case KVP_TYPE_NUMERIC:
- string_to_gnc_numeric(content, &cm_numeric);
- return kvp_value_new_gnc_numeric(cm_numeric);
- break;
- case KVP_TYPE_STRING:
- return kvp_value_new_string(content);
- break;
- case KVP_TYPE_GUID:
- cm_guid = g_new(GUID, 1);
- if(TRUE == string_to_guid(content, cm_guid))
+ case KVP_TYPE_NUMERIC:
{
- return kvp_value_new_guid(cm_guid);
+ string_to_gnc_numeric(content, &cm_numeric);
+ return kvp_value_new_gnc_numeric(cm_numeric);
+ break;
}
- break;
- case KVP_TYPE_TIMESPEC:
- strptime(content, QSF_XSD_TIME, &kvp_time);
- kvp_time_t = mktime(&kvp_time);
- timespecFromTime_t(&cm_date, kvp_time_t);
- return kvp_value_new_timespec(cm_date);
- break;
- case KVP_TYPE_BINARY:
+ case KVP_TYPE_STRING:
+ {
+ return kvp_value_new_string(content);
+ break;
+ }
+ case KVP_TYPE_GUID:
+ {
+ cm_guid = g_new(GUID, 1);
+ if(TRUE == string_to_guid(content, cm_guid))
+ {
+ return kvp_value_new_guid(cm_guid);
+ }
+ break;
+ }
+ case KVP_TYPE_TIMESPEC:
+ {
+ strptime(content, QSF_XSD_TIME, &kvp_time);
+ kvp_time_t = mktime(&kvp_time);
+ timespecFromTime_t(&cm_date, kvp_time_t);
+ return kvp_value_new_timespec(cm_date);
+ break;
+ }
+ case KVP_TYPE_BINARY:
// return kvp_value_new_binary(value->value.binary.data,
// value->value.binary.datasize);
break;
- case KVP_TYPE_GLIST:
+ case KVP_TYPE_GLIST:
// return kvp_value_new_glist(value->value.list);
break;
- case KVP_TYPE_FRAME:
+ case KVP_TYPE_FRAME:
// return kvp_value_new_frame(value->value.frame);
break;
}
@@ -1099,12 +1139,14 @@
object_set = params->object_set;
if(safe_strcmp(qof_type, QOF_TYPE_STRING) == 0) {
string_setter = (void(*)(QofEntity*, const gchar*))cm_setter;
- if(string_setter != NULL) { string_setter(qsf_ent, (gchar*)xmlNodeGetContent(node)); }
+ 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;
timechk = NULL;
- timechk = strptime((char*)xmlNodeGetContent(node), QSF_XSD_TIME, &qsf_time);
+ timechk = strptime((char*)xmlNodeGetContent(node), QSF_XSD_TIME,
+ &qsf_time);
g_return_if_fail(timechk != NULL);
qsf_time_t = mktime(&qsf_time);
if(qsf_time_t != -3600)
@@ -1136,7 +1178,8 @@
else {
reference = qof_entity_get_reference_from(qsf_ent, cm_param);
if(reference) {
- params->referenceList = g_list_append(params->referenceList, reference);
+ params->referenceList = g_list_append(params->referenceList,
+ reference);
}
}
}
@@ -1276,12 +1319,6 @@
{
QofBackendProvider *prov;
-/* #ifdef ENABLE_NLS
- setlocale (LC_ALL, "");
- bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR);
- bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
- textdomain (GETTEXT_PACKAGE);
- #endif*/
prov = g_new0 (QofBackendProvider, 1);
prov->provider_name = "QSF Backend Version 0.2";
prov->access_method = "file";
Modified: gnucash/trunk/lib/libqof/backend/file/qsf-xml-map.c
===================================================================
--- gnucash/trunk/lib/libqof/backend/file/qsf-xml-map.c 2006-04-17 09:05:19 UTC (rev 13796)
+++ gnucash/trunk/lib/libqof/backend/file/qsf-xml-map.c 2006-04-17 13:06:33 UTC (rev 13797)
@@ -14,7 +14,7 @@
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
+ * GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
@@ -72,61 +72,161 @@
static void
qsf_map_validation_handler(xmlNodePtr child, xmlNsPtr ns, qsf_validator *valid)
{
- xmlChar *qof_version, *match;
- GString *buff;
+ xmlChar *qof_version, *obj_type;
+ gboolean match, is_registered;
+ gchar *buff;
xmlNodePtr child_node;
- QofIdType obj_type;
+ QsfStatus type, incoming_type;
+ match = FALSE;
+ buff = NULL;
+ is_registered = FALSE;
+ type = QSF_NO_OBJECT;
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)
+ buff = g_strdup_printf("%i", QSF_QOF_VERSION);
+ if(xmlStrcmp(qof_version, BAD_CAST buff) != 0)
{
+ PERR (" Wrong QOF_VERSION in map '%s', should be %s",
+ qof_version, buff);
valid->error_state = ERR_QSF_BAD_QOF_VERSION;
+ g_free(buff);
return;
}
+ g_free(buff);
for(child_node = child->children; child_node != NULL;
child_node = child_node->next)
{
if (qsf_is_element(child_node, ns, MAP_DEFINE_TAG)) {
- g_hash_table_insert(valid->validation_table,
- xmlGetProp(child_node, BAD_CAST MAP_E_TYPE),
- xmlNodeGetContent(child_node));
+ obj_type = xmlGetProp(child_node, MAP_E_TYPE);
+ type = QSF_DEFINED_OBJECT;
+ is_registered = qof_class_is_registered(obj_type);
+ if(is_registered) { type = QSF_REGISTERED_OBJECT; }
+ g_hash_table_insert(valid->map_table, obj_type,
+ GINT_TO_POINTER(type));
}
}
}
if(qsf_is_element(child, ns, MAP_OBJECT_TAG)) {
- match = NULL;
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))
+ /* check each listed object is either registered or calculated. */
+ type = GPOINTER_TO_INT(g_hash_table_lookup(valid->map_table, obj_type));
+ switch(type)
+ {
+ case QSF_DEFINED_OBJECT :
+ /* we have a calculation for an unregistered object. */
+ /* Ignore the calculation that exists to support bidirectional maps. */
+ /* Check that the incoming QSF contains data for this object */
{
+ /* lookup the same object in QSF object_table */
+ incoming_type = GPOINTER_TO_INT(g_hash_table_lookup(valid->object_table,
+ obj_type));
+ switch (incoming_type)
+ {
+ case QSF_DEFINED_OBJECT :
+ {
+ valid->incoming_count++;
+ g_hash_table_insert(valid->map_table, obj_type,
+ GINT_TO_POINTER(type));
+ break; /* good, proceed. */
+ }
+ default :
+ {
+ PERR (" Missing data: %s", obj_type);
+ type = QSF_INVALID_OBJECT; break;
+ }
+ }
+ break;
+ }
+ case QSF_REGISTERED_OBJECT : /* use this calculation. */
+ {
+ type = QSF_CALCULATED_OBJECT;
+ valid->map_calculated_count++;
valid->qof_registered_count++;
- PINFO (" %s is to be calculated", obj_type);
+ /* store the result */
+ g_hash_table_insert(valid->map_table, obj_type, GINT_TO_POINTER(type));
+ break;
}
- else { PINFO (" %s to be mapped", obj_type); }
+ default :
+ {
+ type = QSF_INVALID_OBJECT;
+ break;
+ }
}
+ PINFO (" final type=%s result=%d", obj_type, type);
+ if(type == QSF_INVALID_OBJECT) { valid->error_state = ERR_QSF_WRONG_MAP; }
}
}
-gboolean is_qsf_object_with_map_be(gchar *map_file, qsf_param *params)
+static QofBackendError
+check_qsf_object_with_map_internal(xmlDocPtr map_doc, xmlDocPtr doc)
{
- xmlDocPtr doc, map_doc;
- gint valid_count, calc_count;
+ xmlNodePtr map_root, object_root;
struct qsf_node_iterate iter;
- xmlNodePtr map_root, object_root;
+ qsf_validator valid;
xmlNsPtr map_ns;
- qsf_validator valid;
- gchar *path;
- gchar *map_path;
+ valid.map_table = g_hash_table_new(g_str_hash, g_str_equal);
+ valid.object_table = g_hash_table_new(g_str_hash, g_str_equal);
+ map_root = xmlDocGetRootElement(map_doc);
+ object_root = xmlDocGetRootElement(doc);
+ valid.map_calculated_count = 0;
+ valid.valid_object_count = 0;
+ valid.qof_registered_count = 0;
+ valid.incoming_count = 0;
+ valid.error_state = ERR_BACKEND_NO_ERR;
+ map_ns = map_root->ns;
+ iter.ns = object_root->ns;
+ qsf_valid_foreach(object_root, qsf_object_validation_handler, &iter, &valid);
+ iter.ns = map_ns;
+ qsf_valid_foreach(map_root, qsf_map_validation_handler, &iter, &valid);
+ if (valid.error_state != ERR_BACKEND_NO_ERR) {
+ PINFO (" Map is wrong. Trying the next map.");
+ g_hash_table_destroy(valid.object_table);
+ g_hash_table_destroy(valid.map_table);
+ return valid.error_state;
+ }
+ /* check all counted objects are valid:
+ Objects to be calculated must also be registered
+ so that new objects can be created and populated
+ from the incoming data: qof_registered_count > 0
+ The incoming data must contain valid objects -
+ not an empty QofBook: valid_object_count > 0
+ The map must contain at least some calculations:
+ map_calculated_count > 0
+ */
+ if((valid.qof_registered_count < 1)
+ || (valid.map_calculated_count < 1)
+ || (valid.valid_object_count < 1)
+ || (valid.incoming_count < g_hash_table_size(valid.object_table)))
+ {
+ PINFO (" Map is wrong. map:%d object:%d reg:%d incoming:%d size:%d",
+ valid.map_calculated_count, valid.valid_object_count,
+ valid.qof_registered_count, valid.incoming_count,
+ g_hash_table_size(valid.object_table));
+ if(valid.error_state != ERR_BACKEND_NO_ERR)
+ {
+ valid.error_state = ERR_QSF_WRONG_MAP;
+ }
+ g_hash_table_destroy(valid.object_table);
+ g_hash_table_destroy(valid.map_table);
+ return valid.error_state;
+ }
+ g_hash_table_destroy(valid.object_table);
+ g_hash_table_destroy(valid.map_table);
+ return ERR_BACKEND_NO_ERR;
+}
+
+gboolean is_qsf_object_with_map_be(gchar *map_file, qsf_param *params)
+{
+ xmlDocPtr doc, map_doc;
+ QofBackendError result;
+ gchar *path, *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);
+ PINFO (" checking map file '%s'", map_path);
if(path == NULL) {
qof_backend_set_error(params->be, ERR_FILEIO_FILE_NOT_FOUND);
return FALSE;
@@ -140,73 +240,24 @@
qof_backend_set_error(params->be, ERR_QSF_INVALID_OBJ);
return FALSE;
}
- object_root = xmlDocGetRootElement(doc);
if(map_path == NULL) {
qof_backend_set_error(params->be, ERR_FILEIO_FILE_NOT_FOUND);
return FALSE;
}
- valid.validation_table = g_hash_table_new(g_str_hash, g_str_equal);
map_doc = xmlParseFile(map_path);
if(map_doc == NULL) {
qof_backend_set_error(params->be, ERR_FILEIO_PARSE_ERROR);
return FALSE;
}
- if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_MAP_SCHEMA, map_doc)) {
- qof_backend_set_error(params->be, ERR_QSF_INVALID_MAP);
- return FALSE;
- }
- map_root = xmlDocGetRootElement(map_doc);
- valid.map_calculated_count = 0;
- valid.valid_object_count = 0;
- valid.qof_registered_count = 0;
- valid.error_state = ERR_BACKEND_NO_ERR;
- map_ns = map_root->ns;
- iter.ns = object_root->ns;
- qsf_valid_foreach(object_root, qsf_object_validation_handler, &iter, &valid);
- iter.ns = map_ns;
- qsf_valid_foreach(map_root, qsf_map_validation_handler, &iter, &valid);
- if (valid.error_state != ERR_BACKEND_NO_ERR) {
- qof_backend_set_error(params->be, valid.error_state);
- g_hash_table_destroy(valid.validation_table);
- return FALSE;
- }
- /* 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;
+ result = check_qsf_object_with_map_internal(map_doc, doc);
+ qof_backend_set_error(params->be, result);
+ return (result == ERR_BACKEND_NO_ERR) ? TRUE : FALSE;
}
gboolean is_qsf_object_with_map(const gchar *path, gchar *map_file)
{
xmlDocPtr doc, map_doc;
- gint valid_count;
- struct qsf_node_iterate iter;
- xmlNodePtr map_root, object_root;
- xmlNsPtr map_ns;
- qsf_validator valid;
+ QofBackendError result;
gchar *map_path;
map_path = g_strdup_printf("%s/%s", QSF_SCHEMA_DIR, map_file);
@@ -220,39 +271,12 @@
if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc)) {
return FALSE;
}
- object_root = xmlDocGetRootElement(doc);
if(map_path == NULL) {
return FALSE;
}
- valid.validation_table = g_hash_table_new(g_str_hash, g_str_equal);
map_doc = xmlParseFile(map_path);
- if(map_doc == NULL) {
- return FALSE;
- }
- if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_MAP_SCHEMA, map_doc)) {
- return FALSE;
- }
- map_root = xmlDocGetRootElement(map_doc);
- valid.map_calculated_count = 0;
- valid.valid_object_count = 0;
- valid.error_state = ERR_BACKEND_NO_ERR;
- map_ns = map_root->ns;
- iter.ns = map_ns;
- qsf_valid_foreach(map_root, qsf_map_validation_handler, &iter, &valid);
- iter.ns = object_root->ns;
- qsf_valid_foreach(object_root, qsf_object_validation_handler, &iter, &valid);
- if (valid.error_state != ERR_BACKEND_NO_ERR) {
- 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) {
- return TRUE;
- }
- return FALSE;
+ result = check_qsf_object_with_map_internal(map_doc, doc);
+ return (result == ERR_BACKEND_NO_ERR) ? TRUE : FALSE;
}
gboolean is_qsf_map_be(qsf_param *params)
@@ -283,16 +307,17 @@
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.object_table = g_hash_table_new(g_str_hash, g_str_equal);
+ valid.map_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) {
qof_backend_set_error(params->be, valid.error_state);
- g_hash_table_destroy(valid.validation_table);
+ g_hash_table_destroy(valid.object_table);
return FALSE;
}
qof_backend_get_error(params->be);
- g_hash_table_destroy(valid.validation_table);
+ g_hash_table_destroy(valid.object_table);
return TRUE;
}
@@ -315,17 +340,16 @@
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);
+ valid.map_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);
+ g_hash_table_destroy(valid.map_table);
return FALSE;
}
- g_hash_table_destroy(valid.validation_table);
+ g_hash_table_destroy(valid.map_table);
return TRUE;
}
-
static void
qsf_map_default_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params )
{
@@ -335,11 +359,13 @@
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);
- }
+ iterate = xmlGetProp(child, MAP_ITERATE_ATTR);
+ if((qof_util_bool_to_int(iterate) == 1) &&
+ (qof_class_is_registered(xmlGetProp(child, BAD_CAST MAP_E_TYPE))))
+ {
+ params->qof_foreach = xmlGetProp(child, BAD_CAST MAP_E_TYPE);
+ PINFO (" iterating over '%s' objects", params->qof_foreach);
+ }
if(NULL == g_hash_table_lookup(params->qsf_define_hash,
xmlGetProp(child, BAD_CAST MAP_E_TYPE)))
{
@@ -398,17 +424,17 @@
qsf_map_top_node_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params)
{
xmlChar *qof_version;
- GString *buff;
+ gchar *buff;
struct qsf_node_iterate iter;
if(!params->qsf_define_hash) return;
if(!params->qsf_default_hash) return;
- ENTER (" child=%s", child->name);
+ ENTER (" map top node child=%s", child->name);
+ buff = NULL;
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) {
+ buff = g_strdup_printf("%i", QSF_QOF_VERSION);
+ if(xmlStrcmp(qof_version, BAD_CAST buff) != 0) {
qof_backend_set_error(params->be, ERR_QSF_BAD_QOF_VERSION);
LEAVE (" ERR_QSF_BAD_QOF_VERSION set");
return;
@@ -453,7 +479,8 @@
if(qsf_is_element(cur_node, params->map_ns, QSF_CONDITIONAL_SET))
{
content = (gchar*)xmlGetProp(cur_node, BAD_CAST QSF_OPTION);
- if(qsf_strings_equal(xmlGetProp(cur_node, BAD_CAST QSF_OPTION), "qsf_lookup_string"))
+ 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));
@@ -565,8 +592,7 @@
result = regexec(®, (gchar*)format,(size_t)0,NULL,0);
if(result == REG_NOMATCH) { format = BAD_CAST "%F"; }
regfree(®);
- /** QSF_DATE_LENGTH preset for all internal and QSF_XSD_TIME string formats.
- */
+ /* QSF_DATE_LENGTH preset for all internal and QSF_XSD_TIME string formats. */
strftime(qsf_time_now_as_string, QSF_DATE_LENGTH, (char*)format, gmtime(output));
LEAVE (" ok");
}
@@ -609,7 +635,8 @@
/* 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, (gchar*)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,
@@ -644,6 +671,8 @@
static gint
identify_source_func(gconstpointer qsf_object, gconstpointer map)
{
+ PINFO (" qsf_object=%s, map=%s",
+ ((qsf_objects*)qsf_object)->object_type, (QofIdType)map);
return safe_strcmp(((qsf_objects*)qsf_object)->object_type, (QofIdType)map);
}
@@ -652,22 +681,27 @@
{
xmlNodePtr export_node;
xmlChar *output_content;
- xmlNodePtr node;
+ xmlNodePtr input_node;
GList *source;
- DEBUG (" %s", xmlNodeGetContent(param_node));
output_content = xmlNodeGetContent(param_node);
+ DEBUG (" %s", output_content);
/* 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;
+ PINFO (" checking %s", BAD_CAST xmlGetProp(param_node, MAP_OBJECT_ATTR));
+ if(!source) { DEBUG (" no source found in list."); return; }
params->object_set = source->data;
- node = g_hash_table_lookup(params->object_set->parameters, output_content);
+ input_node = g_hash_table_lookup(params->object_set->parameters,
+ output_content);
+ DEBUG (" node_value=%s, content=%s",
+ xmlGetProp(child, BAD_CAST MAP_VALUE_ATTR),
+ xmlNodeGetContent(input_node));
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)); }
+ xmlNodeAddContent(export_node, xmlNodeGetContent(input_node));
}
static void
@@ -712,7 +746,7 @@
qsf_string_default_handler("qsf_time_string",
params->qsf_default_hash, params->lister, child, qsf_ns);
}
- qsf_map_calculate_output(param_node, child, params);
+ qsf_map_calculate_output(param_node, child, params);
}
qsf_calculate_conditional( param_node, child, params);
qsf_calculate_else(param_node, child, params);
@@ -776,11 +810,12 @@
map_root = xmlDocGetRootElement(mapDoc);
params->foreach_limit = 0;
iter.ns = params->map_ns;
+ /* sets qof_foreach iterator, defines and defaults. */
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);
-
+ PINFO (" counted %d records", params->foreach_limit);
params->count = 0;
for(cur_node = map_root->children; cur_node != NULL; cur_node = cur_node->next)
{
@@ -790,24 +825,25 @@
gint i;
params->lister = NULL;
+ PINFO (" found an object tag. starting calculation");
/* cur_node describes the target object */
- if(!qof_class_is_registered(BAD_CAST
+ 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;
- for(i = 0; i < params->foreach_limit; i++)
+ PINFO (" params->foreach_limit=%d", params->foreach_limit);
+ for(i = -1; 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);*/
+ 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-04-17 09:05:19 UTC (rev 13796)
+++ gnucash/trunk/lib/libqof/backend/file/qsf-xml.c 2006-04-17 13:06:33 UTC (rev 13797)
@@ -14,7 +14,7 @@
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
+ * GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
@@ -122,22 +122,28 @@
xmlNodePtr cur_node;
xmlChar *object_declaration;
guint count;
+ QsfStatus type;
+ gboolean is_registered;
count = 0;
+ type = QSF_NO_OBJECT;
+ is_registered = FALSE;
for(cur_node = child->children; cur_node != NULL;
cur_node = cur_node->next)
{
if(qsf_is_element(cur_node, ns, QSF_OBJECT_TAG)) {
object_declaration = xmlGetProp(cur_node, BAD_CAST QSF_OBJECT_TYPE);
- count = g_hash_table_size(valid->validation_table);
- g_hash_table_insert(valid->validation_table, object_declaration, xmlNodeGetContent(cur_node));
- if(g_hash_table_size(valid->validation_table) > count)
+ is_registered = qof_class_is_registered(object_declaration);
+ if(is_registered) { type = QSF_REGISTERED_OBJECT; }
+ else { type = QSF_DEFINED_OBJECT; }
+ count = g_hash_table_size(valid->object_table);
+ g_hash_table_insert(valid->object_table, object_declaration,
+ GINT_TO_POINTER(type));
+ /* if insert was successful - i.e. object is unique so far */
+ if(g_hash_table_size(valid->object_table) > count)
{
valid->valid_object_count++;
- if(TRUE == qof_class_is_registered((QofIdTypeConst) object_declaration))
- {
- valid->qof_registered_count++;
- }
+ if(is_registered) { valid->qof_registered_count++; }
}
}
}
@@ -161,13 +167,13 @@
}
object_root = xmlDocGetRootElement(doc);
/* check that all objects in the file are already registered in QOF */
- valid.validation_table = g_hash_table_new(g_str_hash, g_str_equal);
+ valid.object_table = g_hash_table_new(g_str_hash, g_str_equal);
valid.qof_registered_count = 0;
valid.valid_object_count = 0;
iter.ns = object_root->ns;
qsf_valid_foreach(object_root, qsf_object_validation_handler, &iter, &valid);
- table_count = g_hash_table_size(valid.validation_table);
- g_hash_table_destroy(valid.validation_table);
+ table_count = g_hash_table_size(valid.object_table);
+ g_hash_table_destroy(valid.object_table);
if(table_count == valid.qof_registered_count) { return TRUE; }
return FALSE;
}
@@ -214,18 +220,18 @@
}
params->file_type = IS_QSF_OBJ;
object_root = xmlDocGetRootElement(doc);
- valid.validation_table = g_hash_table_new(g_str_hash, g_str_equal);
+ valid.object_table = g_hash_table_new(g_str_hash, g_str_equal);
valid.qof_registered_count = 0;
iter.ns = object_root->ns;
qsf_valid_foreach(object_root, qsf_object_validation_handler, &iter, &valid);
- table_count = g_hash_table_size(valid.validation_table);
+ table_count = g_hash_table_size(valid.object_table);
if(table_count == valid.qof_registered_count)
{
- g_hash_table_destroy(valid.validation_table);
+ g_hash_table_destroy(valid.object_table);
qof_backend_set_error(params->be, ERR_BACKEND_NO_ERR);
return TRUE;
}
- g_hash_table_destroy(valid.validation_table);
+ g_hash_table_destroy(valid.object_table);
qof_backend_set_error(params->be, ERR_QSF_NO_MAP);
return FALSE;
}
@@ -262,17 +268,17 @@
/* retrieve list of maps from config frame. */
for(maps = params->map_files; maps; maps=maps->next)
{
- QofBackendError err;
+ QofBackendError err;
result = is_qsf_object_with_map_be(maps->data, params);
- 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); }
+ 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;
}
@@ -364,5 +370,5 @@
}
qsf_node_foreach(child, qsf_object_node_handler, &iter, params);
}
- LEAVE (" ");
+ LEAVE (" ");
}
Modified: gnucash/trunk/lib/libqof/backend/file/qsf-xml.h
===================================================================
--- gnucash/trunk/lib/libqof/backend/file/qsf-xml.h 2006-04-17 09:05:19 UTC (rev 13796)
+++ gnucash/trunk/lib/libqof/backend/file/qsf-xml.h 2006-04-17 13:06:33 UTC (rev 13797)
@@ -14,7 +14,7 @@
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
+ * GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
@@ -331,6 +331,35 @@
#define QSF_OBJECT_SCHEMA "qsf-object.xsd.xml" /**< Name of the QSF Object Schema. */
#define QSF_MAP_SCHEMA "qsf-map.xsd.xml" /**< Name of the QSF Map Schema. */
+
+/** \brief Status of various object during mapping.
+
+When handling a map, the incoming QSF objects are not registered with this
+instance of QOF - they originate from another QOF user. Each object in a map
+needs to be defined. If the object is registered, the map is checked to locate
+a calculation that can be used to generate this object. If the object is not
+registered, the incoming QSF is checked to ensure it provides the object data
+for the calculation. If anything goes wrong, QSF_INVALID_OBJECT is used.
+
+Maps can be unidirectional or bidirectional so QOF registration is used to
+determine which calculations should be used and which should be ignored.
+
+All QSF_REGISTERED_OBJECT types need a calculation - if any types remain tagged
+as QSF_REGISTERED_OBJECT when the map validation is complete, the validation
+must fail. The only acceptable end values for QsfStatus are QSF_DEFINED_OBJECT,
+QSF_CALCULATED_OBJECT or QSF_INVALID_OBJECT.
+*/
+typedef enum {
+ QSF_NO_OBJECT = 0, /**< Init value only. */
+ QSF_DEFINED_OBJECT, /**< The object is unregistered but defined.
+Objects of this type must exist in the incoming QSF and must
+provide data for the calculation of registered objects. */
+ QSF_REGISTERED_OBJECT, /**< Temporary value. The object is registered
+and defined - a calculation is needed but has not been found, yet. */
+ QSF_CALCULATED_OBJECT, /**< The object is registered, defined and can be calculated. */
+ QSF_INVALID_OBJECT /**< Oops value. */
+}QsfStatus;
+
/** \brief QSF Parameters
This struct is a catch-all for all parameters required
@@ -347,26 +376,27 @@
GList *referenceList; /**< Table of references, ::QofEntityReference. */
GHashTable *qsf_parameter_hash; /**< Hashtable of parameters for each object */
GHashTable *qsf_calculate_hash, *qsf_default_hash, *qsf_define_hash;
- GSList *supported_types; /**< The list of QOF types currently supported, in QSF order. */
- xmlDocPtr input_doc; /**< Pointer to the input xml document(s). */
- xmlDocPtr output_doc; /**< Pointer to the output xml document(s). */
- xmlNodePtr child_node; /**< The current child_node. */
- xmlNodePtr convert_node; /**< Node in the converted object */
- xmlNodePtr param_node; /**< Node for parameter data. */
- xmlNodePtr output_node; /**< Node in the output document. */
- xmlNodePtr output_root; /**< Root node of the output document. */
- 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 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. */
- QofParam *qof_param; /**< used by kvp to handle the frame hash table */
- QofBook *book; /**< the current QofBook.
+ GSList *supported_types; /**< The list of QOF types currently supported,
+ in QSF order. */
+ xmlDocPtr input_doc; /**< Pointer to the input xml document(s). */
+ xmlDocPtr output_doc; /**< Pointer to the output xml document(s). */
+ xmlNodePtr child_node; /**< The current child_node. */
+ xmlNodePtr convert_node; /**< Node in the converted object */
+ xmlNodePtr param_node; /**< Node for parameter data. */
+ xmlNodePtr output_node; /**< Node in the output document. */
+ xmlNodePtr output_root; /**< Root node of the output document. */
+ 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 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. */
+ QofParam *qof_param; /**< used by kvp to handle the frame hash table */
+ QofBook *book; /**< the current QofBook.
Theoretically, QSF can handle multiple QofBooks - currently limited to 1.
*/
@@ -392,10 +422,19 @@
QofBackendError error_state;
const gchar *object_path;
const gchar *map_path;
- GHashTable *validation_table;
- gint valid_object_count;
- gint map_calculated_count;
- gint qof_registered_count;
+ GHashTable *object_table; /**< Names of all incoming objects (from the
+ object_type) and status (QOF registration). */
+ GHashTable *map_table; /**< Names of all defined objects (from the
+ define tag) and status (presence of a calculation.)*/
+ /* Need to match object names, not just counts. */
+ gint valid_object_count; /**< Number of unique incoming objects as
+ defined in ::QSF_OBJECT_TAG tags in the QSF.*/
+ gint map_calculated_count; /**< Number of objects that can be calculated
+ by this map. ::MAP_OBJECT_TAG. */
+ gint qof_registered_count; /**< Number of objects (in either the QSF
+ or the map) that are registered with QofObject. */
+ gint incoming_count; /**< Number of unique objects in the incoming
+ QSF file. Used to ensure all incoming objects are used.*/
}qsf_validator;
/** \brief shorthand function
Modified: gnucash/trunk/lib/libqof/qof/deprecated.h
===================================================================
--- gnucash/trunk/lib/libqof/qof/deprecated.h 2006-04-17 09:05:19 UTC (rev 13796)
+++ gnucash/trunk/lib/libqof/qof/deprecated.h 2006-04-17 13:06:33 UTC (rev 13797)
@@ -24,7 +24,6 @@
#ifndef _DEPRECATED_H
#define _DEPRECATED_H
-#include <glib.h> /* deprecated */
#include "qof.h"
/** @file deprecated.h
Modified: gnucash/trunk/lib/libqof/qof/kvp_frame.c
===================================================================
--- gnucash/trunk/lib/libqof/qof/kvp_frame.c 2006-04-17 09:05:19 UTC (rev 13796)
+++ gnucash/trunk/lib/libqof/qof/kvp_frame.c 2006-04-17 13:06:33 UTC (rev 13797)
@@ -868,7 +868,7 @@
return kvp_value_get_numeric(kvp_frame_get_slot (frame, key));
}
-const char *
+char *
kvp_frame_get_string(const KvpFrame *frame, const char *path)
{
char *key = NULL;
Modified: gnucash/trunk/lib/libqof/qof/kvp_frame.h
===================================================================
--- gnucash/trunk/lib/libqof/qof/kvp_frame.h 2006-04-17 09:05:19 UTC (rev 13796)
+++ gnucash/trunk/lib/libqof/qof/kvp_frame.h 2006-04-17 13:06:33 UTC (rev 13797)
@@ -183,7 +183,7 @@
* The kvp_frame_set_frame_nc() routine works as above, but does
* *NOT* copy the frame.
*/
-void kvp_frame_set_string(KvpFrame * frame, const gchar * path, const gchar* str);
+void kvp_frame_set_string(KvpFrame * frame, const gchar * path, const char* str);
void kvp_frame_set_guid(KvpFrame * frame, const gchar * path, const GUID *guid);
void kvp_frame_set_frame(KvpFrame *frame, const gchar *path, KvpFrame *chld);
@@ -348,7 +348,7 @@
gint64 kvp_frame_get_gint64(const KvpFrame *frame, const gchar *path);
double kvp_frame_get_double(const KvpFrame *frame, const gchar *path);
gnc_numeric kvp_frame_get_numeric(const KvpFrame *frame, const gchar *path);
-const gchar * kvp_frame_get_string(const KvpFrame *frame, const gchar *path);
+gchar * kvp_frame_get_string(const KvpFrame *frame, const gchar *path);
GUID * kvp_frame_get_guid(const KvpFrame *frame, const gchar *path);
void * kvp_frame_get_binary(const KvpFrame *frame, const gchar *path,
guint64 * size_return);
@@ -677,7 +677,7 @@
slot values. You must handle that in proc, with a suitable
recursive call if desired. */
void kvp_frame_for_each_slot(KvpFrame *f,
- void (*proc)(const gchar *key,
+ void (*proc)(const char *key,
KvpValue *value,
gpointer data),
gpointer data);
Modified: gnucash/trunk/lib/libqof/qof/qofbookmerge.c
===================================================================
--- gnucash/trunk/lib/libqof/qof/qofbookmerge.c 2006-04-17 09:05:19 UTC (rev 13796)
+++ gnucash/trunk/lib/libqof/qof/qofbookmerge.c 2006-04-17 13:06:33 UTC (rev 13797)
@@ -297,9 +297,11 @@
iter.fcn = cb;
subList = NULL;
iter.ruleList = NULL;
- for (node = mergeData->mergeList; node != NULL; node = node->next) {
+ for (node = mergeData->mergeList; node != NULL; node = node->next)
+ {
currentRule = node->data;
- if(currentRule->mergeResult == mergeResult) {
+ if(currentRule->mergeResult == mergeResult)
+ {
subList = g_list_prepend(subList, currentRule);
}
}
@@ -746,7 +748,7 @@
{
QofBookMergeData *mergeData;
QofBookMergeRule *currentRule;
- GList *node;
+ GList *check;
g_return_val_if_fail((importBook != NULL)&&(targetBook != NULL), NULL);
mergeData = g_new(QofBookMergeData, 1);
@@ -762,12 +764,13 @@
mergeData->currentRule = currentRule;
qof_object_foreach_type(qof_book_merge_foreach_type, mergeData);
g_return_val_if_fail(mergeData->mergeObjectParams, NULL);
- if(mergeData->orphan_list != NULL) {
+ if(mergeData->orphan_list != NULL)
+ {
qof_book_merge_match_orphans(mergeData);
}
-
- for (node = mergeData->mergeList; node != NULL; node = node->next) {
- currentRule = node->data;
+ for (check = mergeData->mergeList; check != NULL; check = check->next)
+ {
+ currentRule = check->data;
if(currentRule->mergeResult == MERGE_INVALID) {
mergeData->abort = TRUE;
return(NULL);
@@ -948,7 +951,8 @@
if(mergeData->abort == TRUE) return -1;
check = g_list_copy(mergeData->mergeList);
g_return_val_if_fail(check != NULL, -1);
- for (node = check; node != NULL; node = node->next) {
+ for (node = check; node != NULL; node = node->next)
+ {
currentRule = node->data;
if(currentRule->mergeResult == MERGE_INVALID) {
qof_book_merge_abort(mergeData);
@@ -962,9 +966,9 @@
}
g_list_free(check);
qof_book_merge_commit_foreach(qof_book_merge_commit_rule_loop,
- MERGE_NEW, mergeData);
+ MERGE_NEW, mergeData);
qof_book_merge_commit_foreach(qof_book_merge_commit_rule_loop,
- MERGE_UPDATE, mergeData);
+ MERGE_UPDATE, mergeData);
/* Placeholder for QofObject merge_helper_cb - all objects
and all parameters set */
while(mergeData->mergeList != NULL) {
@@ -1000,8 +1004,8 @@
iter.fcn = cb;
iter.data = mergeData;
matching_rules = NULL;
- iter.ruleList = NULL;
- for (node = mergeData->mergeList; node != NULL; node = node->next) {
+ for (node = mergeData->mergeList; node != NULL; node = node->next)
+ {
currentRule = node->data;
if(currentRule->mergeResult == mergeResult) {
matching_rules = g_list_prepend(matching_rules, currentRule);
Modified: gnucash/trunk/lib/libqof/qof/qofchoice.c
===================================================================
--- gnucash/trunk/lib/libqof/qof/qofchoice.c 2006-04-17 09:05:19 UTC (rev 13796)
+++ gnucash/trunk/lib/libqof/qof/qofchoice.c 2006-04-17 13:06:33 UTC (rev 13797)
@@ -14,7 +14,7 @@
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
+ * GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
Modified: gnucash/trunk/lib/libqof/qof/qofutil.c
===================================================================
--- gnucash/trunk/lib/libqof/qof/qofutil.c 2006-04-17 09:05:19 UTC (rev 13796)
+++ gnucash/trunk/lib/libqof/qof/qofutil.c 2006-04-17 13:06:33 UTC (rev 13797)
@@ -54,6 +54,7 @@
return NULL;
}
+#ifndef HAVE_STRCASESTR
/* Search for str2 in str1, ignore case. Return pointer to first
* match, or null. */
gchar *
@@ -63,6 +64,7 @@
gchar * retval = strncasestr (str1, str2, len);
return retval;
}
+#endif
gint
safe_strcmp (const gchar * da, const gchar * db)
Modified: gnucash/trunk/lib/libqof/qof/qofutil.h
===================================================================
--- gnucash/trunk/lib/libqof/qof/qofutil.h 2006-04-17 09:05:19 UTC (rev 13796)
+++ gnucash/trunk/lib/libqof/qof/qofutil.h 2006-04-17 13:06:33 UTC (rev 13797)
@@ -197,6 +197,7 @@
* and the strstr functions, except that they ignore the case. */
extern gchar *strncasestr(const guchar *str1, const guchar *str2,
size_t len);
+
extern gchar *strcasestr(const gchar *str1, const gchar *str2);
/** The ultostr() subroutine is the inverse of strtoul(). It accepts a
More information about the gnucash-changes
mailing list