#include <stdlib.h>
#include <string.h>

#include <time.h>

#include <libxml/tree.h>
#include <libxml/parser.h>
#include <libxml/xmlstring.h>
#include <libxml/xmlschemas.h>

#include <libxml/xpath.h>


#include "configuration.h"

#include "logger.h"
#include "utilities.h"

#include "MathsLibraryManager.h"

#include "problema.h"
#include "group.h"
#include "result.h"
#include "user.h"

#define PROBLEM_NODE "probleme"
#define GROUP_NODE   "group"
#define RESULTS_NODE "resultats"
#define USER_NODE    "user"

#define PROBLEM_SCHEMA "resources/problem.xsd"
#define GROUP_SCHEMA   "resources/group.xsd"
#define RESULT_SCHEMA  "resources/result.xsd"
#define USER_SCHEMA    "resources/user.xsd"

static boolean is_valid(const xmlDocPtr doc, const char *schema_filename) {
	xmlSchemaParserCtxtPtr parser_ctxt =
			xmlSchemaNewParserCtxt(schema_filename);
	if (parser_ctxt == NULL) {
		/* unable to create a parser context for the schema */
		return -1;
	}
	xmlSchemaPtr schema = xmlSchemaParse(parser_ctxt);
	if (schema == NULL) {
		/* the schema itself is not valid */
		xmlSchemaFreeParserCtxt(parser_ctxt);
		return -2;
	}
	xmlSchemaValidCtxtPtr valid_ctxt = xmlSchemaNewValidCtxt(schema);
	if (valid_ctxt == NULL) {
		/* unable to create a validation context for the schema */
		xmlSchemaFreeParserCtxt(parser_ctxt);
		xmlSchemaFree(schema);
		return -3;
	}

	xmlSchemaSetValidErrors(valid_ctxt, (xmlSchemaValidityErrorFunc) fprintf,
			(xmlSchemaValidityWarningFunc) fprintf, stderr);

	int is_valid = (xmlSchemaValidateDoc(valid_ctxt, doc) == 0);
	xmlSchemaFreeParserCtxt(parser_ctxt);
	xmlSchemaFree(schema);
	xmlSchemaFreeValidCtxt(valid_ctxt);
	/* force the return value to be non-negative on success */
	return is_valid ? 1 : 0;
}

static boolean prefix_node_iterate(xmlNodePtr node, Problema* problem,
		boolean(*callback)(xmlNodePtr, Problema*)) {
	xmlNodePtr n;

	for (n = node; n != NULL; n = n->next) {
		if (!callback(n, problem))
			return FALSE;

		if ((n->type == XML_ELEMENT_NODE) && (n->children != NULL)) {
			if (!prefix_node_iterate(n->children, problem, callback))
				return FALSE;
		}
	}

	return TRUE;
}

static boolean buildProblem(xmlNodePtr cursor, Problema *problem) {
	xmlNodePtr deepcursor = NULL;

	xmlChar *xmlBuffer = NULL;

	logMessage(DEBUG2, "iterate node", (char *) cursor->name);

	if (!strcmp((const char *) cursor->name, PROBLEM_NODE)) {

		xmlBuffer = xmlGetProp(cursor, (const xmlChar *) "id");
		logMessage(DEBUG3, "checking 'id' attribute", (char *) xmlBuffer);
		problem->setId(problem, atoi((char *) xmlBuffer));
		xmlFree(xmlBuffer);

	} else if (!strcmp((const char *) cursor->name, "nom_probleme")) {

		logMessage(DEBUG3, "checking 'nom_probleme' node",
				(char *) cursor->name);
		/* 'nom_probleme' node */
		problem->name = (char *) xmlNodeGetContent(cursor);
		logMessage(DEBUG3, "checking node value", problem->name);

	} else if (!strcmp((const char *) cursor->name, "fonction")) {
		char *function_name = NULL;

		logMessage(DEBUG3, "checking 'fonction' node", (char *) cursor->name);

		/* 'fonction' node */
		deepcursor = cursor->xmlChildrenNode;
		while (deepcursor) {

			logMessage(DEBUG3, "iterate cursor", (char *) deepcursor->name);

			if (!strcmp((const char *) deepcursor->name,
					"representation-textuelle")) {

				logMessage(DEBUG3, "checking 'representation-textuelle' node",
						(char *) deepcursor->name);
				problem->functionRepresentation = (char *) xmlNodeGetContent(
						deepcursor);
				logMessage(DEBUG3, "checking node value",
						problem->functionRepresentation);

			} else if (!strcmp((const char *) deepcursor->name, "dimension")) {

				logMessage(DEBUG3, "checking 'dimension' node",
						(char *) deepcursor->name);
				xmlBuffer = xmlNodeGetContent(deepcursor);
				logMessage(DEBUG3, "checking node value", (char *) xmlBuffer);
				problem->_dimension = atoi((char *) xmlBuffer);
				xmlFree(xmlBuffer);

			} else if (!strcmp((const char *) deepcursor->name,
					"appel-fonction")) {

				logMessage(DEBUG3, "checking 'appel-fonction' node",
						(char *) deepcursor->name);
				function_name = (char *) xmlNodeGetContent(deepcursor);
				logMessage(DEBUG3, "checking node value", function_name);

			}

			deepcursor = deepcursor->next;
		}

		if (function_name) {
			problem->_function = loadProblemFunction(function_name);
			xmlFree(function_name);

			if (!problem->_function) {
				logMessage(SEVERE, "loadProblemFunction",
						"unable to load function from problem library");
				return FALSE;
			}

			logMessage(DEBUG2, "success",
					"function pointer successfully loaded from library");
		}

	} else if (!strcmp((const char *) cursor->name, "solution")) {
		logMessage(DEBUG3, "checking 'solution' node", (char *) cursor->name);
		int i = 0;

		problem->_solution = (double *) malloc(problem->_dimension
				* sizeof(double));
		deepcursor = cursor->xmlChildrenNode;
		while (deepcursor) {
			if (!strcmp((const char *) deepcursor->name, "point")) {
				logMessage(DEBUG3, "checking 'point' node",
						(char *) deepcursor->name);
				xmlBuffer = xmlNodeGetContent(deepcursor);
				logMessage(DEBUG3, "checking 'point' value node",
						(char *) xmlBuffer);
				problem->_solution[i] = atof((char *) xmlBuffer);
				xmlFree(xmlBuffer);
				i++;
			}
			deepcursor = deepcursor->next;
		}

		logMessage(DEBUG3, "checking fetched solution", printVector(
				problem->_solution, problem->_dimension));

	} else if (!strcmp((const char *) cursor->name, "contraintes")) {

		xmlNodePtr tag_cursor = NULL;

		logMessage(DEBUG3, "checking 'contraintes' node", (char *) cursor->name);
		/* 'contraintes' node */
		deepcursor = cursor->xmlChildrenNode;
		while (deepcursor) {

			if (!strcmp((const char *) deepcursor->name, "contrainte-egalite")
					|| !strcmp((const char *) deepcursor->name,
							"contrainte-inegalite")) {

				char *constraint_text = NULL;
				char *constraint_name = NULL;
				problem_constraint constraint = NULL;

				tag_cursor = deepcursor->xmlChildrenNode;
				while (tag_cursor) {

					logMessage(DEBUG3, "iterate cursor",
							(char *) tag_cursor->name);

					if (!strcmp((const char *) tag_cursor->name,
							"representation-textuelle")) {

						logMessage(DEBUG3,
								"checking 'representation-textuelle' node",
								(char *) tag_cursor->name);
						constraint_text
								= (char *) xmlNodeGetContent(tag_cursor);
						logMessage(DEBUG3, "checking node value",
								constraint_text);

					} else if (!strcmp((const char *) tag_cursor->name,
							"appel-fonction")) {

						logMessage(DEBUG3, "checking 'appel-fonction' node",
								(char *) tag_cursor->name);
						constraint_name
								= (char *) xmlNodeGetContent(tag_cursor);
						logMessage(DEBUG3, "checking node value",
								constraint_name);

					}

					tag_cursor = tag_cursor->next;
				}

				if (constraint_name) {
					constraint = loadConstraintFunction(constraint_name);
					if (!constraint) {
						logMessage(SEVERE, "loadProblemFunction",
								"unable to load constraint from library");
						xmlFree(constraint_text);
						xmlFree(constraint_name);
						return FALSE;
					}
					logMessage(DEBUG2, "success",
							"constraint pointer successfully loaded from library");
					if (!strcmp((const char *) deepcursor->name,
							"contrainte-egalite"))
						addConstraint(problem, constraint_text, EQUALITY,
								constraint);
					else
						addConstraint(problem, constraint_text, INEQUALITY,
								constraint);
					logMessage(DEBUG2, "success",
							"constraint successfully added to problem");
				}

				xmlFree(constraint_text);
				xmlFree(constraint_name);
			}

			deepcursor = deepcursor->next;
		}
	} else if (!strcmp((const char *) cursor->name, "derivees")) {

		xmlNodePtr tag_cursor = NULL;

		logMessage(DEBUG3, "checking 'derivees' node", (char *) cursor->name);
		/* 'derivees' node */
		deepcursor = cursor->xmlChildrenNode;
		while (deepcursor) {

			if (!strcmp((const char *) deepcursor->name, "derivee")) {
				logMessage(DEBUG3, "checking 'derivee' node",
						(char *) deepcursor->name);

				char *derivative_text = NULL;
				char *derivative_name = NULL;
				int ordre;
				problem_function derivative = NULL;

				xmlBuffer = xmlGetProp(deepcursor, (const xmlChar *) "ordre");
				ordre = atoi((char *) xmlBuffer);
				xmlFree(xmlBuffer);

				logMessage(DEBUG3, "checking ordre value", integerToString(
						ordre));

				tag_cursor = deepcursor->xmlChildrenNode;
				while (tag_cursor) {

					logMessage(DEBUG3, "iterate cursor",
							(char *) tag_cursor->name);

					if (!strcmp((const char *) tag_cursor->name,
							"representation-textuelle")) {

						logMessage(DEBUG3,
								"checking 'representation-textuelle' node",
								(char *) tag_cursor->name);
						derivative_text
								= (char *) xmlNodeGetContent(tag_cursor);
						logMessage(DEBUG3, "checking node value",
								derivative_text);

					} else if (!strcmp((const char *) tag_cursor->name,
							"appel-fonction")) {

						logMessage(DEBUG3, "checking 'appel-fonction' node",
								(char *) tag_cursor->name);
						derivative_name
								= (char *) xmlNodeGetContent(tag_cursor);
						logMessage(DEBUG3, "checking node value",
								derivative_name);

					}

					tag_cursor = tag_cursor->next;
				}

				if (derivative_name) {
					derivative = loadProblemFunction(derivative_name);
					if (!derivative) {
						sprintf(buffer,
								"unable to load %s derivative from library",
								derivative_name);
						logMessage(SEVERE, "loadProblemFunction", buffer);
						xmlFree(derivative_text);
						xmlFree(derivative_name);
						return FALSE;
					}
					logMessage(DEBUG2, "success",
							"derivative pointer successfully loaded from library");

					addDerivee(problem, derivative, ordre);
					logMessage(DEBUG2, "success",
							"derivative successfully added to problem");
				}

				xmlFree(derivative_text);
				xmlFree(derivative_name);
			}

			deepcursor = deepcursor->next;
		}
	}

	return TRUE;
}

