r6890 - in dumbhippo/trunk/client: common/ddm common/hippo linux
- From: commits mugshot org
- To: online-desktop-list gnome org
- Subject: r6890 - in dumbhippo/trunk/client: common/ddm common/hippo linux
- Date: Fri, 9 Nov 2007 17:07:00 -0600 (CST)
Author: otaylor
Date: 2007-11-09 17:06:59 -0600 (Fri, 09 Nov 2007)
New Revision: 6890
Added:
dumbhippo/trunk/client/common/ddm/ddm-rule.c
dumbhippo/trunk/client/common/ddm/test-rules.c
dumbhippo/trunk/client/common/ddm/test-utils.c
dumbhippo/trunk/client/common/ddm/test-utils.h
Modified:
dumbhippo/trunk/client/common/ddm/ddm-data-model-dbus.c
dumbhippo/trunk/client/common/ddm/ddm-data-model-internal.h
dumbhippo/trunk/client/common/ddm/ddm-data-model.c
dumbhippo/trunk/client/common/ddm/ddm-data-model.h
dumbhippo/trunk/client/common/ddm/ddm-data-resource-internal.h
dumbhippo/trunk/client/common/ddm/ddm-data-resource.c
dumbhippo/trunk/client/common/ddm/ddm-rule.h
dumbhippo/trunk/client/common/ddm/static-file-backend.c
dumbhippo/trunk/client/common/ddm/test-data.xml
dumbhippo/trunk/client/common/ddm/test-local-data.xml
dumbhippo/trunk/client/common/ddm/test-multipart-fetch.c
dumbhippo/trunk/client/common/ddm/test-notification.c
dumbhippo/trunk/client/common/ddm/test-static-file-backend.c
dumbhippo/trunk/client/common/hippo/hippo-data-model-backend.c
dumbhippo/trunk/client/linux/Makefile-libddm.am
Log:
test-utils.[ch] test-static-file-backend.c test-notifcation.c
test-multipart-fetch.c: Factor out common test code
hippo-data-model-backend.c ddm-data-model-dbus.c: Fix
value.u.string = FALSE.
ddm-rule.[ch]: Add internal DDMRule object
ddm-data-model.[ch]: Add ddm_data_model_add_rule()
ddm-data-model.{c,-internal.h}, ddm-data-resource.{c,-internal.h}:
First cut implementation of rules, with some stunning inefficiency.
(mostly in _ddm_data_model_find_{source,targets}.
test-rules.c: Simple test of rules
Modified: dumbhippo/trunk/client/common/ddm/ddm-data-model-dbus.c
===================================================================
--- dumbhippo/trunk/client/common/ddm/ddm-data-model-dbus.c 2007-11-09 21:25:03 UTC (rev 6889)
+++ dumbhippo/trunk/client/common/ddm/ddm-data-model-dbus.c 2007-11-09 23:06:59 UTC (rev 6890)
@@ -442,7 +442,7 @@
ddm_data_model_set_global_resource(dbus_model->ddm_model, global_resource);
value.type = DDM_DATA_BOOLEAN;
- value.u.string = FALSE;
+ value.u.boolean = FALSE;
ddm_data_resource_update_property(global_resource,
ddm_qname_get(DDM_GLOBAL_RESOURCE_CLASS, "online"),
Modified: dumbhippo/trunk/client/common/ddm/ddm-data-model-internal.h
===================================================================
--- dumbhippo/trunk/client/common/ddm/ddm-data-model-internal.h 2007-11-09 21:25:03 UTC (rev 6889)
+++ dumbhippo/trunk/client/common/ddm/ddm-data-model-internal.h 2007-11-09 23:06:59 UTC (rev 6890)
@@ -4,6 +4,7 @@
#include "ddm-data-model.h"
#include "ddm-data-resource.h"
+#include "ddm-rule.h"
#include "ddm-work-item.h"
G_BEGIN_DECLS
@@ -21,6 +22,20 @@
DDMClient *_ddm_data_model_get_local_client (DDMDataModel *model);
+/* Result should be freed by caller */
+GSList *_ddm_data_model_find_sources (DDMDataModel *model,
+ const char *source_class_id,
+ DDMCondition *condition);
+GSList *_ddm_data_model_find_targets (DDMDataModel *model,
+ const char *target_class_id,
+ DDMCondition *condition);
+
+/* Result owned by model */
+GSList *_ddm_data_model_get_target_rules(DDMDataModel *model,
+ const char *class_id);
+GSList *_ddm_data_model_get_source_rules(DDMDataModel *model,
+ const char *class_id);
+
G_END_DECLS
#endif /* __DDM_DATA_MODEL_INTERNAL__H__ */
Modified: dumbhippo/trunk/client/common/ddm/ddm-data-model.c
===================================================================
--- dumbhippo/trunk/client/common/ddm/ddm-data-model.c 2007-11-09 21:25:03 UTC (rev 6889)
+++ dumbhippo/trunk/client/common/ddm/ddm-data-model.c 2007-11-09 23:06:59 UTC (rev 6890)
@@ -10,6 +10,7 @@
#include "ddm-data-resource-internal.h"
#include "ddm-data-query-internal.h"
#include "ddm-local-client.h"
+#include "ddm-rule.h"
static void ddm_data_model_init (DDMDataModel *model);
static void ddm_data_model_class_init (DDMDataModelClass *klass);
@@ -24,6 +25,9 @@
void *backend_data;
GFreeFunc free_backend_data_func;
+ GHashTable *rules_by_target;
+ GHashTable *rules_by_source;
+
DDMClient *local_client;
GHashTable *resources;
@@ -58,11 +62,29 @@
G_DEFINE_TYPE(DDMDataModel, ddm_data_model, G_TYPE_OBJECT);
static void
+free_rule_list(GSList *rule_list)
+{
+ g_slist_foreach(rule_list, (GFunc)ddm_rule_free, NULL);
+ g_slist_free(rule_list);
+}
+
+static void
ddm_data_model_init(DDMDataModel *model)
{
model->resources = g_hash_table_new_full(g_str_hash, g_str_equal,
NULL,
(GDestroyNotify)ddm_data_resource_unref);
+
+ /* rules_by_target and rules_by_source together own the reference to the rule.
+ * We consider the reference owned by rules_by_target
+ */
+ model->rules_by_target = g_hash_table_new_full(g_str_hash, g_str_equal,
+ (GDestroyNotify)g_free,
+ (GDestroyNotify)free_rule_list);
+ model->rules_by_source = g_hash_table_new_full(g_str_hash, g_str_equal,
+ (GDestroyNotify)g_free,
+ (GDestroyNotify)g_slist_free);
+
model->changed_resources = g_hash_table_new(g_direct_hash, NULL);
model->work_items = g_queue_new();
@@ -648,6 +670,47 @@
}
static void
+get_values_foreach(gpointer key,
+ gpointer value,
+ gpointer data)
+{
+ GSList **values = data;
+
+ *values = g_slist_prepend(*values, value);
+}
+
+static GSList *
+hash_table_get_values(GHashTable *hash_table)
+{
+ GSList *values = NULL;
+
+ g_hash_table_foreach(hash_table, get_values_foreach, &values);
+
+ return values;
+}
+
+static void
+data_model_flush_rules(DDMDataModel *model)
+{
+ GSList *resources_to_process;
+ GSList *l;
+
+ if (g_hash_table_size(model->changed_resources) == 0)
+ return;
+
+ /* We need to snapshot the changed resources, since the set of changd resources
+ * may be extended as we process rules.
+ */
+ resources_to_process = hash_table_get_values(model->changed_resources);
+
+ for (l = resources_to_process; l; l = l->next) {
+ _ddm_data_resource_update_rule_properties(l->data);
+ }
+
+ g_slist_free(resources_to_process);
+}
+
+static void
data_model_flush_notifications(DDMDataModel *model)
{
DDMClientNotificationSet *notification_set;
@@ -728,11 +791,145 @@
if (model->backend->flush)
model->backend->flush(model, model->backend_data);
+ data_model_flush_rules(model);
data_model_flush_notifications(model);
data_model_flush_work_items(model);
}
void
+ddm_data_model_add_rule (DDMDataModel *model,
+ const char *target_class_id,
+ const char *target_property,
+ const char *source_class_id,
+ DDMDataCardinality cardinality,
+ gboolean default_include,
+ const char *default_children,
+ const char *condition)
+{
+ DDMRule *rule;
+ GSList *target_rules;
+ GSList *source_rules;
+
+ g_return_if_fail(DDM_IS_DATA_MODEL(model));
+ g_return_if_fail(target_class_id != NULL);
+ g_return_if_fail(target_property != NULL);
+ g_return_if_fail(source_class_id != NULL);
+ g_return_if_fail(cardinality == DDM_DATA_CARDINALITY_01 || cardinality == DDM_DATA_CARDINALITY_N);
+ g_return_if_fail(condition != NULL);
+
+ rule = ddm_rule_new(target_class_id, target_property,
+ source_class_id,
+ cardinality, default_include, default_children,
+ condition);
+
+ if (rule == NULL) /* failed validation, will have warned */
+ return;
+
+ target_rules = g_hash_table_lookup(model->rules_by_target, target_class_id);
+ target_rules = g_slist_prepend(target_rules, rule);
+ g_hash_table_replace(model->rules_by_target,
+ g_strdup(target_class_id),
+ target_rules);
+
+ source_rules = g_hash_table_lookup(model->rules_by_source, source_class_id);
+ source_rules = g_slist_prepend(source_rules, rule);
+ g_hash_table_replace(model->rules_by_source,
+ g_strdup(source_class_id),
+ source_rules);
+}
+
+typedef struct {
+ const char *class_id;
+ DDMCondition *condition;
+ gboolean find_sources;
+ GSList *results;
+} FindResourcesClosure;
+
+static void
+find_resources_foreach(gpointer key,
+ gpointer value,
+ gpointer data)
+{
+ DDMDataResource *resource = value;
+ FindResourcesClosure *closure = data;
+ const char *class_id = ddm_data_resource_get_class_id(resource);
+ gboolean match;
+
+ if (class_id == NULL || strcmp(class_id, closure->class_id) != 0)
+ return;
+
+ if (closure->find_sources)
+ match = ddm_condition_matches_source(closure->condition, resource);
+ else
+ match = ddm_condition_matches_target(closure->condition, resource);
+
+ if (!match)
+ return;
+
+ closure->results = g_slist_prepend(closure->results, resource);
+}
+
+static GSList *
+find_resources(DDMDataModel *model,
+ const char *class_id,
+ DDMCondition *condition,
+ gboolean find_sources)
+{
+ /* This is the most inefficient implementation possible; to improve, you'd
+ * want to:
+ *
+ * A) Index resources in the model by class_id
+ * B) Index resources in the model by property values that rules match upon
+ *
+ * It might be easiest to do B with an explicit:
+ *
+ * ddm_data_model_add_index(DDMDataModel *model,
+ * const char *property_uri);
+ */
+
+ FindResourcesClosure closure;
+
+ closure.class_id = class_id;
+ closure.condition = condition;
+ closure.find_sources = find_sources;
+ closure.results = NULL;
+
+ g_hash_table_foreach(model->resources, find_resources_foreach, &closure);
+
+ return closure.results;
+}
+
+GSList *
+_ddm_data_model_find_sources(DDMDataModel *model,
+ const char *source_class_id,
+ DDMCondition *condition)
+{
+ return find_resources(model, source_class_id, condition, TRUE);
+}
+
+GSList *
+_ddm_data_model_find_targets(DDMDataModel *model,
+ const char *target_class_id,
+ DDMCondition *condition)
+{
+ return find_resources(model, target_class_id, condition, FALSE);
+}
+
+GSList *
+_ddm_data_model_get_target_rules(DDMDataModel *model,
+ const char *class_id)
+{
+ return g_hash_table_lookup(model->rules_by_target, class_id);
+}
+
+GSList *
+_ddm_data_model_get_source_rules(DDMDataModel *model,
+ const char *class_id)
+{
+ return g_hash_table_lookup(model->rules_by_source, class_id);
+}
+
+void
_ddm_data_model_query_answered (DDMDataModel *model,
DDMDataQuery *query)
{
Modified: dumbhippo/trunk/client/common/ddm/ddm-data-model.h
===================================================================
--- dumbhippo/trunk/client/common/ddm/ddm-data-model.h 2007-11-09 21:25:03 UTC (rev 6889)
+++ dumbhippo/trunk/client/common/ddm/ddm-data-model.h 2007-11-09 23:06:59 UTC (rev 6890)
@@ -38,6 +38,16 @@
GFreeFunc free_backend_data_func);
/* Used testing purposes; you can't call query or update on such a backend */
DDMDataModel *ddm_data_model_new_no_backend (void);
+
+void ddm_data_model_add_rule (DDMDataModel *model,
+ const char *target_class_id,
+ const char *target_property,
+ const char *source_class_id,
+ DDMDataCardinality cardinality,
+ gboolean default_include,
+ const char *default_children,
+ const char *condition);
+
gboolean ddm_data_model_get_connected (DDMDataModel *model);
gboolean ddm_data_model_is_ready (DDMDataModel *model);
@@ -66,6 +76,7 @@
DDMDataQuery *ddm_data_model_update_params (DDMDataModel *model,
const char *method,
GHashTable *params);
+
DDMDataResource *ddm_data_model_lookup_resource (DDMDataModel *model,
const char *resource_id);
DDMDataResource *ddm_data_model_ensure_resource (DDMDataModel *model,
Modified: dumbhippo/trunk/client/common/ddm/ddm-data-resource-internal.h
===================================================================
--- dumbhippo/trunk/client/common/ddm/ddm-data-resource-internal.h 2007-11-09 21:25:03 UTC (rev 6889)
+++ dumbhippo/trunk/client/common/ddm/ddm-data-resource-internal.h 2007-11-09 23:06:59 UTC (rev 6890)
@@ -31,6 +31,8 @@
void _ddm_data_resource_send_local_notifications (DDMDataResource *resource,
GSList *changed_properties);
+void _ddm_data_resource_update_rule_properties(DDMDataResource *resource);
+
void _ddm_data_resource_resolve_notifications (DDMDataResource *resource,
DDMClientNotificationSet *notification_set);
Modified: dumbhippo/trunk/client/common/ddm/ddm-data-resource.c
===================================================================
--- dumbhippo/trunk/client/common/ddm/ddm-data-resource.c 2007-11-09 21:25:03 UTC (rev 6889)
+++ dumbhippo/trunk/client/common/ddm/ddm-data-resource.c 2007-11-09 23:06:59 UTC (rev 6890)
@@ -7,6 +7,7 @@
#include "ddm-data-fetch.h"
#include "ddm-data-model-internal.h"
#include "ddm-data-resource-internal.h"
+#include "ddm-rule.h"
typedef enum {
CONNECTION_TYPE_ANY,
@@ -19,11 +20,24 @@
typedef struct _DataClient DataClient;
struct _DDMDataProperty {
+ DDMDataResource *resource;
+
DDMQName *qname;
DDMDataValue value;
DDMDataFetch *default_children;
guint cardinality : 4;
guint default_include : 1;
+
+ /* We could use a flag bit and smaller allocation to save space for non-rule-properties */
+
+ /* Rule this property came from or NULL */
+ DDMRule *rule;
+
+ /* List of sources for this rule. For CARDINALITY_N, this is the same as value.u.list,
+ * but for CARDINALITY_01, we pick just one source out out of the list of sources.
+ */
+ GSList *rule_sources;
+
};
struct _DataConnection {
@@ -51,6 +65,9 @@
char *class_id;
gboolean local;
+ /* Properties that reference this resource as the source of a rule */
+ GSList *referencing_rule_properties;
+
GSList *clients;
GSList *connections; /* Local connections */
GSList *properties;
@@ -945,6 +962,7 @@
{
DDMDataProperty *property = g_new0(DDMDataProperty, 1);
+ property->resource = resource;
property->qname = qname;
property->cardinality = cardinality;
property->value.type = DDM_DATA_NONE;
@@ -962,6 +980,16 @@
ddm_data_property_free(property);
}
+static void
+mark_property_changed(DDMDataResource *resource,
+ DDMDataProperty *property)
+{
+ if (g_slist_find(resource->changed_properties, property->qname) == NULL) {
+ resource->changed_properties = g_slist_prepend(resource->changed_properties, property->qname);
+ _ddm_data_model_mark_changed(resource->model, resource);
+ }
+}
+
/* return value is whether something changed (we need to emit notification) */
gboolean
ddm_data_resource_update_property(DDMDataResource *resource,
@@ -1116,10 +1144,8 @@
property->default_children = ddm_data_fetch_from_string(default_children);
}
- if (changed && g_slist_find(resource->changed_properties, property->qname) == NULL) {
- resource->changed_properties = g_slist_prepend(resource->changed_properties, property->qname);
- _ddm_data_model_mark_changed(resource->model, resource);
- }
+ if (changed)
+ mark_property_changed(resource, property);
return changed;
}
@@ -1514,7 +1540,339 @@
}
}
+static DDMDataProperty *
+resource_ensure_rule_property(DDMDataResource *resource,
+ DDMRule *rule)
+{
+ GSList *l;
+ DDMDataProperty *property;
+
+ for (l = resource->properties; l; l = l->next) {
+ property = l->data;
+ if (property->qname == rule->target_property)
+ return property;
+ }
+
+ property = g_new0(DDMDataProperty, 1);
+
+ property->resource = resource;
+ property->qname = rule->target_property;
+ property->cardinality = rule->cardinality;
+ property->value.type = DDM_DATA_NONE;
+ property->default_include = rule->default_include;
+ property->default_children = rule->default_children;
+ if (property->default_children)
+ ddm_data_fetch_ref(property->default_children);
+
+ property->rule = rule;
+ property->rule_sources = NULL;
+
+ resource->properties = g_slist_prepend(resource->properties, property);
+
+ return property;
+}
+
+static void
+property_update_value_from_rule_sources(DDMDataProperty *property)
+{
+ gboolean changed = FALSE;
+
+ if (property->cardinality == DDM_DATA_CARDINALITY_N) {
+ if (property->rule_sources == NULL) {
+ if (DDM_DATA_BASE(property->value.type) != DDM_DATA_NONE) {
+ g_assert(property->value.type == (DDM_DATA_RESOURCE | DDM_DATA_LIST));
+
+ g_slist_free(property->value.u.list);
+ property->value.type = DDM_DATA_NONE;
+ changed = TRUE;
+ }
+ } else {
+ if (DDM_DATA_BASE(property->value.type) != DDM_DATA_NONE) {
+ g_assert(property->value.type == (DDM_DATA_RESOURCE | DDM_DATA_LIST));
+ g_slist_free(property->value.u.list);
+ } else {
+ property->value.type = DDM_DATA_RESOURCE | DDM_DATA_LIST;
+ }
+
+ property->value.u.list = g_slist_copy(property->rule_sources);
+ changed = TRUE;
+ }
+ } else { /* DDM_DATA_CARDINALITY_01 */
+ if (property->rule_sources == NULL) {
+ if (DDM_DATA_BASE(property->value.type) != DDM_DATA_NONE) {
+ g_assert(property->value.type == DDM_DATA_RESOURCE);
+
+ property->value.type = DDM_DATA_NONE;
+ changed = TRUE;
+ }
+ } else {
+ if (DDM_DATA_BASE(property->value.type) != DDM_DATA_NONE) {
+ g_assert(property->value.type == DDM_DATA_RESOURCE);
+
+ if (property->rule_sources->data != property->value.u.resource) {
+ property->value.u.resource = property->rule_sources->data;
+ changed = TRUE;
+ }
+ } else {
+ property->value.type = DDM_DATA_RESOURCE;
+ property->value.u.resource = property->rule_sources->data;
+ changed = TRUE;
+ }
+ }
+ }
+
+ if (changed)
+ mark_property_changed(property->resource, property);
+
+}
+
+static int
+compare_resources(gconstpointer a,
+ gconstpointer b)
+{
+ return ((size_t)a < (size_t)b) ? -1 : (((size_t)a == (size_t)b) ? 0 : 1);
+}
+
+static void
+property_add_rule_source(DDMDataProperty *property,
+ DDMDataResource *source)
+{
+ GSList *l;
+ GSList *prev = NULL;
+
+ l = property->rule_sources;
+ while (TRUE) {
+ int cmp;
+
+ if (l) {
+ cmp = compare_resources(source, l->data);
+ } else {
+ cmp = 1;
+ }
+
+ if (cmp == 0)
+ return;
+ else if (cmp > 0) {
+ GSList *node = g_slist_prepend(l, source);
+
+ if (prev)
+ prev->next = node;
+ else
+ property->rule_sources = node;
+
+ g_debug("Adding rule source %s to %s:%s#%s",
+ source->resource_id, property->resource->resource_id,
+ property->qname->uri, property->qname->name);
+
+ source->referencing_rule_properties = g_slist_prepend(source->referencing_rule_properties, property->resource);
+ property_update_value_from_rule_sources(property);
+
+ return;
+ }
+
+ prev = l;
+ l = l->next;
+ }
+}
+
+static void
+property_remove_rule_source(DDMDataProperty *property,
+ DDMDataResource *source)
+{
+ GSList *l;
+ GSList *prev = NULL;
+
+ for (l = property->rule_sources; l; l = l->next) {
+ int cmp = compare_resources(source, l->data);
+ if (cmp == 0) {
+ if (prev)
+ prev->next = l->next;
+ else
+ property->rule_sources = l->next;
+ g_slist_free1(l);
+
+ source->referencing_rule_properties = g_slist_remove(source->referencing_rule_properties, property->resource);
+ property_update_value_from_rule_sources(property);
+
+ g_debug("Removing rule source %s from %s:%s#%s",
+ source->resource_id, property->resource->resource_id,
+ property->qname->uri, property->qname->name);
+
+ return;
+ } else if (cmp > 0) {
+ break;
+ }
+
+ prev = l;
+ }
+}
+
+/* Diff two lists sorted by the comparison function 'compare', and create
+ * two new lists (free with g_slist_free) of the values that were added
+ * or removed.
+ */
+static void
+find_deltas(GSList *list,
+ GSList *new_list,
+ GCompareFunc compare,
+ GSList **added,
+ GSList **removed)
+{
+ GSList *l = list;
+ GSList *m = new_list;
+
+ *added = NULL;
+ *removed = NULL;
+
+ while (l || m) {
+ int cmp;
+
+ if (l && m)
+ cmp = (*compare)(l->data, m->data);
+ else if (l)
+ cmp = -1;
+ else
+ cmp = 1;
+
+ if (cmp < 0) {
+ /* value to remove */
+ *removed = g_slist_prepend(*removed, l->data);
+
+ l = l->next;
+ } else if (cmp > 0) {
+ /* value to add */
+ *added = g_slist_prepend(*added, m->data);
+
+ m = m->next;
+ } else {
+ l = l->next;
+ m = m->next;
+ }
+ }
+}
+
+/* takes ownership of sources */
+static void
+property_update_rule_sources(DDMDataProperty *property,
+ GSList *sources)
+{
+ GSList *added;
+ GSList *removed;
+ GSList *l;
+
+ sources = g_slist_sort(sources, compare_resources);
+
+ find_deltas(property->rule_sources, sources, compare_resources, &added, &removed);
+
+ if (added == NULL && removed == NULL) {
+ g_slist_free(sources);
+ return;
+ }
+
+ g_debug("Recomputed rule sources for %s:%s#%s",
+ property->resource->resource_id,
+ property->qname->uri, property->qname->name);
+
+ g_slist_free(property->rule_sources);
+ property->rule_sources = sources;
+
+ for (l = removed; l; l = l->next) {
+ DDMDataResource *source = l->data;
+ g_debug(" removed %s", source->resource_id);
+ source->referencing_rule_properties = g_slist_remove(source->referencing_rule_properties,
+ property);
+ }
+
+ for (l = added; l; l = l->next) {
+ DDMDataResource *source = l->data;
+ g_debug(" added %s", source->resource_id);
+ source->referencing_rule_properties = g_slist_prepend(source->referencing_rule_properties,
+ property);
+ }
+
+ property_update_value_from_rule_sources(property);
+
+ g_slist_free(added);
+ g_slist_free(removed);
+}
+
void
+_ddm_data_resource_update_rule_properties(DDMDataResource *resource)
+{
+ GSList *target_rules;
+ GSList *source_rules;
+ GSList *l;
+
+ /* First remove any property values that previously referenced this resource
+ * that no longer apply
+ */
+ l = resource->referencing_rule_properties;
+ while (l) {
+ DDMDataProperty *property = l->data;
+ DDMCondition *condition;
+ GSList *l_next = l->next;
+
+ condition = ddm_rule_build_source_condition(property->rule, property->resource);
+
+ if (!ddm_condition_matches_source(condition, resource))
+ property_remove_rule_source(property, resource);
+
+ ddm_condition_free(condition);
+
+ l = l_next;
+ }
+
+ /* Now find properties that currently reference this resource and, if necessary
+ * add them.
+ */
+ source_rules = _ddm_data_model_get_source_rules(resource->model, resource->class_id);
+ for (l = source_rules; l; l = l->next) {
+ DDMRule *rule = l->data;
+ DDMCondition *condition;
+ GSList *targets;
+ GSList *ll;
+
+ condition = ddm_rule_build_target_condition(rule, resource);
+ targets = _ddm_data_model_find_targets(resource->model,
+ rule->target_class_id,
+ condition);
+
+ for (ll = targets; ll; ll = ll->next) {
+ DDMDataResource *target = ll->data;
+ DDMDataProperty *property;
+
+ property = resource_ensure_rule_property(target, rule);
+ property_add_rule_source(property, resource);
+ }
+
+ ddm_condition_free(condition);
+ g_slist_free(targets);
+ }
+
+ /* Finally, for all rules with this class as target, find all matching sources, and
+ * merge them into the current property value
+ */
+ target_rules = _ddm_data_model_get_target_rules(resource->model, resource->class_id);
+ for (l = target_rules; l; l = l->next) {
+ DDMRule *rule = l->data;
+ DDMCondition *condition;
+ DDMDataProperty *property;
+ GSList *sources;
+
+ condition = ddm_rule_build_source_condition(rule, resource);
+ sources = _ddm_data_model_find_sources(resource->model,
+ rule->source_class_id,
+ condition);
+
+ property = resource_ensure_rule_property(resource, rule);
+
+ /* update_rule_sources takes ownership of sources */
+ property_update_rule_sources(property, sources);
+ ddm_condition_free(condition);
+ }
+}
+
+void
_ddm_data_resource_resolve_notifications (DDMDataResource *resource,
DDMClientNotificationSet *notification_set)
{
Added: dumbhippo/trunk/client/common/ddm/ddm-rule.c
===================================================================
--- dumbhippo/trunk/client/common/ddm/ddm-rule.c 2007-11-09 21:25:03 UTC (rev 6889)
+++ dumbhippo/trunk/client/common/ddm/ddm-rule.c 2007-11-09 23:06:59 UTC (rev 6890)
@@ -0,0 +1,70 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+
+#include "ddm-rule.h"
+
+DDMRule *
+ddm_rule_new (const char *target_class_id,
+ const char *target_property_uri,
+ const char *source_class_id,
+ DDMDataCardinality cardinality,
+ gboolean default_include,
+ const char *default_children_str,
+ const char *condition_str)
+{
+ DDMQName *target_property;
+ DDMCondition *condition;
+ DDMDataFetch *default_children;
+ DDMRule *rule;
+
+ target_property = ddm_qname_from_uri(target_property_uri);
+ if (target_property == NULL) /* Will already have warned */
+ return NULL;
+
+ condition = ddm_condition_from_string(condition_str);
+ if (condition == NULL) /* Will already have warned */
+ return NULL;
+
+ if (default_children_str) {
+ default_children = ddm_data_fetch_from_string(default_children_str);
+ if (default_children == NULL) /* Will have already warned */
+ return NULL;
+ } else {
+ default_children = NULL;
+ }
+
+ rule = g_new0(DDMRule, 1);
+ rule->target_class_id = g_strdup(target_class_id);
+ rule->target_property= target_property;
+ rule->source_class_id = g_strdup(source_class_id);
+ rule->cardinality = cardinality;
+ rule->default_children = default_children;
+ rule->condition = condition;
+
+ return rule;
+}
+
+void
+ddm_rule_free (DDMRule *rule)
+{
+ g_free(rule->target_class_id);
+ g_free(rule->source_class_id);
+ if (rule->default_children)
+ ddm_data_fetch_unref(rule->default_children);
+ ddm_condition_free(rule->condition);
+
+ g_free(rule);
+}
+
+DDMCondition *
+ddm_rule_build_target_condition(DDMRule *rule,
+ DDMDataResource *source_resource)
+{
+ return ddm_condition_reduce_source(rule->condition, source_resource);
+}
+
+DDMCondition *
+ddm_rule_build_source_condition(DDMRule *rule,
+ DDMDataResource *target_resource)
+{
+ return ddm_condition_reduce_target(rule->condition, target_resource);
+}
Modified: dumbhippo/trunk/client/common/ddm/ddm-rule.h
===================================================================
--- dumbhippo/trunk/client/common/ddm/ddm-rule.h 2007-11-09 21:25:03 UTC (rev 6889)
+++ dumbhippo/trunk/client/common/ddm/ddm-rule.h 2007-11-09 23:06:59 UTC (rev 6890)
@@ -3,6 +3,7 @@
#ifndef __DDM_RULE_H__
#define __DDM_RULE_H__
+#include "ddm-data-fetch.h"
#include "ddm-data-resource.h"
G_BEGIN_DECLS
@@ -50,6 +51,16 @@
} u;
};
+struct _DDMRule {
+ char *target_class_id;
+ DDMQName *target_property;
+ char *source_class_id;
+ DDMDataCardinality cardinality;
+ gboolean default_include;
+ DDMDataFetch *default_children;
+ DDMCondition *condition;
+};
+
typedef struct {
DDMCondition *left;
DDMCondition *right;
@@ -108,6 +119,13 @@
const char *default_children,
const char *condition);
+DDMQName *ddm_rule_get_target_property (DDMRule *rule);
+DDMDataCardinality *ddm_rule_get_cardinality (DDMRule *rule);
+const char *ddm_rule_get_target_class_id (DDMRule *rule);
+const char *ddm_rule_get_source_class_id (DDMRule *rule);
+
+void ddm_rule_free (DDMRule *rule);
+
DDMCondition *ddm_rule_build_target_condition(DDMRule *rule,
DDMDataResource *source_resource);
DDMCondition *ddm_rule_build_source_condition(DDMRule *rule,
Modified: dumbhippo/trunk/client/common/ddm/static-file-backend.c
===================================================================
--- dumbhippo/trunk/client/common/ddm/static-file-backend.c 2007-11-09 21:25:03 UTC (rev 6889)
+++ dumbhippo/trunk/client/common/ddm/static-file-backend.c 2007-11-09 23:06:59 UTC (rev 6890)
@@ -343,6 +343,27 @@
static_file_flush
};
+static void
+setup_global_resource(DDMDataModel *model)
+{
+ DDMDataResource *global_resource;
+ DDMDataValue value;
+
+ global_resource = ddm_data_model_ensure_resource(model,
+ DDM_GLOBAL_RESOURCE, DDM_GLOBAL_RESOURCE_CLASS);
+ ddm_data_model_set_global_resource(model, global_resource);
+
+ value.type = DDM_DATA_BOOLEAN;
+ value.u.boolean = TRUE;
+
+ ddm_data_resource_update_property(global_resource,
+ ddm_qname_get(DDM_GLOBAL_RESOURCE_CLASS, "online"),
+ DDM_DATA_UPDATE_REPLACE,
+ DDM_DATA_CARDINALITY_1,
+ FALSE, NULL,
+ &value);
+}
+
DDMDataModel*
ddm_static_file_model_new (const char *filename,
GError **error)
@@ -353,6 +374,8 @@
static_file_model = get_static_file_model(model);
static_file_model->backend_model = ddm_data_model_new_no_backend();
+
+ setup_global_resource(model);
if (!ddm_static_file_parse(filename, static_file_model->backend_model, error)) {
/* FIXME: cleanup and free the models */
Modified: dumbhippo/trunk/client/common/ddm/test-data.xml
===================================================================
--- dumbhippo/trunk/client/common/ddm/test-data.xml 2007-11-09 21:25:03 UTC (rev 6889)
+++ dumbhippo/trunk/client/common/ddm/test-data.xml 2007-11-09 23:06:59 UTC (rev 6890)
@@ -7,11 +7,13 @@
</resource>
<resource xmlns="http://mugshot.org/p/o/user" m:resourceId="user/USER2">
<name m:type="+s">Sally Smith</name>
+ <aim m:type="s?">SSCoolJ</aim>
</resource>
<resource xmlns="http://mugshot.org/p/o/user" m:resourceId="user/USER1">
<name m:type="+s">John Doe</name>
<externalAccounts m:type="+r?" m:defaultChildren="+" m:resourceId="externalAccount/USER1.MYSPACE"/>
<contacts m:type="r*" m:resourceId="user/USER2"/>
<contacters m:type="r*" m:update="clear"/>
+ <aim m:type="s?">JohnDoe1</aim>
</resource>
</m:model>
Modified: dumbhippo/trunk/client/common/ddm/test-local-data.xml
===================================================================
--- dumbhippo/trunk/client/common/ddm/test-local-data.xml 2007-11-09 21:25:03 UTC (rev 6889)
+++ dumbhippo/trunk/client/common/ddm/test-local-data.xml 2007-11-09 23:06:59 UTC (rev 6890)
@@ -1,6 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?><!-- -*- sgml-indent-step: 4; fill-column: 120 -*- -->
<m:model xmlns:m="http://mugshot.org/p/system" m:resourceBase="online-desktop:/o/">
- <resource xmlns="online-desktop://p/o/buddy" m:resourceId="pidgin-buddy/AIM.JohnDoe1">
- <user m:type="r?" m:resourceId="http://mugshot.org/o/user/USER1"/>
+ <resource xmlns="online-desktop:/p/o/buddy" m:resourceId="pidgin-buddy/AIM.JohnDoe1">
+ <name m:type="s">JohnDoe1</name>
+ <protocol m:type="s">aim</protocol>
+ <!-- This is for testing multipart fetches without rules -->
+ <fixedUser m:type="r?" m:resourceId="http://mugshot.org/o/user/USER1"/>
</resource>
</m:model>
Modified: dumbhippo/trunk/client/common/ddm/test-multipart-fetch.c
===================================================================
--- dumbhippo/trunk/client/common/ddm/test-multipart-fetch.c 2007-11-09 21:25:03 UTC (rev 6889)
+++ dumbhippo/trunk/client/common/ddm/test-multipart-fetch.c 2007-11-09 23:06:59 UTC (rev 6890)
@@ -1,85 +1,21 @@
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
-#include <string.h>
+#include "test-utils.h"
-#include "static-file-backend.h"
-#include "ddm-data-query.h"
-
-static void
-on_query_result (DDMDataResource *result,
- gpointer user_data)
-{
- DDMDataResource **result_location = user_data;
- *result_location = result;
-}
-
-static void
-on_query_error (DDMDataError error,
- const char *message,
- gpointer user_data)
-{
- const char **message_location = user_data;
-
- g_assert(message != NULL);
- *message_location = g_strdup(message);
-}
-
-static DDMDataResource *
-query_resource(DDMDataModel *model,
- const char *resource_id,
- const char *fetch)
-{
- DDMDataQuery *query;
- DDMDataResource *result = NULL;
- const char *error = NULL;
-
- query = ddm_data_model_query_resource_by_id(model, resource_id, fetch);
- ddm_data_query_set_single_handler(query, on_query_result, &result);
- ddm_data_query_set_error_handler(query, on_query_error, &error);
-
- while (ddm_data_model_needs_flush(model))
- ddm_data_model_flush(model);
-
- if (error != NULL)
- g_error("Error from getResource, resource_id=%s, fetch=%s: %s", resource_id, fetch, error);
-
- return result;
-}
-
int
main(int argc, char **argv)
{
- GError *error = NULL;
DDMDataModel *model;
- const char *srcdir;
- char *filename;
DDMDataResource *result;
DDMDataResource *user1;
DDMDataResource *buddy1;
DDMDataResource *user;
- g_type_init();
+ model = test_init(TRUE);
+
+ result = test_query_resource("online-desktop:/o/pidgin-buddy/AIM.JohnDoe1", "fixedUser name");
- srcdir = g_getenv("DDM_SRCDIR");
- if (srcdir == NULL)
- g_error("DDM_SRCDIR is not set");
-
- filename = g_build_filename(srcdir, "test-data.xml", NULL);
- model = ddm_static_file_model_new(filename, &error);
- if (model == NULL)
- g_error("Failed to create test model: %s", error->message);
-
- g_free(filename);
-
- filename = g_build_filename(srcdir, "test-local-data.xml", NULL);
- if (!ddm_static_load_local_file(filename, model, &error))
- g_error("Failed to add_local data to test model: %s", error->message);
-
- g_free(filename);
-
- result = query_resource(model, "online-desktop:/o/pidgin-buddy/AIM.JohnDoe1", "user name");
-
buddy1 = ddm_data_model_lookup_resource(model, "online-desktop:/o/pidgin-buddy/AIM.JohnDoe1");
g_assert(buddy1 != NULL);
@@ -88,7 +24,7 @@
user = NULL;
ddm_data_resource_get(buddy1,
- "user", DDM_DATA_RESOURCE, &user,
+ "fixedUxuser", DDM_DATA_RESOURCE, &user,
NULL);
g_assert(user == user1);
Modified: dumbhippo/trunk/client/common/ddm/test-notification.c
===================================================================
--- dumbhippo/trunk/client/common/ddm/test-notification.c 2007-11-09 21:25:03 UTC (rev 6889)
+++ dumbhippo/trunk/client/common/ddm/test-notification.c 2007-11-09 23:06:59 UTC (rev 6890)
@@ -1,60 +1,9 @@
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
#include <string.h>
+#include "test-utils.h"
-#include "static-file-backend.h"
-#include "ddm-data-query.h"
-
-static DDMDataModel *model = NULL;
-
static void
-on_query_result (DDMDataResource *result,
- gpointer user_data)
-{
- DDMDataResource **result_location = user_data;
- *result_location = result;
-}
-
-static void
-on_query_error (DDMDataError error,
- const char *message,
- gpointer user_data)
-{
- const char **message_location = user_data;
-
- g_assert(message != NULL);
- *message_location = g_strdup(message);
-}
-
-static void
-flush_model(DDMDataModel *model) {
- while (ddm_data_model_needs_flush(model))
- ddm_data_model_flush(model);
-
-}
-
-static DDMDataResource *
-query_resource(DDMDataModel *model,
- const char *resource_id,
- const char *fetch)
-{
- DDMDataQuery *query;
- DDMDataResource *result = NULL;
- const char *error = NULL;
-
- query = ddm_data_model_query_resource_by_id(model, resource_id, fetch);
- ddm_data_query_set_single_handler(query, on_query_result, &result);
- ddm_data_query_set_error_handler(query, on_query_error, &error);
-
- flush_model(model);
-
- if (error != NULL)
- g_error("Error from getResource, resource_id=%s, fetch=%s: %s", resource_id, fetch, error);
-
- return result;
-}
-
-static void
on_buddy1_changed(DDMDataResource *resource,
GSList *changed_properties,
gpointer data)
@@ -68,7 +17,7 @@
g_assert(strcmp(ddm_data_resource_get_resource_id(resource), "online-desktop:/o/pidgin-buddy/AIM.JohnDoe1") == 0);
- user2 = ddm_data_model_lookup_resource(model, "http://mugshot.org/o/user/USER2");
+ user2 = ddm_data_model_lookup_resource(test_get_model(), "http://mugshot.org/o/user/USER2");
g_assert(user2 != NULL);
user = NULL;
@@ -89,10 +38,8 @@
int
main(int argc, char **argv)
{
- GError *error = NULL;
- const char *srcdir;
- char *filename;
-
+ DDMDataModel *model;
+
DDMDataResource *result;
DDMDataResource *user1;
DDMDataResource *user2;
@@ -103,27 +50,10 @@
gboolean was_changed = FALSE;
- g_type_init();
+ model = test_init(TRUE);
- srcdir = g_getenv("DDM_SRCDIR");
- if (srcdir == NULL)
- g_error("DDM_SRCDIR is not set");
+ result = test_query_resource("online-desktop:/o/pidgin-buddy/AIM.JohnDoe1", "fixedUser name");
- filename = g_build_filename(srcdir, "test-data.xml", NULL);
- model = ddm_static_file_model_new(filename, &error);
- if (model == NULL)
- g_error("Failed to create test model: %s", error->message);
-
- g_free(filename);
-
- filename = g_build_filename(srcdir, "test-local-data.xml", NULL);
- if (!ddm_static_load_local_file(filename, model, &error))
- g_error("Failed to add_local data to test model: %s", error->message);
-
- g_free(filename);
-
- result = query_resource(model, "online-desktop:/o/pidgin-buddy/AIM.JohnDoe1", "user name");
-
buddy1 = ddm_data_model_lookup_resource(model, "online-desktop:/o/pidgin-buddy/AIM.JohnDoe1");
g_assert(buddy1 != NULL);
@@ -132,7 +62,7 @@
user = NULL;
ddm_data_resource_get(buddy1,
- "user", DDM_DATA_RESOURCE, &user,
+ "fixedUser", DDM_DATA_RESOURCE, &user,
NULL);
g_assert(user == user1);
@@ -149,12 +79,12 @@
value.u.resource = user2;
ddm_data_resource_update_property(buddy1,
- ddm_qname_get("online-desktop://p/o/buddy", "user"),
+ ddm_qname_get("online-desktop://p/o/buddy", "fixedUser"),
DDM_DATA_UPDATE_REPLACE, DDM_DATA_CARDINALITY_01,
FALSE, NULL,
&value);
- flush_model(model);
+ test_flush();
g_assert(was_changed);
Added: dumbhippo/trunk/client/common/ddm/test-rules.c
===================================================================
--- dumbhippo/trunk/client/common/ddm/test-rules.c 2007-11-09 21:25:03 UTC (rev 6889)
+++ dumbhippo/trunk/client/common/ddm/test-rules.c 2007-11-09 23:06:59 UTC (rev 6890)
@@ -0,0 +1,96 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+
+#include "test-utils.h"
+
+int
+main(int argc, char **argv)
+{
+ DDMDataModel *model;
+
+ DDMDataResource *user1;
+ DDMDataResource *user2;
+ DDMDataResource *buddy1;
+ DDMDataResource *user;
+ GSList *aimBuddies;
+
+ DDMDataValue value;
+
+ model = test_init(TRUE);
+
+ ddm_data_model_add_rule(model,
+ "online-desktop:/p/o/buddy",
+ "online-desktop:/p/o/buddy#user",
+ "http://mugshot.org/p/o/user",
+ DDM_DATA_CARDINALITY_01, FALSE, NULL,
+ "source.aim = target.name and target.protocol = 'aim'");
+
+ ddm_data_model_add_rule(model,
+ "online-desktop:/p/o/global",
+ "online-desktop:/p/o/global#aimBuddies",
+ "online-desktop:/p/o/buddy",
+ DDM_DATA_CARDINALITY_N, FALSE, NULL,
+ "source.protocol = 'aim'");
+
+ user1 = test_query_resource("http://mugshot.org/o/user/USER1", "aim");
+ g_assert(user1 != NULL);
+
+ user2 = test_query_resource("http://mugshot.org/o/user/USER2", "aim");
+ g_assert(user2 != NULL);
+
+ buddy1 = ddm_data_model_lookup_resource(model, "online-desktop:/o/pidgin-buddy/AIM.JohnDoe1");
+ g_assert(buddy1 != NULL);
+
+ /* Test that the rule was computed on initial data load */
+
+ ddm_data_resource_get(buddy1,
+ "user", DDM_DATA_RESOURCE, &user,
+ NULL);
+ g_assert(user == user1);
+
+ /* Try changing the source property, check that the rule-property gets unset */
+
+ value.type = DDM_DATA_STRING;
+ value.u.string = "JohnDoe2";
+
+ ddm_data_resource_update_property(buddy1,
+ ddm_qname_get("online-desktop://p/o/buddy", "name"),
+ DDM_DATA_UPDATE_REPLACE, DDM_DATA_CARDINALITY_1,
+ FALSE, NULL,
+ &value);
+
+ test_flush();
+
+ ddm_data_resource_get(buddy1,
+ "user", DDM_DATA_RESOURCE, &user,
+ NULL);
+ g_assert(user == NULL);
+
+ /* Change it again in a way that will cause it to get reset */
+
+ value.type = DDM_DATA_STRING;
+ value.u.string = "SSCoolJ";
+
+ ddm_data_resource_update_property(buddy1,
+ ddm_qname_get("online-desktop://p/o/buddy", "name"),
+ DDM_DATA_UPDATE_REPLACE, DDM_DATA_CARDINALITY_1,
+ FALSE, NULL,
+ &value);
+
+ test_flush();
+
+ ddm_data_resource_get(buddy1,
+ "user", DDM_DATA_RESOURCE, &user,
+ NULL);
+ g_assert(user == user2);
+
+ /* Test our list valued rule */
+
+ ddm_data_resource_get(ddm_data_model_get_global_resource(model),
+ "aimBuddies", DDM_DATA_RESOURCE | DDM_DATA_LIST, &aimBuddies,
+ NULL);
+
+ g_assert(g_slist_length(aimBuddies) == 1);
+ g_assert(aimBuddies->data == buddy1);
+
+ return 0;
+}
Modified: dumbhippo/trunk/client/common/ddm/test-static-file-backend.c
===================================================================
--- dumbhippo/trunk/client/common/ddm/test-static-file-backend.c 2007-11-09 21:25:03 UTC (rev 6889)
+++ dumbhippo/trunk/client/common/ddm/test-static-file-backend.c 2007-11-09 23:06:59 UTC (rev 6890)
@@ -2,57 +2,12 @@
#include <string.h>
-#include "static-file-backend.h"
-#include "ddm-data-query.h"
+#include "test-utils.h"
-static void
-on_query_result (DDMDataResource *result,
- gpointer user_data)
-{
- DDMDataResource **result_location = user_data;
- *result_location = result;
-}
-
-static void
-on_query_error (DDMDataError error,
- const char *message,
- gpointer user_data)
-{
- const char **message_location = user_data;
-
- g_assert(message != NULL);
- *message_location = g_strdup(message);
-}
-
-static DDMDataResource *
-query_resource(DDMDataModel *model,
- const char *resource_id,
- const char *fetch)
-{
- DDMDataQuery *query;
- DDMDataResource *result = NULL;
- const char *error = NULL;
-
- query = ddm_data_model_query_resource_by_id(model, resource_id, fetch);
- ddm_data_query_set_single_handler(query, on_query_result, &result);
- ddm_data_query_set_error_handler(query, on_query_error, &error);
-
- while (ddm_data_model_needs_flush(model))
- ddm_data_model_flush(model);
-
- if (error != NULL)
- g_error("Error from getResource, resource_id=%s, fetch=%s: %s", resource_id, fetch, error);
-
- return result;
-}
-
int
main(int argc, char **argv)
{
- GError *error = NULL;
DDMDataModel *model;
- const char *srcdir;
- char *filename;
DDMDataResource *result;
DDMDataResource *user1;
@@ -61,21 +16,10 @@
GSList *contacts;
GSList *contacters;
- g_type_init();
+ model = test_init(FALSE);
- srcdir = g_getenv("DDM_SRCDIR");
- if (srcdir == NULL)
- g_error("DDM_SRCDIR is not set");
+ result = test_query_resource("http://mugshot.org/o/user/USER1", "name;contacts;contacters");
- filename = g_build_filename(srcdir, "test-data.xml", NULL);
- model = ddm_static_file_model_new(filename, &error);
- if (model == NULL)
- g_error("Failed to create test model: %s", error->message);
-
- g_free(filename);
-
- result = query_resource(model, "http://mugshot.org/o/user/USER1", "name;contacts;contacters");
-
user1 = ddm_data_model_lookup_resource(model, "http://mugshot.org/o/user/USER1");
g_assert(user1 != NULL);
Added: dumbhippo/trunk/client/common/ddm/test-utils.c
===================================================================
--- dumbhippo/trunk/client/common/ddm/test-utils.c 2007-11-09 21:25:03 UTC (rev 6889)
+++ dumbhippo/trunk/client/common/ddm/test-utils.c 2007-11-09 23:06:59 UTC (rev 6890)
@@ -0,0 +1,89 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+
+#include "test-utils.h"
+#include "ddm-data-query.h"
+
+static DDMDataModel *model;
+
+DDMDataModel *
+test_init (gboolean load_local)
+{
+ GError *error = NULL;
+ const char *srcdir;
+ char *filename;
+
+ g_type_init();
+
+ srcdir = g_getenv("DDM_SRCDIR");
+ if (srcdir == NULL)
+ g_error("DDM_SRCDIR is not set");
+
+ filename = g_build_filename(srcdir, "test-data.xml", NULL);
+ model = ddm_static_file_model_new(filename, &error);
+ if (model == NULL)
+ g_error("Failed to create test model: %s", error->message);
+
+ g_free(filename);
+
+ if (load_local) {
+ filename = g_build_filename(srcdir, "test-local-data.xml", NULL);
+ if (!ddm_static_load_local_file(filename, model, &error))
+ g_error("Failed to add_local data to test model: %s", error->message);
+
+ g_free(filename);
+ }
+
+ return model;
+}
+
+DDMDataModel *
+test_get_model(void)
+{
+ return model;
+}
+
+void
+test_flush (void)
+{
+ while (ddm_data_model_needs_flush(model))
+ ddm_data_model_flush(model);
+}
+
+static void
+on_query_result (DDMDataResource *result,
+ gpointer user_data)
+{
+ DDMDataResource **result_location = user_data;
+ *result_location = result;
+}
+
+static void
+on_query_error (DDMDataError error,
+ const char *message,
+ gpointer user_data)
+{
+ const char **message_location = user_data;
+
+ g_assert(message != NULL);
+ *message_location = g_strdup(message);
+}
+
+DDMDataResource *
+test_query_resource(const char *resource_id,
+ const char *fetch)
+{
+ DDMDataQuery *query;
+ DDMDataResource *result = NULL;
+ const char *error = NULL;
+
+ query = ddm_data_model_query_resource_by_id(model, resource_id, fetch);
+ ddm_data_query_set_single_handler(query, on_query_result, &result);
+ ddm_data_query_set_error_handler(query, on_query_error, &error);
+
+ test_flush();
+
+ if (error != NULL)
+ g_error("Error from getResource, resource_id=%s, fetch=%s: %s", resource_id, fetch, error);
+
+ return result;
+}
Added: dumbhippo/trunk/client/common/ddm/test-utils.h
===================================================================
--- dumbhippo/trunk/client/common/ddm/test-utils.h 2007-11-09 21:25:03 UTC (rev 6889)
+++ dumbhippo/trunk/client/common/ddm/test-utils.h 2007-11-09 23:06:59 UTC (rev 6890)
@@ -0,0 +1,19 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+
+#ifndef __TEST_UTILS_H__
+#define __TEST_UTILS_H__
+
+#include "static-file-backend.h"
+#include "ddm-data-query.h"
+
+G_BEGIN_DECLS
+
+DDMDataModel * test_init (gboolean load_local);
+DDMDataModel * test_get_model (void);
+void test_flush (void);
+DDMDataResource *test_query_resource (const char *resource_id,
+ const char *fetch);
+
+G_END_DECLS
+
+#endif /* __TEST_UTILS_H__ */
Modified: dumbhippo/trunk/client/common/hippo/hippo-data-model-backend.c
===================================================================
--- dumbhippo/trunk/client/common/hippo/hippo-data-model-backend.c 2007-11-09 21:25:03 UTC (rev 6889)
+++ dumbhippo/trunk/client/common/hippo/hippo-data-model-backend.c 2007-11-09 23:06:59 UTC (rev 6890)
@@ -162,7 +162,7 @@
DDM_GLOBAL_RESOURCE, DDM_GLOBAL_RESOURCE_CLASS);
value.type = DDM_DATA_BOOLEAN;
- value.u.string = FALSE;
+ value.u.boolean = FALSE;
ddm_data_resource_update_property(global_resource,
ddm_qname_get(DDM_GLOBAL_RESOURCE_CLASS, "online"),
Modified: dumbhippo/trunk/client/linux/Makefile-libddm.am
===================================================================
--- dumbhippo/trunk/client/linux/Makefile-libddm.am 2007-11-09 21:25:03 UTC (rev 6889)
+++ dumbhippo/trunk/client/linux/Makefile-libddm.am 2007-11-09 23:06:59 UTC (rev 6890)
@@ -58,6 +58,7 @@
$(COMMONSRCDIR)/ddm/ddm-local-client.c \
$(COMMONSRCDIR)/ddm/ddm-local-client.h \
$(COMMONSRCDIR)/ddm/ddm-notification-set.c \
+ $(COMMONSRCDIR)/ddm/ddm-rule.c \
$(COMMONSRCDIR)/ddm/ddm-rule.h \
$(COMMONSRCDIR)/ddm/ddm-qname.c \
$(COMMONSRCDIR)/ddm/ddm-work-item.c \
@@ -90,8 +91,11 @@
nodist_libddm_test_la_SOURCES = \
$(COMMONSRCDIR)/ddm/static-file-backend.c \
$(COMMONSRCDIR)/ddm/static-file-backend.h \
- $(COMMONSRCDIR)/ddm/static-file-parser.c
+ $(COMMONSRCDIR)/ddm/static-file-parser.c \
+ $(COMMONSRCDIR)/ddm/test-utils.c \
+ $(COMMONSRCDIR)/ddm/test-utils.h
+
######################################################################
# Test programs
@@ -101,6 +105,7 @@
test-condition-reduce \
test-multipart-fetch \
test-notification \
+ test-rules \
test-static-file-parser \
test-static-file-backend
@@ -139,6 +144,11 @@
nodist_test_notification_SOURCES=$(COMMONSRCDIR)/ddm/test-notification.c
+test_rules_CPPFLAGS = $(AM_CPPFLAGS) $(LIBDDM_CFLAGS) -DDDM_COMPILATION=1
+test_rules_LDADD=libddm-1.la libddm-test.la
+
+nodist_test_rules_SOURCES=$(COMMONSRCDIR)/ddm/test-rules.c
+
test_static_file_parser_CPPFLAGS = $(AM_CPPFLAGS) $(LIBDDM_CFLAGS) -DDDM_COMPILATION=1
test_static_file_parser_LDADD=libddm-1.la libddm-test.la
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]