Final changes for QOF 0.6.4 - Improvements in map handling.

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@13797 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Neil Williams
2006-04-17 13:06:33 +00:00
parent c8cffa2094
commit 293e60d88f
15 changed files with 446 additions and 315 deletions

View File

@@ -1,3 +1,23 @@
2006-04-17 Neil Williams <linux@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@wilddev.net> 2006-04-16 Chris Lyttle <chris@wilddev.net>
* NEWS: Added some text about the release. * NEWS: Added some text about the release.

View File

@@ -472,8 +472,8 @@ if test x$QOF_XML_DIR = x; then
QOF_VERSION="internal" QOF_VERSION="internal"
QOF_PREFIX="internal" QOF_PREFIX="internal"
QOF_XML_DIR='${datadir}/xml/qsf' QOF_XML_DIR='${datadir}/xml/qsf'
LIBQOF_LIBRARY_VERSION=1:4:0 LIBQOF_LIBRARY_VERSION=1:5:0
LIBQOF_BACKEND_QSF_LIBRARY_VERSION=0:3:0 LIBQOF_BACKEND_QSF_LIBRARY_VERSION=0:4:0
AC_SUBST(LIBQOF_LIBRARY_VERSION) AC_SUBST(LIBQOF_LIBRARY_VERSION)
AC_SUBST(LIBQOF_BACKEND_QSF_LIBRARY_VERSION) AC_SUBST(LIBQOF_BACKEND_QSF_LIBRARY_VERSION)
AC_DEFINE(HAVE_LIBQOF,,[We will use the internal QOF code]) AC_DEFINE(HAVE_LIBQOF,,[We will use the internal QOF code])

View File

@@ -1,71 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<qsf-map xmlns="http://qof.sourceforge.net/"> <qsf-map xmlns="http://qof.sourceforge.net/">
<definition qof_version="3"> <definition qof_version="3">
<define e_type="pilot_address"/> <define e_type="pilot_address" foreach="true"/>
<define e_type="gncBillTerm"/>
<define e_type="gncCustomer"/> <define e_type="gncCustomer"/>
<define e_type="gncAddress" foreach="true"/> <define e_type="gncAddress" foreach="true"/>
</definition> </definition>
<object type="gncCustomer"> <object type="gncCustomer">
<calculate type="string" value="id"/> <calculate type="string" value="id"/>
<calculate type="string" value="notes"> <calculate type="string" value="notes">
<set>entryNote</set> <set object="pilot_address">entryNote</set>
</calculate> </calculate>
<calculate type="string" value="name"> <calculate type="string" value="name">
<set>entryCompany</set> <set object="pilot_address">entryCompany</set>
</calculate> </calculate>
<calculate type="guid" value="guid"/> <calculate type="guid" value="guid"/>
<calculate type="guid" value="addr"> <calculate type="guid" value="addr">
<set>guid</set> <set object="pilot_address">guid</set>
</calculate> </calculate>
<calculate type="guid" value="customer_terms"/> <calculate type="guid" value="customer_terms"/>
<calculate type="guid" value="shipaddr"/> <calculate type="guid" value="shipaddr"/>
<calculate type="boolean" value="active"> <calculate type="boolean" value="active"/>
<set>true</set>
</calculate>
<calculate type="boolean" value="tax table override"/> <calculate type="boolean" value="tax table override"/>
<calculate type="numeric" value="amount of discount"/> <calculate type="numeric" value="amount of discount"/>
<calculate type="numeric" value="amount of credit"/> <calculate type="numeric" value="amount of credit"/>
</object> </object>
<object type="gncAddress"> <object type="gncAddress">
<calculate type="string" value="city"> <calculate type="string" value="city">
<set>entryZip</set> <set object="pilot_address">entryCity</set>
</calculate> </calculate>
<calculate type="string" value="street"> <calculate type="string" value="street">
<set>entryAddress</set> <set object="pilot_address">entryAddress</set>
</calculate> </calculate>
<calculate type="string" value="fax"> <calculate type="string" value="fax">
<set>entryPhone2</set> <set object="pilot_address">entryPhone2</set>
</calculate> </calculate>
<calculate type="string" value="number"/> <calculate type="string" value="number"/>
<calculate type="string" value="name"> <calculate type="string" value="name">
<set>entryFirstname</set> <set object="pilot_address">entryFirstname</set>
<set>entryLastname</set> <set object="pilot_address">entryLastname</set>
</calculate> </calculate>
<calculate type="string" value="email"> <calculate type="string" value="email">
<set>entryPhone5</set> <set object="pilot_address">entryPhone5</set>
</calculate> </calculate>
<calculate type="string" value="locality"> <calculate type="string" value="locality">
<set>entryState</set> <set object="pilot_address">entryState</set>
</calculate> </calculate>
<calculate type="string" value="phone"> <calculate type="string" value="phone">
<set>entryPhone1</set> <set object="pilot_address">entryPhone1</set>
</calculate> </calculate>
<calculate type="guid" value="guid"/> <calculate type="guid" value="guid"/>
<calculate type="guid" value="owner"> <calculate type="guid" value="owner">
<set>guid</set> <set object="pilot_address">guid</set>
</calculate> </calculate>
</object> </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"> <object type="pilot_address">
<calculate type="string" value="entryCity"> <calculate type="string" value="entryCity">
<set object="gncAddress">city</set> <set object="gncAddress">city</set>

View File

@@ -14,7 +14,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 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 * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software

View File