static Problema* parseProblem(xmlDocPtr document) {
	xmlNodePtr root = NULL;
	xmlNodePtr cursor = NULL;

	xmlXPathContextPtr xpathContext = NULL;
	xmlXPathObjectPtr xpathNodeSet = NULL;

	xmlChar *xmlBuffer = NULL;

	Problema *problem = NULL;
	int i;

	logMessage(DEBUG1, "enter method", "parseProblem");

	handleError(
			!document,
			NULL,
			"illegal argument",
			"document is null");

	logMessage(DEBUG2, "parameter : document", (char *) (document->URL));

	handleError(
			is_valid(document,PROBLEM_SCHEMA) <= 0,
			NULL,
			"schema validation",
			"xml document not validate");

	/* Register all files included in XML file */
	xmlXPathInit();
	xpathContext = xmlXPathNewContext(document);
	xpathNodeSet = xmlXPathEval((const xmlChar *) "//chemin/text()",
			xpathContext);

	logMessage(DEBUG1, "xpath result length", integerToString(
			xmlXPathNodeSetGetLength(xpathNodeSet->nodesetval)));
	logMessage(DEBUG1, "xpath loop", "start");
	for (i = 0; i < xmlXPathNodeSetGetLength(xpathNodeSet->nodesetval); i++) {
		cursor = xmlXPathNodeSetItem(xpathNodeSet->nodesetval,i);
		if (cursor->type == XML_TEXT_NODE) {
			logMessage(DEBUG1, "xpath loop item name ", (char *) cursor->name);
			xmlBuffer = xmlNodeGetContent(cursor);
			logMessage(DEBUG1, "xpath loop item value", (char *) xmlBuffer);
			if (!putFunctionIntoProblemLibrary((char *) xmlBuffer)) {
				xmlFree(xmlBuffer);
				logMessage(SEVERE, "Xpath exploration error",
						"Needed source file wasn't found");
				return NULL;
			}
			xmlFree(xmlBuffer);
		}
	}
	logMessage(DEBUG1, "xpath loop", "end");

	xmlXPathFreeObject(xpathNodeSet);
	xmlXPathFreeContext(xpathContext);
	/* Register into problem library */

	//Done, now we just need to load from library, not adding recompile the library !

	problem = createProblemaSkeleton();

	root = xmlDocGetRootElement(document);

	if (!prefix_node_iterate(root, problem, buildProblem)) {
		logMessage(SEVERE, "parsing problem",
				"unexpected problem during parsing");
		destroyProblema(problem);
		logMessage(DEBUG3, "problem destruction", "Done.");
		return NULL;
	}

	sprintf(buffer, "problem : %p", problem);
	logMessage(DEBUG3, "exiting method", buffer);

	return problem;
}

