qsf-xml.h File Reference


Detailed Description

Private QSF header - not for use by applications.

Author:
Copyright (C) 2004-2005 Neil Williams <linux@codehelp.co.uk>

Definition in file qsf-xml.h.

#include <stdio.h>
#include <stdlib.h>
#include <regex.h>
#include <time.h>
#include "qof.h"
#include <libintl.h>

Go to the source code of this file.

Data Structures

struct  qsf_object_set
 Holds a description of the QofObject. More...
struct  qsf_metadata
 QSF Parameters. More...
struct  qsf_validates
 Validation metadata. More...
struct  qsf_node_iterate
 One iterator, two typedefs. More...

QSF Object XML

#define QSF_ROOT_TAG   "qof-qsf"
#define QSF_DEFAULT_NS   "http://qof.sourceforge.net/"
#define QSF_DATE_LENGTH   MAX_DATE_LENGTH
#define QSF_BOOK_TAG   "book"
#define QSF_BOOK_GUID   "book-guid"
#define QSF_BOOK_COUNT   "count"
#define QSF_OBJECT_TAG   "object"
#define QSF_OBJECT_TYPE   "type"
#define QSF_OBJECT_COUNT   "count"
#define QSF_XML_VERSION   "1.0"

Representing KVP as XML

<kvp type="kvp" path="/from-sched-xaction" value="guid">c858b9a3235723b55bc1179f0e8c1322</kvp> A kvp type KVP parameter located at $path containing a GUID $value.

The relevance of type="kvp" won't be evident in GnuCash, they all use "kvp".

A non-GnuCash example helps: <kvp type="pilot_addr_kvp" path="/user/name" value="guid">c858b9a3235723b55bc1179f0e8c1322</kvp> A pilot_addr_kvp type KVP parameter located at /user/name containing a guid value.

#define QSF_OBJECT_KVP   "path"
#define QSF_OBJECT_VALUE   "value"

QSF Map XML

#define MAP_ROOT_TAG   "qsf-map"
#define MAP_DEFINITION_TAG   "definition"
#define MAP_DEFINE_TAG   "define"
#define MAP_ITERATE_ATTR   "foreach"
#define MAP_DEFAULT_TAG   "default"
#define MAP_OBJECT_TAG   "object"
#define MAP_CALCULATE_TAG   "calculate"
#define MAP_QOF_VERSION   "qof_version"
#define MAP_NAME_ATTR   "name"
#define MAP_TYPE_ATTR   "type"
#define MAP_VALUE_ATTR   "value"
#define MAP_OBJECT_ATTR   "object"
#define MAP_E_TYPE   "e_type"
#define MAP_ENUM_TYPE   "enum"
#define QSF_BOOLEAN_DEFAULT   "boolean"
 A specific boolean default for this map.
#define QSF_CONDITIONAL   "if"
#define QSF_CONDITIONAL_SET   "set"
#define QSF_CONDITIONAL_ELSE   "else"
#define QSF_OPTION   "option"
#define QSF_FORMATTING_OPTION   "format"

Why two sets of functions and typedefs?

These functions are in pairs, one to use in an existing session and one to use when deciding which backend should be selected for a new session.
  • When there is an existing QofSession, the qsf_param context will be available, so set error codes in the backend. Use the *_be functions.
  • When just determining the type of file, qsf_param is not necessary and no backend is available (it has not been selected yet). Use the twin function. e.g. in qsf_file_type()


typedef void(* qsf_nodeCB )(xmlNodePtr, xmlNsPtr, qsf_param *)
 map and qsf object callback
typedef void(* qsf_validCB )(xmlNodePtr, xmlNsPtr, qsf_validator *)
 validator callback
gboolean is_qsf_object_be (qsf_param *params)
 Validate a QSF file and identify a suitable QSF map.
gboolean is_qsf_object (const gchar *path)
 Validate a QSF file and identify a suitable QSF map.
gboolean is_our_qsf_object_be (qsf_param *params)
 Validate a QSF file and determine type.
gboolean is_our_qsf_object (const gchar *path)
 Validate a QSF file.
gboolean is_qsf_map_be (qsf_param *params)
 Validate a QSF map file.
gboolean is_qsf_map (const gchar *path)
 Validate a QSF map file.
gboolean is_qsf_object_with_map_be (gchar *map_path, qsf_param *params)
 Validate a QSF file and a selected QSF map.
gboolean is_qsf_object_with_map (const gchar *path, gchar *map_file)
 Validate a QSF file and a selected QSF map.

Defines

#define _(String)   dgettext (GETTEXT_PACKAGE, String)
#define QSF_QOF_VERSION   QOF_OBJECT_VERSION
#define QSF_XSD_TIME   QOF_UTC_DATE_FORMAT
#define QSF_XML_BOOLEAN_TEST   "true"
#define QSF_OBJECT_SCHEMA   "qsf-object.xsd.xml"
#define QSF_MAP_SCHEMA   "qsf-map.xsd.xml"

Typedefs

typedef qsf_object_set qsf_objects
 Holds a description of the QofObject.
typedef qsf_metadata qsf_param
 QSF Parameters.
typedef qsf_validates qsf_validator
 Validation metadata.

Enumerations

enum  qsf_type {
  QSF_UNDEF = 0, IS_QSF_MAP, IS_QSF_OBJ, HAVE_QSF_MAP,
  OUR_QSF_OBJ
}
enum  QsfStatus {
  QSF_NO_OBJECT = 0, QSF_DEFINED_OBJECT, QSF_REGISTERED_OBJECT, QSF_CALCULATED_OBJECT,
  QSF_INVALID_OBJECT
}
 Status of various object during mapping. More...

Functions

gint qsf_compare_tag_strings (const xmlChar *node_name, gchar *tag_name)
 shorthand function
gint qsf_strings_equal (const xmlChar *node_name, gchar *tag_name)
 shorthand function
gint qsf_is_element (xmlNodePtr a, xmlNsPtr ns, gchar *c)
 shorthand function
gint qsf_check_tag (qsf_param *params, gchar *qof_type)
 shorthand function
