Ok, here is an updated set of headers.  I've flushed out the types a
bit more as per your suggestions, and I've flushed out the model as
well.

There are now three registries:
        1) core data types
        2) gnucash objects' data parameters
        3) gnucash objects' "parent" objects

The third registry basically allows you to register functions that
basically say: "given a split, return the account" and then perform
queries against the account object.

When you build a query term, you basically supply an object_type,
parameter_name, comparitor, predicate_data, and query_operator.  When
you run the query, you tell the query what kind of object you're
looking for and it will iterate over those objects.  For each term it
uses registry 3 to convert from the requested object to the querried
object, registry 2 to lookup the core type and access function, and
registry 1 to look up the match_predicate function.  In this way
you can build a query that says:

        Return all splits where account->account_name equals regex (name)

In this example:
 - "split" is the requested object,
 - "account" is the querried object,
 - "account_name" is the parameter (of type QUERYCORE_STRING),
 - "equals" is the comparitor,
 - "regex (name)" is the predicate_data (for type QUERYCORE_STRING)

I _think_ that this API can fully implement the existing Query API.
Please send me comments.

Thanks,

-derek

/*
 * QueryNew.h -- API for finding Gnucash objects
 * Copyright (C) 2002 Derek Atkins <[EMAIL PROTECTED]>
 *
 */

#ifndef GNC_QUERYNEW_H
#define GNC_QUERYNEW_H

/* A Query */
typedef struct querynew_s QueryNew;

/* Query Term Operators, for combining Query Terms */
typedef enum {
  QUERY_AND=1,
  QUERY_OR,
  QUERY_NAND,
  QUERY_NOR,
  QUERY_XOR
} QueryOp;


/* Standard Query Term comparitors, for how to process a query term.
 * Note that not all core types implement all comparitors
 */
typedef enum {
  COMPARE_LT = 1,
  COMPARE_LTE,
  COMPARE_EQUAL,
  COMPARE_GT,
  COMPARE_GTE
} query_compare_t;


/* Types of Gnucash Queriable Objects  (const char *) */
#define QUERY_TYPE_SPLIT        "split"
#define QUERY_TYPE_ACCOUNT      "account"
#define QUERY_TYPE_TRANSACTION  "transaction"


/* Type of Query Core Objects (String, Date, Numeric, GUID, etc. */
typedef const char * QueryCoreType;

/*
 * List of known core query types... 
 * Each core query type defines it's set of optional "comparitor qualifiers".
 */
#define QUERYCORE_STRING        "string"
typedef enum {
  STRING_MATCH_CASEINSENSITIVE  = 1,
  STRING_MATCH_REGEXP
} string_match_t;

#define QUERYCORE_DATE          "date"
typedef enum {
  DATE_MATCH_ROUNDED = 1
} date_match_t;

#define QUERYCORE_NUMERIC       "numeric"
typedef enum {
  NUMERIC_MATCH_ABS = 1,
  NUMERIC_MATCH_NEG_ONLY,
  NUMERIC_MATCH_POS_ONLY
} numeric_match_t;

#define QUERYCORE_GUID          "guid"
typedef enum {
  GUID_MATCH_ALL = 1,
  GUID_MATCH_ANY
  GUID_MATCH_NONE
} guid_match_t;

#define QUERYCORE_INT64         "gint64"
#define QUERYCORE_DOUBLE        "double"
#define QUERYCORE_BOOLEAN       "boolean"
#define QUERYCORE_KVP           "kvp"

/* A CHAR type is for a RECNCell */
#define QUERYCORE_CHAR          "character"


/* Basic API Functions */

/* This is the general function that adds a new Query Term to a query.
 * It will find the 'obj_type' object of the search item and compare
 * the 'param_name' parameter to the predicate data via the comparitor.
 *
 * For example:
 *
 * acct_name_pred_data = make_string_pred_data(STRING_MATCH_CASEINSENSITIVE,
 *                                             account_name);
 * gncQueryAddTerm (query, QUERY_TYPE_ACCOUNT, QUERY_ACCOUNT_NAME,
 *                  COMPARE_EQUAL, acct_name_pred_data, QUERY_AND);
 */
void gncQueryAddTerm (QueryNew *query,
                      const char *obj_type, const char *param_name,
                      query_compare_t comparitor, gpointer pred_data,
                      QueryOp op);


/* Run the query:
 *
 * ex: gncQueryRun (query, QUERY_TYPE_SPLIT);
 */