static Group* parseGroup(xmlDocPtr document) {
	xmlNodePtr root = NULL;
	xmlNodePtr cursor = NULL;
	xmlNodePtr deepcursor = NULL;

	xmlChar *xmlBuffer = NULL;

	logMessage(DEBUG1, "enter method", "parseGroup");

	Group *group = NULL;

	handleError(
			!document,
			NULL,
			"illegal argument",
			"document is null");

	logMessage(DEBUG2, "parameter : document", (char *) (document->URL));

	handleError(
			is_valid(document,GROUP_SCHEMA) <= 0,
			NULL,
			"schema validation",
			"xml document not validate");

	logMessage(DEBUG2, "Schema validation", "document is valid");

	group = createGroupSkeleton();

	root = xmlDocGetRootElement(document);

	xmlBuffer = xmlGetProp(root, (const xmlChar *) "id");
	logMessage(DEBUG3, "checking 'id' attribute", (char *) xmlBuffer);
	group->setId(group, atoi((char *) xmlBuffer));
	xmlFree(xmlBuffer);

	xmlBuffer = xmlGetProp(root, (const xmlChar *) "name");
	logMessage(DEBUG3, "checking 'name' attribute", (char *) xmlBuffer);
	strcpy(group->_name, (char *) xmlBuffer);
	xmlFree(xmlBuffer);

	xmlBuffer = xmlGetProp(root, (const xmlChar *) "responsable");
	logMessage(DEBUG3, "checking 'responsable' attribute", (char *) xmlBuffer);
	group->_respo = atoi((char *) xmlBuffer);
	xmlFree(xmlBuffer);

	// Iterate over children
	cursor = root->xmlChildrenNode;
	while (cursor) {
		logMessage(DEBUG3, "iterate cursor", (char *) cursor->name);
		if (!strcmp((const char *) cursor->name, "users")) {
			logMessage(DEBUG3, "checking 'users' node", (char *) cursor->name);
			/* 'users' node */
			deepcursor = cursor->xmlChildrenNode;
			while (deepcursor) {
				logMessage(DEBUG3, "iterate cursor", (char *) deepcursor->name);
				if (!strcmp((const char *) deepcursor->name, "user")) {
					logMessage(DEBUG3, "checking 'user' node",
							(char *) deepcursor->name);
					xmlBuffer = xmlGetProp(deepcursor, (const xmlChar *) "id");
					logMessage(DEBUG3, "checking 'id' attribute",
							(char *) xmlBuffer);
					group->addUser(group, atoi((char *) xmlBuffer));
					xmlFree(xmlBuffer);
				}

				deepcursor = deepcursor->next;
			}
		} else if (!strcmp((const char *) cursor->name, "problems")) {
			logMessage(DEBUG3, "checking 'problems' node",
					(char *) cursor->name);
			/* 'problems' node */
			deepcursor = cursor->xmlChildrenNode;
			while (deepcursor) {
				logMessage(DEBUG3, "iterate cursor", (char *) deepcursor->name);
				if (!strcmp((const char *) deepcursor->name, "problem")) {
					logMessage(DEBUG3, "checking 'problem' node",
							(char *) deepcursor->name);
					xmlBuffer = xmlGetProp(deepcursor, (const xmlChar *) "id");
					logMessage(DEBUG3, "checking 'id' attribute",
							(char *) xmlBuffer);
					group->addProblem(group, atoi((char *) xmlBuffer));
					xmlFree(xmlBuffer);
				}

				deepcursor = deepcursor->next;
			}
		}

		cursor = cursor->next;
	}

	sprintf(buffer, "group : %p", group);
	logMessage(DEBUG3, "exiting method", buffer);

	return group;
}

