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... | |
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" |
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" |
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 } |
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) |
| #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.
| #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:
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.
| #define MAP_DEFINE_TAG "define" |
| #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.
| #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.
| #define MAP_ENUM_TYPE "enum" |
| #define MAP_ITERATE_ATTR "foreach" |
| #define MAP_NAME_ATTR "name" |
| #define MAP_OBJECT_ATTR "object" |
| #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.
| #define MAP_QOF_VERSION "qof_version" |
| #define MAP_ROOT_TAG "qsf-map" |
| #define MAP_TYPE_ATTR "type" |
| #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.
| #define QSF_BOOK_COUNT "count" |
| #define QSF_BOOK_GUID "book-guid" |
| #define QSF_BOOK_TAG "book" |
| #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.
| #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
| #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.
| #define QSF_DATE_LENGTH MAX_DATE_LENGTH |
Max length of QSF_XSD_TIME.
MAX_DATE_LENGTH itself is defined in gnc-date.h
| #define QSF_DEFAULT_NS "http://qof.sourceforge.net/" |
| #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.
| #define QSF_MAP_SCHEMA "qsf-map.xsd.xml" |
| #define QSF_OBJECT_COUNT "count" |
| #define QSF_OBJECT_KVP "path" |
| #define QSF_OBJECT_SCHEMA "qsf-object.xsd.xml" |
| #define QSF_OBJECT_TAG "object" |
| #define QSF_OBJECT_TYPE "type" |
| #define QSF_OPTION "option" |
| #define QSF_QOF_VERSION QOF_OBJECT_VERSION |
| #define QSF_XML_BOOLEAN_TEST "true" |
| #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.
| 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.
| 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 *) |
| enum qsf_type |
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;
| gboolean is_our_qsf_object | ( | const gchar * | path | ) |
Validate a QSF file.
| path | Absolute or relative path to the file to be validated |
Files that pass the test can be imported into the QOF appliction without the need for a QSF map.
Definition at line 144 of file qsf-xml.c.
00145 { 00146 xmlDocPtr doc; 00147 struct qsf_node_iterate iter; 00148 xmlNodePtr object_root; 00149 qsf_validator valid; 00150 gint table_count; 00151 00152 g_return_val_if_fail((path != NULL),FALSE); 00153 doc = xmlParseFile(path); 00154 if(doc == NULL) { return FALSE; } 00155 if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc)) { 00156 PINFO (" validation failed %s %s %s", QSF_SCHEMA_DIR, 00157 QSF_OBJECT_SCHEMA, path); 00158 return FALSE; 00159 } 00160 object_root = xmlDocGetRootElement(doc); 00161 /* check that all objects in the file are already registered in QOF */ 00162 valid.validation_table = g_hash_table_new(g_str_hash, g_str_equal); 00163 valid.qof_registered_count = 0; 00164 valid.valid_object_count = 0; 00165 iter.ns = object_root->ns; 00166 qsf_valid_foreach(object_root, qsf_object_validation_handler, &iter, &valid); 00167 table_count = g_hash_table_size(valid.validation_table); 00168 g_hash_table_destroy(valid.validation_table); 00169 if(table_count == valid.qof_registered_count) { return TRUE; } 00170 return FALSE; 00171 }
| gboolean is_our_qsf_object_be | ( | qsf_param * | params | ) |
Validate a QSF file and determine type.
| params | Pointer to qsf_param context |
Files that pass the test can be imported into the QOF appliction without the need for a QSF map.
Definition at line 187 of file qsf-xml.c.
00188 { 00189 xmlDocPtr doc; 00190 struct qsf_node_iterate iter; 00191 xmlNodePtr object_root; 00192 qsf_validator valid; 00193 gint table_count; 00194 gchar *path; 00195 00196 g_return_val_if_fail((params != NULL),FALSE); 00197 path = g_strdup(params->filepath); 00198 if(path == NULL) { 00199 qof_backend_set_error(params->be, ERR_FILEIO_FILE_NOT_FOUND); 00200 return FALSE; 00201 } 00202 if(params->file_type != QSF_UNDEF) { return FALSE; } 00203 doc = xmlParseFile(path); 00204 if(doc == NULL) { 00205 qof_backend_set_error(params->be, ERR_FILEIO_PARSE_ERROR); 00206 return FALSE; 00207 } 00208 if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc)) 00209 { 00210 qof_backend_set_error(params->be, ERR_QSF_INVALID_OBJ); 00211 return FALSE; 00212 } 00213 params->file_type = IS_QSF_OBJ; 00214 object_root = xmlDocGetRootElement(doc); 00215 valid.validation_table = g_hash_table_new(g_str_hash, g_str_equal); 00216 valid.qof_registered_count = 0; 00217 iter.ns = object_root->ns; 00218 qsf_valid_foreach(object_root, qsf_object_validation_handler, &iter, &valid); 00219 table_count = g_hash_table_size(valid.validation_table); 00220 if(table_count == valid.qof_registered_count) 00221 { 00222 g_hash_table_destroy(valid.validation_table); 00223 qof_backend_set_error(params->be, ERR_BACKEND_NO_ERR); 00224 return TRUE; 00225 } 00226 g_hash_table_destroy(valid.validation_table); 00227 qof_backend_set_error(params->be, ERR_QSF_NO_MAP); 00228 return FALSE; 00229 }
| gboolean is_qsf_map | ( | const gchar * | path | ) |
Validate a QSF map file.
| path | Absolute or relative path to the file to be validated |
The file is validated aginst the QSF map schema, qsf-map.xsd.xsml. This function is called by is_qsf_object. If called directly, the map file is validated and closed, no data is retrieved. QSF maps do not contain user data but are used to import QSF object files from other applications.
Definition at line 301 of file qsf-xml-map.c.
00302 { 00303 xmlDocPtr doc; 00304 struct qsf_node_iterate iter; 00305 qsf_validator valid; 00306 xmlNodePtr map_root; 00307 xmlNsPtr map_ns; 00308 00309 g_return_val_if_fail((path != NULL),FALSE); 00310 if(path == NULL) { return FALSE; } 00311 doc = xmlParseFile(path); 00312 if(doc == NULL) { return FALSE; } 00313 if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_MAP_SCHEMA, doc)) { 00314 return FALSE; 00315 } 00316 map_root = xmlDocGetRootElement(doc); 00317 map_ns = map_root->ns; 00318 iter.ns = map_ns; 00319 valid.error_state = ERR_BACKEND_NO_ERR; 00320 valid.validation_table = g_hash_table_new(g_str_hash, g_str_equal); 00321 qsf_valid_foreach(map_root, qsf_map_validation_handler, &iter, &valid); 00322 if (valid.error_state != ERR_BACKEND_NO_ERR) { 00323 g_hash_table_destroy(valid.validation_table); 00324 return FALSE; 00325 } 00326 g_hash_table_destroy(valid.validation_table); 00327 return TRUE; 00328 }
| gboolean is_qsf_map_be | ( | qsf_param * | params | ) |
Validate a QSF map file.
| params | Pointer to qsf_param context |
Definition at line 260 of file qsf-xml-map.c.
00261 { 00262 xmlDocPtr doc; 00263 struct qsf_node_iterate iter; 00264 qsf_validator valid; 00265 xmlNodePtr map_root; 00266 xmlNsPtr map_ns; 00267 gchar *path; 00268 00269 g_return_val_if_fail((params != NULL),FALSE); 00270 qof_backend_get_error(params->be); 00271 path = g_strdup(params->filepath); 00272 if(path == NULL) { 00273 qof_backend_set_error(params->be, ERR_FILEIO_FILE_NOT_FOUND); 00274 return FALSE; 00275 } 00276 doc = xmlParseFile(path); 00277 if(doc == NULL) { 00278 qof_backend_set_error(params->be, ERR_FILEIO_PARSE_ERROR); 00279 return FALSE; 00280 } 00281 if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_MAP_SCHEMA, doc)) { 00282 qof_backend_set_error(params->be, ERR_QSF_INVALID_MAP); 00283 return FALSE; 00284 } 00285 map_root = xmlDocGetRootElement(doc); 00286 map_ns = map_root->ns; 00287 iter.ns = map_ns; 00288 valid.validation_table = g_hash_table_new(g_str_hash, g_str_equal); 00289 valid.error_state = ERR_BACKEND_NO_ERR; 00290 qsf_valid_foreach(map_root, qsf_map_validation_handler, &iter, &valid); 00291 if (valid.error_state != ERR_BACKEND_NO_ERR) { 00292 qof_backend_set_error(params->be, valid.error_state); 00293 g_hash_table_destroy(valid.validation_table); 00294 return FALSE; 00295 } 00296 qof_backend_get_error(params->be); 00297 g_hash_table_destroy(valid.validation_table); 00298 return TRUE; 00299 }
| gboolean is_qsf_object | ( | const gchar * | path | ) |
Validate a QSF file and identify a suitable QSF map.
| path | Absolute or relative path to the file to be validated. |
The file is validated against the QSF object schema, qsf-object.xsd.xml and each object described in the file is checked to find out if a suitable QSF map exists. Map files are accepted if all objects described in the QSF object file are defined in the QSF map.
Definition at line 173 of file qsf-xml.c.
00174 { 00175 xmlDocPtr doc; 00176 00177 g_return_val_if_fail((path != NULL),FALSE); 00178 if(path == NULL) { return FALSE; } 00179 doc = xmlParseFile(path); 00180 if(doc == NULL) { return FALSE; } 00181 if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc)) { return FALSE; } 00182 /* Note cannot test against a map here, so if the file is valid QSF, 00183 accept it and work out the details later. */ 00184 return TRUE; 00185 }
| gboolean is_qsf_object_be | ( | qsf_param * | params | ) |
Validate a QSF file and identify a suitable QSF map.
| params | Pointer to qsf_param context |
The file is validated against the QSF object schema, qsf-object.xsd.xml and each object described in the file is checked to find out if a suitable QSF map exists. Map files are accepted if all objects described in the QSF object file are defined in the QSF map.
Definition at line 231 of file qsf-xml.c.
00232 { 00233 gboolean result; 00234 xmlDocPtr doc; 00235 GList *maps; 00236 gchar *path; 00237 00238 g_return_val_if_fail((params != NULL),FALSE); 00239 path = g_strdup(params->filepath); 00240 if(path == NULL) { 00241 qof_backend_set_error(params->be, ERR_FILEIO_FILE_NOT_FOUND); 00242 return FALSE; 00243 } 00244 /* skip validation if is_our_qsf_object has already been called. */ 00245 if(ERR_QSF_INVALID_OBJ == qof_backend_get_error(params->be)) { return FALSE; } 00246 if(params->file_type == QSF_UNDEF) 00247 { 00248 doc = xmlParseFile(path); 00249 if(doc == NULL) { 00250 qof_backend_set_error(params->be, ERR_FILEIO_PARSE_ERROR); 00251 return FALSE; 00252 } 00253 if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc)) 00254 { 00255 qof_backend_set_error(params->be, ERR_QSF_INVALID_OBJ); 00256 return FALSE; 00257 } 00258 } 00259 result = FALSE; 00260 /* retrieve list of maps from config frame. */ 00261 for(maps = params->map_files; maps; maps=maps->next) 00262 { 00263 QofBackendError err; 00264 result = is_qsf_object_with_map_be(maps->data, params); 00265 err = qof_backend_get_error(params->be); 00266 if((err == ERR_BACKEND_NO_ERR) && result) 00267 { 00268 params->map_path = maps->data; 00269 PINFO ("map chosen = %s", params->map_path); 00270 break; 00271 } 00272 /* pop the error back on the stack. */ 00273 else { qof_backend_set_error(params->be, err); } 00274 } 00275 return result; 00276 }
| gboolean is_qsf_object_with_map | ( | const gchar * | path, | |
| gchar * | map_file | |||
| ) |
Validate a QSF file and a selected QSF map.
| map_path | Absolute or relative path to the selected QSF map file | |
| params | Pointer to qsf_param context |
Definition at line 204 of file qsf-xml-map.c.
00205 { 00206 xmlDocPtr doc, map_doc; 00207 gint valid_count; 00208 struct qsf_node_iterate iter; 00209 xmlNodePtr map_root, object_root; 00210 xmlNsPtr map_ns; 00211 qsf_validator valid; 00212 gchar *map_path; 00213 00214 map_path = g_strdup_printf("%s/%s", QSF_SCHEMA_DIR, map_file); 00215 if(path == NULL) { 00216 return FALSE; 00217 } 00218 doc = xmlParseFile(path); 00219 if(doc == NULL) { 00220 return FALSE; 00221 } 00222 if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc)) { 00223 return FALSE; 00224 } 00225 object_root = xmlDocGetRootElement(doc); 00226 if(map_path == NULL) { 00227 return FALSE; 00228 } 00229 valid.validation_table = g_hash_table_new(g_str_hash, g_str_equal); 00230 map_doc = xmlParseFile(map_path); 00231 if(map_doc == NULL) { 00232 return FALSE; 00233 } 00234 if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_MAP_SCHEMA, map_doc)) { 00235 return FALSE; 00236 } 00237 map_root = xmlDocGetRootElement(map_doc); 00238 valid.map_calculated_count = 0; 00239 valid.valid_object_count = 0; 00240 valid.error_state = ERR_BACKEND_NO_ERR; 00241 map_ns = map_root->ns; 00242 iter.ns = map_ns; 00243 qsf_valid_foreach(map_root, qsf_map_validation_handler, &iter, &valid); 00244 iter.ns = object_root->ns; 00245 qsf_valid_foreach(object_root, qsf_object_validation_handler, &iter, &valid); 00246 if (valid.error_state != ERR_BACKEND_NO_ERR) { 00247 g_hash_table_destroy(valid.validation_table); 00248 return FALSE; 00249 } 00250 valid_count = 0 - g_hash_table_size(valid.validation_table); 00251 valid_count += valid.map_calculated_count; 00252 valid_count += valid.valid_object_count; 00253 g_hash_table_destroy(valid.validation_table); 00254 if(valid_count == 0) { 00255 return TRUE; 00256 } 00257 return FALSE; 00258 }
| gboolean is_qsf_object_with_map_be | ( | gchar * | map_path, | |
| qsf_param * | params | |||
| ) |
Validate a QSF file and a selected QSF map.
| map_path | Absolute or relative path to the selected QSF map file | |
| params | Pointer to qsf_param context |
This backend twin also sets QofBackendError codes.
Definition at line 117 of file qsf-xml-map.c.
00118 { 00119 xmlDocPtr doc, map_doc; 00120 gint valid_count, calc_count; 00121 struct qsf_node_iterate iter; 00122 xmlNodePtr map_root, object_root; 00123 xmlNsPtr map_ns; 00124 qsf_validator valid; 00125 gchar *path; 00126 gchar *map_path; 00127 00128 g_return_val_if_fail((params != NULL),FALSE); 00129 PINFO (" mapfile=%s", map_file); 00130 path = g_strdup(params->filepath); 00131 map_path = g_strdup_printf("%s/%s", QSF_SCHEMA_DIR, map_file); 00132 if(path == NULL) { 00133 qof_backend_set_error(params->be, ERR_FILEIO_FILE_NOT_FOUND); 00134 return FALSE; 00135 } 00136 doc = xmlParseFile(path); 00137 if(doc == NULL) { 00138 qof_backend_set_error(params->be, ERR_FILEIO_PARSE_ERROR); 00139 return FALSE; 00140 } 00141 if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc)) { 00142 qof_backend_set_error(params->be, ERR_QSF_INVALID_OBJ); 00143 return FALSE; 00144 } 00145 object_root = xmlDocGetRootElement(doc); 00146 if(map_path == NULL) { 00147 qof_backend_set_error(params->be, ERR_FILEIO_FILE_NOT_FOUND); 00148 return FALSE; 00149 } 00150 valid.validation_table = g_hash_table_new(g_str_hash, g_str_equal); 00151 map_doc = xmlParseFile(map_path); 00152 if(map_doc == NULL) { 00153 qof_backend_set_error(params->be, ERR_FILEIO_PARSE_ERROR); 00154 return FALSE; 00155 } 00156 if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_MAP_SCHEMA, map_doc)) { 00157 qof_backend_set_error(params->be, ERR_QSF_INVALID_MAP); 00158 return FALSE; 00159 } 00160 map_root = xmlDocGetRootElement(map_doc); 00161 valid.map_calculated_count = 0; 00162 valid.valid_object_count = 0; 00163 valid.qof_registered_count = 0; 00164 valid.error_state = ERR_BACKEND_NO_ERR; 00165 map_ns = map_root->ns; 00166 iter.ns = object_root->ns; 00167 qsf_valid_foreach(object_root, qsf_object_validation_handler, &iter, &valid); 00168 iter.ns = map_ns; 00169 qsf_valid_foreach(map_root, qsf_map_validation_handler, &iter, &valid); 00170 if (valid.error_state != ERR_BACKEND_NO_ERR) { 00171 qof_backend_set_error(params->be, valid.error_state); 00172 g_hash_table_destroy(valid.validation_table); 00173 return FALSE; 00174 } 00175 /* check all counted objects are valid */ 00176 /* Should be: 00177 the same number of valid object calculations as there are defined in the map. 00178 And the number of calculations must match the number of unregistered 00179 objects plus the number of registered objects defined. */ 00180 valid_count = g_hash_table_size(valid.validation_table) - valid.map_calculated_count; 00181 calc_count = valid.map_calculated_count - 00182 (valid.valid_object_count + valid.qof_registered_count); 00183 if(valid_count == 0 && calc_count == 0) { 00184 g_hash_table_destroy(valid.validation_table); 00185 qof_backend_get_error(params->be); 00186 return TRUE; 00187 } 00188 qof_backend_set_error(params->be, ERR_QSF_WRONG_MAP); 00189 /* the object is OK, only the map is wrong. */ 00190 PINFO (" Map is wrong. map:%d object:%d reg:%d size:%d result:%d", 00191 valid.map_calculated_count, valid.valid_object_count, 00192 valid.qof_registered_count, 00193 g_hash_table_size(valid.validation_table), valid_count); 00194 if(valid_count != 0) { 00195 PINFO (" size - map != 0. actual: %d.", valid_count); 00196 } 00197 if(calc_count != 0) { 00198 PINFO (" map - (object + registered) != 0. Actual: %d.", calc_count); 00199 } 00200 g_hash_table_destroy(valid.validation_table); 00201 return TRUE; 00202 }
| void qsf_book_node_handler | ( | xmlNodePtr | child, | |
| xmlNsPtr | qsf_ns, | |||
| qsf_param * | params | |||
| ) |
Book and book-guid node handler.
Reads the book count="" attribute (currently only 1 QofBook is supported per QSF object file) Sets the book-guid as the GUID of the current QofBackend QofBook in qsf_param. Calls the next handler, qsf_object_node_handler, with the child of the book tag.
Definition at line 333 of file qsf-xml.c.
00334 { 00335 gchar *book_count_s, *tail; 00336 gint book_count; 00337 xmlNodePtr child_node; 00338 struct qsf_node_iterate iter; 00339 gchar *buffer; 00340 GUID book_guid; 00341 00342 g_return_if_fail(child); 00343 g_return_if_fail(params); 00344 ENTER (" child=%s", child->name); 00345 if(qsf_is_element(child, ns, QSF_BOOK_TAG)) { 00346 book_count_s = (gchar*)xmlGetProp(child, BAD_CAST QSF_BOOK_COUNT); 00347 if(book_count_s) { 00348 book_count = (gint)strtol(book_count_s, &tail, 0); 00349 /* More than one book not currently supported. */ 00350 g_return_if_fail(book_count == 1); 00351 } 00352 iter.ns = ns; 00353 child_node = child->children->next; 00354 if(qsf_is_element(child_node, ns, QSF_BOOK_GUID)) { 00355 DEBUG (" trying to set book GUID"); 00356 buffer = g_strdup((gchar*)xmlNodeGetContent(child_node)); 00357 g_return_if_fail(TRUE == string_to_guid(buffer, &book_guid)); 00358 qof_instance_set_guid(QOF_INSTANCE(params->book), &book_guid); 00359 xmlNewChild(params->output_node, params->qsf_ns, 00360 BAD_CAST QSF_BOOK_GUID, BAD_CAST buffer); 00361 g_free(buffer); 00362 } 00363 qsf_node_foreach(child, qsf_object_node_handler, &iter, params); 00364 } 00365 LEAVE (" "); 00366 }
| 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 63 of file qsf-xml.c.
00064 { 00065 return qsf_is_element(params->child_node, params->qsf_ns, qof_type); 00066 }