void qsf_object_validation_handler (xmlNodePtr child, xmlNsPtr ns, qsf_validator *valid)
 Checks all incoming objects for QOF registration.
gboolean qsf_is_valid (const gchar *schema_dir, const gchar *schema_filename, xmlDocPtr doc)
 Compares an xmlDoc in memory against the schema file.
GList ** qsf_map_prepare_list (GList **maps)
 Prepare the default list of maps.
void qsf_book_node_handler (xmlNodePtr child, xmlNsPtr qsf_ns, qsf_param *params)
 Book and book-guid node handler.
KvpValuestring_to_kvp_value (const gchar *content, KvpValueType type)
 Convert a string value into KvpValue.
void qsf_valid_foreach (xmlNodePtr parent, qsf_validCB cb, struct qsf_node_iterate *iter, qsf_validator *valid)
void qsf_node_foreach (xmlNodePtr parent, qsf_nodeCB cb, struct qsf_node_iterate *iter, qsf_param *params)
xmlDocPtr qsf_object_convert (xmlDocPtr mapDoc, xmlNodePtr qsf_root, qsf_param *params)
 Convert between QSF objects.
void qsf_object_node_handler (xmlNodePtr child, xmlNsPtr qsf_ns, qsf_param *params)


Define Documentation

#define MAP_CALCULATE_TAG   "calculate"
 

One calculation for every parameter that needs to be set.

QSF follows the same rule as qof_book_merge. Only if a getter and a setter function are defined for a parameter is it available to QSF. If a QofAccessFunc and QofSetterFunc are both defined for any QofObject parameter, that parameter MUST be calculated in any map that defines that object.

Definition at line 193 of file qsf-xml.h.

#define MAP_DEFAULT_TAG   "default"
 

User editable defaults for data not available within the available QSF objects.

Some defaults will relate to how to format descriptive dates, whether discount should be considered, which account to use for certain QSF data from applications that don't use accounts.

Some defaults are pre-defined and cannot be over-written:

  • qsf_time_now
  • qsf_time_string

Attributes (All are mandatory):

name The text name for this default. Certain pre-defined defaults exist but user- or map-defined defaults can have any unique text name. Spaces are NOT allowed, use undersccores instead. The value of name must not duplicate any existing default, define, object or parameter unless the special type, enum, is used.

type QOF_TYPE - must be one of the recognised QOF data types for the qof_version in use or the special type, enum.

value Text representation of the required value. For numeric, use the format [0-9]?/[0-9]?

Attention:
Using boolean defaults
A boolean default is not output in the QSF directly, instead the value is used in the calculations to modify certain values. If the boolean default is set to true, the if statement containing the boolean name will be evaluated. If the boolean default is set to false, the corresponding else will be evaluted. Make sure your calculations contain an appropriate else statement so that the boolean value can be adjusted without invalidating the map!

QSF deals with partial QofBooks - each object is fully described but the book does not have to contain any specific object types or have any particular structure. To merge partial books into usual QofBook data sources, the map must deal with entities that need to be referenced in the target QofBook but which simply don't exist in the QofBook used to generate the QSF. e.g. pilot-link knows nothing of Accounts yet when QSF creates a gncInvoice from qof-datebook, gncInvoice needs to know the GUID of certain accounts in the target QofBook. This is handled in the map by specifying the name of the account as a default for that map. When imported, the QSF QofBackend looks up the object required using the name of the parameter to obtain the parameter type. This is the only situation where QSF converts between QOF data types. A string description of the required object is converted to the GUID for that specific entity. The map cannot contain the GUID as it is generic and used by multiple users.

Attention:
Using enumerators
  • enum types are the only defaults that are allowed to use the same name value more than once.
  • enum types are used to increase the readability of a QSF map.
  • The enum name acts to group the enum values together - in a similar fashion to radio buttons in HTML forms.
  • enum types are used only where the QOF object itself uses an enum type.
e.g. the tax_included enum type allows maps to use the full name of the enum value GNC_TAXINCLUDED_YES, instead of the cryptic digit value, 1.

Definition at line 125 of file qsf-xml.h.

#define MAP_DEFINE_TAG   "define"
 

defines each object supported by this QSF map

Attributes: e_type Copied directly from the QofObject definition. Content: The full QofObject description for the defined QOF object.

Definition at line 118 of file qsf-xml.h.

#define MAP_DEFINITION_TAG   "definition"
 

Second level container for defined objects

Attributes: qof_version - Taken from the QOF_OBJECT_VERSION macro in QOF, At the time of QSF development, QOF_OBJECT_VERSION is defined as 3. All QSF maps and QSF objects must use the same qof_version which in turn must match the QOF_OBJECT_VERSION for the QOF library in use by the calling process.

No text content allowed.

Definition at line 109 of file qsf-xml.h.

#define MAP_E_TYPE   "e_type"
 

Validates the objects defined in the map

The e_type will be used to match incoming QSF objects with the relevant QSF map. The value of the e_type must be the value of the e_type for that object in the originating QOF application. The define tag must contain the value of the description of the same object in the same originating QOF application.

Definition at line 231 of file qsf-xml.h.

#define MAP_ENUM_TYPE   "enum"
 

Todo:
enum is an attempt to make enumerator values descriptive in the maps and QSF (possibly). Not working yet.

Definition at line 240 of file qsf-xml.h.

#define MAP_ITERATE_ATTR   "foreach"
 

Dictate which object type is the basis for iteration in a hierarchical object set.

Definition at line 123 of file qsf-xml.h.

#define MAP_NAME_ATTR   "name"
 

The name of the default setting.

Use this name to refer to the value of this default in the map calculations.

Make sure that the type of this default matches the type of the parameter being set by the parent calculation!

Definition at line 207 of file qsf-xml.h.

#define MAP_OBJECT_ATTR   "object"
 

The object to use to provide the data being set using the map.

Definition at line 229 of file qsf-xml.h.

#define MAP_OBJECT_TAG   "object"
 

Contains all the calculations to make one object from others.

Note that creating an object for the import application can involve using data from more than one QSF object, as well as defaults and lookups in the import application itself. Conditionals, simple arithmetic and date/time formatting options are also available.

Definition at line 185 of file qsf-xml.h.