void parseSimpleResult(xmlNodePtr resultSimpleNode, Result* result) {
	xmlChar* xmlBuffer;
	xmlNodePtr deepcursor;
	xmlNodePtr subcursor;

	logMessage(DEBUG3, "checking 'resultat-simple' node",
			(char *) resultSimpleNode->name);

	xmlBuffer = xmlGetProp(resultSimpleNode, (const xmlChar *) "id");
	result->setId(result, atoi((char *) xmlBuffer));
	xmlFree(xmlBuffer);

	logMessage(DEBUG3, "fetched id", integerToString(result->getId(result)));

	deepcursor = resultSimpleNode->xmlChildrenNode;
	while (deepcursor) {
		logMessage(DEBUG2, "iterate", (char *) deepcursor->name);
		if (!strcmp((const char *) deepcursor->name, "probleme")) {
			logMessage(DEBUG3, "checking 'probleme' node",
					(char *) deepcursor->name);

			xmlBuffer = xmlGetProp(deepcursor, (const xmlChar *) "id");
			result->setProblemId(result, atoi((char *) xmlBuffer));
			xmlFree(xmlBuffer);

			logMessage(DEBUG3, "fetched id", integerToString(
					result->getProblemId(result)));
		} else if (!strcmp((const char *) deepcursor->name, "methode")) {
			logMessage(DEBUG3, "checking 'methode' node",
					(char *) deepcursor->name);

			xmlBuffer = xmlGetProp(deepcursor, (const xmlChar *) "id");
			result->setMethodId(result, atoi((char *) xmlBuffer));
			xmlFree(xmlBuffer);

			logMessage(DEBUG3, "fetched id", integerToString(
					result->getMethodId(result)));
		} else if (!strcmp((const char *) deepcursor->name, "run_date")) {
			logMessage(DEBUG3, "checking 'methode' node",
					(char *) deepcursor->name);

			xmlBuffer = xmlNodeGetContent(deepcursor);
			logMessage(DEBUG3, "fetched content", (char *) xmlBuffer);

			logMessage(DEBUG3, "set", "initialize run date structure");
			memset(&(result->run_date), 0, sizeof(time_t));
			logMessage(DEBUG3, "set", "parsing date string");
			strptime((char *) xmlBuffer, "%Y-%m-%d", &(result->run_date));
			xmlFree(xmlBuffer);

			strftime(buffer, sizeof(buffer), "%Y-%m-%d", &(result->run_date));
			logMessage(DEBUG3, "fetched date", buffer);
		} else if (!strcmp((const char *) deepcursor->name, "point_depart")) {
			logMessage(DEBUG3, "checking 'point_depart' node",
					(char *) deepcursor->name);

			xmlXPathContextPtr xpathContext = NULL;
			xmlXPathObjectPtr xpathRes = NULL;

			logMessage(DEBUG3, "step 1", "created fake document");
			xmlDocPtr doc = xmlNewDoc((const xmlChar *) "1.0");
			xmlNodePtr copy = xmlCopyNode(deepcursor, 1);
			xmlDocSetRootElement(doc, copy);

			logMessage(DEBUG3, "step 2", "XPath setting");
			xmlXPathInit();
			xpathContext = xmlXPathNewContext(doc);
			xpathRes = xmlXPathEvalExpression(
					(const xmlChar *) "count(//point)", xpathContext);

			int vectorsize = xmlXPathCastToNumber(xpathRes);
			logMessage(DEBUG3, "fetched vector size", integerToString(
					vectorsize));

			logMessage(DEBUG3, "step 3", "freeing XPath data");
			xmlXPathFreeObject(xpathRes);
			xmlXPathFreeContext(xpathContext);
			xmlFreeDoc(doc);

			logMessage(DEBUG3, "step 4", "dump vector datas");
			result->_problem_dimension = vectorsize;
			result->_initial_vector = (double *) malloc(vectorsize
					* sizeof(double));

			subcursor = deepcursor->xmlChildrenNode;
			int i = 0;
			while (subcursor) {
				xmlBuffer = xmlNodeGetContent(subcursor);
				result->_initial_vector[i++] = atof((char *) xmlBuffer);
				xmlFree(xmlBuffer);
				subcursor = subcursor->next;
			}

			result->_data_loaded |= INITIAL_VECTOR_LOADED;

			logMessage(DEBUG3, "checking created vector", printVector(
					result->_initial_vector, result->_problem_dimension));
		} else if (!strcmp((const char *) deepcursor->name, "parametres")) {
			logMessage(DEBUG3, "checking 'parametres' node",
					(char *) deepcursor->name);

			subcursor = deepcursor->xmlChildrenNode;
			while (subcursor) {
				if (!strcmp((const char *) subcursor->name, "epsilon")) {
					xmlBuffer = xmlNodeGetContent(subcursor);
					double value = atof((char *) xmlBuffer);
					setParameterProperty(&(result->_initialParameters),
							EPSILON_LOADED, (void *) &value);

					sprintf(buffer, "checking '%s' node",
							(char*) subcursor->name);
					logMessage(DEBUG3, buffer, (char *) xmlBuffer);

					xmlFree(xmlBuffer);
				} else if (!strcmp((const char *) subcursor->name, "pas")) {
					xmlBuffer = xmlNodeGetContent(subcursor);
					double value = atof((char *) xmlBuffer);
					setParameterProperty(&(result->_initialParameters),
							STEP_LOADED, (void *) &value);

					sprintf(buffer, "checking '%s' node",
							(char*) subcursor->name);
					logMessage(DEBUG3, buffer, (char *) xmlBuffer);

					xmlFree(xmlBuffer);
				} else if (!strcmp((const char *) subcursor->name, "patience")) {
					xmlBuffer = xmlNodeGetContent(subcursor);
					int value = atoi((char *) xmlBuffer);
					setParameterProperty(&(result->_initialParameters),
							PATIENCE_LOADED, (void *) &value);

					sprintf(buffer, "checking '%s' node",
							(char*) subcursor->name);
					logMessage(DEBUG3, buffer, (char *) xmlBuffer);

					xmlFree(xmlBuffer);
				} else if (!strcmp((const char *) subcursor->name,
						"temperature")) {
					xmlBuffer = xmlNodeGetContent(subcursor);
					double value = atof((char *) xmlBuffer);
					setParameterProperty(&(result->_initialParameters),
							TEMPERATURE_LOADED, (void *) &value);

					sprintf(buffer, "checking '%s' node",
							(char*) subcursor->name);
					logMessage(DEBUG3, buffer, (char *) xmlBuffer);

					xmlFree(xmlBuffer);
				} else if (!strcmp((const char *) subcursor->name,
						"pas-exploration")) {
					xmlBuffer = xmlNodeGetContent(subcursor);
					double value = atof((char *) xmlBuffer);
					setParameterProperty(&(result->_initialParameters),
							NEIGHBOR_STEP_LOADED, (void *) &value);

					sprintf(buffer, "checking '%s' node",
							(char*) subcursor->name);
					logMessage(DEBUG3, buffer, (char *) xmlBuffer);

					xmlFree(xmlBuffer);
				} else if (!strcmp((const char *) subcursor->name,
						"maximum-iteration-par-niveau")) {
					xmlBuffer = xmlNodeGetContent(subcursor);
					int value = atoi((char *) xmlBuffer);
					setParameterProperty(&(result->_initialParameters),
							LEVEL_LIMIT_LOADED, (void *) &value);

					sprintf(buffer, "checking '%s' node",
							(char*) subcursor->name);
					logMessage(DEBUG3, buffer, (char *) xmlBuffer);

					xmlFree(xmlBuffer);
				} else if (!strcmp((const char *) subcursor->name,
						"taille-population")) {
					xmlBuffer = xmlNodeGetContent(subcursor);
					int value = atoi((char *) xmlBuffer);
					setParameterProperty(&(result->_initialParameters),
							POPULATION_SIZE_LOADED, (void *) &value);

					sprintf(buffer, "checking '%s' node",
							(char*) subcursor->name);
					logMessage(DEBUG3, buffer, (char *) xmlBuffer);

					xmlFree(xmlBuffer);
				} else if (!strcmp((const char *) subcursor->name,
						"probabilite-croisement")) {
					xmlBuffer = xmlNodeGetContent(subcursor);
					double value = atof((char *) xmlBuffer);
					setParameterProperty(&(result->_initialParameters),
							CROSS_PROBA_LOADED, (void *) &value);

					sprintf(buffer, "checking '%s' node",
							(char*) subcursor->name);
					logMessage(DEBUG3, buffer, (char *) xmlBuffer);

					xmlFree(xmlBuffer);
				} else if (!strcmp((const char *) subcursor->name,
						"probabilite-mutation")) {
					xmlBuffer = xmlNodeGetContent(subcursor);
					double value = atof((char *) xmlBuffer);
					setParameterProperty(&(result->_initialParameters),
							MUTATION_PROBA_LOADED, (void *) &value);

					sprintf(buffer, "checking '%s' node",
							(char*) subcursor->name);
					logMessage(DEBUG3, buffer, (char *) xmlBuffer);

					xmlFree(xmlBuffer);
				} else if (!strcmp((const char *) subcursor->name,
						"borne-superieure")) {
					xmlBuffer = xmlNodeGetContent(subcursor);
					double value = atof((char *) xmlBuffer);
					setParameterProperty(&(result->_initialParameters),
							BOUNDS_MAX_LOADED, (void *) &value);

					sprintf(buffer, "checking '%s' node",
							(char*) subcursor->name);
					logMessage(DEBUG3, buffer, (char *) xmlBuffer);

					xmlFree(xmlBuffer);
				} else if (!strcmp((const char *) subcursor->name,
						"borne-inferieure")) {
					xmlBuffer = xmlNodeGetContent(subcursor);
					double value = atof((char *) xmlBuffer);
					setParameterProperty(&(result->_initialParameters),
							BOUNDS_MIN_LOADED, (void *) &value);

					sprintf(buffer, "checking '%s' node",
							(char*) subcursor->name);
					logMessage(DEBUG3, buffer, (char *) xmlBuffer);

					xmlFree(xmlBuffer);
				}
				subcursor = subcursor->next;
			}

			result->_data_loaded |= INITIAL_PARAMETERS_LOADED;
		} else if (!strcmp((const char *) deepcursor->name,
				"point_valeur_optimisation")) {
			logMessage(DEBUG3, "checking 'point_valeur_optimisation' node",
					(char *) deepcursor->name);

			result->_result_vector = (double *) malloc(
					result->_problem_dimension * sizeof(double));

			subcursor = deepcursor->xmlChildrenNode;
			int i = 0;
			while (subcursor) {
				xmlBuffer = xmlNodeGetContent(subcursor);
				result->_result_vector[i++] = atof((char *) xmlBuffer);
				xmlFree(xmlBuffer);
				subcursor = subcursor->next;
			}

			result->_data_loaded |= RESULT_VECTOR_LOADED;

			logMessage(DEBUG3, "checking created vector", printVector(
					result->_result_vector, result->_problem_dimension));
		} else if (!strcmp((const char *) deepcursor->name, "valeur")) {
			logMessage(DEBUG3, "checking 'valeur' node",
					(char *) deepcursor->name);

			xmlBuffer = xmlNodeGetContent(deepcursor);
			result->_result_value = atof((char *) xmlBuffer);
			xmlFree(xmlBuffer);

			result->_data_loaded |= RESULT_VALUE_LOADED;

			logMessage(DEBUG3, "fetched value", doubleToString(
					result->_result_value));
		} else if (!strcmp((const char *) deepcursor->name,
				"complexite_iteration")) {
			logMessage(DEBUG3, "checking 'complexite_iteration' node",
					(char *) deepcursor->name);

			xmlBuffer = xmlNodeGetContent(deepcursor);
			result->_result_complexity = atoi((char *) xmlBuffer);
			xmlFree(xmlBuffer);

			result->_data_loaded |= RESULT_COMPLEXITY_LOADED;

			logMessage(DEBUG3, "fetched complexity", integerToString(
					result->_result_complexity));
		} else if (!strcmp((const char *) deepcursor->name, "erreur_absolue")) {
			logMessage(DEBUG3, "checking 'erreur_absolue' node",
					(char *) deepcursor->name);

			xmlBuffer = xmlNodeGetContent(deepcursor);
			result->_result_error = atof((char *) xmlBuffer);
			xmlFree(xmlBuffer);

			logMessage(DEBUG3, "fetched erreur_absolue", doubleToString(
					result->_result_error));
		}
		deepcursor = deepcursor->next;
	}
}