GList * gncQueryRun (QueryNew *query, const char *obj_type);

#endif /* GNC_QUERYNEW_H */
/*
 * QueryCore.h -- API for providing core Query data types
 * Copyright (C) 2002 Derek Atkins <[EMAIL PROTECTED]>
 *
 */

#ifndef GNC_QUERYCORE_H
#define GNC_QUERYCORE_H

#include "QueryNew.h"
#include "QueryObject.h"        /* for QueryAccess */

/* 
 * An arbitrary Query Predicate.  Given the gnucash object and the
 * particular parameter get-function (obtained from the registry by
 * the Query internals), compare the object's parameter to the
 * predicate data given the match_options
 */
typedef int (*QueryPredicate) (gpointer object,
                               QueryAccess get_fcn,
                               query_compare_t how,
                               gint match_options,
                               gpointer pdata);

/* A callback for how to destroy a query predicate's pdata */
typedef void (*QueryPredDataFree) (gpointer pdata);


/* This function registers a new Core Object with the QueryNew
 * subsystem.  It maps the "core_name" object to the given
 * query_predicate and predicate_data_free functions.
 */
void gncQueryRegisterCoreObject (char const *core_name,
                                 QueryPredicate pred,
                                 QueryPredDataFree pd_free);


/* An example:
 *
 * gncQueryRegisterCoreObject (QUERYCORE_STRING, string_match_predicate,
 *                             string_free_pdata);
 */


#endif /* GNC_QUERYCORE_H */
/*
 * QueryObject.h -- API for registering queriable Gnucash objects
 * Copyright (C) 2002 Derek Atkins <[EMAIL PROTECTED]>
 *
 */

#ifndef GNC_QUERYOBJECT_H
#define GNC_QUERYOBJECT_H

#include "QueryNew.h"

/* Define an arbitrary function pointer for access functions.  This is
 * because C doesn't have templates, so we just cast a lot.  Real
 * functions must be of the form:
 * 
 * <param_type> function (object_type *obj);
 */
typedef void (*QueryAccess)(gpointer);

/* This structure is for each queriable parameter in an object */
typedef struct query_object_def {
  const char *  param_name;
  QueryCoreType param_type;
  QueryAccess   param_getfcn;
} QueryObjectDef;

/* This function registers a new Gnucash Object with the QueryNew
 * subsystem.  It registers the "obj_name" object which provides the
 * "methods" set of queriable parameters.  The "methods" array must
 * be a NULL-terminated array.
 */
void gncQueryRegisterObject (const char * obj_name,
                             const QueryObjectDef *methods[]);

/* An example:
 *
 * #define MY_QUERY_OBJ_MEMO    "memo"
 * #define MY_QUERY_OBJ_VALUE   "value"
 * #define MY_QUERY_OBJ_DATE    "date"
 *
 * static QueryObjectDef myQueryObject[] = {
 * { MY_QUERY_OBJ_MEMO, QUERYCORE_STRING, myMemoGetter },
 * { MY_QUERY_OBJ_VALUE, QUERYCORE_NUMERIC, myValueGetter },
 * { MY_QUERY_OBJ_DATE, QUERYCORE_DATE, myDateGetter },
 * NULL };
 *
 * gncQueryRegisterObject ("myObjectName", &myQueryObject);
 */

/* This function-type will convert from one object-type to another */
typedef gpointer (*QueryConvert)(gpointer);

typedef struct query_convert_def {
  const char *  object_name;
  QueryConvert  object_getfcn;
} QueryConvertDef;

/* This function registers a new Gnucash Object and provides a
 * set of methods to obtain other Gnucash objects from this one.
 * The methods array much be NULL-terminated.
 */
void gncQueryRegisterConversion (const char *obj_name,
                                 const QueryConvertDef *methods[]);

/* An example:
 *
 * static QueryConvertDef myQueryObjects[] = {
 * { QUERY_TYPE_ACCOUNT, myAccountGetter },
 * { QUERY_TYPE_TRANSACTION, myTransactionGetter },
 * NULL };
 *
 * gncQueryRegisterConversion ("myObjectName", &myQueryObjects);
 */

#endif /* GNC_QUERYOBJECT_H */


-- 
       Derek Atkins, SB '93 MIT EE, SM '95 MIT Media Laboratory
       Member, MIT Student Information Processing Board  (SIPB)
       URL: http://web.mit.edu/warlord/    PP-ASEL-IA     N1NWH
       [EMAIL PROTECTED]                        PGP key available

Reply via email to