mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
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:
parent
c8cffa2094
commit
293e60d88f
20
ChangeLog
20
ChangeLog
@ -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>
|
||||
|
||||
* NEWS: Added some text about the release.
|
||||
|
@ -472,8 +472,8 @@ if test x$QOF_XML_DIR = x; then
|
||||
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])
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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 @@ static void option_cb (QofBackendOption *option, gpointer data)
|
||||
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 @@ qsf_get_config(QofBackend *be)
|
||||
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 @@ qsf_get_config(QofBackend *be)
|
||||
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 @@ qsf_session_begin(QofBackend *be, QofSession *session, const gchar *book_path,
|
||||
}
|
||||
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 @@ qsfdoc_to_qofbook(xmlDocPtr doc, qsf_param *params)
|
||||
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 @@ load_our_qsf_object(QofBook *book, const gchar *fullpath, qsf_param *params)
|
||||
/* 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 @@ qsf_file_type(QofBackend *be, QofBook *book)
|
||||
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 @@ qsf_from_kvp_helper(const gchar *path, KvpValue *content, gpointer data)
|
||||
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 @@ qsf_entity_foreach(QofEntity *ent, gpointer data)
|
||||
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 @@ qsf_entity_foreach(QofEntity *ent, gpointer data)
|
||||
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 @@ qsf_entity_foreach(QofEntity *ent, gpointer data)
|
||||
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 @@ write_qsf_from_book(const char *path, QofBook *book, qsf_param *params)
|
||||
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 @@ write_qsf_to_stdout(QofBook *book, qsf_param *params)
|
||||
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 @@ string_to_kvp_value(const gchar *content, KvpValueType type)
|
||||
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);
|
||||
}
|
||||
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))
|
||||
switch(type)
|
||||
{
|
||||
case KVP_TYPE_GINT64:
|
||||
{
|
||||
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_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_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);
|
||||
}
|
||||
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 @@ qsf_object_commitCB(gpointer key, gpointer value, gpointer data)
|
||||
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 @@ qsf_object_commitCB(gpointer key, gpointer value, gpointer data)
|
||||
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 @@ qsf_provider_init(void)
|
||||
{
|
||||
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";
|
||||
|
@ -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 @@ qsf_string_default_handler(const gchar *default_name, GHashTable *qsf_default_ha
|
||||
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 */
|
||||
{
|
||||
valid->qof_registered_count++;
|
||||
PINFO (" %s is to be calculated", obj_type);
|
||||
/* 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++;
|
||||
/* 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)
|
||||
{
|
||||
xmlDocPtr doc, map_doc;
|
||||
gint valid_count, calc_count;
|
||||
struct qsf_node_iterate iter;
|
||||
xmlNodePtr map_root, object_root;
|
||||
xmlNsPtr map_ns;
|
||||
qsf_validator valid;
|
||||
gchar *path;
|
||||
gchar *map_path;
|
||||
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 @@ gboolean is_qsf_object_with_map_be(gchar *map_file, qsf_param *params)
|
||||
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 @@ gboolean is_qsf_object_with_map(const gchar *path, gchar *map_file)
|
||||
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 @@ gboolean is_qsf_map_be(qsf_param *params)
|
||||
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 @@ gboolean is_qsf_map(const gchar *path)
|
||||
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 @@ qsf_map_default_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params )
|
||||
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 @@ static void
|
||||
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 @@ qsf_set_handler(xmlNodePtr parent, GHashTable *default_hash,
|
||||
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 @@ qsf_set_format_value(xmlChar *format, gchar *qsf_time_now_as_string,
|
||||
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 @@ qsf_calculate_conditional(xmlNodePtr param_node, xmlNodePtr child, qsf_param *pa
|
||||
/* 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 @@ qsf_add_object_tag(qsf_param *params, gint count)
|
||||
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 @@ qsf_map_calculate_output(xmlNodePtr param_node, xmlNodePtr child, qsf_param *par
|
||||
{
|
||||
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_map_object_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params)
|
||||
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 @@ qsf_object_convert(xmlDocPtr mapDoc, xmlNodePtr qsf_root, qsf_param *params)
|
||||
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 @@ qsf_object_convert(xmlDocPtr mapDoc, xmlNodePtr qsf_root, qsf_param *params)
|
||||
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;
|
||||
}
|
||||
|
@ -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 @@ qsf_object_validation_handler(xmlNodePtr child, xmlNsPtr ns, qsf_validator *vali
|
||||
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 @@ gboolean is_our_qsf_object(const gchar *path)
|
||||
}
|
||||
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 @@ gboolean is_our_qsf_object_be(qsf_param *params)
|
||||
}
|
||||
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 @@ gboolean is_qsf_object_be(qsf_param *params)
|
||||
/* 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_book_node_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params)
|
||||
}
|
||||
qsf_node_foreach(child, qsf_object_node_handler, &iter, params);
|
||||
}
|
||||
LEAVE (" ");
|
||||
LEAVE (" ");
|
||||
}
|
||||
|
@ -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 @@ Both defaults use UTC.
|
||||
|
||||
#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 @@ typedef struct qsf_metadata
|
||||
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 @@ typedef struct qsf_validates
|
||||
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
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
#ifndef _DEPRECATED_H
|
||||
#define _DEPRECATED_H
|
||||
#include <glib.h> /* deprecated */
|
||||
#include "qof.h"
|
||||
|
||||
/** @file deprecated.h
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
const char *
|
||||
char *
|
||||
kvp_frame_get_string(const KvpFrame *frame, const char *path)
|
||||
{
|
||||
char *key = NULL;
|
||||
|
@ -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
|
||||
* *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 @@ KvpFrame * kvp_frame_add_value_nc(KvpFrame * frame, const gchar * path, KvpValue
|
||||
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 @@ gboolean kvp_value_binary_append(KvpValue *v, void *data, guint64 size);
|
||||
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);
|
||||
|
@ -297,9 +297,11 @@ qof_book_merge_commit_foreach (
|
||||
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 @@ qof_book_merge_init( QofBook *importBook, QofBook *targetBook)
|
||||
{
|
||||
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 @@ qof_book_merge_init( QofBook *importBook, QofBook *targetBook)
|
||||
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 @@ qof_book_merge_commit(QofBookMergeData *mergeData )
|
||||
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 @@ qof_book_merge_commit(QofBookMergeData *mergeData )
|
||||
}
|
||||
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 @@ qof_book_merge_rule_foreach(QofBookMergeData *mergeData,
|
||||
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);
|
||||
|
@ -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
|
||||
|
@ -54,6 +54,7 @@ strncasestr(const guchar *str1, const guchar *str2, size_t len)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef HAVE_STRCASESTR
|
||||
/* Search for str2 in str1, ignore case. Return pointer to first
|
||||
* match, or null. */
|
||||
gchar *
|
||||
@ -63,6 +64,7 @@ strcasestr(const gchar *str1, const gchar *str2)
|
||||
gchar * retval = strncasestr (str1, str2, len);
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
gint
|
||||
safe_strcmp (const gchar * da, const gchar * db)
|
||||
|
@ -197,6 +197,7 @@ gint null_strcmp (const gchar * da, const gchar * db);
|
||||
* 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
|
||||
|
Loading…
Reference in New Issue
Block a user