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.
| |
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. | |
KvpValue * | string_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) |
|
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. |
|
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:
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]?
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.
|
|
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. |
|
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. |
|
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. |
|
|
|
Dictate which object type is the basis for iteration in a hierarchical object set. |
|
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! |
|
The object to use to provide the data being set using the map. |
|
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. |
|
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. |
|
Top level root tag for QSF Maps |
|
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. |
|
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. |
|
Sequential counter of each book in this file |
|
QOF GUID tag for the QofBook described by this QSF object file |
|
First level child: book tag - the QofBook. |
|
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. |
|
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 |
|
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. |
|
Max length of QSF_XSD_TIME. MAX_DATE_LENGTH itself is defined in gnc-date.h |
|
Default namespace for QSF root tag The map namespace is not included as maps are not currently written out by QOF. |
|
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. |
|
Name of the QSF Map Schema. |
|
Sequential counter for each QSF object in this file |
|
The path to this KVP value in the entity frame. |
|
Name of the QSF Object Schema. |
|
Second level child: object tag |
|
QSF parameter name for object type specifiers |
|
The KVP Value. |
|
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. |
|
QOF Version check. Make sure the same version of QOF is in use in both applications. |
|
The top level root tag |
|
needs to be lowercase for XML validation |
|
The current XML version. |
|
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. |
|
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. |
|
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. |
|
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. |
|
Validation metadata. The validation is a separate parse with separate data. This is used to determine which backend should load the data. |
|
validator callback
|
|
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;
|
|
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.
Definition at line 352 of file qsf-xml.h. 00352 { 00353 QSF_NO_OBJECT = 0, 00354 QSF_DEFINED_OBJECT, 00357 QSF_REGISTERED_OBJECT, 00359 QSF_CALCULATED_OBJECT, 00360 QSF_INVALID_OBJECT 00361 }QsfStatus;
|
|
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 }
|
|
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 }
|
|
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");
|
|
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 }
|
|
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 }
|
|
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 }
|
|
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 }
|
|
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);
|
|
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 }
|
|
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 }
|
|
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.
|
|
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 }
|
|
Compares an xmlDoc in memory against the schema file.
Incorrect validation will result in output to the terminal window.
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 }
|
|
Prepare the default list of maps.
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 }
|
|
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 }
|
|
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. |
|
< 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
|
|
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 }
|
|
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 }
|
|
Validate the children of the parent node.
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 }
|
|
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 }
|