From 3bda15f90fa056ca06ec69829efc9fca2e158a86 Mon Sep 17 00:00:00 2001
From: Andrea Zagli <azagli@libero.it>
Date: Sun, 13 Mar 2016 16:47:25 +0100
Subject: [PATCH] Added function ZakGFlowModel::list_processes.

Started parsing of xml definition.
---
 .gitignore        |  2 ++
 src/commons.c     | 21 ++++++++++++
 src/commons.h     |  3 ++
 src/model.c       | 86 +++++++++++++++++++++++++++++++++++++++++++++--
 src/model.h       |  2 ++
 tests/Makefile.am |  6 +++-
 tests/model.c     | 52 ++++++++++++++++++++++++++++
 7 files changed, 168 insertions(+), 4 deletions(-)
 create mode 100644 tests/model.c

diff --git a/.gitignore b/.gitignore
index eb59166..235be29 100644
--- a/.gitignore
+++ b/.gitignore
@@ -51,3 +51,5 @@ intltool-*
 Rules-quot
 *.exe
 *.csv
+*.bpmn
+tests/model
\ No newline at end of file
diff --git a/src/commons.c b/src/commons.c
index 9503714..ef86469 100644
--- a/src/commons.c
+++ b/src/commons.c
@@ -27,3 +27,24 @@
 #endif
 
 #include "commons.h"
+
+xmlNodeSet
+*zak_gflow_commons_xml_search (xmlXPathContext *xpcontext, xmlNode *xnode_start, const xmlChar *xpath_expr)
+{
+	xmlXPathObject *xpresult;
+	xmlNodeSet *xnodeset;
+
+	xpcontext->node = xnode_start;
+	xpresult = xmlXPathEvalExpression (xpath_expr, xpcontext);
+	if (xpresult != NULL
+		&& !xmlXPathNodeSetIsEmpty (xpresult->nodesetval))
+		{
+			xnodeset = xpresult->nodesetval;
+		}
+	else
+		{
+			xnodeset = NULL;
+		}
+
+	return xnodeset;
+}
diff --git a/src/commons.h b/src/commons.h
index 1c52810..cfda9f5 100644
--- a/src/commons.h
+++ b/src/commons.h
@@ -21,10 +21,13 @@
 
 #include <glib-object.h>
 
+#include <libxml/xpath.h>
+
 
 G_BEGIN_DECLS
 
 
+xmlNodeSet *zak_gflow_commons_xml_search (xmlXPathContext *xpcontext, xmlNode *xnode_start, const xmlChar *xpath_expr);
 
 
 G_END_DECLS
diff --git a/src/model.c b/src/model.c
index e8cff4a..3e4cc49 100644
--- a/src/model.c
+++ b/src/model.c
@@ -24,13 +24,15 @@
 #include <gmodule.h>
 
 #include <libxml/xpath.h>
-
-#include "model.h"
+#include <libxml/xpathInternals.h>
 
 #ifdef G_OS_WIN32
 	#include <windows.h>
 #endif
 
+#include "commons.h"
+#include "model.h"
+
 static void zak_gflow_model_class_init (ZakGFlowModelClass *class);
 static void zak_gflow_model_init (ZakGFlowModel *zak_gflow_model);
 
@@ -48,6 +50,9 @@ static void zak_gflow_model_finalize (GObject *gobject);
 
 typedef struct
 	{
+		xmlDoc *xdoc;
+		xmlNode *xroot;
+		xmlXPathContext *xpcontext;
 	} ZakGFlowModelPrivate;
 
 G_DEFINE_TYPE_WITH_PRIVATE (ZakGFlowModel, zak_gflow_model, G_TYPE_OBJECT)
@@ -137,12 +142,54 @@ ZakGFlowModel
 	ZakGFlowModel *model;
 	ZakGFlowModelPrivate *priv;
 
+	xmlNode *root;
+
+	xmlNs *ns;
+	gchar *prefix;
+
 	g_return_val_if_fail (xmldoc != NULL, NULL);
 
 	model = ZAK_GFLOW_MODEL (g_object_new (zak_gflow_model_get_type (), NULL));
 
 	priv = zak_gflow_model_get_instance_private (model);
 