#define MAP_QOF_VERSION   "qof_version"
 

This is the QOF_OBJECT_VERSION from QOF.

QSF maps may need to be updated if QOF itself is upgraded. This setting is coded into QOF and maps for one version cannot necessarily be used by other versions. At the first release of QSF, QOF_OBJECT_VERSION = 3.

Definition at line 201 of file qsf-xml.h.

#define MAP_ROOT_TAG   "qsf-map"
 

Top level root tag for QSF Maps

Definition at line 108 of file qsf-xml.h.

#define MAP_TYPE_ATTR   "type"
 

QSF will NOT convert between QOF types.

QSF will allow a conditional to use a parameter of one type to determine the value from a parameter of another type, but the final value assigned MUST be of the same type as the parent calculation.

Definition at line 214 of file qsf-xml.h.

#define MAP_VALUE_ATTR   "value"
 

The value of the tag, used in defaults and calculations.

The value of a default is a string representation of the value to be inserted into the calculation where the default is used.

The value of a calculation is the name of the parameter that will be set by that calculation.

Definition at line 220 of file qsf-xml.h.

#define QSF_BOOK_COUNT   "count"
 

Sequential counter of each book in this file

Definition at line 82 of file qsf-xml.h.

#define QSF_BOOK_GUID   "book-guid"
 

QOF GUID tag for the QofBook described by this QSF object file

Definition at line 80 of file qsf-xml.h.

#define QSF_BOOK_TAG   "book"
 

First level child: book tag - the QofBook.

Definition at line 79 of file qsf-xml.h.

#define QSF_CONDITIONAL   "if"
 

child of calculate.

Conditionals can reference objects as if within the original application. In operation, the map is overlaid across both sets of defined objects, an import object in the source application and an output object for the destination object. The current import and output QSF objects are therefore always available to the map. Conditionals can reference parameter as well as object values.

Definition at line 246 of file qsf-xml.h.

#define QSF_CONDITIONAL_ELSE   "else"
 

Alternative

if(){} else{} is also supported. Nesting of conditionals causes problems for validating the final map against any sensible XML Schema and a map that doesn't validate will be rejected. When editing conditionals in a QSF map, ALWAYS validate the map using xmllint. If necessary, define a variable at the foot of the definitions block, using a similar syntax to a default, then use that variable in another conditional

variable name="my_rate" type="numeric" value="0/1"

The syntax for xmllint is:

xmllint --schema <schema file> <qsf-file>

Use the qsf-object.xsd.xml schema for objects and qsf-map.xsd.xml for map files.

e.g. xmllint --schema qsf-object.xsd.xml --noout qof-qsf.xml

Definition at line 262 of file qsf-xml.h.

#define QSF_CONDITIONAL_SET   "set"
 

Assignment statement

Map assignments can use the native values within the output object. The output object must support setting the relevant parameter using the value exactly as given in the map because the relevant set() function will be called using this value. This may reduce the readability of the map but the relevant application could also be modified to support a more readable set function.

Definition at line 254 of file qsf-xml.h.

#define QSF_DATE_LENGTH   MAX_DATE_LENGTH
 

Max length of QSF_XSD_TIME.

MAX_DATE_LENGTH itself is defined in gnc-date.h

Definition at line 76 of file qsf-xml.h.

#define QSF_DEFAULT_NS   "http://qof.sourceforge.net/"
 

Default namespace for QSF root tag

The map namespace is not included as maps are not currently written out by QOF.

Definition at line 72 of file qsf-xml.h.

#define QSF_FORMATTING_OPTION   "format"
 

How to format dates/times

When the QSF map uses a date/time value as a string, the formatting can be adjusted to personal preference. format will only be evaluated if the calculated parameter is a QOF_TYPE_STRING - any format attributes on other data types will be ignored.

Definition at line 289 of file qsf-xml.h.

#define QSF_MAP_SCHEMA   "qsf-map.xsd.xml"
 

Name of the QSF Map Schema.

Definition at line 333 of file qsf-xml.h.

#define QSF_OBJECT_COUNT   "count"
 

Sequential counter for each QSF object in this file

Definition at line 85 of file qsf-xml.h.

#define QSF_OBJECT_KVP   "path"
 

The path to this KVP value in the entity frame.

Definition at line 102 of file qsf-xml.h.

#define QSF_OBJECT_SCHEMA   "qsf-object.xsd.xml"
 

Name of the QSF Object Schema.

Definition at line 332 of file qsf-xml.h.

#define QSF_OBJECT_TAG   "object"
 

Second level child: object tag

Definition at line 83 of file qsf-xml.h.

#define QSF_OBJECT_TYPE   "type"
 

QSF parameter name for object type specifiers

Definition at line 84 of file qsf-xml.h.

#define QSF_OBJECT_VALUE   "value"
 

The KVP Value.

Definition at line 103 of file qsf-xml.h.

#define QSF_OPTION   "option"
 

enum operator

Not implemented yet - may need to change once work starts. Theoretically, option will specify when an enumerator value is in use - it is quite possible that it will be unnecessary.

Definition at line 282 of file qsf-xml.h.

#define QSF_QOF_VERSION   QOF_OBJECT_VERSION
 

QOF Version check.

Make sure the same version of QOF is in use in both applications.

Definition at line 64 of file qsf-xml.h.

#define QSF_ROOT_TAG   "qof-qsf"
 

The top level root tag

Definition at line 71 of file qsf-xml.h.

#define QSF_XML_BOOLEAN_TEST   "true"
 

needs to be lowercase for XML validation

Definition at line 330 of file qsf-xml.h.

#define QSF_XML_VERSION   "1.0"
 

The current XML version.

Definition at line 87 of file qsf-xml.h.

#define QSF_XSD_TIME   QOF_UTC_DATE_FORMAT
 

xsd:dateTime format in coordinated universal time, UTC.

You can reproduce the string from the GNU/Linux command line using the date utility:

date -u +Y-m-dTH:M:SZ

2004-12-12T23:39:11Z

The datestring must be timezone independent and include all specified fields.

Remember to use gmtime() NOT localtime()!. From the command line, use the -u switch with the date command: date -u

