| qof_book_merge: 'Query Object Framework: Design and direction.' | ||
|---|---|---|
| Prev | Chapter 5. QSF - QOF Serialization Format. | Next |
qsf-map is an XML format used to map a series of QOF objects from one application to a series of different QOF objects in another application. The map works by defining the steps of the calculations involved, including conditionals, pattern matching, defaults, simple assignments and arithmetic operators. The example snippet below does not include all necessary data for a working map for reasons of brevity but does try to include at least one example of each QSF map tag and construct.
1: <definition qof_version="3"> 2: <define e_type="qof-expenses">Pilot-link QOF expenses</define> 3: <define e_type="qof_datebook">Pilot-link QOF datebook</define> 4: <define e_type="gncInvoice">Invoice</define> 5: <define e_type="Trans">Transaction</define> 6: <define e_type="gncEntry">Order/Invoice/Bill Entry</define> 7: <default name="mileage_rate" type="numeric" value="28/100"/> 8: </definition> 9: <object type="gncEntry"> 10: <calculate type="string" value="action"> 11: <if type="qof-expenses"> 12: <set>Material</set> 13: </if> 14: <else type="qof-datebook"> 15: <set>Hours</set> 16: </else> 17: </calculate> 18: <calculate type="numeric" value="iprice"> 19: <if type="string" value="expense_type"> 20: <equals type="string" value="etMileage"> 21: <set>mileage_rate</set> 22: </equals> 23: </if> 24: </calculate> 25: <calculate type="string" value="desc"> 26: <if boolean="use_weekday_descriptor"> 27: <set format="%A">qsf_time_string</set> 28: </if> 29: <else> 30: <set object="qof-expenses">expense_vendor</set> 31: </else> 32: </calculate> 33: </object>
qsf_time_now : Format: QOF_TYPE_DATE. The current time taken from the moment the QSF object file is loaded at runtime.
qsf_time_string : Format: QOF_TYPE_STRING. The current timestamp taken from the moment the QSF object file is loaded 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.
qsf_time_precision : Format: QOF_TYPE_STRING. This dictates how precisely date objects are matched. e.g. in the test environment of a conversion from pilot-link to GnuCash invoices, events and expenses that occur on the same day should be considered part of the same invoice - even if the actual timestamps are several hours apart. The preset default uses the GNU C Library formatting and is set to %j - the same day of the year. This default can be overridden by specifying it directly in the map as a local default. If you do change this default, take care in case the calling process is not using the same locale. Other useful options for this value might be %U for a weekly precision, %C for annual precision, %F for an absolute day match, %c for an absolute match including timezone. Note that this value is always compared as the string returned by strftime() using that format. Formats that return a NULL or invalid string and formats that don't specify a % will cause the map to revert to the preset %j default. Complex formats using ordinary characters and/or multiple format specifiers are not supported.
qsf_lookup_from_string : Format: QOF_TYPE_BOOLEAN. Always true. Used to allow references to QOF objects outside the QSF object data. e.g. The gncInvoice includes a reference to the account to use for posting the invoice plus accounts to use for certain entry types. These cannot be specified by GUID in the QSF map in order to retain portability. Instead, specify the qsf_lookup_from_string and add the descriptive name of the account to use. qof_book_merge will create the account if appropriate.
Line 1: Interface Version. All QOF objects used in the map must use the same QOF interface version. Back
Line 2 to 6: Definitions. The definition tag defines the objects from both applications that will be used in the map. The e_type and descriptive contents of each description must appear exactly as defined in the QofObject definitions within the relevant application. Defined objects must also be unique: the e_type values and descriptive contents from different applications must not overlap within the map. If there is a name collision between two applications, a request should be made to the application developers to modify the settings of one of the two applications. If subsequent lines define suitable calculations, the map can be used in either direction. Back
Line 7: Defaults. Defaults are independent of object definitions. The calculations can assign the default to any parameter that matches the required QOF type. Back
Line 9: Map Objects. Each defined object must have one calculation defined in the map for each QofClass parameter that has both a get() and a set() routine defined as not NULL (a principle established with qof_book_merge). Each calculation must end with a set tag. Empty calculations for required parameters will cause the map to fail. Back
Line 10: Calculations. Each calculation is defined by specifying the type and name of the parameter in the current output object to be SET. The map is processed by the receiving application which understands the output object. Back
Line 11: Conditionals. 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. This conditional specifies that if the type of the current import QSF object is qof-expenses, the current output gncEntry object should use the action parameter defined within the conditional. Conditionals can reference parameter as well as object values. Back
Line 12: Assignments. 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. Back
Line 14: Nesting. 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. Back
<variable name="my_rate" type="numeric" value="0/1"/>
Line 21: Conversions. A value of one type can be used to set a suitable value of a different parameter with a different type but converting between types is NOT supported. You must define a function within one of the applications that can handle the conversion from the relevant import type. Any request to set a parameter with a value that does not match the required type will be ignored. The only exceptions to this are for GUID's and enumerator values. Back
GUID: The GUID for reference objects cannot be specified directly in the QSF map in order to retain portability. Instead, a default value is available. qsf_lookup_from_string provides the descriptive name of the account to use. QSF will lookup the appropriate GUID using QOF.
enumerator values: Setting the plain integer decreases the human readability of the map and increases the chance of errors. By defining the enumerator values in the map, the readable versions can be used in the calculation.
Both GUID's and enumerator values use the option attribute of the set tag. This allows QSF to do these strictly limited type conversions before calling the set function for the parameter.
Line 26: Boolean preferences. Use a default boolean value to adjust strings like descriptions and notes according to user preference. Back
Line 30: QSF objects. When the map needs to draw in a real value from the QSF objects, use the type attribute to specify the QSF object to use. Back
An example QSF map file, pilot-qsf-GnuCashInvoice.xml, and the QSF Map Schema are now available.
The simple QSF parser shows how the QSF map can be built into a xmlHashTable (the QOF version of this parser will use GHashTable which has certain advantages) that can be used to lookup the calculation needed for each tag in the output QSF object file. The parser reads the input QSF object file into a hash then iterates over the QSF map to build the definitions and default hashes. Each calculation is then parsed to create the output tags in a new QSF XML tree. When all calculations are complete, the output tree is written to the output file using xmlDocDump.
The pilot-qsf-GnuCashInvoice QSF map is not yet complete - none of the datebook or address data is currently handled. The QSF map Schema and format may change slightly during this process - development is ongoing.