+	root = xmlDocGetRootElement (xmldoc);
+	if (root == NULL
+		|| xmlStrcmp (root->name, (const xmlChar *)"definitions"))
+		{
+			g_warning ("No valid root element.");
+		}
+	else
+		{
+			priv->xdoc = xmldoc;
+			priv->xroot = root;
+
+			/* registering namespaces */
+			priv->xpcontext = xmlXPathNewContext (priv->xdoc);
+
+			ns = priv->xroot->nsDef;
+			while (ns)
+				{
+					if (ns->prefix == NULL)
+						{
+							prefix = g_strdup ("bpmn");
+						}
+					else
+						{
+							prefix = g_strdup ((gchar *)ns->prefix);
+						}
+
+					if (xmlXPathRegisterNs (priv->xpcontext, (const xmlChar *)prefix, ns->href) != 0)
+						{
+							g_warning ("Error on registering namespace <%s>.", prefix);
+						}
+
+					g_free (prefix);
+
+					ns = ns->next;
+				}
+		}
+
 	return model;
 }
 
@@ -152,7 +199,7 @@ ZakGFlowModel
  *
  */
 ZakGFlowModel
-*zak_gflow_model_load_from_file (const gchar *filename)
+*zak_gflow_model_new_from_file (const gchar *filename)
 {
 	ZakGFlowModel *model;
 
@@ -169,6 +216,39 @@ ZakGFlowModel
 	return model;
 }
 
+/**
+ * zak_gflow_model_list_processes:
+ * @model:
+ *
+ */
+GPtrArray
+*zak_gflow_model_list_processes (ZakGFlowModel *model)
+{
+	GPtrArray *ar;
+	ZakGFlowModelPrivate *priv;
+
+	xmlNodeSet *xnodeset;
+
+	gint i;
+
+	ar = NULL;
+
+	priv = zak_gflow_model_get_instance_private (model);
+
+	xnodeset = zak_gflow_commons_xml_search (priv->xpcontext, priv->xroot, (const xmlChar *)"child::bpmn:process");
+	if (xnodeset != NULL
+		&& xnodeset->nodeNr > 0)
+		{
+			ar = g_ptr_array_new ();
+			for (i = 0; i < xnodeset->nodeNr; i++)
+				{
+					g_ptr_array_add (ar, g_strdup ((gchar *)xmlGetProp (xnodeset->nodeTab[i], (const xmlChar *)"id")));
+				}
+		}
+
+	return ar;
+}
+
 /* PRIVATE */
 static void
 zak_gflow_model_set_property (GObject *object,
diff --git a/src/model.h b/src/model.h
index 7bf009d..a3c7af1 100644
--- a/src/model.h
+++ b/src/model.h
@@ -43,6 +43,8 @@ struct _ZakGFlowModelClass
 ZakGFlowModel *zak_gflow_model_new_from_xml (xmlDoc *xmldoc);
 ZakGFlowModel *zak_gflow_model_new_from_file (const gchar *filename);
 
+GPtrArray *zak_gflow_model_list_processes (ZakGFlowModel *model);
+
 ZakGFlowInstance *zak_gflow_model_start (ZakGFlowModel *model, const gchar *model_id);
 
 
diff --git a/tests/Makefile.am b/tests/Makefile.am
index e1b5b22..431dda1 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -8,4 +8,8 @@ LIBS = $(ZAKGFLOW_LIBS) \
 
 LDADD = $(top_builddir)/src/libzakgflow.la
 
-noinst_PROGRAMS =
+noinst_PROGRAMS = \
+                  model
+
+EXTRADIST = \
+            diagram.bpmn
diff --git a/tests/model.c b/tests/model.c
new file mode 100644
index 0000000..c87eca1
--- /dev/null
+++ b/tests/model.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016 Andrea Zagli <azagli@libero.it>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "model.h"
+
+int
+main (int argc, char *argv[])
+{
+	ZakGFlowModel *model;
+	GPtrArray *processes;
+	gint i;
+
+	model = zak_gflow_model_new_from_file (argv[1]);
+	if (model == NULL)
+		{
+			g_warning ("No model loaded from xml file <%s>.", argv[1]);
+		}
+	else
+		{
+			processes = zak_gflow_model_list_processes (model);
+			if (processes != NULL
+				&& processes->len > 0)
+				{
+					printf ("PROCESSES\n");
+					for (i = 0; i < processes->len; i++)
+						{
+							printf (" - %s", (gchar *)g_ptr_array_index (processes, i));
+						}
+				}
+			else
+				{
+					g_warning ("No processes in xml file.");
+				}
+		}
+
+	return 0;
+}
-- 
2.49.0