static ResultArray* parseResult(xmlDocPtr document) {
	xmlNodePtr root = NULL;
	xmlNodePtr cursor = NULL;
	xmlNodePtr deepcursor = NULL;

	xmlChar *xmlBuffer = NULL;

	logMessage(DEBUG1, "enter method", "parseResult");

	ResultArray* results = (ResultArray *) malloc(sizeof(ResultArray));
	results->size = 0;
	results->benchId = 0;
	memset(results->result, 0, MAX_ITEM * sizeof(Result *));

	handleError(
			!document,
			results,
			"illegal argument",
			"document is null");

	logMessage(DEBUG2, "parameter : document", (char *) (document->URL));

	handleError(
			is_valid(document,RESULT_SCHEMA) <= 0,
			results,
			"schema validation",
			"xml document not validate");

	logMessage(DEBUG2, "Schema validation", "document is valid");

	root = xmlDocGetRootElement(document);

	cursor = root->xmlChildrenNode;
	if (!strcmp((const char *) cursor->name, "resultat-simple")) {

		results->result[results->size] = createResultSkeleton();

		parseSimpleResult(cursor, results->result[results->size]);

		logMessage(DEBUG2, "fetch finished", "incremente array size");
		results->size++;
	} else if (!strcmp((const char *) cursor->name, "resultat-benchmark")) {
		xmlBuffer = xmlGetProp(cursor, (const xmlChar *) "id");
		results->benchId = atoi((char *) xmlBuffer);
		xmlFree(xmlBuffer);

		deepcursor = cursor->xmlChildrenNode;
		while (deepcursor) {
			if (!strcmp((const char *) deepcursor->name, "resultat-simple")) {
				results->result[results->size] = createResultSkeleton();
				parseSimpleResult(deepcursor, results->result[results->size]);
				results->size++;
			}
			deepcursor = deepcursor->next;
		}
	}

	sprintf(buffer, "results : %p", results);
	logMessage(DEBUG3, "exiting method", "");

	return results;
}

static User* parseUser(xmlDocPtr document) {
	xmlNodePtr root = NULL;
	xmlNodePtr cursor = NULL;
	xmlNodePtr deepcursor = NULL;

	xmlChar *xmlBuffer = NULL;

	logMessage(DEBUG1, "enter method", "parseGroup");

	User *user = NULL;

	handleError(
			!document,
			NULL,
			"illegal argument",
			"document is null");

	logMessage(DEBUG2, "parameter : document", (char *) (document->URL));

	handleError(
			is_valid(document,USER_SCHEMA) <= 0,
			NULL,
			"schema validation",
			"xml document not validate");

	logMessage(DEBUG2, "Schema validation", "document is valid");

	user = createUserSkeleton();

	root = xmlDocGetRootElement(document);

	xmlBuffer = xmlGetProp(root, (const xmlChar *) "id");
	logMessage(DEBUG3, "checking 'id' attribute", (char *) xmlBuffer);
	user->setId(user, atoi((char *) xmlBuffer));
	xmlFree(xmlBuffer);

	// Iterate over children
	cursor = root->xmlChildrenNode;
	while (cursor) {
		logMessage(DEBUG3, "iterate cursor", (char *) cursor->name);
		if (!strcmp((const char *) cursor->name, "login")) {
			logMessage(DEBUG3, "checking 'login' node", (char *) cursor->name);
			xmlBuffer = xmlNodeGetContent(cursor);

			user->setLogin(user, (char *) xmlBuffer);

			xmlFree(xmlBuffer);
		} else if (!strcmp((const char *) cursor->name, "password")) {

			logMessage(DEBUG3, "checking 'password' node",
					(char *) cursor->name);
			xmlBuffer = xmlNodeGetContent(cursor);

			user->setPassword(user, (char *) xmlBuffer);

			xmlFree(xmlBuffer);

		} else if (!strcmp((const char *) cursor->name, "groups")) {

			logMessage(DEBUG3, "checking 'groups' node", (char *) cursor->name);

			deepcursor = cursor->xmlChildrenNode;
			while (deepcursor) {
				if (!strcmp((const char *) deepcursor->name, "group")) {
					int groupid;
					int roleid;

					logMessage(DEBUG3, "checking 'group' node",
							(char *) deepcursor->name);

					xmlBuffer = xmlGetProp(deepcursor, (const xmlChar *) "id");
					logMessage(DEBUG3, "checking 'id' attribute",
							(char *) xmlBuffer);
					groupid = atoi((char *) xmlBuffer);
					xmlFree(xmlBuffer);
					xmlBuffer = xmlGetProp(deepcursor,
							(const xmlChar *) "associated-role-id");
					logMessage(DEBUG3,
							"checking 'associated-role-id' attribute",
							(char *) xmlBuffer);
					roleid = atoi((char *) xmlBuffer);
					xmlFree(xmlBuffer);

					user->addGroup(user, groupid, roleid);
				}

				deepcursor = deepcursor->next;
			}

		}

		cursor = cursor->next;
	}

	sprintf(buffer, "user : %p", user);
	logMessage(DEBUG3, "exiting method", buffer);

	return user;
}

char* writeProblemXML(Problema *problem) {

	xmlDocPtr doc = NULL;
	xmlNodePtr root = NULL;
	xmlNodePtr cursor = NULL;
	xmlNodePtr creationNode = NULL;

	xmlChar *xmlBufferData = NULL;
	int bufferDataSize = -1;

	ConstraintList *iterator = NULL;

	logMessage(DEBUG1, "entering method", "writeProblem XML");

	handleError(
			!problem,NULL,
			"illegal argument",
			"given problem is null");

	root = xmlNewNode(NULL, (const xmlChar *) PROBLEM_NODE);

	xmlSetProp(root, (const xmlChar *) "xmlns:xsi",
			(const xmlChar *) "http://www.w3.org/2001/XMLSchema-instance");
	xmlSetProp(root, (const xmlChar *) "xsi:noNamespaceSchemaLocation",
			(const xmlChar *) "resources/problem.xsd");

	// Setting id value as an attribute
	xmlSetProp(root, (const xmlChar *) "id", (const xmlChar *) integerToString(
			problem->getId(problem)));

	xmlNewTextChild(root, NULL, (const xmlChar *) "nom_probleme",
			(const xmlChar *) problem->name);

	//Creating fonction node
	creationNode = xmlNewNode(NULL, (const xmlChar *) "fonction");
	xmlAddChild(root, creationNode);

	//Writing function datas
	xmlNewTextChild(creationNode, NULL, (const xmlChar *) "dimension",
			(const xmlChar *) integerToString(problem->_dimension));

	xmlNewTextChild(creationNode, NULL,
			(const xmlChar *) "representation-textuelle",
			(const xmlChar *) problem->functionRepresentation);

	//Creating contraintes node
	creationNode = xmlNewNode(NULL, (const xmlChar *) "contraintes");
	xmlAddChild(root, creationNode);

	//writing constraint data
	cursor = creationNode;
	for (iterator = problem->_constraints; iterator; iterator = iterator->next) {
		switch (iterator->type) {
		case EQUALITY:
			creationNode = xmlNewNode(NULL,
					(const xmlChar *) "contrainte-egalite");
			break;
		case INEQUALITY:
			creationNode = xmlNewNode(NULL,
					(const xmlChar *) "contrainte-inegalite");
			break;
		}

		xmlNewTextChild(creationNode, NULL,
				(const xmlChar *) "representation-textuelle",
				(const xmlChar *) iterator->text);

		xmlAddChild(cursor, creationNode);
	}

	doc = xmlNewDoc((const xmlChar *) "1.0");

	xmlDocSetRootElement(doc, root);

	xmlDocDumpFormatMemoryEnc(doc, &xmlBufferData, &bufferDataSize, "UTF-8", 1); //Indent lines

	logMessage(DEBUG1, "exiting method", (char *) xmlBufferData);

	return (char *) xmlBufferData;
}