@@ -14,7 +14,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 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 * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@@ -24,23 +24,24 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include "config.h" #include "config.h"
#include <errno.h>
#include <sys/stat.h>
#include <glib.h> #include <glib.h>
#include "qof.h"
#include "qof-backend-qsf.h"
#include <libxml/xmlmemory.h> #include <libxml/xmlmemory.h>
#include <libxml/tree.h> #include <libxml/tree.h>
#include <libxml/parser.h> #include <libxml/parser.h>
#include <libxml/xmlschemas.h> #include <libxml/xmlschemas.h>
#include "qof.h"
#include "qof-backend-qsf.h"
#include "qsf-xml.h" #include "qsf-xml.h"
#include "qsf-dir.h" #include "qsf-dir.h"
#include <errno.h>
#include <sys/stat.h>
#define QSF_TYPE_BINARY "binary" #define QSF_TYPE_BINARY "binary"
#define QSF_TYPE_GLIST "glist" #define QSF_TYPE_GLIST "glist"
#define QSF_TYPE_FRAME "frame" #define QSF_TYPE_FRAME "frame"
static QofLogModule log_module = QOF_MOD_QSF; static QofLogModule log_module = QOF_MOD_QSF;
static void qsf_object_commitCB(gpointer key, gpointer value, gpointer data); static void qsf_object_commitCB(gpointer key, gpointer value, gpointer data);
struct QSFBackend_s struct QSFBackend_s
@@ -60,14 +61,14 @@ static void option_cb (QofBackendOption *option, gpointer data)
g_return_if_fail(params); g_return_if_fail(params);
if(0 == safe_strcmp(QSF_COMPRESS, option->option_name)) { if(0 == safe_strcmp(QSF_COMPRESS, option->option_name)) {
params->use_gz_level = (*(gint64*)option->value); 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)) { if (0 == safe_strcmp(QSF_MAP_FILES, option->option_name)) {
params->map_files = g_list_copy((GList*)option->value); params->map_files = g_list_copy((GList*)option->value);
} }
if (0 == safe_strcmp(QSF_ENCODING, option->option_name)) { if (0 == safe_strcmp(QSF_ENCODING, option->option_name)) {
params->encoding = g_strdup(option->value); params->encoding = g_strdup(option->value);
DEBUG (" encoding=%s", params->encoding); PINFO (" encoding=%s", params->encoding);
} }
} }
@@ -104,6 +105,7 @@ qsf_get_config(QofBackend *be)
option->tooltip = _("QOF can compress QSF XML files using gzip. " option->tooltip = _("QOF can compress QSF XML files using gzip. "
"Note that compression is not used when outputting to STDOUT."); "Note that compression is not used when outputting to STDOUT.");
option->type = KVP_TYPE_GINT64; option->type = KVP_TYPE_GINT64;
/* GINT_TO_POINTER can only be used for 32bit values. */
option->value = (gpointer)&params->use_gz_level; option->value = (gpointer)&params->use_gz_level;
qof_backend_prepare_option(be, option); qof_backend_prepare_option(be, option);
g_free(option); g_free(option);
@@ -132,6 +134,8 @@ qsf_get_config(QofBackend *be)
GList** GList**
qsf_map_prepare_list(GList **maps) 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-GnuCashInvoice.xml");
*maps = g_list_prepend(*maps, "pilot-qsf-gncCustomer.xml"); *maps = g_list_prepend(*maps, "pilot-qsf-gncCustomer.xml");
return maps; return maps;
@@ -246,10 +250,10 @@ qsf_session_begin(QofBackend *be, QofSession *session, const gchar *book_path,
} }
if(create_if_nonexistent) if(create_if_nonexistent)
{ {
FILE *f; FILE *f;
f = fopen(qsf_be->fullpath, "a+"); f = fopen(qsf_be->fullpath, "a+");
if(f) {fclose(f); } if(f) {fclose(f); }
else else
{ {
qof_backend_set_error(be, ERR_BACKEND_READONLY); qof_backend_set_error(be, ERR_BACKEND_READONLY);
@@ -364,11 +368,13 @@ qsfdoc_to_qofbook(xmlDocPtr doc, qsf_param *params)
object_list = g_list_next(object_list); object_list = g_list_next(object_list);
params->qsf_parameter_hash = params->object_set->parameters; params->qsf_parameter_hash = params->object_set->parameters;
if(!qof_class_is_registered(params->object_set->object_type)) { continue; } 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); g_return_val_if_fail(inst != NULL, FALSE);
params->qsf_ent = &inst->entity; params->qsf_ent = &inst->entity;
qof_begin_edit(inst); 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_commit_edit(inst);
} }
qof_object_foreach_type(insert_ref_cb, params); qof_object_foreach_type(insert_ref_cb, params);
@@ -437,24 +443,25 @@ load_our_qsf_object(QofBook *book, const gchar *fullpath, qsf_param *params)
/* Determine the type of QSF and load it into the QofBook /* 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 - 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 - 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 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, 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 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. 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 - 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. match a QSF object.
returns NULL on error, otherwise a pointer to the QofBook. Use returns NULL on error, otherwise a pointer to the QofBook. Use
the qof_book_merge API to merge the new data into the current the qof_book_merge API to merge the new data into the current
QofBook. QofBook.
*/ */
static void static void
qsf_file_type(QofBackend *be, QofBook *book) qsf_file_type(QofBackend *be, QofBook *book)
{ {
QSFBackend *qsf_be; QSFBackend *qsf_be;
QofBackendError err;
qsf_param *params; qsf_param *params;
FILE *f; FILE *f;
gchar *path; gchar *path;
@@ -487,7 +494,16 @@ qsf_file_type(QofBackend *be, QofBook *book)
if(!result) { qof_backend_set_error(be, ERR_FILEIO_PARSE_ERROR); } if(!result) { qof_backend_set_error(be, ERR_FILEIO_PARSE_ERROR); }
return; 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)) { if(is_qsf_map_be(params)) {
params->file_type = IS_QSF_MAP; params->file_type = IS_QSF_MAP;
qof_backend_set_error(be, ERR_QSF_MAP_NOT_OBJ); qof_backend_set_error(be, ERR_QSF_MAP_NOT_OBJ);
@@ -608,7 +624,8 @@ qsf_from_kvp_helper(const gchar *path, KvpValue *content, gpointer data)
node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns, node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns,
BAD_CAST qof_param->param_type)); BAD_CAST qof_param->param_type));
xmlNodeAddContent(node, BAD_CAST kvp_value_to_bare_string(content)); 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); 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_KVP, BAD_CAST full_path);
xmlNewProp(node, BAD_CAST QSF_OBJECT_VALUE, xmlNewProp(node, BAD_CAST QSF_OBJECT_VALUE,
@@ -792,11 +809,13 @@ qsf_entity_foreach(QofEntity *ent, gpointer data)
if(!own_guid) if(!own_guid)
{ {
cm_guid = qof_entity_get_guid(ent); 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); guid_to_string_buff(cm_guid, cm_sa);
string_buffer = g_strdup(cm_sa); string_buffer = g_strdup(cm_sa);
xmlNodeAddContent(node, BAD_CAST string_buffer); 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); g_free(string_buffer);
own_guid = TRUE; own_guid = TRUE;
} }
@@ -828,12 +847,14 @@ qsf_entity_foreach(QofEntity *ent, gpointer data)
param_list = g_slist_next(param_list); param_list = g_slist_next(param_list);
continue; 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); cm_guid = qof_entity_get_guid(choice_ent);
guid_to_string_buff(cm_guid, cm_sa); guid_to_string_buff(cm_guid, cm_sa);
string_buffer = g_strdup(cm_sa); string_buffer = g_strdup(cm_sa);
xmlNodeAddContent(node, BAD_CAST string_buffer); 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); xmlNewProp(node, BAD_CAST "name", BAD_CAST choice_ent->e_type);
g_free(string_buffer); g_free(string_buffer);
param_list = g_slist_next(param_list); param_list = g_slist_next(param_list);
@@ -852,12 +873,16 @@ qsf_entity_foreach(QofEntity *ent, gpointer data)
for( supported = g_slist_copy(params->supported_types); for( supported = g_slist_copy(params->supported_types);
supported != NULL; supported = g_slist_next(supported)) 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)); node = xmlAddChild(object_node,
string_buffer = g_strdup(qof_book_merge_param_as_string(qof_param, ent)); 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); 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); g_free(string_buffer);
} }
} }
@@ -932,13 +957,14 @@ write_qsf_from_book(const char *path, QofBook *book, qsf_param *params)
be = qof_book_get_backend(book); be = qof_book_get_backend(book);
qsf_doc = qofbook_to_qsf(book, params); qsf_doc = qofbook_to_qsf(book, params);
write_result = 0; 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); params->use_gz_level, params->encoding);
if((params->use_gz_level > 0) && (params->use_gz_level <= 9)) if((params->use_gz_level > 0) && (params->use_gz_level <= 9))
{ {
xmlSetDocCompressMode(qsf_doc, params->use_gz_level); 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); write_result = xmlSaveFormatFileEnc(path, qsf_doc, params->encoding, 1);
if(write_result < 0) if(write_result < 0)
{ {
@@ -954,8 +980,9 @@ write_qsf_to_stdout(QofBook *book, qsf_param *params)
xmlDocPtr qsf_doc; xmlDocPtr qsf_doc;
qsf_doc = qofbook_to_qsf(book, params); qsf_doc = qofbook_to_qsf(book, params);
g_return_if_fail(qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, qsf_doc) == TRUE); g_return_if_fail(
DEBUG (" use_gz_level=%" G_GINT64_FORMAT " encoding=%s", 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); params->use_gz_level, params->encoding);
xmlSaveFormatFileEnc("-", qsf_doc, params->encoding, 1); xmlSaveFormatFileEnc("-", qsf_doc, params->encoding, 1);
fprintf(stdout, "\n"); fprintf(stdout, "\n");
@@ -993,49 +1020,62 @@ string_to_kvp_value(const gchar *content, KvpValueType type)
time_t kvp_time_t; time_t kvp_time_t;
Timespec cm_date; Timespec cm_date;
switch(type) { switch(type)
case KVP_TYPE_GINT64: {
errno = 0; case KVP_TYPE_GINT64:
cm_i64 = strtoll(content, &tail, 0);
if(errno == 0) {
return kvp_value_new_gint64(cm_i64);
}
break;
case KVP_TYPE_DOUBLE:
errno = 0;
cm_double = strtod(content, &tail);
if(errno == 0) {
return kvp_value_new_double(cm_double);
}
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))
{ {
return kvp_value_new_guid(cm_guid); errno = 0;
cm_i64 = strtoll(content, &tail, 0);
if(errno == 0) {
return kvp_value_new_gint64(cm_i64);
}
break;
} }
break; case KVP_TYPE_DOUBLE:
case KVP_TYPE_TIMESPEC: {
strptime(content, QSF_XSD_TIME, &kvp_time); errno = 0;
kvp_time_t = mktime(&kvp_time); cm_double = strtod(content, &tail);
timespecFromTime_t(&cm_date, kvp_time_t); if(errno == 0) {
return kvp_value_new_timespec(cm_date); return kvp_value_new_double(cm_double);
break; }
case KVP_TYPE_BINARY: 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))
{
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, // return kvp_value_new_binary(value->value.binary.data,
// value->value.binary.datasize); // value->value.binary.datasize);
break; break;
case KVP_TYPE_GLIST: case KVP_TYPE_GLIST:
// return kvp_value_new_glist(value->value.list); // return kvp_value_new_glist(value->value.list);
break; break;
case KVP_TYPE_FRAME: case KVP_TYPE_FRAME:
// return kvp_value_new_frame(value->value.frame); // return kvp_value_new_frame(value->value.frame);
break; break;
} }
@@ -1099,12 +1139,14 @@ qsf_object_commitCB(gpointer key, gpointer value, gpointer data)
object_set = params->object_set; object_set = params->object_set;
if(safe_strcmp(qof_type, QOF_TYPE_STRING) == 0) { if(safe_strcmp(qof_type, QOF_TYPE_STRING) == 0) {
string_setter = (void(*)(QofEntity*, const gchar*))cm_setter; 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) { if(safe_strcmp(qof_type, QOF_TYPE_DATE) == 0) {
date_setter = (void(*)(QofEntity*, Timespec))cm_setter; date_setter = (void(*)(QofEntity*, Timespec))cm_setter;
timechk = NULL; 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); g_return_if_fail(timechk != NULL);
qsf_time_t = mktime(&qsf_time); qsf_time_t = mktime(&qsf_time);
if(qsf_time_t != -3600) if(qsf_time_t != -3600)
@@ -1136,7 +1178,8 @@ qsf_object_commitCB(gpointer key, gpointer value, gpointer data)
else { else {
reference = qof_entity_get_reference_from(qsf_ent, cm_param); reference = qof_entity_get_reference_from(qsf_ent, cm_param);
if(reference) { if(reference) {
params->referenceList = g_list_append(params->referenceList, reference); params->referenceList = g_list_append(params->referenceList,
reference);
} }
} }
} }
@@ -1276,12 +1319,6 @@ qsf_provider_init(void)
{ {
QofBackendProvider *prov; 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 = g_new0 (QofBackendProvider, 1);
prov->provider_name = "QSF Backend Version 0.2"; prov->provider_name = "QSF Backend Version 0.2";
prov->access_method = "file"; prov->access_method = "file";

View File

@@ -14,7 +14,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 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 * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@@ -72,61 +72,161 @@ qsf_string_default_handler(const gchar *default_name, GHashTable *qsf_default_ha
static void static void
qsf_map_validation_handler(xmlNodePtr child, xmlNsPtr ns, qsf_validator *valid) qsf_map_validation_handler(xmlNodePtr child, xmlNsPtr ns, qsf_validator *valid)
{ {
xmlChar *qof_version, *match; xmlChar *qof_version, *obj_type;
GString *buff; gboolean match, is_registered;
gchar *buff;
xmlNodePtr child_node; 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)) { if (qsf_is_element(child, ns, MAP_DEFINITION_TAG)) {
qof_version = xmlGetProp(child, BAD_CAST MAP_QOF_VERSION); qof_version = xmlGetProp(child, BAD_CAST MAP_QOF_VERSION);
buff = g_string_new(" "); buff = g_strdup_printf("%i", QSF_QOF_VERSION);
g_string_printf(buff, "%i", QSF_QOF_VERSION); if(xmlStrcmp(qof_version, BAD_CAST buff) != 0)
if(xmlStrcmp(qof_version, BAD_CAST buff->str) != 0)
{ {
PERR (" Wrong QOF_VERSION in map '%s', should be %s",
qof_version, buff);
valid->error_state = ERR_QSF_BAD_QOF_VERSION; valid->error_state = ERR_QSF_BAD_QOF_VERSION;
g_free(buff);
return; return;
} }
g_free(buff);
for(child_node = child->children; child_node != NULL; for(child_node = child->children; child_node != NULL;
child_node = child_node->next) child_node = child_node->next)
{ {
if (qsf_is_element(child_node, ns, MAP_DEFINE_TAG)) { if (qsf_is_element(child_node, ns, MAP_DEFINE_TAG)) {
g_hash_table_insert(valid->validation_table, obj_type = xmlGetProp(child_node, MAP_E_TYPE);
xmlGetProp(child_node, BAD_CAST MAP_E_TYPE), type = QSF_DEFINED_OBJECT;
xmlNodeGetContent(child_node)); 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)) { if(qsf_is_element(child, ns, MAP_OBJECT_TAG)) {
match = NULL;
obj_type = 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); /* check each listed object is either registered or calculated. */
if(match) { type = GPOINTER_TO_INT(g_hash_table_lookup(valid->map_table, obj_type));
valid->map_calculated_count++; switch(type)
if(TRUE == qof_class_is_registered((QofIdTypeConst) obj_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 */
{ {
valid->qof_registered_count++; /* lookup the same object in QSF object_table */
PINFO (" %s is to be calculated", obj_type); 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++;
/* store the result */
g_hash_table_insert(valid->map_table, obj_type, GINT_TO_POINTER(type));
break;
}
default :
{
type = QSF_INVALID_OBJECT;
break;
} }
else { PINFO (" %s to be mapped", obj_type); }
} }
PINFO (" final type=%s result=%d", obj_type, type);
if(type == QSF_INVALID_OBJECT) { valid->error_state = ERR_QSF_WRONG_MAP; }
} }
} }
static QofBackendError
check_qsf_object_with_map_internal(xmlDocPtr map_doc, xmlDocPtr doc)
{
xmlNodePtr map_root, object_root;
struct qsf_node_iterate iter;
qsf_validator valid;
xmlNsPtr map_ns;
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) gboolean is_qsf_object_with_map_be(gchar *map_file, qsf_param *params)
{ {
xmlDocPtr doc, map_doc; xmlDocPtr doc, map_doc;
gint valid_count, calc_count; QofBackendError result;
struct qsf_node_iterate iter; gchar *path, *map_path;
xmlNodePtr map_root, object_root;
xmlNsPtr map_ns;
qsf_validator valid;
gchar *path;
gchar *map_path;
g_return_val_if_fail((params != NULL),FALSE); g_return_val_if_fail((params != NULL),FALSE);
PINFO (" mapfile=%s", map_file);
path = g_strdup(params->filepath); path = g_strdup(params->filepath);
map_path = g_strdup_printf("%s/%s", QSF_SCHEMA_DIR, map_file); map_path = g_strdup_printf("%s/%s", QSF_SCHEMA_DIR, map_file);
PINFO (" checking map file '%s'", map_path);
if(path == NULL) { if(path == NULL) {
qof_backend_set_error(params->be, ERR_FILEIO_FILE_NOT_FOUND); qof_backend_set_error(params->be, ERR_FILEIO_FILE_NOT_FOUND);
return FALSE; return FALSE;
@@ -140,73 +240,24 @@ gboolean is_qsf_object_with_map_be(gchar *map_file, qsf_param *params)
qof_backend_set_error(params->be, ERR_QSF_INVALID_OBJ); qof_backend_set_error(params->be, ERR_QSF_INVALID_OBJ);
return FALSE; return FALSE;
} }
object_root = xmlDocGetRootElement(doc);
if(map_path == NULL) { if(map_path == NULL) {
qof_backend_set_error(params->be, ERR_FILEIO_FILE_NOT_FOUND); qof_backend_set_error(params->be, ERR_FILEIO_FILE_NOT_FOUND);
return FALSE; return FALSE;
} }
valid.validation_table = g_hash_table_new(g_str_hash, g_str_equal);
map_doc = xmlParseFile(map_path); map_doc = xmlParseFile(map_path);
if(map_doc == NULL) { if(map_doc == NULL) {
qof_backend_set_error(params->be, ERR_FILEIO_PARSE_ERROR); qof_backend_set_error(params->be, ERR_FILEIO_PARSE_ERROR);
return FALSE; return FALSE;
} }
if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_MAP_SCHEMA, map_doc)) { result = check_qsf_object_with_map_internal(map_doc, doc);
qof_backend_set_error(params->be, ERR_QSF_INVALID_MAP); qof_backend_set_error(params->be, result);
return FALSE; return (result == ERR_BACKEND_NO_ERR) ? TRUE : 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;
} }
gboolean is_qsf_object_with_map(const gchar *path, gchar *map_file) gboolean is_qsf_object_with_map(const gchar *path, gchar *map_file)
{ {
xmlDocPtr doc, map_doc; xmlDocPtr doc, map_doc;
gint valid_count; QofBackendError result;
struct qsf_node_iterate iter;
xmlNodePtr map_root, object_root;
xmlNsPtr map_ns;
qsf_validator valid;
gchar *map_path; gchar *map_path;
map_path = g_strdup_printf("%s/%s", QSF_SCHEMA_DIR, map_file); map_path = g_strdup_printf("%s/%s", QSF_SCHEMA_DIR, map_file);
@@ -220,39 +271,12 @@ gboolean is_qsf_object_with_map(const gchar *path, gchar *map_file)
if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc)) { if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc)) {
return FALSE; return FALSE;
} }
object_root = xmlDocGetRootElement(doc);
if(map_path == NULL) { if(map_path == NULL) {
return FALSE; return FALSE;
} }
valid.validation_table = g_hash_table_new(g_str_hash, g_str_equal);
map_doc = xmlParseFile(map_path); map_doc = xmlParseFile(map_path);
if(map_doc == NULL) { result = check_qsf_object_with_map_internal(map_doc, doc);
return FALSE; return (result == ERR_BACKEND_NO_ERR) ? TRUE : 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;
} }
gboolean is_qsf_map_be(qsf_param *params) gboolean is_qsf_map_be(qsf_param *params)
@@ -283,16 +307,17 @@ gboolean is_qsf_map_be(qsf_param *params)
map_root = xmlDocGetRootElement(doc); map_root = xmlDocGetRootElement(doc);
map_ns = map_root->ns; map_ns = map_root->ns;
iter.ns = map_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; valid.error_state = ERR_BACKEND_NO_ERR;
qsf_valid_foreach(map_root, qsf_map_validation_handler, &iter, &valid); qsf_valid_foreach(map_root, qsf_map_validation_handler, &iter, &valid);
if (valid.error_state != ERR_BACKEND_NO_ERR) { if (valid.error_state != ERR_BACKEND_NO_ERR) {
qof_backend_set_error(params->be, valid.error_state); 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; return FALSE;
} }
qof_backend_get_error(params->be); qof_backend_get_error(params->be);
g_hash_table_destroy(valid.validation_table); g_hash_table_destroy(valid.object_table);
return TRUE; return TRUE;
} }
@@ -315,17 +340,16 @@ gboolean is_qsf_map(const gchar *path)
map_ns = map_root->ns; map_ns = map_root->ns;
iter.ns = map_ns; iter.ns = map_ns;
valid.error_state = ERR_BACKEND_NO_ERR; 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); qsf_valid_foreach(map_root, qsf_map_validation_handler, &iter, &valid);
if (valid.error_state != ERR_BACKEND_NO_ERR) { if (valid.error_state != ERR_BACKEND_NO_ERR) {
g_hash_table_destroy(valid.validation_table); g_hash_table_destroy(valid.map_table);
return FALSE; return FALSE;
} }
g_hash_table_destroy(valid.validation_table); g_hash_table_destroy(valid.map_table);
return TRUE; return TRUE;
} }
static void static void
qsf_map_default_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params ) qsf_map_default_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params )
{ {
@@ -335,11 +359,13 @@ qsf_map_default_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params )
g_return_if_fail(params->qsf_define_hash != NULL); g_return_if_fail(params->qsf_define_hash != NULL);
iterate = NULL; iterate = NULL;
if (qsf_is_element(child, ns, MAP_DEFINE_TAG)) { if (qsf_is_element(child, ns, MAP_DEFINE_TAG)) {
iterate = xmlGetProp(child, MAP_ITERATE_ATTR); iterate = xmlGetProp(child, MAP_ITERATE_ATTR);
if(qof_util_bool_to_int(iterate) == 1) 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); {
} 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, if(NULL == g_hash_table_lookup(params->qsf_define_hash,
xmlGetProp(child, BAD_CAST MAP_E_TYPE))) xmlGetProp(child, BAD_CAST MAP_E_TYPE)))
{ {
@@ -398,17 +424,17 @@ static void
qsf_map_top_node_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params) qsf_map_top_node_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params)
{ {
xmlChar *qof_version; xmlChar *qof_version;
GString *buff; gchar *buff;
struct qsf_node_iterate iter; struct qsf_node_iterate iter;
if(!params->qsf_define_hash) return; if(!params->qsf_define_hash) return;
if(!params->qsf_default_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)) { if(qsf_is_element(child, ns, MAP_DEFINITION_TAG)) {
qof_version = xmlGetProp(child, BAD_CAST MAP_QOF_VERSION); qof_version = xmlGetProp(child, BAD_CAST MAP_QOF_VERSION);
buff = g_string_new(" "); buff = g_strdup_printf("%i", QSF_QOF_VERSION);
g_string_printf(buff, "%i", QSF_QOF_VERSION); if(xmlStrcmp(qof_version, BAD_CAST buff) != 0) {
if(xmlStrcmp(qof_version, BAD_CAST buff->str) != 0) {
qof_backend_set_error(params->be, ERR_QSF_BAD_QOF_VERSION); qof_backend_set_error(params->be, ERR_QSF_BAD_QOF_VERSION);
LEAVE (" ERR_QSF_BAD_QOF_VERSION set"); LEAVE (" ERR_QSF_BAD_QOF_VERSION set");
return; return;
@@ -453,7 +479,8 @@ qsf_set_handler(xmlNodePtr parent, GHashTable *default_hash,
if(qsf_is_element(cur_node, params->map_ns, QSF_CONDITIONAL_SET)) if(qsf_is_element(cur_node, params->map_ns, QSF_CONDITIONAL_SET))
{ {
content = (gchar*)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")) if(qsf_strings_equal(xmlGetProp(cur_node,
BAD_CAST QSF_OPTION), "qsf_lookup_string"))
{ {
lookup_node = (xmlNodePtr) g_hash_table_lookup(default_hash, lookup_node = (xmlNodePtr) g_hash_table_lookup(default_hash,
xmlNodeGetContent(cur_node)); xmlNodeGetContent(cur_node));
@@ -565,8 +592,7 @@ qsf_set_format_value(xmlChar *format, gchar *qsf_time_now_as_string,
result = regexec(&reg, (gchar*)format,(size_t)0,NULL,0); result = regexec(&reg, (gchar*)format,(size_t)0,NULL,0);
if(result == REG_NOMATCH) { format = BAD_CAST "%F"; } if(result == REG_NOMATCH) { format = BAD_CAST "%F"; }
regfree(&reg); regfree(&reg);
/** 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)); strftime(qsf_time_now_as_string, QSF_DATE_LENGTH, (char*)format, gmtime(output));
LEAVE (" ok"); LEAVE (" ok");
} }
@@ -609,7 +635,8 @@ qsf_calculate_conditional(xmlNodePtr param_node, xmlNodePtr child, qsf_param *pa
/* Is the default set to true? */ /* Is the default set to true? */
if( 0 == qsf_compare_tag_strings(output_content, QSF_XML_BOOLEAN_TEST)) 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, export_node = xmlAddChild(params->lister, xmlNewNode(params->qsf_ns,
xmlGetProp(child, BAD_CAST QSF_OBJECT_TYPE))); xmlGetProp(child, BAD_CAST QSF_OBJECT_TYPE)));
xmlNewProp(export_node, BAD_CAST QSF_OBJECT_TYPE, xmlNewProp(export_node, BAD_CAST QSF_OBJECT_TYPE,
@@ -644,6 +671,8 @@ qsf_add_object_tag(qsf_param *params, gint count)
static gint static gint
identify_source_func(gconstpointer qsf_object, gconstpointer map) 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); return safe_strcmp(((qsf_objects*)qsf_object)->object_type, (QofIdType)map);
} }
@@ -652,22 +681,27 @@ qsf_map_calculate_output(xmlNodePtr param_node, xmlNodePtr child, qsf_param *par
{ {
xmlNodePtr export_node; xmlNodePtr export_node;
xmlChar *output_content; xmlChar *output_content;
xmlNodePtr node; xmlNodePtr input_node;
GList *source; GList *source;
DEBUG (" %s", xmlNodeGetContent(param_node));
output_content = xmlNodeGetContent(param_node); output_content = xmlNodeGetContent(param_node);
DEBUG (" %s", output_content);
/* source refers to the source object that provides the data */ /* source refers to the source object that provides the data */
source = g_list_find_custom(params->qsf_object_list, source = g_list_find_custom(params->qsf_object_list,
BAD_CAST xmlGetProp(param_node, MAP_OBJECT_ATTR), identify_source_func); 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; 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, export_node = xmlAddChild(params->lister, xmlNewNode(params->qsf_ns,
xmlGetProp(child, BAD_CAST QSF_OBJECT_TYPE))); xmlGetProp(child, BAD_CAST QSF_OBJECT_TYPE)));
xmlNewProp(export_node, BAD_CAST QSF_OBJECT_TYPE, xmlNewProp(export_node, BAD_CAST QSF_OBJECT_TYPE,
xmlGetProp(child, BAD_CAST MAP_VALUE_ATTR)); xmlGetProp(child, BAD_CAST MAP_VALUE_ATTR));
if(node) { xmlNodeAddContent(export_node, xmlNodeGetContent(node)); } xmlNodeAddContent(export_node, xmlNodeGetContent(input_node));
} }
static void static void
@@ -712,7 +746,7 @@ qsf_map_object_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params)
qsf_string_default_handler("qsf_time_string", qsf_string_default_handler("qsf_time_string",
params->qsf_default_hash, params->lister, child, qsf_ns); 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_conditional( param_node, child, params);
qsf_calculate_else(param_node, child, params); qsf_calculate_else(param_node, child, params);
@@ -776,11 +810,12 @@ qsf_object_convert(xmlDocPtr mapDoc, xmlNodePtr qsf_root, qsf_param *params)
map_root = xmlDocGetRootElement(mapDoc); map_root = xmlDocGetRootElement(mapDoc);
params->foreach_limit = 0; params->foreach_limit = 0;
iter.ns = params->map_ns; iter.ns = params->map_ns;
/* sets qof_foreach iterator, defines and defaults. */
qsf_node_foreach(map_root, qsf_map_top_node_handler, &iter, params); qsf_node_foreach(map_root, qsf_map_top_node_handler, &iter, params);
/* identify the entities of iterator type. */ /* identify the entities of iterator type. */
iter.ns = params->qsf_ns; iter.ns = params->qsf_ns;
qsf_node_foreach(qsf_root->children->next, iterator_cb, &iter, params); qsf_node_foreach(qsf_root->children->next, iterator_cb, &iter, params);
PINFO (" counted %d records", params->foreach_limit);
params->count = 0; params->count = 0;
for(cur_node = map_root->children; cur_node != NULL; cur_node = cur_node->next) for(cur_node = map_root->children; cur_node != NULL; cur_node = cur_node->next)
{ {
@@ -790,24 +825,25 @@ qsf_object_convert(xmlDocPtr mapDoc, xmlNodePtr qsf_root, qsf_param *params)
gint i; gint i;
params->lister = NULL; params->lister = NULL;
PINFO (" found an object tag. starting calculation");
/* cur_node describes the target object */ /* 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; } xmlGetProp(cur_node, MAP_TYPE_ATTR))) { continue; }
qsf_add_object_tag(params, params->count); qsf_add_object_tag(params, params->count);
params->count++; params->count++;
iter.ns = params->map_ns; 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); qsf_node_foreach(cur_node, qsf_map_object_handler, &iter, params);
params->qsf_object_list = g_list_next(params->qsf_object_list); params->qsf_object_list = g_list_next(params->qsf_object_list);
qsf_add_object_tag(params, params->count);
params->count++; params->count++;
} }
} }
} }
params->file_type = OUR_QSF_OBJ; params->file_type = OUR_QSF_OBJ;
/* use for debugging */ /* use for debugging */
/* xmlSaveFormatFileEnc("-", output_doc, "UTF-8", 1);*/ xmlSaveFormatFileEnc("-", output_doc, "UTF-8", 1);
LEAVE (" "); LEAVE (" ");
return output_doc; return output_doc;
} }

View File

@@ -14,7 +14,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 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 * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@@ -122,22 +122,28 @@ qsf_object_validation_handler(xmlNodePtr child, xmlNsPtr ns, qsf_validator *vali
xmlNodePtr cur_node; xmlNodePtr cur_node;
xmlChar *object_declaration; xmlChar *object_declaration;
guint count; guint count;
QsfStatus type;
gboolean is_registered;
count = 0; count = 0;
type = QSF_NO_OBJECT;
is_registered = FALSE;
for(cur_node = child->children; cur_node != NULL; for(cur_node = child->children; cur_node != NULL;
cur_node = cur_node->next) cur_node = cur_node->next)
{ {
if(qsf_is_element(cur_node, ns, QSF_OBJECT_TAG)) { if(qsf_is_element(cur_node, ns, QSF_OBJECT_TAG)) {
object_declaration = xmlGetProp(cur_node, BAD_CAST QSF_OBJECT_TYPE); object_declaration = xmlGetProp(cur_node, BAD_CAST QSF_OBJECT_TYPE);
count = g_hash_table_size(valid->validation_table); is_registered = qof_class_is_registered(object_declaration);
g_hash_table_insert(valid->validation_table, object_declaration, xmlNodeGetContent(cur_node)); if(is_registered) { type = QSF_REGISTERED_OBJECT; }
if(g_hash_table_size(valid->validation_table) > count) 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++; valid->valid_object_count++;
if(TRUE == qof_class_is_registered((QofIdTypeConst) object_declaration)) if(is_registered) { valid->qof_registered_count++; }
{
valid->qof_registered_count++;
}
} }
} }
} }
@@ -161,13 +167,13 @@ gboolean is_our_qsf_object(const gchar *path)
} }
object_root = xmlDocGetRootElement(doc); object_root = xmlDocGetRootElement(doc);
/* check that all objects in the file are already registered in QOF */ /* 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.qof_registered_count = 0;
valid.valid_object_count = 0; valid.valid_object_count = 0;
iter.ns = object_root->ns; iter.ns = object_root->ns;
qsf_valid_foreach(object_root, qsf_object_validation_handler, &iter, &valid); 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);
g_hash_table_destroy(valid.validation_table); g_hash_table_destroy(valid.object_table);
if(table_count == valid.qof_registered_count) { return TRUE; } if(table_count == valid.qof_registered_count) { return TRUE; }
return FALSE; return FALSE;
} }
@@ -214,18 +220,18 @@ gboolean is_our_qsf_object_be(qsf_param *params)
} }
params->file_type = IS_QSF_OBJ; params->file_type = IS_QSF_OBJ;
object_root = xmlDocGetRootElement(doc); 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; valid.qof_registered_count = 0;
iter.ns = object_root->ns; iter.ns = object_root->ns;
qsf_valid_foreach(object_root, qsf_object_validation_handler, &iter, &valid); 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) 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); qof_backend_set_error(params->be, ERR_BACKEND_NO_ERR);
return TRUE; 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); qof_backend_set_error(params->be, ERR_QSF_NO_MAP);
return FALSE; return FALSE;
} }
@@ -262,17 +268,17 @@ gboolean is_qsf_object_be(qsf_param *params)
/* retrieve list of maps from config frame. */ /* retrieve list of maps from config frame. */
for(maps = params->map_files; maps; maps=maps->next) for(maps = params->map_files; maps; maps=maps->next)
{ {
QofBackendError err; QofBackendError err;
result = is_qsf_object_with_map_be(maps->data, params); result = is_qsf_object_with_map_be(maps->data, params);
err = qof_backend_get_error(params->be); err = qof_backend_get_error(params->be);
if((err == ERR_BACKEND_NO_ERR) && result) if((err == ERR_BACKEND_NO_ERR) && result)
{ {
params->map_path = maps->data; params->map_path = maps->data;
PINFO ("map chosen = %s", params->map_path); PINFO ("map chosen = %s", params->map_path);
break; break;
} }
/* pop the error back on the stack. */ /* pop the error back on the stack. */
else { qof_backend_set_error(params->be, err); } else { qof_backend_set_error(params->be, err); }
} }
return result; return result;
} }
@@ -364,5 +370,5 @@ qsf_book_node_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params)
} }
qsf_node_foreach(child, qsf_object_node_handler, &iter, params); qsf_node_foreach(child, qsf_object_node_handler, &iter, params);
} }
LEAVE (" "); LEAVE (" ");
} }