To generate a timestamp based on a real time, use the qsf_time_now and qsf_time_string defaults.

qsf_time_now : Format: QOF_TYPE_DATE. The current time taken from the moment the default is read into a QSF object at runtime.

qsf_time_string : Format: QOF_TYPE_STRING. The current timestamp taken from the moment the default is read into a QSF object at runtime. This form is used when the output parameter needs a formatted date string, not an actual date object. The format is determined by the optional format attribute of the set tag which takes the same operators as the GNU C Library for strftime() and output may therefore be dependent on the locale of the calling process - take care. Default value is F, used when qsf_time_string is set without the format attribute.

Both defaults use UTC.

Definition at line 299 of file qsf-xml.h.


Typedef Documentation

typedef void(* qsf_nodeCB)(xmlNodePtr, xmlNsPtr, qsf_param *)
 

map and qsf object callback

This callback cannot do both the map and the validation tasks because validation sometimes needs to be done without qsf_params.

e.g. when selecting which backend should be used for a particular data source where two or more backends share the same access_method.

Definition at line 524 of file qsf-xml.h.

typedef struct qsf_object_set qsf_objects
 

Holds a description of the QofObject.

Used when converting QOF objects from another application. The incoming, unknown, objects need to be stored prior to conversion. This allows many-to-many conversions where an invoice can receive data from an incoming expense AND datebook and use data from an incoming contacts object to lookup the customer for the invoice.

typedef struct qsf_metadata qsf_param
 

QSF Parameters.

This struct is a catch-all for all parameters required for various stages of the process. There are lots of elements here that will finally be removed.

typedef struct qsf_validates qsf_validator
 

Validation metadata.

The validation is a separate parse with separate data. This is used to determine which backend should load the data.

typedef void(* qsf_validCB)(xmlNodePtr, xmlNsPtr, qsf_validator *)
 

validator callback

Todo:
The need for separate metadata means a separate callback typedef is needed for the validator, but this should be fixed to only need one.

Definition at line 530 of file qsf-xml.h.


Enumeration Type Documentation

enum qsf_type
 

Enumerator:
QSF_UNDEF  Initial undefined value.
IS_QSF_MAP  A QSF map
IS_QSF_OBJ  A QSF object without a map - it may or may not need one.
HAVE_QSF_MAP  A QSF object with the map it needs.
OUR_QSF_OBJ  A QSF object that can be loaded without a map.

Definition at line 41 of file qsf-xml.h.

00041               {
00042         QSF_UNDEF = 0, 
00043         IS_QSF_MAP,   
00044         IS_QSF_OBJ,   
00045         HAVE_QSF_MAP, 
00046         OUR_QSF_OBJ,  
00047 }qsf_type;

enum QsfStatus
 

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.

Enumerator:
QSF_NO_OBJECT  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.

Definition at line 352 of file qsf-xml.h.


Function Documentation

gboolean is_our_qsf_object const gchar *  path  ) 
 

Validate a QSF file.

< Name of the QSF Object Schema.

< Name of the QSF Object Schema.

Definition at line 152 of file qsf-xml.c.

00153 {
00154         xmlDocPtr doc;
00155         struct qsf_node_iterate iter;
00156         xmlNodePtr object_root;
00157         qsf_validator valid;
00158         gint table_count;
00159 
00160         g_return_val_if_fail((path != NULL),FALSE);
00161         doc = xmlParseFile(path);
00162         if(doc == NULL)  { return FALSE; }
00163         if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc)) { 
00164                 PINFO (" validation failed %s %s %s", QSF_SCHEMA_DIR, 
00165                         QSF_OBJECT_SCHEMA, path);
00166                 return FALSE; 
00167         }
00168         object_root = xmlDocGetRootElement(doc);
00169         /* check that all objects in the file are already registered in QOF */
00170         valid.object_table = g_hash_table_new(g_str_hash, g_str_equal);
00171         valid.qof_registered_count = 0;
00172         valid.valid_object_count = 0;
00173         iter.ns = object_root->ns;
00174         qsf_valid_foreach(object_root, qsf_object_validation_handler, &iter, &valid);
00175         table_count = g_hash_table_size(valid.object_table);
00176         g_hash_table_destroy(valid.object_table);
00177         if(table_count == valid.qof_registered_count) { return TRUE; }
00178         return FALSE;
00179 }

gboolean is_our_qsf_object_be qsf_param params  ) 
 

Validate a QSF file and determine type.

< Name of the QSF Object Schema.

Definition at line 195 of file qsf-xml.c.

00196 {
00197         xmlDocPtr doc;
00198         struct qsf_node_iterate iter;
00199         xmlNodePtr object_root;
00200         qsf_validator valid;
00201         gint table_count;
00202         gchar *path;
00203 
00204         g_return_val_if_fail((params != NULL),FALSE);
00205         path = g_strdup(params->filepath);
00206         if(path == NULL) {
00207                 qof_backend_set_error(params->be, ERR_FILEIO_FILE_NOT_FOUND);
00208                 return FALSE;
00209         }
00210         if(params->file_type != QSF_UNDEF) { return FALSE; }
00211         doc = xmlParseFile(path);
00212         if(doc == NULL)  {
00213                 qof_backend_set_error(params->be, ERR_FILEIO_PARSE_ERROR);
00214                 return FALSE;
00215         }
00216         if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc))
00217         {
00218                 qof_backend_set_error(params->be, ERR_QSF_INVALID_OBJ);
00219                 return FALSE;
00220         }
00221         params->file_type = IS_QSF_OBJ;
00222         object_root = xmlDocGetRootElement(doc);
00223         valid.object_table = g_hash_table_new(g_str_hash, g_str_equal);
00224         valid.qof_registered_count = 0;
00225         iter.ns = object_root->ns;
00226         qsf_valid_foreach(object_root, qsf_object_validation_handler, &iter, &valid);
00227         table_count = g_hash_table_size(valid.object_table);
00228         if(table_count == valid.qof_registered_count)
00229         {
00230                 g_hash_table_destroy(valid.object_table);
00231                 qof_backend_set_error(params->be, ERR_BACKEND_NO_ERR);
00232                 return TRUE;
00233         }
00234         g_hash_table_destroy(valid.object_table);
00235         qof_backend_set_error(params->be, ERR_QSF_NO_MAP);
00236         return FALSE;
00237 }