char* writeGroupXML(Group *group) {

	xmlDocPtr doc = NULL;
	xmlNodePtr root = NULL;
	xmlNodePtr cursor = NULL;
	xmlNodePtr creationNode = NULL;

	xmlChar *xmlBufferData = NULL;
	int bufferDataSize = -1;
	int i;

	logMessage(DEBUG1, "entering method", "write Group XML");

	handleError(
			!group,NULL,
			"illegal argument",
			"given group is null");

	root = xmlNewNode(NULL, (const xmlChar *) GROUP_NODE);

	xmlSetProp(root, (const xmlChar *) "xmlns:xsi",
			(const xmlChar *) "http://www.w3.org/2001/XMLSchema-instance");
	xmlSetProp(root, (const xmlChar *) "xsi:noNamespaceSchemaLocation",
			(const xmlChar *) "resources/group.xsd");

	// Setting id value as an attribute
	xmlSetProp(root, (const xmlChar *) "id", (const xmlChar *) integerToString(
			group->getId(group)));

	xmlSetProp(root, (const xmlChar *) "responsable",
			(const xmlChar *) integerToString(group->_respo));

	xmlSetProp(root, (const xmlChar *) "name", (const xmlChar *) group->_name);

	//Creating users node
	creationNode = xmlNewNode(NULL, (const xmlChar *) "users");
	xmlAddChild(root, creationNode);

	for (i = 0; i < group->_users.size; i++) {
		cursor = xmlNewNode(NULL, (const xmlChar *) "user");
		xmlSetProp(cursor, (const xmlChar *) "id",
				(const xmlChar *) integerToString(group->_users.ids[i]));
		xmlAddChild(creationNode, cursor);
	}
	//Creating problems node
	creationNode = xmlNewNode(NULL, (const xmlChar *) "problems");
	xmlAddChild(root, creationNode);

	for (i = 0; i < group->_problems.size; i++) {
		cursor = xmlNewNode(NULL, (const xmlChar *) "problem");
		xmlSetProp(cursor, (const xmlChar *) "id",
				(const xmlChar *) integerToString(group->_problems.ids[i]));
		xmlAddChild(creationNode, cursor);
	}

	doc = xmlNewDoc((const xmlChar *) "1.0");

	xmlDocSetRootElement(doc, root);

	xmlDocDumpFormatMemoryEnc(doc, &xmlBufferData, &bufferDataSize, "UTF-8", 1); //Indent lines

	logMessage(DEBUG1, "exiting method", (char *) xmlBufferData);

	return (char *) xmlBufferData;
}

static
void writeSimpleResult(xmlNodePtr root, Result *result) {
	xmlNodePtr cursor = NULL;
	xmlNodePtr creationNode = NULL;
	int i;

	logMessage(DEBUG1, "entering", "writeSimpleResultXML");
	logMessage(DEBUG1, "root parameter", (char *) root->name);
	sprintf(buffer, "%p", result);
	logMessage(DEBUG1, "result pointer", buffer);

	cursor = xmlNewNode(NULL, (const xmlChar *) "resultat-simple");
	xmlAddChild(root, cursor);

	// Setting id value as an attribute
	xmlSetProp(cursor, (const xmlChar *) "id",
			(const xmlChar *) integerToString(result->getId(result)));

	creationNode = xmlNewNode(NULL, (const xmlChar *) "probleme");
	xmlSetProp(creationNode, (const xmlChar *) "id",
			(const xmlChar *) integerToString(result->getProblemId(result)));
	xmlAddChild(cursor, creationNode);

	creationNode = xmlNewNode(NULL, (const xmlChar *) "methode");
	xmlSetProp(creationNode, (const xmlChar *) "id",
			(const xmlChar *) integerToString(result->getMethodId(result)));
	xmlAddChild(cursor, creationNode);

	strftime(buffer, sizeof(buffer), "%Y-%m-%d", &(result->run_date));
	logMessage(DEBUG3, "date buffer", buffer);
	xmlNewTextChild(cursor, NULL, (const xmlChar *) "run_date",
			(const xmlChar *) buffer);

	creationNode = xmlNewNode(NULL, (const xmlChar *) "point_depart");
	xmlAddChild(cursor, creationNode);
	for (i = 0; i < result->_problem_dimension; i++)
		xmlNewTextChild(creationNode, NULL, (const xmlChar *) "point",
				(const xmlChar *) doubleToString(result->_initial_vector[i]));

	creationNode = xmlNewNode(NULL, (const xmlChar *) "parametres");
	xmlAddChild(cursor, creationNode);

	if (result->_initialParameters.data_loaded & PATIENCE_LOADED)
		xmlNewTextChild(creationNode, NULL, (const xmlChar *) "patience",
				(const xmlChar *) integerToString(
						*((int *) getParameterProperty(
								result->_initialParameters, PATIENCE_LOADED))));
	if (result->_initialParameters.data_loaded & EPSILON_LOADED)
		xmlNewTextChild(creationNode, NULL, (const xmlChar *) "epsilon",
				(const xmlChar *) doubleToString(
						*((double *) getParameterProperty(
								result->_initialParameters, EPSILON_LOADED))));
	if (result->_initialParameters.data_loaded & BOUNDS_MIN_LOADED)
		xmlNewTextChild(
				creationNode,
				NULL,
				(const xmlChar *) "borne-inferieure",
				(const xmlChar *) doubleToString(
						*((double *) getParameterProperty(
								result->_initialParameters, BOUNDS_MIN_LOADED))));
	if (result->_initialParameters.data_loaded & BOUNDS_MAX_LOADED)
		xmlNewTextChild(
				creationNode,
				NULL,
				(const xmlChar *) "borne-superieure",
				(const xmlChar *) doubleToString(
						*((double *) getParameterProperty(
								result->_initialParameters, BOUNDS_MAX_LOADED))));
	if (result->_initialParameters.data_loaded & STEP_LOADED)
		xmlNewTextChild(creationNode, NULL, (const xmlChar *) "pas",
				(const xmlChar *) doubleToString(
						*((double *) getParameterProperty(
								result->_initialParameters, STEP_LOADED))));
	if (result->_initialParameters.data_loaded & TEMPERATURE_LOADED)
		xmlNewTextChild(
				creationNode,
				NULL,
				(const xmlChar *) "temperature",
				(const xmlChar *) doubleToString(
						*((double *) getParameterProperty(
								result->_initialParameters, TEMPERATURE_LOADED))));
	if (result->_initialParameters.data_loaded & NEIGHBOR_STEP_LOADED)
		xmlNewTextChild(creationNode, NULL,
				(const xmlChar *) "pas-exploration",
				(const xmlChar *) doubleToString(
						*((double *) getParameterProperty(
								result->_initialParameters,
								NEIGHBOR_STEP_LOADED))));
	if (result->_initialParameters.data_loaded & LEVEL_LIMIT_LOADED)
		xmlNewTextChild(
				creationNode,
				NULL,
				(const xmlChar *) "maximum-iteration-niveau",
				(const xmlChar *) integerToString(
						*((int *) getParameterProperty(
								result->_initialParameters, LEVEL_LIMIT_LOADED))));
	if (result->_initialParameters.data_loaded & POPULATION_SIZE_LOADED)
		xmlNewTextChild(creationNode, NULL,
				(const xmlChar *) "taille-population",
				(const xmlChar *) integerToString(
						*((int *) getParameterProperty(
								result->_initialParameters,
								POPULATION_SIZE_LOADED))));
	if (result->_initialParameters.data_loaded & CROSS_PROBA_LOADED)
		xmlNewTextChild(
				creationNode,
				NULL,
				(const xmlChar *) "probabilite-croisement",
				(const xmlChar *) doubleToString(
						*((double *) getParameterProperty(
								result->_initialParameters, CROSS_PROBA_LOADED))));
	if (result->_initialParameters.data_loaded & MUTATION_PROBA_LOADED)
		xmlNewTextChild(creationNode, NULL,
				(const xmlChar *) "probabilite-mutation",
				(const xmlChar *) doubleToString(
						*((double *) getParameterProperty(
								result->_initialParameters,
								MUTATION_PROBA_LOADED))));

	creationNode = xmlNewNode(NULL,
			(const xmlChar *) "point_valeur_optimisation");
	xmlAddChild(cursor, creationNode);
	for (i = 0; i < result->_problem_dimension; i++)
		xmlNewTextChild(creationNode, NULL, (const xmlChar *) "point",
				(const xmlChar *) doubleToString(result->_result_vector[i]));

	xmlNewTextChild(cursor, NULL, (const xmlChar *) "complexite_iteration",
			(const xmlChar *) integerToString(result->_result_complexity));

	if (result->_data_loaded & RESULT_ERROR_LOADED)
		xmlNewTextChild(cursor, NULL, (const xmlChar *) "erreur_absolue",
				(const xmlChar *) doubleToString(result->_result_error));
}

