Derek Atkins warlord at MIT.EDU
Thu Jul 7 07:03:25 EDT 2005

Quoting Neil Williams <linux at>:

> On Wednesday 06 July 2005 10:11 pm, Derek Atkins wrote:
> (bear with me, this is a long one).

Uh oh... ;)     Me, I'm gonna snip stuff to shorten it..

> How's this for starters?
> Each choice type would need it's own definition of the allowable objects - 
> each of which would need to be registered as normal. Objects would declare 
> themselves to be one option of a particular choice. That could be a new 
> component of QofObject, "choice". If GncOwner declared itself as 
> choice: QOF_CHOICE, 
> GncCustomer could set:
> choice: GNC_ID_OWNER
> in it's QofObject definition, declaring gncCustomer as an option for 
> (maybe choice_parent: instead). That should be easily extensible.

I don't like that.  It means that each object can be in only one choice.  I'd
rather have the definitions of the allowable objects as part of the choice
definition.  It would mean that you'd need to store either a GList of types or
a HashTable of types for each choice object you define, but it's more
extensible than what you've got.

Perhaps an API like:

  qof_choice_add_class(GNC_ID_OWNER, GNC_ID_CUSTOMER);
  qof_choice_add_class(GNC_ID_OWNER, GNC_ID_VENDOR);
  qof_choice_add_class(GNC_ID_OWNER, GNC_ID_EMPLOYEE);
  qof_choice_add_class(GNC_ID_OWNER, GNC_ID_JOB);

And then you could use QOF_CHOICE "GNC_ID_OWNER" elsewhere in the qof

> So GncOwner would end up with a QofObject description but could set a NULL 
> foreach:. Queries would use the original QofAccessFuncs to obtain the 
> GncCustomer etc..

Just need to make sure our code all checks for this...

> The GncInvoice would have a GNC_ID_OWNER parameter (as before) and QOF would
> lookup a new static table (alongside the existing GList* in qofobject.c) that
> identifies the allowable choices for that object as it is identified as a 
> choice. A simple gboolean qof_object_is_choice(QofIdType) and GList* 
> qof_object_get_choices(QofIdType) that each refer to a static GHashTable 
> qof_choice_table;.

That works.  :)

> The table would be populated by the same qof_object_register() function - it
> would also be v.small.
> QOF could use the original GNC_ID_OWNER type parameter to retrieve the 
> owner.customer etc. instance (this keeps existing queries happy). QOF would 
> look up the param_type and if it's a QOF_CHOICE, handle it as a simple 
> QofEntity instead of using the param_type that is set to GNC_ID_OWNER.
> QOF now has a QofEntity and therefore a ent->e_type, belonging to the current
> invoice object, using the GNC_ID_OWNER QofParam. That is sufficient for QSF 
> to write out a QofEntityReference and export it. This would also allow 
> recursion as the invoice entity would contain an owner that would provide the
> entity that can be copied to the export book.

Yea, this is exactly what I was talking about earlier..  :)

> This would be done in QSF for all QOF_CHOICE objects - an extra conditional.
> The QSF would then contain:
> <object type="gncInvoice">
>   <guid type="guid">invoice_guid_as_string</guid>
>   <guid type="gncCustomer">customer_guid_as_string</guid>
> ...
> </object>
> On importing/merging, QOF would create the GncCustomer etc. from it's object
> tag block in the same file. When populating the invoice, QOF would come 
> across the GNC_ID_OWNER QofParam and lookup GNC_ID_OWNER in the choice table.
> QOF would need to create an owner object to pass to the QofSetterFunc for the
> invoice. GncOwner, as a choice object, would look up it's registered choices
> and accept the entity using the QofSetterFunc for that type. The invoice for
> it's part would use the param_setfcn to receive the owner. 

Note that in many cases the Owner is "inlined" in the object and not a
standalone reference, so if you did this you'd have to malloc, set the setter,
and then free the object.  (or the QofSetter would just need to free it).

> Would that work?

I _think_ so.

> (Phew! That took two hours to work out!)
> (and it'll take a few minutes to read and understand too!)
> :-))
> > Well, I was kind of thinking that it might be easier to have an "Export
> > Book" 
> Next on my list ...
> > The downside is that this requires extra work outside of QOF; each object
> > would need to know all the references to other objects and be able to add
> > them to the Export Book.
> i.e. the export routine in GnuCash is hard-coded with the list of objects
> that 
> comprise the book.
> Not if QOF_CHOICE works - it should allow the recursion needed to find the 
> references within QOF with no explicit help from the export routine - just 
> the objects concerned.


> > Well, it would work just fine IFF you added an API that would allow QOF to
> > ask the invoice to return all the sub-objects so that QOF could export
> > them.
> That's what should happen. The Choice will allow the invoice to tell QOF
> about 
> a GncCustomer (as opposed to a vendor etc.). The Collect will allow the 
> invoice to tell QOF about the list of GncEntry entities. As you recommended,
> two is better than one.

I do try to provide good advice ;)


       Derek Atkins, SB '93 MIT EE, SM '95 MIT Media Laboratory
       Member, MIT Student Information Processing Board  (SIPB)
       URL:    PP-ASEL-IA     N1NWH
       warlord at MIT.EDU                        PGP key available

More information about the gnucash-devel mailing list