gboolean is_qsf_map const gchar *  path  ) 
 

Validate a QSF map file.

< Name of the QSF Map Schema.

Definition at line 412 of file qsf-xml-map.c.

00414                         {
00415                                 qof_backend_set_error(params->be, ERR_QSF_BAD_MAP);
00416                                 PERR (" ERR_QSF_BAD_MAP set");
00417                                 return;
00418                         }
00419                 }
00420         }
00421 }
00422 
00423 static void
00424 qsf_map_top_node_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params)
00425 {
00426         xmlChar *qof_version;
00427         gchar *buff;
00428         struct qsf_node_iterate iter;
00429 
00430         if(!params->qsf_define_hash) return;
00431         if(!params->qsf_default_hash) return;
00432         ENTER (" map top node child=%s", child->name);
00433         buff = NULL;
00434         if(qsf_is_element(child, ns, MAP_DEFINITION_TAG)) {
00435                 qof_version = xmlGetProp(child, BAD_CAST MAP_QOF_VERSION);
00436                 buff = g_strdup_printf("%i", QSF_QOF_VERSION);
00437                 if(xmlStrcmp(qof_version, BAD_CAST buff) != 0) {
00438                         qof_backend_set_error(params->be, ERR_QSF_BAD_QOF_VERSION);
00439                         LEAVE (" ERR_QSF_BAD_QOF_VERSION set");

gboolean is_qsf_map_be qsf_param params  ) 
 

Validate a QSF map file.

< Name of the QSF Map Schema.

Definition at line 370 of file qsf-xml-map.c.

00371                 {
00372                         g_hash_table_insert(params->qsf_define_hash,
00373                                 xmlGetProp(child, BAD_CAST MAP_E_TYPE), params->child_node);
00374                 }
00375                 else {
00376                         qof_backend_set_error(params->be, ERR_QSF_BAD_MAP);
00377                         PERR (" ERR_QSF_BAD_MAP set");
00378                         return;
00379                 }
00380         }
00381         if(qsf_is_element(child, ns, MAP_DEFAULT_TAG)) {
00382                 if(qsf_strings_equal(xmlGetProp(child, BAD_CAST MAP_TYPE_ATTR), MAP_ENUM_TYPE))
00383                 {
00384                         qsf_enum = xmlNodeGetContent(child);
00386                         PERR (" enum todo incomplete");
00390                         if(NULL == g_hash_table_lookup(params->qsf_default_hash,
00391                                 xmlNodeGetContent(child)))
00392                         {
00393                                 g_hash_table_insert(params->qsf_default_hash,
00394                                         xmlNodeGetContent(child), child);
00395                         }
00396                         else
00397                         {
00398                                 qof_backend_set_error(params->be, ERR_QSF_BAD_MAP);
00399                                 PERR (" ERR_QSF_BAD_MAP set");
00400                                 return;
00401                         }
00402                 }
00404                 else {
00405                         if(NULL == g_hash_table_lookup(params->qsf_default_hash,
00406                                         xmlGetProp(child, BAD_CAST MAP_NAME_ATTR)))
00407                         {
00408                                 g_hash_table_insert(params->qsf_default_hash,
00409                                         xmlGetProp(child, BAD_CAST MAP_NAME_ATTR), child);
00410                         }

gboolean is_qsf_object const gchar *  path  ) 
 

Validate a QSF file and identify a suitable QSF map.

< Name of the QSF Object Schema.

Definition at line 181 of file qsf-xml.c.

00182 {
00183         xmlDocPtr doc;
00184 
00185         g_return_val_if_fail((path != NULL),FALSE);
00186         if(path == NULL) { return FALSE; }
00187         doc = xmlParseFile(path);
00188         if(doc == NULL) { return FALSE; }
00189         if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc)) { return FALSE; }
00190         /* Note cannot test against a map here, so if the file is valid QSF,
00191         accept it and work out the details later. */
00192         return TRUE;
00193 }

gboolean is_qsf_object_be qsf_param params  ) 
 

Validate a QSF file and identify a suitable QSF map.

< Name of the QSF Object Schema.

Definition at line 239 of file qsf-xml.c.

00240 {
00241         gboolean result;
00242         xmlDocPtr doc;
00243         GList *maps;
00244         gchar *path;
00245 
00246         g_return_val_if_fail((params != NULL),FALSE);
00247         path = g_strdup(params->filepath);
00248         if(path == NULL) {
00249                 qof_backend_set_error(params->be, ERR_FILEIO_FILE_NOT_FOUND);
00250                 return FALSE;
00251         }
00252         /* skip validation if is_our_qsf_object has already been called. */
00253         if(ERR_QSF_INVALID_OBJ == qof_backend_get_error(params->be)) { return FALSE; }
00254         if(params->file_type == QSF_UNDEF)
00255         {
00256                 doc = xmlParseFile(path);
00257                 if(doc == NULL) {
00258                         qof_backend_set_error(params->be, ERR_FILEIO_PARSE_ERROR);
00259                         return FALSE;
00260                 }
00261                 if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc))
00262                 {
00263                         qof_backend_set_error(params->be, ERR_QSF_INVALID_OBJ);
00264                         return FALSE;
00265                 }
00266         }
00267         result = FALSE;
00268         /* retrieve list of maps from config frame. */
00269         for(maps = params->map_files; maps; maps=maps->next)
00270         {
00271                 QofBackendError err;
00272                 result = is_qsf_object_with_map_be(maps->data, params);
00273                 err = qof_backend_get_error(params->be);
00274                 if((err == ERR_BACKEND_NO_ERR) && result)
00275                 {
00276                         params->map_path = maps->data;
00277                         PINFO ("map chosen = %s", params->map_path);
00278                         break;
00279                 }
00280                 /* pop the error back on the stack. */
00281                 else { qof_backend_set_error(params->be, err); }
00282         }
00283         return result;
00284 }

gboolean is_qsf_object_with_map const gchar *  path,
gchar *  map_file
 

Validate a QSF file and a selected QSF map.