char* writeResultXML(ResultArray *results) {

	xmlDocPtr doc = NULL;
	xmlNodePtr root = NULL;
	xmlNodePtr cursor = NULL;

	xmlChar *xmlBuffer = NULL;
	int bufferDataSize = -1;
	int i;

	logMessage(DEBUG1, "entering method", "write Result XML");

	handleError(
			!results,
			NULL,
			"illegal argument",
			"given result is null");

	root = xmlNewNode(NULL, (const xmlChar *) RESULTS_NODE);

	xmlSetProp(root, (const xmlChar *) "xmlns:xsi",
			(const xmlChar *) "http://www.w3.org/2001/XMLSchema-instance");
	xmlSetProp(root, (const xmlChar *) "xsi:noNamespaceSchemaLocation",
			(const xmlChar *) "resources/result.xsd");
	logMessage(DEBUG3, "created root node", (char *) root->name);

	logMessage(DEBUG2, "bench id ?", integerToString(results->benchId));
	logMessage(DEBUG2, "bench id > 0 ", printBoolean(results->benchId > 0));
	if (results->benchId > 0) {
		cursor = xmlNewNode(NULL, (const xmlChar *) "result-benchmark");
		xmlSetProp(cursor, (const xmlChar *) "id",
				(const xmlChar *) integerToString(results->benchId));
		xmlAddChild(root, cursor);

		logMessage(DEBUG2, "result loop", "start");
		for (i = 0; i < results->size; i++) {
			sprintf(buffer, "%p", results->result[i]);
			logMessage(DEBUG3, "iterate pointer", buffer);
			logMessage(DEBUG2, "iterate", integerToString(
					results->result[i]->getId(results->result[i])));
			writeSimpleResult(cursor, results->result[i]);
		}
		logMessage(DEBUG2, "result loop", "end");
	} else {
		writeSimpleResult(root, results->result[0]);
	}

	doc = xmlNewDoc((const xmlChar *) "1.0");

	xmlDocSetRootElement(doc, root);

	xmlDocDumpFormatMemoryEnc(doc, &xmlBuffer, &bufferDataSize, "UTF-8", 1); //Indent lines

	//	logMessage(DEBUG1, "exiting method", (char *)xmlBuffer);

	return (char *) xmlBuffer;
}

char* writeUserXML(User* user) {
	xmlDocPtr doc = NULL;
	xmlNodePtr root = NULL;
	xmlNodePtr cursor = NULL;
	xmlNodePtr creationNode = NULL;

	xmlChar *xmlBuffer = NULL;
	int bufferDataSize = -1;
	int i;

	logMessage(DEBUG1, "entering method", "write User XML");

	handleError(
			!user,
			NULL,
			"illegal argument",
			"given user is null");

	root = xmlNewNode(NULL, (const xmlChar *) USER_NODE);
	xmlSetProp(root, (const xmlChar *) "xmlns:xsi",
			(const xmlChar *) "http://www.w3.org/2001/XMLSchema-instance");
	xmlSetProp(root, (const xmlChar *) "xsi:noNamespaceSchemaLocation",
			(const xmlChar *) "resources/user.xsd");

	// Setting id value as an attribute
	xmlSetProp(root, (const xmlChar *) "id", (const xmlChar *) integerToString(
			user->getId(user)));

	xmlNewTextChild(root, NULL, (const xmlChar *) "login",
			(const xmlChar *) user->login);

	xmlNewTextChild(root, NULL, (const xmlChar *) "password",
			(const xmlChar *) user->password);

	creationNode = xmlNewNode(NULL, (const xmlChar *) "groups");
	xmlAddChild(root, creationNode);
	for (i = 0; i < user->groups.size; i++) {
		cursor = xmlNewNode(NULL, (const xmlChar *) "group");
		xmlAddChild(creationNode, cursor);

		xmlSetProp(cursor, (const xmlChar *) "id",
				(const xmlChar *) integerToString(user->groups.group[i][ID]));
		xmlSetProp(cursor, (const xmlChar *) "associated-role-id",
				(const xmlChar *) integerToString(
						user->groups.group[i][ROLE_ID]));
	}

	doc = xmlNewDoc((const xmlChar *) "1.0");

	xmlDocSetRootElement(doc, root);

	xmlDocDumpFormatMemoryEnc(doc, &xmlBuffer, &bufferDataSize, "UTF-8", 1); //Indent lines

	logMessage(DEBUG1, "exiting method", (char *) xmlBuffer);

	return (char *) xmlBuffer;
}

Problema* parseProblemFromFile(const char* xmlfilepath) {
	xmlDocPtr document = NULL;
	Problema *problem = NULL;

	logMessage(DEBUG2, "method entry", "parseProblemFromFile");

	document = xmlParseFile(xmlfilepath);

	problem = parseProblem(document);

	if (document)
		xmlFreeDoc(document);

	return problem;
}

Problema* parseProblemFromString(const char* xml) {
	xmlDocPtr document = NULL;
	Problema *problem = NULL;

	logMessage(DEBUG2, "method entry", "parseProblemFromString");

	document = xmlParseMemory(xml, strlen(xml));

	problem = parseProblem(document);

	if (document)
		xmlFreeDoc(document);

	return problem;
}

Group* parseGroupFromFile(const char* xmlfilepath) {
	xmlDocPtr document = NULL;
	Group *group = NULL;

	logMessage(DEBUG2, "method entry", "parseGroupFromFile");

	document = xmlParseFile(xmlfilepath);

	group = parseGroup(document);

	if (document)
		xmlFreeDoc(document);

	return group;
}

Group* parseGroupFromString(const char* xml) {
	xmlDocPtr document = NULL;
	Group *group = NULL;

	logMessage(DEBUG2, "method entry", "parseGroupFromString");

	document = xmlParseMemory(xml, strlen(xml));

	group = parseGroup(document);

	if (document)
		xmlFreeDoc(document);

	return group;
}

ResultArray* parseResultFromFile(const char* xmlfilepath) {
	xmlDocPtr document = NULL;
	ResultArray* result = NULL;

	logMessage(DEBUG2, "method entry", "parseResultFromFile");
	logMessage(DEBUG3, "parameters : filepath", (char *) xmlfilepath);
	document = xmlParseFile(xmlfilepath);

	result = parseResult(document);

	if (document)
		xmlFreeDoc(document);

	return result;
}
ResultArray* parseResultFromString(const char* xml) {
	xmlDocPtr document = NULL;
	ResultArray* result = NULL;

	logMessage(DEBUG2, "method entry", "parseResultFromString");

	document = xmlParseMemory(xml, strlen(xml));

	result = parseResult(document);

	if (document)
		xmlFreeDoc(document);

	return result;
}

