[libgda] Initial creation of DataSourceManager object



commit cbfe042e86a8265582683908062c70c63fbdb658
Author: Vivien Malerba <malerba gnome-db org>
Date:   Wed Jul 14 14:01:26 2010 +0200

    Initial creation of DataSourceManager object

 tools/browser/data-manager/Makefile.am           |    4 +-
 tools/browser/data-manager/data-console.c        |   25 +-
 tools/browser/data-manager/data-source-manager.c |  458 ++++++++++++++++++++++
 tools/browser/data-manager/data-source-manager.h |   70 ++++
 tools/browser/data-manager/spec-editor.c         |  408 +++----------------
 tools/browser/data-manager/spec-editor.h         |   10 +-
 6 files changed, 614 insertions(+), 361 deletions(-)
---
diff --git a/tools/browser/data-manager/Makefile.am b/tools/browser/data-manager/Makefile.am
index 054eb53..208ed9c 100644
--- a/tools/browser/data-manager/Makefile.am
+++ b/tools/browser/data-manager/Makefile.am
@@ -31,7 +31,9 @@ libperspective_la_SOURCES = \
 	spec-editor.c \
 	spec-editor.h \
 	data-manager-perspective.h \
-	data-manager-perspective.c
+	data-manager-perspective.c \
+	data-source-manager.h \
+	data-source-manager.c
 
 $(OBJECTS): marshal.c marshal.h
 
diff --git a/tools/browser/data-manager/data-console.c b/tools/browser/data-manager/data-console.c
index 78d1984..19b42a0 100644
--- a/tools/browser/data-manager/data-console.c
+++ b/tools/browser/data-manager/data-console.c
@@ -34,6 +34,7 @@
 #include "../common/popup-container.h"
 #include <libgda/sql-parser/gda-sql-parser.h>
 #include <libgda-ui/libgda-ui.h>
+#include "data-source-manager.h"
 
 #define PAGE_XML 0
 #define PAGE_DATA 1
@@ -44,6 +45,8 @@ typedef enum {
 } LayoutType;
 
 struct _DataConsolePrivate {
+	DataSourceManager *mgr;
+
 	LayoutType layout_type;
 	BrowserConnection *bcnc;
 	GtkWidget *notebook;
@@ -129,6 +132,8 @@ data_console_dispose (GObject *object)
 			g_object_unref (dconsole->priv->bcnc);
 		if (dconsole->priv->agroup)
 			g_object_unref (dconsole->priv->agroup);
+		if (dconsole->priv->mgr)
+			g_object_unref (dconsole->priv->mgr);
 		g_free (dconsole->priv);
 		dconsole->priv = NULL;
 	}
@@ -173,7 +178,7 @@ static void execute_clicked_cb (GtkButton *button, DataConsole *dconsole);
 static void help_clicked_cb (GtkButton *button, DataConsole *dconsole);
 #endif
 static void spec_editor_toggled_cb (GtkToggleButton *button, DataConsole *dconsole);
-static void spec_editor_changed_cb (SpecEditor *sped, DataConsole *dconsole);
+static void data_source_mgr_changed_cb (DataSourceManager *mgr, DataConsole *dconsole);
 
 /**
  * data_console_new
@@ -190,6 +195,9 @@ data_console_new (BrowserConnection *bcnc)
 	dconsole = DATA_CONSOLE (g_object_new (DATA_CONSOLE_TYPE, NULL));
 
 	dconsole->priv->bcnc = g_object_ref (bcnc);
+	dconsole->priv->mgr = data_source_manager_new (bcnc);
+	g_signal_connect (dconsole->priv->mgr, "changed",
+			  G_CALLBACK (data_source_mgr_changed_cb), dconsole);
 	
 	/* header */
         GtkWidget *label;
@@ -255,9 +263,7 @@ data_console_new (BrowserConnection *bcnc)
 	hbox = gtk_hbox_new (FALSE, 0);
 	gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
 
-	dconsole->priv->sped = spec_editor_new (dconsole->priv->bcnc);
-	g_signal_connect (dconsole->priv->sped, "changed",
-			  G_CALLBACK (spec_editor_changed_cb), dconsole);
+	dconsole->priv->sped = spec_editor_new (dconsole->priv->mgr);
 	gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (dconsole->priv->sped), TRUE, TRUE, 0);
 
 #define DEFAULT_XML \
@@ -359,7 +365,8 @@ execute_clicked_cb (GtkButton *button, DataConsole *dconsole)
 static void
 help_clicked_cb (GtkButton *button, DataConsole *dconsole)
 {
-	browser_show_help ((GtkWindow*) gtk_widget_get_toplevel (dconsole), "data-manager-perspective");
+	browser_show_help ((GtkWindow*) gtk_widget_get_toplevel ((GtkWidget*) dconsole),
+			   "data-manager-perspective");
 }
 #endif
 
@@ -382,7 +389,7 @@ spec_editor_toggled_cb (GtkToggleButton *button, DataConsole *dconsole)
 }
 
 static void