< Name of the QSF Object Schema.

Definition at line 345 of file qsf-xml-map.c.

00345                                                      {
00346                 g_hash_table_destroy(valid.map_table);
00347                 return FALSE;
00348         }
00349         g_hash_table_destroy(valid.map_table);
00350         return TRUE;
00351 }
00352 
00353 static void
00354 qsf_map_default_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params )
00355 {
00356         xmlChar *qsf_enum;
00357         gchar* iterate;
00358 
00359         g_return_if_fail(params->qsf_define_hash != NULL);
00360         iterate = NULL;
00361         if (qsf_is_element(child, ns, MAP_DEFINE_TAG)) {
00362                 iterate = xmlGetProp(child, MAP_ITERATE_ATTR);
00363                 if((qof_util_bool_to_int(iterate) == 1) &&
00364                         (qof_class_is_registered(xmlGetProp(child, BAD_CAST MAP_E_TYPE))))
00365                 {
00366                         params->qof_foreach = xmlGetProp(child, BAD_CAST MAP_E_TYPE);
00367                         PINFO (" iterating over '%s' objects", params->qof_foreach);
00368                 }

gboolean is_qsf_object_with_map_be gchar *  map_file,
qsf_param params
 

Validate a QSF file and a selected QSF map.

< Name of the QSF Object Schema.

Definition at line 308 of file qsf-xml-map.c.

00314                                                      {
00315                 qof_backend_set_error(params->be, valid.error_state);
00316                 g_hash_table_destroy(valid.object_table);
00317                 return FALSE;
00318         }
00319         qof_backend_get_error(params->be);
00320         g_hash_table_destroy(valid.object_table);
00321         return TRUE;
00322 }
00323 
00324 gboolean is_qsf_map(const gchar *path)
00325 {
00326         xmlDocPtr doc;
00327         struct qsf_node_iterate iter;
00328         qsf_validator valid;
00329         xmlNodePtr map_root;
00330         xmlNsPtr map_ns;
00331 
00332         g_return_val_if_fail((path != NULL),FALSE);
00333         if(path == NULL) { return FALSE; }
00334         doc = xmlParseFile(path);
00335         if(doc == NULL) { return FALSE; }
00336         if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_MAP_SCHEMA, doc)) {
00337                 return FALSE;
00338         }
00339         map_root = xmlDocGetRootElement(doc);
00340         map_ns = map_root->ns;
00341         iter.ns = map_ns;
00342         valid.error_state = ERR_BACKEND_NO_ERR;
00343         valid.map_table = g_hash_table_new(g_str_hash, g_str_equal);

void qsf_book_node_handler xmlNodePtr  child,
xmlNsPtr  ns,
qsf_param params
 

Book and book-guid node handler.

< First level child: book tag - the QofBook.

< Sequential counter of each book in this file

< QOF GUID tag for the QofBook described by this QSF object file

< QOF GUID tag for the QofBook described by this QSF object file

Definition at line 342 of file qsf-xml.c.

00342 {
00343         gchar *book_count_s, *tail;
00344         gint book_count;
00345         xmlNodePtr child_node;
00346         struct qsf_node_iterate iter;
00347         gchar *buffer;
00348         GUID book_guid;
00349 
00350         g_return_if_fail(child);
00351         g_return_if_fail(params);
00352         ENTER (" child=%s", child->name);
00353         if(qsf_is_element(child, ns, QSF_BOOK_TAG)) {
00354                 book_count_s = (gchar*)xmlGetProp(child, BAD_CAST QSF_BOOK_COUNT);
00355                 if(book_count_s) {
00356                         book_count = (gint)strtol(book_count_s, &tail, 0);
00357                         /* More than one book not currently supported. */
00358                         g_return_if_fail(book_count == 1);
00359                 }
00360                 iter.ns = ns;
00361                 child_node = child->children->next;
00362                 if(qsf_is_element(child_node, ns, QSF_BOOK_GUID)) {
00363                         DEBUG (" trying to set book GUID");
00364                         buffer = g_strdup((gchar*)xmlNodeGetContent(child_node));
00365                         g_return_if_fail(TRUE == string_to_guid(buffer, &book_guid));
00366                         qof_entity_set_guid((QofEntity*)params->book, &book_guid);
00367                         xmlNewChild(params->output_node, params->qsf_ns, 
00368                         BAD_CAST QSF_BOOK_GUID, BAD_CAST buffer);
00369                         g_free(buffer);
00370                 }
00371                 qsf_node_foreach(child, qsf_object_node_handler, &iter, params);
00372         }
00373         LEAVE (" ");
00374 }
00375 }

gint qsf_check_tag qsf_param params,
gchar *  qof_type
 

shorthand function

This may look repetitive but each one is used separately as well as in a block.

Definition at line 65 of file qsf-xml.c.

00066 {
00067         return qsf_is_element(params->child_node, params->qsf_ns, qof_type);
00068 }

gint qsf_compare_tag_strings const xmlChar *  node_name,
gchar *  tag_name
 

shorthand function

This may look repetitive but each one is used separately as well as in a block.

Definition at line 41 of file qsf-xml.c.

00042 {
00043         return xmlStrcmp(node_name, (const xmlChar *)tag_name);
00044 }

gint qsf_is_element xmlNodePtr  a,
xmlNsPtr  ns,
gchar *  c
 

shorthand function

This may look repetitive but each one is used separately as well as in a block.

Definition at line 54 of file qsf-xml.c.

00055 {
00056         g_return_val_if_fail(a != NULL, 0);
00057         g_return_val_if_fail(ns != NULL, 0);
00058         g_return_val_if_fail(c != NULL, 0);
00059         if ((a->ns == ns) && (a->type == XML_ELEMENT_NODE) &&
00060                 qsf_strings_equal(a->name, c)) { return 1; }
00061         return 0;
00062 }

gboolean qsf_is_valid const gchar *  schema_dir,
const gchar *  schema_filename,
xmlDocPtr  doc
 

Compares an xmlDoc in memory against the schema file.