User* parseUserFromFile(const char* xmlfilepath) {
	xmlDocPtr document = NULL;
	User *user = NULL;

	logMessage(DEBUG2, "method entry", "parseUserFromFile");

	document = xmlParseFile(xmlfilepath);

	user = parseUser(document);

	if (document)
		xmlFreeDoc(document);

	return user;
}
User* parseUserFromString(const char* xml) {
	xmlDocPtr document = NULL;
	User *user = NULL;

	logMessage(DEBUG2, "method entry", "parseUserFromString");

	document = xmlParseMemory(xml, strlen(xml));

	user = parseUser(document);

	if (document)
		xmlFreeDoc(document);

	return user;
}

double* parseVectorFromString(const char* xml) {
	xmlDocPtr document = NULL;
	double   *vector  = NULL;
	xmlNode  *cursor = NULL;
	int arraycursor = 0;
	int i;

	xmlChar *xmlBuffer = NULL;

	xmlXPathContextPtr xpathContext = NULL;
	xmlXPathObjectPtr xpathNodeSet = NULL;

	logMessage(DEBUG2, "method entry", "parseVectorFromString");

	document = xmlParseMemory(xml, strlen(xml));

	if (document) {
		/* Register all files included in XML file */
		xmlXPathInit();
		xpathContext = xmlXPathNewContext(document);
		xpathNodeSet = xmlXPathEval((const xmlChar *) "//point/text()",
				xpathContext);

		logMessage(DEBUG1, "xpath result length", integerToString(
				xmlXPathNodeSetGetLength(xpathNodeSet->nodesetval)));
		vector = (double *)malloc( xmlXPathNodeSetGetLength(xpathNodeSet->nodesetval) * sizeof(double) );

		logMessage(DEBUG1, "xpath loop", "start");
		for (i = 0; i < xmlXPathNodeSetGetLength(xpathNodeSet->nodesetval); i++) {
			cursor = xmlXPathNodeSetItem(xpathNodeSet->nodesetval,i);
			if (cursor->type == XML_TEXT_NODE) {
				logMessage(DEBUG1, "xpath loop item name ", (char *) cursor->name);
				xmlBuffer = xmlNodeGetContent(cursor);
				logMessage(DEBUG1, "xpath loop item value", (char *) xmlBuffer);

				vector[arraycursor++] = atof((char *)xmlBuffer);

				xmlFree(xmlBuffer);
			}
		}
		logMessage(DEBUG1, "xpath loop", "end");

		xmlXPathFreeObject(xpathNodeSet);
		xmlXPathFreeContext(xpathContext);
		xmlFreeDoc(document);
		/*  */
	}

	return vector;
}

MethodParameters parseConditionsFromString (const char* xml) {
	xmlDocPtr document = NULL;
	xmlChar *xmlBuffer = NULL;
	xmlNode *cursor    = NULL;
	MethodParameters params;
	params.data_loaded = 0;
	int i;
	for(i=0;i<MAX_ITEM;i++)
		params.parameters[i] = NULL;

	logMessage(DEBUG2, "method entry", "parseConditionsFromString");

	document = xmlParseMemory(xml, strlen(xml));

	if (document) {

		cursor = xmlDocGetRootElement(document); //parameters
		cursor = cursor->xmlChildrenNode;
		while(cursor)
		{
			logMessage(DEBUG2,"iterate node",(char *) cursor->name);
			if( !strcmp((const char *) cursor->name, "patience") )
			{
				xmlBuffer = xmlNodeGetContent(cursor);
				logMessage(DEBUG2,"node value",(char *) xmlBuffer);
				int value = atoi((const char *)xmlBuffer);
				logMessage(DEBUG2,"real value",integerToString(value));
				setParameterProperty(&params,PATIENCE_LOADED,&value);
				free(xmlBuffer);
			}
			else if( !strcmp((const char *) cursor->name, "epsilon") )
			{
				xmlBuffer = xmlNodeGetContent(cursor);
				logMessage(DEBUG2,"node value",(char *) xmlBuffer);
				double value = atof((const char *)xmlBuffer);
				setParameterProperty(&params,EPSILON_LOADED,&value);
				free(xmlBuffer);
			}
			else if( !strcmp((const char *) cursor->name, "pas") )
			{
				xmlBuffer = xmlNodeGetContent(cursor);
				logMessage(DEBUG2,"node value",(char *) xmlBuffer);
				double value = atof((const char *)xmlBuffer);
				setParameterProperty(&params,STEP_LOADED,&value);
				free(xmlBuffer);
			}
			else if( !strcmp((const char *) cursor->name, "temperature") )
			{
				xmlBuffer = xmlNodeGetContent(cursor);
				logMessage(DEBUG2,"node value",(char *) xmlBuffer);
				double value = atof((const char *)xmlBuffer);
				setParameterProperty(&params,TEMPERATURE_LOADED,&value);
				free(xmlBuffer);
			}
			else if( !strcmp((const char *) cursor->name, "pas-exploration") )
			{
				xmlBuffer = xmlNodeGetContent(cursor);
				logMessage(DEBUG2,"node value",(char *) xmlBuffer);
				double value = atof((const char *)xmlBuffer);
				setParameterProperty(&params,NEIGHBOR_STEP_LOADED,&value);
				free(xmlBuffer);
			}
			else if( !strcmp((const char *) cursor->name, "taille-population") )
			{
				xmlBuffer = xmlNodeGetContent(cursor);
				logMessage(DEBUG2,"node value",(char *) xmlBuffer);
				int value = atoi((const char *)xmlBuffer);
				setParameterProperty(&params,POPULATION_SIZE_LOADED,&value);
				free(xmlBuffer);
			}
			else if( !strcmp((const char *) cursor->name, "probabilite-croisement") )
			{
				xmlBuffer = xmlNodeGetContent(cursor);
				logMessage(DEBUG2,"node value",(char *) xmlBuffer);
				double value = atof((const char *)xmlBuffer);
				setParameterProperty(&params,CROSS_PROBA_LOADED,&value);
				free(xmlBuffer);
			}
			else if( !strcmp((const char *) cursor->name, "probabilite-mutation") )
			{
				xmlBuffer = xmlNodeGetContent(cursor);
				logMessage(DEBUG2,"node value",(char *) xmlBuffer);
				double value = atof((const char *)xmlBuffer);
				setParameterProperty(&params,MUTATION_PROBA_LOADED,&value);
				free(xmlBuffer);
			}
			else if( !strcmp((const char *) cursor->name, "borne-inferieure") )
			{
				xmlBuffer = xmlNodeGetContent(cursor);
				logMessage(DEBUG2,"node value",(char *) xmlBuffer);
				double value = atof((const char *)xmlBuffer);
				setParameterProperty(&params,BOUNDS_MIN_LOADED,&value);
				free(xmlBuffer);
			}
			else if( !strcmp((const char *) cursor->name, "borne-superieure") )
			{
				xmlBuffer = xmlNodeGetContent(cursor);
				logMessage(DEBUG2,"node value",(char *) xmlBuffer);
				double value = atof((const char *)xmlBuffer);
				setParameterProperty(&params,BOUNDS_MAX_LOADED,&value);
				free(xmlBuffer);
			}

			cursor = cursor->next;
		}
		xmlFreeDoc(document);

	}

	return params;
}