View File

@@ -14,7 +14,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 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 * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@@ -331,6 +331,35 @@ Both defaults use UTC.
#define QSF_OBJECT_SCHEMA "qsf-object.xsd.xml" /**< Name of the QSF Object Schema. */ #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. */ #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 /** \brief QSF Parameters
This struct is a catch-all for all parameters required This struct is a catch-all for all parameters required
@@ -347,26 +376,27 @@ typedef struct qsf_metadata
GList *referenceList; /**< Table of references, ::QofEntityReference. */ GList *referenceList; /**< Table of references, ::QofEntityReference. */
GHashTable *qsf_parameter_hash; /**< Hashtable of parameters for each object */ GHashTable *qsf_parameter_hash; /**< Hashtable of parameters for each object */
GHashTable *qsf_calculate_hash, *qsf_default_hash, *qsf_define_hash; GHashTable *qsf_calculate_hash, *qsf_default_hash, *qsf_define_hash;
GSList *supported_types; /**< The list of QOF types currently supported, in QSF order. */ GSList *supported_types; /**< The list of QOF types currently supported,
xmlDocPtr input_doc; /**< Pointer to the input xml document(s). */ in QSF order. */
xmlDocPtr output_doc; /**< Pointer to the output xml document(s). */ xmlDocPtr input_doc; /**< Pointer to the input xml document(s). */
xmlNodePtr child_node; /**< The current child_node. */ xmlDocPtr output_doc; /**< Pointer to the output xml document(s). */
xmlNodePtr convert_node; /**< Node in the converted object */ xmlNodePtr child_node; /**< The current child_node. */
xmlNodePtr param_node; /**< Node for parameter data. */ xmlNodePtr convert_node; /**< Node in the converted object */
xmlNodePtr output_node; /**< Node in the output document. */ xmlNodePtr param_node; /**< Node for parameter data. */
xmlNodePtr output_root; /**< Root node of the output document. */ xmlNodePtr output_node; /**< Node in the output document. */
xmlNodePtr book_node; /**< Node for the book. */ xmlNodePtr output_root; /**< Root node of the output document. */
xmlNodePtr lister; /**< Comparison node for map defaults. */ xmlNodePtr book_node; /**< Node for the book. */
xmlNsPtr qsf_ns, map_ns; /**< Separate namespaces for QSF objects and QSF maps. */ xmlNodePtr lister; /**< Comparison node for map defaults. */
const gchar *qof_type; /**< Holds details of the QOF_TYPE */ xmlNsPtr qsf_ns, map_ns; /**< Separate namespaces for QSF objects and QSF maps. */
QofIdType qof_obj_type; /**< current QofObject type (e_type) for the parameters. */ const gchar *qof_type; /**< Holds details of the QOF_TYPE */
QofIdType qof_foreach; /**< How to iterate over hierarchical entities. */ QofIdType qof_obj_type; /**< current QofObject type (e_type) for the parameters. */
gint foreach_limit; /**< How many iterations are found in the QSF */ QofIdType qof_foreach; /**< How to iterate over hierarchical entities. */
QofEntity *qsf_ent; /**< Current entity in the book. */ gint foreach_limit; /**< How many iterations are found in the QSF */
QofBackend *be; /**< the current QofBackend for this operation. */ QofEntity *qsf_ent; /**< Current entity in the book. */
gboolean knowntype; /**< detect references by comparing with known QOF types. */ QofBackend *be; /**< the current QofBackend for this operation. */
QofParam *qof_param; /**< used by kvp to handle the frame hash table */ gboolean knowntype; /**< detect references by comparing with known QOF types. */
QofBook *book; /**< the current QofBook. 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. Theoretically, QSF can handle multiple QofBooks - currently limited to 1.
*/ */
@@ -392,10 +422,19 @@ typedef struct qsf_validates
QofBackendError error_state; QofBackendError error_state;
const gchar *object_path; const gchar *object_path;
const gchar *map_path; const gchar *map_path;
GHashTable *validation_table; GHashTable *object_table; /**< Names of all incoming objects (from the
gint valid_object_count; object_type) and status (QOF registration). */
gint map_calculated_count; GHashTable *map_table; /**< Names of all defined objects (from the
gint qof_registered_count; 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; }qsf_validator;
/** \brief shorthand function /** \brief shorthand function

View File

@@ -24,7 +24,6 @@
#ifndef _DEPRECATED_H #ifndef _DEPRECATED_H
#define _DEPRECATED_H #define _DEPRECATED_H
#include <glib.h> /* deprecated */
#include "qof.h" #include "qof.h"
/** @file deprecated.h /** @file deprecated.h

View File

@@ -868,7 +868,7 @@ kvp_frame_get_numeric(const KvpFrame *frame, const char *path)
return kvp_value_get_numeric(kvp_frame_get_slot (frame, key)); return kvp_value_get_numeric(kvp_frame_get_slot (frame, key));
} }
const char * char *
kvp_frame_get_string(const KvpFrame *frame, const char *path) kvp_frame_get_string(const KvpFrame *frame, const char *path)
{ {
char *key = NULL; char *key = NULL;

View File

@@ -183,7 +183,7 @@ Use kvp_frame_set_string instead of kvp_frame_set_str
* The kvp_frame_set_frame_nc() routine works as above, but does * The kvp_frame_set_frame_nc() routine works as above, but does
* *NOT* copy the frame. * *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_guid(KvpFrame * frame, const gchar * path, const GUID *guid);
void kvp_frame_set_frame(KvpFrame *frame, const gchar *path, KvpFrame *chld); void kvp_frame_set_frame(KvpFrame *frame, const gchar *path, KvpFrame *chld);
@@ -348,7 +348,7 @@ KvpFrame * kvp_frame_add_value_nc(KvpFrame * frame, const gchar * path, KvpValue
gint64 kvp_frame_get_gint64(const KvpFrame *frame, const gchar *path); gint64 kvp_frame_get_gint64(const KvpFrame *frame, const gchar *path);
double kvp_frame_get_double(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); 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); GUID * kvp_frame_get_guid(const KvpFrame *frame, const gchar *path);
void * kvp_frame_get_binary(const KvpFrame *frame, const gchar *path, void * kvp_frame_get_binary(const KvpFrame *frame, const gchar *path,
guint64 * size_return); guint64 * size_return);
@@ -677,7 +677,7 @@ gboolean kvp_value_binary_append(KvpValue *v, void *data, guint64 size);
slot values. You must handle that in proc, with a suitable slot values. You must handle that in proc, with a suitable
recursive call if desired. */ recursive call if desired. */
void kvp_frame_for_each_slot(KvpFrame *f, void kvp_frame_for_each_slot(KvpFrame *f,
void (*proc)(const gchar *key, void (*proc)(const char *key,
KvpValue *value, KvpValue *value,
gpointer data), gpointer data),
gpointer data); gpointer data);