Parameters:
schema_dir set at compile time to $prefix/share/qsf/
schema_filename Either the QSF Object Schema or the QSF Map Schema.
doc The xmlDoc read from the file using libxml2.
Ensure that you call the right schema_filename for the doc in question!

Incorrect validation will result in output to the terminal window.

Returns:
TRUE if the doc validates against the assigned schema, otherwise FALSE.

Definition at line 71 of file qsf-xml.c.

00072 {
00073         xmlSchemaParserCtxtPtr qsf_schema_file;
00074         xmlSchemaPtr qsf_schema;
00075         xmlSchemaValidCtxtPtr qsf_context;
00076         gchar *schema_path;
00077         gint result;
00078 
00079         g_return_val_if_fail(doc || schema_filename, FALSE);
00080         schema_path = g_strdup_printf("%s/%s", schema_dir, schema_filename);
00081         qsf_schema_file = xmlSchemaNewParserCtxt(schema_path);
00082         qsf_schema = xmlSchemaParse(qsf_schema_file);
00083         qsf_context = xmlSchemaNewValidCtxt(qsf_schema);
00084         result = xmlSchemaValidateDoc(qsf_context, doc);
00085         xmlSchemaFreeParserCtxt(qsf_schema_file);
00086         xmlSchemaFreeValidCtxt(qsf_context);
00087         xmlSchemaFree(qsf_schema);
00088         if(result == 0) { return TRUE; }
00089         return FALSE;
00090 }

GList** qsf_map_prepare_list GList **  maps  ) 
 

Prepare the default list of maps.

Todo:
Automate this once map support is stable

Definition at line 135 of file qsf-backend.c.

00136 {
00137         /* Add new map filenames here. */
00139         *maps = g_list_prepend(*maps, "pilot-qsf-GnuCashInvoice.xml");
00140         *maps = g_list_prepend(*maps, "pilot-qsf-gncCustomer.xml");
00141         return maps;
00142 }

void qsf_node_foreach xmlNodePtr  parent,
qsf_nodeCB  cb,
struct qsf_node_iterate iter,
qsf_param params
 

Iterate over the children of the parent node.

Only iterates over the immediate children of the parent - this function is not recursive.

Definition at line 106 of file qsf-xml.c.

00108 {
00109         xmlNodePtr cur_node;
00110 
00111         g_return_if_fail(iter->ns);
00112         iter->fcn = &cb;
00113         for(cur_node = parent->children; cur_node != NULL; cur_node = cur_node->next)
00114         {
00115                 cb(cur_node, iter->ns, params);
00116         }
00117 }

xmlDocPtr qsf_object_convert xmlDocPtr  mapDoc,
xmlNodePtr  qsf_root,
qsf_param params
 

Convert between QSF objects.

< The current XML version.

< The top level root tag

< First level child: book tag - the QofBook.

< Sequential counter of each book in this file

< Contains all the calculations to make one object from others.

Note that creating an object for the import application can involve using data from more than one QSF object, as well as defaults and lookups in the import application itself. Conditionals, simple arithmetic and date/time formatting options are also available.

< QSF will NOT convert between QOF types.

QSF will allow a conditional to use a parameter of one type to determine the value from a parameter of another type, but the final value assigned MUST be of the same type as the parent calculation.

Definition at line 1175 of file qsf-xml-map.c.

void qsf_object_node_handler xmlNodePtr  child,
xmlNsPtr  qsf_ns,
qsf_param params
 

< Second level child: object tag

< QSF parameter name for object type specifiers

< Sequential counter for each QSF object in this file

Definition at line 309 of file qsf-xml.c.

00310 {
00311         struct qsf_node_iterate iter;
00312         qsf_objects *object_set;
00313         gchar *tail, *object_count_s;
00314         gint64 c;
00315 
00316         g_return_if_fail(child != NULL);
00317         g_return_if_fail(qsf_ns != NULL);
00318         params->qsf_ns = qsf_ns;
00319         if(qsf_is_element(child, qsf_ns, QSF_OBJECT_TAG)) {
00320                 params->qsf_parameter_hash = NULL;
00321                 c = 0;
00322                 object_set = g_new(qsf_objects, 1);
00323                 params->object_set = object_set;
00324                 object_set->object_count = 0;
00325                 object_set->parameters = g_hash_table_new(g_str_hash, g_str_equal);
00326                 object_set->object_type = g_strdup((gchar*)xmlGetProp(child, 
00327                         BAD_CAST QSF_OBJECT_TYPE));
00328                 object_count_s = g_strdup((gchar*)xmlGetProp(child, 
00329                         BAD_CAST QSF_OBJECT_COUNT));
00330                 c = (gint64)strtol(object_count_s, &tail, 0);
00331                 object_set->object_count = (gint)c;
00332                 g_free(object_count_s);
00333                 params->qsf_object_list = g_list_prepend(params->qsf_object_list, object_set);
00334                 iter.ns = qsf_ns;
00335                 params->qsf_parameter_hash = object_set->parameters;
00336                 qsf_node_foreach(child, qsf_parameter_handler, &iter, params);
00337         }
00338 }
00339 

void qsf_object_validation_handler xmlNodePtr  child,
xmlNsPtr  ns,
qsf_validator valid
 

Checks all incoming objects for QOF registration.

< Second level child: object tag

< QSF parameter name for object type specifiers

Definition at line 120 of file qsf-xml.c.

00121 {
00122         xmlNodePtr cur_node;
00123         xmlChar *object_declaration;
00124         guint count;
00125         QsfStatus type;
00126         gboolean is_registered;
00127 
00128         count = 0;
00129         type = QSF_NO_OBJECT;
00130         is_registered = FALSE;
00131         for(cur_node = child->children; cur_node != NULL;
00132                 cur_node = cur_node->next)
00133         {
00134                 if(qsf_is_element(cur_node, ns, QSF_OBJECT_TAG)) {
00135                         object_declaration = xmlGetProp(cur_node, BAD_CAST QSF_OBJECT_TYPE);
00136                         is_registered = qof_class_is_registered(object_declaration);
00137                         if(is_registered) { type = QSF_REGISTERED_OBJECT; }
00138                         else { type = QSF_DEFINED_OBJECT; }
00139                         count = g_hash_table_size(valid->object_table);
00140                         g_hash_table_insert(valid->object_table, object_declaration,
00141                                 GINT_TO_POINTER(type));
00142                         /* if insert was successful - i.e. object is unique so far */
00143                         if(g_hash_table_size(valid->object_table) > count)
00144                         {
00145                                 valid->valid_object_count++;
00146                                 if(is_registered) { valid->qof_registered_count++; }
00147                         }
00148                 }
00149         }
00150 }