-spec_editor_changed_cb (SpecEditor *sped, DataConsole *dconsole)
+data_source_mgr_changed_cb (DataSourceManager *mgr, DataConsole *dconsole)
 {
 	if (dconsole->priv->params_form) {
 		gtk_widget_destroy (dconsole->priv->params_form);
@@ -391,7 +398,7 @@ spec_editor_changed_cb (SpecEditor *sped, DataConsole *dconsole)
 
 	GdaSet *params;
 	gboolean show_variables = FALSE;
-	params = spec_editor_get_params (sped);
+	params = data_source_manager_get_params (mgr);
 	if (params) {
 		dconsole->priv->params_form = gdaui_basic_form_new (params);
 		g_object_set ((GObject*) dconsole->priv->params_form,
@@ -462,7 +469,7 @@ compose_mode_toggled_cb (GtkToggleAction *action, DataConsole *dconsole)
 		/* Get Data sources */
 		GArray *sources_array;
 		GError *lerror = NULL;
-		sources_array = spec_editor_get_sources_array (dconsole->priv->sped, &lerror);
+		sources_array = data_source_manager_get_sources_array (dconsole->priv->mgr, &lerror);
 		if (sources_array) {
 			if (dconsole->priv->data) {
 				/* destroy existing data widgets */
@@ -472,7 +479,7 @@ compose_mode_toggled_cb (GtkToggleAction *action, DataConsole *dconsole)
 
 			GtkWidget *wid;
 			wid = create_widget (dconsole, sources_array, &lerror);
-			spec_editor_destroy_sources_array (sources_array);
+			data_source_manager_destroy_sources_array (sources_array);
 			if (wid) {
 				dconsole->priv->data = wid;
 				gtk_box_pack_start (GTK_BOX (dconsole->priv->data_box), wid, TRUE, TRUE, 0);
diff --git a/tools/browser/data-manager/data-source-manager.c b/tools/browser/data-manager/data-source-manager.c
new file mode 100644
index 0000000..18be2e7
--- /dev/null
+++ b/tools/browser/data-manager/data-source-manager.c
@@ -0,0 +1,458 @@
+/*
+ * Copyright (C) 2010 Vivien Malerba
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+#include "browser-connection.h"
+#include <libgda/thread-wrapper/gda-thread-wrapper.h>
+#include "support.h"
+#include "marshal.h"
+#include <sql-parser/gda-sql-parser.h>
+#include <libgda/gda-data-model-extra.h>
+#include <libgda/gda-sql-builder.h>
+
+#include "data-source-manager.h"
+
+
+/* signals */
+enum {
+	CHANGED,
+	LAST_SIGNAL
+};
+
+gint data_source_manager_signals [LAST_SIGNAL] = { 0 };
+
+/* 
+ * Main static functions 
+ */
+static void data_source_manager_class_init (DataSourceManagerClass *klass);
+static void data_source_manager_init (DataSourceManager *mgr);
+static void data_source_manager_dispose (GObject *object);
+
+/* get a pointer to the parents to be able to call their destructor */
+static GObjectClass  *parent_class = NULL;
+
+struct _DataSourceManagerPrivate {
+	BrowserConnection *bcnc;
+	GSList *sources_list;
+        GdaSet *params; /* execution params */
+};
+
+GType
+data_source_manager_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		static GStaticMutex registering = G_STATIC_MUTEX_INIT;
+		static const GTypeInfo info = {
+			sizeof (DataSourceManagerClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) data_source_manager_class_init,
+			NULL,
+			NULL,
+			sizeof (DataSourceManager),
+			0,
+			(GInstanceInitFunc) data_source_manager_init
+		};
+
+		
+		g_static_mutex_lock (&registering);
+		if (type == 0)
+			type = g_type_register_static (G_TYPE_OBJECT, "DataSourceManager", &info, 0);
+		g_static_mutex_unlock (&registering);
+	}
+	return type;
+}
+
+static void
+data_source_manager_class_init (DataSourceManagerClass *klass)
+{
+	GObjectClass   *object_class = G_OBJECT_CLASS (klass);
+	parent_class = g_type_class_peek_parent (klass);
+
+	/* signals */
+	data_source_manager_signals [CHANGED] =
+                g_signal_new ("changed",
+                              G_TYPE_FROM_CLASS (object_class),
+                              G_SIGNAL_RUN_FIRST,
+                              G_STRUCT_OFFSET (DataSourceManagerClass, changed),
+                              NULL, NULL,
+                              _dm_marshal_VOID__VOID, G_TYPE_NONE, 0);
+
+	object_class->dispose = data_source_manager_dispose;
+}
+
+static void
+data_source_manager_init (DataSourceManager *mgr)
+{
+	mgr->priv = g_new0 (DataSourceManagerPrivate, 1);
+}
+
+static void
+data_source_manager_dispose (GObject *object)
+{
+	DataSourceManager *mgr;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (IS_DATA_SOURCE_MANAGER (object));
+
+	mgr = DATA_SOURCE_MANAGER (object);
+	if (mgr->priv) {
+		if (mgr->priv->params)
+			g_object_unref (mgr->priv->params);
+
+		if (mgr->priv->sources_list) {
+			g_slist_foreach (mgr->priv->sources_list, (GFunc) g_object_unref, NULL);
+			g_slist_free (mgr->priv->sources_list);
+			mgr->priv->sources_list = NULL;
+		}
+
+		if (mgr->priv->bcnc)
+			g_object_unref (mgr->priv->bcnc);
+
+		g_free (mgr->priv);
+		mgr->priv = NULL;
+	}
+
+	/* parent class */
+	parent_class->dispose (object);
+}
+
+/**
+ * data_source_manager_new
+ * @bcnc:
+ *
+ * Creates a new #DataSourceManager object
+ *
+ * Returns: a new object
+ */
+DataSourceManager*
+data_source_manager_new (BrowserConnection *bcnc)
+{
+	DataSourceManager *mgr;
+	g_return_val_if_fail (BROWSER_IS_CONNECTION (bcnc), NULL);
+
+	mgr = DATA_SOURCE_MANAGER (g_object_new (DATA_SOURCE_MANAGER_TYPE, NULL));
+	mgr->priv->bcnc = g_object_ref (bcnc);
+
+	return mgr;
+}
+
+/*
+ * Tells if @source1 has an import which can be satisfied by an export in @source2
+ * Returns: %TRUE if there is a dependency
+ */
+static gboolean
+source_depends_on (DataSource *source1, DataSource *source2)
+{
+	GdaSet *import;
+	import = data_source_get_import (source1);
+	if (!import) {
+		g_print ("[%s] has no import\n",
+			 data_source_get_title (source1));
+		return FALSE;
+	}
+
+	GSList *holders;
+	GHashTable *export_columns;
+	export_columns = data_source_get_export_columns (source2);
+	for (holders = import->holders; holders; holders = holders->next) {
+		GdaHolder *holder = (GdaHolder*) holders->data;
+		if (GPOINTER_TO_INT (g_hash_table_lookup (export_columns, gda_holder_get_id (holder))) >= 1) {
+			g_print ("[%s] ====> [%s]\n",
+				 data_source_get_title (source1),
+				 data_source_get_title (source2));
+			return TRUE;
+		}
+	}
+	g_print ("[%s] ..... [%s]\n",
+		 data_source_get_title (source1),
+		 data_source_get_title (source2));
+	return FALSE;
+}
+
+
+static gint
+data_source_compare_func (DataSource *s1, DataSource *s2)
+{
+	if (source_depends_on (s1, s2))
+		return 1;
+	else if (source_depends_on (s2, s1))
+		return -1;
+	else
+		return 0;
+}
+
+/**
+ * data_source_manager_add_source
+ * @mgr:
+ * @source:
+ */
+void
+data_source_manager_add_source (DataSourceManager *mgr, DataSource *source)
+{
+	g_return_if_fail (IS_DATA_SOURCE_MANAGER (mgr));
+	g_return_if_fail (IS_DATA_SOURCE (source));
+
+	g_return_if_fail (! g_slist_find (mgr->priv->sources_list, source));
+	mgr->priv->sources_list = g_slist_insert_sorted (mgr->priv->sources_list,
+							 g_object_ref (source),
+							 (GCompareFunc) data_source_compare_func);
+	g_signal_emit (mgr, data_source_manager_signals[CHANGED], 0);
+
+	GSList *list;
+	gint i;
+	for (i = 0, list = mgr->priv->sources_list; list; list = list->next, i++) {
+		DataSource *source = DATA_SOURCE (list->data);
+		g_print ("\t %d ... %s\n", i, 
+		 data_source_get_title (source));
+	}
+}
+
+/**
+ * data_source_manager_remove_all
+ * @mgr:
+ */
+void
+data_source_manager_remove_all (DataSourceManager *mgr)
+{
+	g_return_if_fail (IS_DATA_SOURCE_MANAGER (mgr));
+
+	if (mgr->priv->sources_list) {
+		GSList *list;
+		list = mgr->priv->sources_list;
+		mgr->priv->sources_list = NULL;
+		g_signal_emit (mgr, data_source_manager_signals[CHANGED], 0);
+
+		g_slist_foreach (list, (GFunc) g_object_unref, NULL);
+		g_slist_free (list);
+	}
+}
+
+/**
+ * data_source_manager_remove_source
+ * @mgr:
+ * @source:
+ */
+void
+data_source_manager_remove_source (DataSourceManager *mgr, DataSource *source)
+{
+	g_return_if_fail (IS_DATA_SOURCE_MANAGER (mgr));
+	g_return_if_fail (IS_DATA_SOURCE (source));
+
+	g_return_if_fail (g_slist_find (mgr->priv->sources_list, source));
+	mgr->priv->sources_list = g_slist_remove (mgr->priv->sources_list, source);
+	g_signal_emit (mgr, data_source_manager_signals[CHANGED], 0);
+	g_object_unref (source);
+}
+
+
+static void
+compute_params (DataSourceManager *mgr)
+{
+	/* cleanning process */
+	if (mgr->priv->params) {
+		browser_connection_keep_variables (mgr->priv->bcnc, mgr->priv->params);
+		g_object_unref (mgr->priv->params);
+        }
+        mgr->priv->params = NULL;
+	
+	/* compute new params */
+	if (mgr->priv->sources_list) {
+		GSList *list;
+		for (list = mgr->priv->sources_list; list; list = list->next) {
+			DataSource *source;
+			GdaSet *set;
+			
+			source = DATA_SOURCE (list->data);
+			set = data_source_get_import (source);
+			if (!set)
+				continue;
+
+			GSList *holders;
+			gboolean found;
+			for (found = FALSE, holders = set->holders; holders; holders = holders->next) {
+				GSList *list2;
+				for (list2 = mgr->priv->sources_list; list2; list2 = list2->next) {
+					if (list2 == list)
+						continue;
+					GHashTable *export_h;
+					export_h = data_source_get_export_columns (DATA_SOURCE (list2->data));
+					if (g_hash_table_lookup (export_h, 
+					      gda_holder_get_id (GDA_HOLDER (holders->data)))) {
+						found = TRUE;
+						break;
+					}
+				}
+			}
+			if (! found) {
+				if (! mgr->priv->params)
+					mgr->priv->params = gda_set_copy (set);
+				else
+					gda_set_merge_with_set (mgr->priv->params, set);
+			}
+		}
+	}
+
+	browser_connection_load_variables (mgr->priv->bcnc, mgr->priv->params);
+}
+
+
+/**
+ * data_source_manager_get_params
+ * @mgr:
+ *
+ * Returns: a pointer to an internal #GdaSet, must not be modified
+ */
+GdaSet *
+data_source_manager_get_params (DataSourceManager *mgr)
+{
+	g_return_val_if_fail (IS_DATA_SOURCE_MANAGER (mgr), NULL);
+
+	compute_params (mgr);
+	return mgr->priv->params;
+}
+
+
+/**
+ * data_source_manager_get_sources_array
+ * @mgr:
+ *
+ * No ref is actually held by any of these pointers, all refs to DataSource are held by
+ * the @sources_list pointers
+ *
+ * Returns: an array of arrays of pointer to the #DataSource objects
+ */
+GArray *
+data_source_manager_get_sources_array (DataSourceManager *mgr, GError **error)
+{
+	g_return_val_if_fail (IS_DATA_SOURCE_MANAGER (mgr), NULL);
+
+	GSList *list;
+	GArray *array = NULL;
+	g_print ("** Creating DataSource arrays\n");
+	for (list = mgr->priv->sources_list; list; list = list->next) {
+		DataSource *source;
+		source = DATA_SOURCE (g_object_ref (G_OBJECT (list->data)));
+		g_print ("Taking into account source [%s]\n",
+			 data_source_get_title (source));
+
+		GdaSet *import;
+		import = data_source_get_import (source);
+		if (!import) {
+			if (! array) {
+				array = g_array_new (FALSE, FALSE, sizeof (GArray*));
+				GArray *subarray = g_array_new (FALSE, FALSE, sizeof (DataSource*));
+				g_array_append_val (array, subarray);
+				g_array_append_val (subarray, source);
+			}
+			else {
+				GArray *subarray = g_array_index (array, GArray*, 0);
+				g_array_append_val (subarray, source);
+			}
+			continue;
+		}
+		
+		if (array) {
+			gint i;
+			gboolean dep_found = FALSE;
+			for (i = array->len - 1; i >= 0 ; i--) {
+				GArray *subarray = g_array_index (array, GArray*, i);
+				gint j;
+				for (j = 0; j < subarray->len; j++) {
+					DataSource *source2 = g_array_index (subarray, DataSource*, j);
+					g_print ("Source [%s] %s on source [%s]\n",
+						 data_source_get_title (source),
+						 source_depends_on (source, source2) ?
+						 "depends" : "does not depend",
+						 data_source_get_title (source2));
+					if (source_depends_on (source, source2)) {
+						dep_found = TRUE;
+						/* add source to column i+1 */
+						if (i == array->len - 1) {
+							GArray *subarray = g_array_new (FALSE, FALSE,
+											sizeof (DataSource*));
+							g_array_append_val (array, subarray);
+							g_array_append_val (subarray, source);
+						}
+						else {
+							GArray *subarray = g_array_index (array, GArray*, i+1);
+							g_array_append_val (subarray, source);
+						}
+						continue;
+					}
+				}
+
+				if (dep_found)
+					break;
+			}
+			if (! dep_found) {
+				/* add source to column 0 */
+				GArray *subarray = g_array_index (array, GArray*, 0);
+				g_array_append_val (subarray, source);
+			}
+		}
+		else {
+			/* add source to column 0 */
+			array = g_array_new (FALSE, FALSE, sizeof (GArray*));
+			GArray *subarray = g_array_new (FALSE, FALSE, sizeof (DataSource*));
+			g_array_append_val (array, subarray);
+			g_array_append_val (subarray, source);
+		}
+	}
+
+	g_print ("** DataSource arrays created\n");
+	return array;
+}
+
+/**
+ * data_source_manager_destroy_sources_array
+ */
+void
+data_source_manager_destroy_sources_array (GArray *array)
+{
+	gint i;
+	g_return_if_fail (array);
+	for (i = 0; i < array->len; i++) {
+		GArray *subarray;
+		subarray = g_array_index (array, GArray *, i);
+		gint j;
+		for (j = 0; j < subarray->len; j++) {
+			DataSource *source;
+			source = g_array_index (subarray, DataSource *, j);
+			g_object_unref (source);
+		}
+
+		g_array_free (subarray, TRUE);
+	}
+	g_array_free (array, TRUE);
+}
+
+/**
+ * data_source_manager_get_browser_cnc
+ * @mgr:
+ */
+BrowserConnection *
+data_source_manager_get_browser_cnc (DataSourceManager *mgr)
+{
+	g_return_val_if_fail (IS_DATA_SOURCE_MANAGER (mgr), NULL);
+	return mgr->priv->bcnc;
+}
diff --git a/tools/browser/data-manager/data-source-manager.h b/tools/browser/data-manager/data-source-manager.h
new file mode 100644
index 0000000..c5d320c
--- /dev/null
+++ b/tools/browser/data-manager/data-source-manager.h
@@ -0,0 +1,70 @@
+/* 
+ * Copyright (C) 2010 Vivien Malerba
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __DATA_SOURCE_MANAGER_H_
+#define __DATA_SOURCE_MANAGER_H_
+
+#include "../browser-connection.h"
+#include "data-source.h"
+
+G_BEGIN_DECLS
+
+#define DATA_SOURCE_MANAGER_TYPE          (data_source_manager_get_type())
+#define DATA_SOURCE_MANAGER(obj)          G_TYPE_CHECK_INSTANCE_CAST (obj, data_source_manager_get_type(), DataSourceManager)
+#define DATA_SOURCE_MANAGER_CLASS(klass)  G_TYPE_CHECK_CLASS_CAST (klass, data_source_manager_get_type (), DataSourceManagerClass)
+#define IS_DATA_SOURCE_MANAGER(obj)       G_TYPE_CHECK_INSTANCE_TYPE (obj, data_source_manager_get_type ())
+
+typedef struct _DataSourceManager DataSourceManager;
+typedef struct _DataSourceManagerClass DataSourceManagerClass;
+typedef struct _DataSourceManagerPrivate DataSourceManagerPrivate;
+
+/* struct for the object's data */
+struct _DataSourceManager
+{
+	GObject            object;
+	DataSourceManagerPrivate *priv;
+};
+
+/* struct for the object's class */
+struct _DataSourceManagerClass
+{
+	GObjectClass       parent_class;
+
+	/* signals */
+	void             (*changed) (DataSourceManager *mgr);
+};
+
+GType               data_source_manager_get_type            (void) G_GNUC_CONST;
+
+DataSourceManager  *data_source_manager_new                 (BrowserConnection *bcnc);
+void                data_source_manager_add_source          (DataSourceManager *mgr, DataSource *source);
+void                data_source_manager_remove_source       (DataSourceManager *mgr, DataSource *source);
+void                data_source_manager_remove_all          (DataSourceManager *mgr);
+
+GdaSet              *data_source_manager_get_params (DataSourceManager *mgr);
+BrowserConnection   *data_source_manager_get_browser_cnc (DataSourceManager *mgr);
+
+GArray              *data_source_manager_get_sources_array (DataSourceManager *mgr, GError **error);
+void                 data_source_manager_destroy_sources_array (GArray *array);
+
+
+G_END_DECLS
+
+#endif
diff --git a/tools/browser/data-manager/spec-editor.c b/tools/browser/data-manager/spec-editor.c
index 1532287..d5192c6 100644
--- a/tools/browser/data-manager/spec-editor.c
+++ b/tools/browser/data-manager/spec-editor.c
@@ -26,7 +26,6 @@
 #include "data-source.h"
 #include <libgda/libgda.h>
 #include "../support.h"
-#include "marshal.h"
 
 #ifdef HAVE_GTKSOURCEVIEW
   #ifdef GTK_DISABLE_SINGLE_INCLUDES
@@ -41,13 +40,11 @@
 #endif
 
 struct _SpecEditorPrivate {
-	BrowserConnection *bcnc;
+	DataSourceManager *mgr;
 
 	SpecEditorMode mode;
 	GtkNotebook *notebook;
 
-        GdaSet *params; /* execution params */
-
 	/* reference for all views */
 	xmlDocPtr doc;
 
@@ -66,12 +63,6 @@ static void spec_editor_class_init (SpecEditorClass *klass);
 static void spec_editor_init       (SpecEditor *sped, SpecEditorClass *klass);
 static void spec_editor_dispose    (GObject *object);
 
-enum {
-	CHANGED,
-        LAST_SIGNAL
-};
-
-static guint spec_editor_signals[LAST_SIGNAL] = { 0 };
 static GObjectClass *parent_class = NULL;
 
 /*
@@ -84,15 +75,6 @@ spec_editor_class_init (SpecEditorClass *klass)
 
 	parent_class = g_type_class_peek_parent (klass);
 
-	/* signals */
-        spec_editor_signals [CHANGED] =
-                g_signal_new ("changed",
-                              G_TYPE_FROM_CLASS (object_class),
-                              G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (SpecEditorClass, changed),
-                              NULL, NULL,
-                              _dm_marshal_VOID__VOID, G_TYPE_NONE, 0);
-
 	object_class->dispose = spec_editor_dispose;
 }
 
@@ -137,10 +119,8 @@ spec_editor_dispose (GObject *object)
 	if (sped->priv) {
 		if (sped->priv->signal_editor_changed_id)
 			g_source_remove (sped->priv->signal_editor_changed_id);
-		if (sped->priv->params)
-			g_object_unref (sped->priv->params);
-		if (sped->priv->bcnc)
-			g_object_unref (sped->priv->bcnc);
+		if (sped->priv->mgr)
+			g_object_unref (sped->priv->mgr);
 
 		if (sped->priv->doc)
 			xmlFreeDoc (sped->priv->doc);
@@ -153,9 +133,65 @@ spec_editor_dispose (GObject *object)
 static gboolean
 signal_editor_changed (SpecEditor *sped)
 {
-	/* send signal */
-	g_signal_emit (sped, spec_editor_signals[CHANGED], 0);
+	/* modify the DataSourceManager */
+	data_source_manager_remove_all (sped->priv->mgr);
+
+	/* create new DataSource objects */
+	GError *lerror = NULL;
+	gchar *xml;
+	xmlDocPtr doc = NULL;
+	GtkTextIter start, end;
+	gtk_text_buffer_get_start_iter (sped->priv->buffer, &start);
+	gtk_text_buffer_get_end_iter (sped->priv->buffer, &end);
+	xml = gtk_text_buffer_get_text (sped->priv->buffer, &start, &end, FALSE);
+	if (xml) {
+		doc = xmlParseDoc (BAD_CAST xml);
+		g_free (xml);
+	}
+
+	if (!doc) {
+		TO_IMPLEMENT;
+		g_set_error (&lerror, 0, 0,
+			     _("Error parsing XML specifications"));
+		goto out;
+	}
+
+	xmlNodePtr node;
+	node = xmlDocGetRootElement (doc);
+	if (!node) {
+		/* nothing to do => finished */
+		xmlFreeDoc (doc);
+		goto out;
+	}
+
+	BrowserConnection *bcnc;
+	GdaSet *params;
+	
+	params = data_source_manager_get_params (sped->priv->mgr);
+	bcnc = data_source_manager_get_browser_cnc (sped->priv->mgr);
+	for (node = node->children; node; node = node->next) {
+		if (!strcmp ((gchar*) node->name, "table") ||
+		    !strcmp ((gchar*) node->name, "query")) {
+			DataSource *source;
+			source = data_source_new_from_xml_node (bcnc, node, &lerror);
+			if (!source) {
+				data_source_manager_remove_all (sped->priv->mgr);
+				TO_IMPLEMENT;
+				goto out;
+			}
+			
+			data_source_set_params (source, params);
+			data_source_manager_add_source (sped->priv->mgr, source);
+			g_object_unref (source);
+		}
+	}
+	xmlFreeDoc (doc);
 
+ out:
+	if (lerror) {
+		TO_IMPLEMENT;
+		g_clear_error (&lerror);
+	}
 	/* remove timeout */
 	sped->priv->signal_editor_changed_id = 0;
 	return FALSE;
@@ -175,15 +211,15 @@ editor_changed_cb (GtkTextBuffer *buffer, SpecEditor *sped)
  * Returns: the newly created editor.
  */
 SpecEditor *
-spec_editor_new (BrowserConnection *bcnc)
+spec_editor_new (DataSourceManager *mgr)
 {
 	SpecEditor *sped;
-	GtkWidget *sw, *nb, *exp, *vbox;
+	GtkWidget *sw, *nb, *vbox;
 
-	g_return_val_if_fail (BROWSER_IS_CONNECTION (bcnc), NULL);
+	g_return_val_if_fail (IS_DATA_SOURCE_MANAGER (mgr), NULL);
 
 	sped = g_object_new (SPEC_EDITOR_TYPE, NULL);
-	sped->priv->bcnc = g_object_ref (bcnc);
+	sped->priv->mgr = g_object_ref (mgr);
 
 	nb = gtk_notebook_new ();
 	gtk_box_pack_start (GTK_BOX (sped), nb, TRUE, TRUE, 0);
@@ -285,317 +321,3 @@ spec_editor_get_mode (SpecEditor *sped)
 	return sped->priv->mode;
 }
 
-static GArray *compute_sources (SpecEditor *sped, GError **error);
-static GSList *compute_sources_list (SpecEditor *sped, GError **error);
-
-static void
-compute_params (SpecEditor *sped)
-{
-	/* cleanning process */
-	if (sped->priv->params) {
-		browser_connection_keep_variables (sped->priv->bcnc, sped->priv->params);
-		g_object_unref (sped->priv->params);
-        }
-        sped->priv->params = NULL;
-	
-	/* compute new params */
-	GSList *sources_list;
-	sources_list = compute_sources_list (sped, NULL);
-	if (sources_list) {
-		GSList *list;
-		for (list = sources_list; list; list = list->next) {
-			DataSource *source;
-			GdaSet *set;
-			
-			source = DATA_SOURCE (list->data);
-			set = data_source_get_import (source);
-			if (!set)
-				continue;
-
-			GSList *holders;
-			gboolean found;
-			for (found = FALSE, holders = set->holders; holders; holders = holders->next) {
-				GSList *list2;
-				for (list2 = sources_list; list2; list2 = list2->next) {
-					if (list2 == list)
-						continue;
-					GHashTable *export_h;
-					export_h = data_source_get_export_columns (DATA_SOURCE (list2->data));
-					if (g_hash_table_lookup (export_h, 
-					      gda_holder_get_id (GDA_HOLDER (holders->data)))) {
-						found = TRUE;
-						break;
-					}
-				}
-			}
-			if (! found) {
-				if (! sped->priv->params)
-					sped->priv->params = gda_set_copy (set);
-				else
-					gda_set_merge_with_set (sped->priv->params, set);
-			}
-		}
-
-		/* cleanups */
-		g_slist_foreach (sources_list, (GFunc) g_object_unref, NULL);
-		g_slist_free (sources_list);
-		sources_list = NULL;
-	}
-
-	browser_connection_load_variables (sped->priv->bcnc, sped->priv->params);
-}
-
-/**
- * spec_editor_get_params
- *
- * Returns: a pointer to an internal #GdaSet, must not be modified
- */
-GdaSet *
-spec_editor_get_params (SpecEditor *sped)
-{
-	g_return_val_if_fail (IS_SPEC_EDITOR (sped), NULL);
-
-	compute_params (sped);
-	return sped->priv->params;
-}
-
-/**
- * spec_editor_get_sources_array
- */
-GArray *
-spec_editor_get_sources_array (SpecEditor *sped, GError **error)
-{
-	g_return_val_if_fail (IS_SPEC_EDITOR (sped), NULL);
-	if (sped->priv->signal_editor_changed_id > 0) {
-		g_source_remove (sped->priv->signal_editor_changed_id);
-		sped->priv->signal_editor_changed_id = 0;
-		compute_params (sped);
-	}
-	return compute_sources (sped, error);
-}
-
-/**
- * spec_editor_destroy_sources_array
- */
-void
-spec_editor_destroy_sources_array (GArray *array)
-{
-	gint i;
-	for (i = 0; i < array->len; i++) {
-		GArray *subarray;
-		subarray = g_array_index (array, GArray *, i);
-		gint j;
-		for (j = 0; j < subarray->len; j++) {
-			DataSource *source;
-			source = g_array_index (subarray, DataSource *, j);
-			g_object_unref (source);
-		}
-
-		g_array_free (subarray, TRUE);
-	}
-	g_array_free (array, TRUE);
-}
-
-/*
- * Tells if @source1 has an import which can be satisfied by an export in @source2
- * Returns: %TRUE if there is a dependency
- */
-static gboolean
-source_depends_on (DataSource *source1, DataSource *source2)
-{
-	GdaSet *import;
-	import = data_source_get_import (source1);
-	if (!import)
-		return FALSE;
-
-	GSList *holders;
-	GHashTable *export_columns;
-	export_columns = data_source_get_export_columns (source2);
-	for (holders = import->holders; holders; holders = holders->next) {
-		GdaHolder *holder = (GdaHolder*) holders->data;
-		if (GPOINTER_TO_INT (g_hash_table_lookup (export_columns, gda_holder_get_id (holder))) >= 1)
-			return TRUE;
-	}
-	return FALSE;
-}
-
-/*
- * Returns: an array of arrays of pointer to the #DataSource objects
- *
- * No ref is actually held by any of these pointers, all refs to DataSource are held by
- * the @sources_list pointers
- */
-static GArray *
-create_sources_array (GSList *sources_list, GError **error)
-{
-	GSList *list;
-	GArray *array = NULL;
-	g_print ("** Creating DataSource arrays\n");
-	for (list = sources_list; list; list = list->next) {
-		DataSource *source;
-		source = DATA_SOURCE (g_object_ref (G_OBJECT (list->data)));
-		g_print ("Taking into account source [%s]\n",
-			 data_source_get_title (source));
-
-		GdaSet *import;
-		import = data_source_get_import (source);
-		if (!import) {
-			if (! array) {
-				array = g_array_new (FALSE, FALSE, sizeof (GArray*));
-				GArray *subarray = g_array_new (FALSE, FALSE, sizeof (DataSource*));
-				g_array_append_val (array, subarray);
-				g_array_append_val (subarray, source);
-			}
-			else {
-				GArray *subarray = g_array_index (array, GArray*, 0);
-				g_array_append_val (subarray, source);
-			}
-			continue;
-		}
-		
-		if (array) {
-			gint i;
-			gboolean dep_found = FALSE;
-			for (i = array->len - 1; i >= 0 ; i--) {
-				GArray *subarray = g_array_index (array, GArray*, i);
-				gint j;
-				for (j = 0; j < subarray->len; j++) {
-					DataSource *source2 = g_array_index (subarray, DataSource*, j);
-					g_print ("Source [%s] %s on source [%s]\n",
-						 data_source_get_title (source),
-						 source_depends_on (source, source2) ?
-						 "depends" : "does not depend",
-						 data_source_get_title (source2));
-					if (source_depends_on (source, source2)) {
-						dep_found = TRUE;
-						/* add source to column i+1 */
-						if (i == array->len - 1) {
-							GArray *subarray = g_array_new (FALSE, FALSE,
-											sizeof (DataSource*));
-							g_array_append_val (array, subarray);
-							g_array_append_val (subarray, source);
-						}
-						else {
-							GArray *subarray = g_array_index (array, GArray*, i+1);
-							g_array_append_val (subarray, source);
-						}
-						continue;
-					}
-				}
-
-				if (dep_found)
-					break;
-			}
-			if (! dep_found) {
-				/* add source to column 0 */
-				GArray *subarray = g_array_index (array, GArray*, 0);
-				g_array_append_val (subarray, source);
-			}
-		}
-		else {
-			/* add source to column 0 */
-			array = g_array_new (FALSE, FALSE, sizeof (GArray*));
-			GArray *subarray = g_array_new (FALSE, FALSE, sizeof (DataSource*));
-			g_array_append_val (array, subarray);
-			g_array_append_val (subarray, source);
-		}
-	}
-
-	g_print ("** DataSource arrays created\n");
-	return array;
-}
-
-static gint
-data_source_compare_func (DataSource *s1, DataSource *s2)
-{
-	if (source_depends_on (s1, s2))
-		return 1;
-	else if (source_depends_on (s2, s1))
-		return -1;
-	else
-		return 0;
-}
-
-static GSList *
-compute_sources_list (SpecEditor *sped, GError **error)
-{
-	gchar *xml;
-	xmlDocPtr doc = NULL;
-	GSList *sources_list = NULL;
-
-	/* create sources_list from XML */
-	GtkTextIter start, end;
-	gtk_text_buffer_get_start_iter (sped->priv->buffer, &start);
-	gtk_text_buffer_get_end_iter (sped->priv->buffer, &end);
-	xml = gtk_text_buffer_get_text (sped->priv->buffer, &start, &end, FALSE);
-	if (xml) {
-		doc = xmlParseDoc (BAD_CAST xml);
-		g_free (xml);
-	}
-
-	if (!doc) {
-		g_set_error (error, 0, 0,
-			     _("Error parsing XML specifications"));
-		goto onerror;
-	}
-
-	xmlNodePtr node;
-	node = xmlDocGetRootElement (doc);
-	if (!node) {
-		/* nothing to do => finished */
-		xmlFreeDoc (doc);
-		return NULL;
-	}
-
-	for (node = node->children; node; node = node->next) {
-		if (!strcmp ((gchar*) node->name, "table") ||
-		    !strcmp ((gchar*) node->name, "query")) {
-			DataSource *source;
-			source = data_source_new_from_xml_node (sped->priv->bcnc, node, error);
-			if (!source)
-				goto onerror;
-			
-			sources_list = g_slist_prepend (sources_list, source);
-			data_source_set_params (source, sped->priv->params);
-		}
-	}
-	xmlFreeDoc (doc);
-	doc = NULL;
-	return g_slist_sort (sources_list, (GCompareFunc) data_source_compare_func);
-
- onerror:
-	if (doc)
-		xmlFreeDoc (doc);
-	if (sources_list) {
-		g_slist_foreach (sources_list, (GFunc) g_object_unref, NULL);
-		g_slist_free (sources_list);
-	}
-	
-	return NULL;
-}
-
-static GArray *
-compute_sources (SpecEditor *sped, GError **error)
-{
-	GArray *sources_array = NULL;
-	GSList *sources_list;
-	GError *lerror = NULL;
-
-	sources_list = compute_sources_list (sped, &lerror);
-	if (!lerror)
-		sources_array = create_sources_array (sources_list, &lerror);
-
-	if (sources_list) {
-		g_slist_foreach (sources_list, (GFunc) g_object_unref, NULL);
-		g_slist_free (sources_list);
-		sources_list = NULL;
-	}
-
-	if (lerror) {
-		browser_show_error ((GtkWindow*) gtk_widget_get_toplevel ((GtkWidget*) sped),
-				    lerror && lerror->message ? lerror->message :_("Error parsing XML specifications"));
-		g_clear_error (&lerror);
-	}
-
-	return sources_array;
-}
diff --git a/tools/browser/data-manager/spec-editor.h b/tools/browser/data-manager/spec-editor.h
index 40485e9..da4fa8f 100644
--- a/tools/browser/data-manager/spec-editor.h
+++ b/tools/browser/data-manager/spec-editor.h
@@ -25,6 +25,7 @@
 
 #include <gtk/gtk.h>
 #include "../browser-connection.h"
+#include "data-source-manager.h"
 
 G_BEGIN_DECLS
 
@@ -46,9 +47,6 @@ struct _SpecEditor {
 
 struct _SpecEditorClass {
 	GtkVBoxClass parent_class;
-
-	/* signals */
-	void        (*changed) (SpecEditor *editor);
 };
 
 typedef enum {
@@ -58,17 +56,13 @@ typedef enum {
 
 
 GType       spec_editor_get_type   (void) G_GNUC_CONST;
-SpecEditor *spec_editor_new        (BrowserConnection *bcnc);
+SpecEditor *spec_editor_new        (DataSourceManager *mgr);
 
 void        spec_editor_set_xml_text (SpecEditor *sped, const gchar *xml);
 gchar      *spec_editor_get_xml_text (SpecEditor *sped);
 void        spec_editor_set_mode     (SpecEditor *sped, SpecEditorMode mode);
 SpecEditorMode spec_editor_get_mode  (SpecEditor *sped);
 
-GdaSet     *spec_editor_get_params   (SpecEditor *sped);
-GArray     *spec_editor_get_sources_array (SpecEditor *sped, GError **error);
-void        spec_editor_destroy_sources_array (GArray *array);
-
 G_END_DECLS
 
 #endif



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]