View File

@@ -297,9 +297,11 @@ qof_book_merge_commit_foreach (
iter.fcn = cb; iter.fcn = cb;
subList = NULL; subList = NULL;
iter.ruleList = 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; currentRule = node->data;
if(currentRule->mergeResult == mergeResult) { if(currentRule->mergeResult == mergeResult)
{
subList = g_list_prepend(subList, currentRule); subList = g_list_prepend(subList, currentRule);
} }
} }
@@ -746,7 +748,7 @@ qof_book_merge_init( QofBook *importBook, QofBook *targetBook)
{ {
QofBookMergeData *mergeData; QofBookMergeData *mergeData;
QofBookMergeRule *currentRule; QofBookMergeRule *currentRule;
GList *node; GList *check;
g_return_val_if_fail((importBook != NULL)&&(targetBook != NULL), NULL); g_return_val_if_fail((importBook != NULL)&&(targetBook != NULL), NULL);
mergeData = g_new(QofBookMergeData, 1); mergeData = g_new(QofBookMergeData, 1);
@@ -762,12 +764,13 @@ qof_book_merge_init( QofBook *importBook, QofBook *targetBook)
mergeData->currentRule = currentRule; mergeData->currentRule = currentRule;
qof_object_foreach_type(qof_book_merge_foreach_type, mergeData); qof_object_foreach_type(qof_book_merge_foreach_type, mergeData);
g_return_val_if_fail(mergeData->mergeObjectParams, NULL); g_return_val_if_fail(mergeData->mergeObjectParams, NULL);
if(mergeData->orphan_list != NULL) { if(mergeData->orphan_list != NULL)
{
qof_book_merge_match_orphans(mergeData); qof_book_merge_match_orphans(mergeData);
} }
for (check = mergeData->mergeList; check != NULL; check = check->next)
for (node = mergeData->mergeList; node != NULL; node = node->next) { {
currentRule = node->data; currentRule = check->data;
if(currentRule->mergeResult == MERGE_INVALID) { if(currentRule->mergeResult == MERGE_INVALID) {
mergeData->abort = TRUE; mergeData->abort = TRUE;
return(NULL); return(NULL);
@@ -948,7 +951,8 @@ qof_book_merge_commit(QofBookMergeData *mergeData )
if(mergeData->abort == TRUE) return -1; if(mergeData->abort == TRUE) return -1;
check = g_list_copy(mergeData->mergeList); check = g_list_copy(mergeData->mergeList);
g_return_val_if_fail(check != NULL, -1); 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; currentRule = node->data;
if(currentRule->mergeResult == MERGE_INVALID) { if(currentRule->mergeResult == MERGE_INVALID) {
qof_book_merge_abort(mergeData); qof_book_merge_abort(mergeData);
@@ -962,9 +966,9 @@ qof_book_merge_commit(QofBookMergeData *mergeData )
} }
g_list_free(check); g_list_free(check);
qof_book_merge_commit_foreach(qof_book_merge_commit_rule_loop, 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, 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 /* Placeholder for QofObject merge_helper_cb - all objects
and all parameters set */ and all parameters set */
while(mergeData->mergeList != NULL) { while(mergeData->mergeList != NULL) {
@@ -1000,8 +1004,8 @@ qof_book_merge_rule_foreach(QofBookMergeData *mergeData,
iter.fcn = cb; iter.fcn = cb;
iter.data = mergeData; iter.data = mergeData;
matching_rules = NULL; 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; currentRule = node->data;
if(currentRule->mergeResult == mergeResult) { if(currentRule->mergeResult == mergeResult) {
matching_rules = g_list_prepend(matching_rules, currentRule); matching_rules = g_list_prepend(matching_rules, currentRule);

View File

@@ -14,7 +14,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 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 * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software

View File

@@ -54,6 +54,7 @@ strncasestr(const guchar *str1, const guchar *str2, size_t len)
return NULL; return NULL;
} }
#ifndef HAVE_STRCASESTR
/* Search for str2 in str1, ignore case. Return pointer to first /* Search for str2 in str1, ignore case. Return pointer to first
* match, or null. */ * match, or null. */
gchar * gchar *
@@ -63,6 +64,7 @@ strcasestr(const gchar *str1, const gchar *str2)
gchar * retval = strncasestr (str1, str2, len); gchar * retval = strncasestr (str1, str2, len);
return retval; return retval;
} }
#endif
gint gint
safe_strcmp (const gchar * da, const gchar * db) safe_strcmp (const gchar * da, const gchar * db)

View File

@@ -197,6 +197,7 @@ gint null_strcmp (const gchar * da, const gchar * db);
* and the strstr functions, except that they ignore the case. */ * and the strstr functions, except that they ignore the case. */
extern gchar *strncasestr(const guchar *str1, const guchar *str2, extern gchar *strncasestr(const guchar *str1, const guchar *str2,
size_t len); size_t len);
extern gchar *strcasestr(const gchar *str1, const gchar *str2); extern gchar *strcasestr(const gchar *str1, const gchar *str2);
/** The ultostr() subroutine is the inverse of strtoul(). It accepts a /** The ultostr() subroutine is the inverse of strtoul(). It accepts a