gint qsf_strings_equal const xmlChar *  node_name,
gchar *  tag_name
 

shorthand function

This may look repetitive but each one is used separately as well as in a block.

Definition at line 47 of file qsf-xml.c.

00048 {
00049         if(0 == qsf_compare_tag_strings(node_name, tag_name)) { return 1; }
00050         return 0;
00051 }

void qsf_valid_foreach xmlNodePtr  parent,
qsf_validCB  cb,
struct qsf_node_iterate iter,
qsf_validator valid
 

Validate the children of the parent node.

Note:
Slightly different to qsf_node_foreach because the validation can be run without qsf_param being initialized.

Definition at line 93 of file qsf-xml.c.

00095 {
00096         xmlNodePtr cur_node;
00097 
00098         iter->v_fcn = &cb;
00099         for(cur_node = parent->children; cur_node != NULL; cur_node = cur_node->next)
00100         {
00101                 cb(cur_node, iter->ns, valid);
00102         }
00103 }

KvpValue* string_to_kvp_value const gchar *  content,
KvpValueType  type
 

Convert a string value into KvpValue.

< xsd:dateTime format in coordinated universal time, UTC.

You can reproduce the string from the GNU/Linux command line using the date utility:

date -u +Y-m-dTH:M:SZ

2004-12-12T23:39:11Z

The datestring must be timezone independent and include all specified fields.

Remember to use gmtime() NOT localtime()!. From the command line, use the -u switch with the date command: date -u

To generate a timestamp based on a real time, use the qsf_time_now and qsf_time_string defaults.

qsf_time_now : Format: QOF_TYPE_DATE. The current time taken from the moment the default is read into a QSF object at runtime.

qsf_time_string : Format: QOF_TYPE_STRING. The current timestamp taken from the moment the default is read into a QSF object at runtime. This form is used when the output parameter needs a formatted date string, not an actual date object. The format is determined by the optional format attribute of the set tag which takes the same operators as the GNU C Library for strftime() and output may therefore be dependent on the locale of the calling process - take care. Default value is F, used when qsf_time_string is set without the format attribute.

Both defaults use UTC.

Definition at line 1093 of file qsf-backend.c.

01136                                                            { return; }
01137         cm_setter = qof_class_get_parameter_setter(obj_type, parameter_name);
01138         cm_param = qof_class_get_parameter(obj_type, parameter_name);
01139         object_set = params->object_set;
01140         if(safe_strcmp(qof_type, QOF_TYPE_STRING) == 0)  {
01141                 string_setter = (void(*)(QofEntity*, const gchar*))cm_setter;
01142                 if(string_setter != NULL) { string_setter(qsf_ent, 
01143                         (gchar*)xmlNodeGetContent(node)); }
01144         }
01145         if(safe_strcmp(qof_type, QOF_TYPE_DATE) == 0) {
01146                 date_setter = (void(*)(QofEntity*, Timespec))cm_setter;
01147                 timechk = NULL;
01148                 timechk = strptime((char*)xmlNodeGetContent(node), QSF_XSD_TIME, 
01149                         &qsf_time);
01150                 g_return_if_fail(timechk != NULL);
01151                 qsf_time_t = mktime(&qsf_time);
01152                 if(qsf_time_t != -3600)
01153                 {
01154                         timespecFromTime_t(&cm_date, qsf_time_t);
01155                         if(date_setter != NULL) { date_setter(qsf_ent, cm_date); }
01156                 }
01157         }
01158         if((safe_strcmp(qof_type, QOF_TYPE_NUMERIC) == 0)  ||
01159         (safe_strcmp(qof_type, QOF_TYPE_DEBCRED) == 0)) {
01160                 numeric_setter = (void(*)(QofEntity*, gnc_numeric))cm_setter;
01161                 string_to_gnc_numeric((char*)xmlNodeGetContent(node), &cm_numeric);
01162                 if(numeric_setter != NULL) { numeric_setter(qsf_ent, cm_numeric); }
01163         }
01164         if(safe_strcmp(qof_type, QOF_TYPE_GUID) == 0) {
01165                 cm_guid = g_new(GUID, 1);
01166                 if(TRUE != string_to_guid((char*)xmlNodeGetContent(node), cm_guid))
01167                 {
01168                         qof_backend_set_error(params->be, ERR_QSF_BAD_OBJ_GUID);
01169                         PINFO (" string to guid conversion failed for %s:%s:%s",
01170                                 xmlNodeGetContent(node), obj_type, qof_type);
01171                         return;
01172                 }
01173                 reference_type = (char*)xmlGetProp(node, BAD_CAST QSF_OBJECT_TYPE);
01174                 if(0 == safe_strcmp(QOF_PARAM_GUID, reference_type))
01175                 {
01176                         qof_entity_set_guid(qsf_ent, cm_guid);
01177                 }
01178                 else {
01179                         reference = qof_entity_get_reference_from(qsf_ent, cm_param);
01180                         if(reference) {
01181                                 params->referenceList = g_list_append(params->referenceList, 
01182                                         reference);
01183                         }
01184                 }
01185         }
01186         if(safe_strcmp(qof_type, QOF_TYPE_INT32) == 0) {
01187                 errno = 0;
01188                 cm_i32 = (gint32)strtol ((char*)xmlNodeGetContent(node), &tail, 0);
01189                 if(errno == 0) {
01190                         i32_setter = (void(*)(QofEntity*, gint32))cm_setter;
01191                         if(i32_setter != NULL) { i32_setter(qsf_ent, cm_i32); }
01192                 }
01193                 else { qof_backend_set_error(params->be, ERR_QSF_OVERFLOW); }
01194         }


Generated on Fri May 12 17:57:21 2006 for QOF by  doxygen 1.4.4