
#ifndef XML_PARAMETERS_H
#define XML_PARAMETERS_H

//This is the header that all possibly-xml-using code must include !


#include<vector>
#include<list>
#include<string>
#include<sstream>
#include<iostream>
#include <libxml++/libxml++.h>       //Works provided you compile with -I path/to/libxml_home_directory

using namespace std;


//Here are all functions you will need to use:



//****************************************************************************************
//************************          (I)   xmlClass          ******************************
//****************************************************************************************

//Whenever you wish to define how a class XMLIZED loads/saves itself from an xml file, it must inherit from class xmlClass.


struct xmlClass
{
  //THIS is the important function you must redefine in the code of each derived XMLIZED object, that defines the associated xml structure:
  virtual void xml_ize(){}

  //And here are the functions you should use in the code of function xml_ize() :

  //adding a sub-field as child xml node of this object:
  template<typename XMLIZED>
  void add_child(XMLIZED & object , std::string name);

  //adding a parameter (base type or string) as xml attribute of this object:
  template<typename XMLIZED>
  void add_param(XMLIZED & object , std::string name);

  //adding a pure xml node that is not associated to a 'physical' c++ object.
  //void add_node ( xmlObject_base & node , std::string name);
  
  //This function must also be redefined in the code of each derived XMLIZED object. But its code is invariant, so you do not have to bother writing it if you use the XML_IZE_MACRO instead (see examples of use).
  virtual const type_info & get_pointer_typeid ()
  {
    return typeid ( this ) ;
  }

  virtual ~xmlClass(){}}
;



//****************************************************************************************
//************************          (II)   xmlParam          *****************************
//****************************************************************************************

//is a 'fake' structure serving as a namespace for all xmlParameters functions to be used in the 'main'
// (except xmlRegister (see III ) that you can use in the main OR in xml_ize() object functions )

struct xmlParam
{

  //adding an object in the xml structure:
  template<typename XMLIZED>
  static void add_object (XMLIZED & object , std::string name);

  //ONCE the structure is defined (automatically with functions xml_ize(), or manually with 'custom', right after):

  //Load the defined xml architecture, with its parameters, from an xml tree:
  template<typename XMLIZED>
  static void load (XMLIZED & object , xmlpp::Node* father_node );

  //Save the defined xml architecture, with its parameters, to an xml tree:
  template<typename XMLIZED>
  static void save (XMLIZED & object , xmlpp::Node* father_node );

  //'Custom' functions: use them to build an xml architecture from the 'main',
  // rather than by defining function xml_ize() in each concerned object's code

  template<typename XMLIZED_1, typename XMLIZED_2>
  static void add_child_custom(XMLIZED_1 & childObject , std::string name, XMLIZED_2 & fatherObject);

  template < typename TYPE , typename XMLIZED >
  static void add_param_custom(TYPE & newParam, std::string paramName, XMLIZED &fatherObject);

  //adding a pure xml node that is not associated to a 'physical' c++ object.
  //template<typename XMLIZED>
  //static void add_node_custom ( xmlObject_base & node , std::string name, XMLIZED &fatherObject);
		  
  //delete all xmlObjects created during the process, and thus all the xml structure defined precedently
  static void delete_structure ();

  
};



//****************************************************************************************
//**********************          (III)   xmlRegister          ***************************
//****************************************************************************************


//Special functions used to secify the xml name of objects that do not exist yet (pointed objects or contained objects), but that can be constructed by reading an xml file, and that can also be saved to an xml file after having been created.


template<uint order, class derivedCLASS>
struct xmlRegister
{

  //the total-chain version... ALWAYS TO BE USED FIRST
  template<class XMLIZED>
  xmlRegister( XMLIZED & object, list<string> registerNames );

  //the single-name version... TO REGISTER VARIANTS FOR THE LAST POINTER, after preceding function was called
  template<class XMLIZED>
  xmlRegister( XMLIZED & object, string registerName );
};

//General syntax:

//'order' is the DEPTH of the registration in the structure. In the total-chain version, the list registerNames MUST have exactly 'order' elements. The list can be directly constructed with helper function xml_names().
//Although it is actually defined as an object, it can be called like a function.
//ex:

//Toto* a		--->	xmlRegister<1,Toto>(a , "name_of_the_toto")
//if Tata inherits from Toto	xmlRegister<1,Tata>(a , "name_of_the_tata") also works

//vector<Toto> b	--->	xmlRegister<1,Toto>(b , "name_of_a_toto")
//Toto** c		--->	xmlRegister<2,Toto>(c , xml_names("name_of_the_toto*" , "name_of_the_toto") )
//vector<Toto*> *d	---> 	xmlRegister<3,Tata>(d, xml_names("name_of_the_vector" , "name_of_a_toto*" , "name_of_the_tata") )

//see directory Example for more help.



//******************************************************************************
//  TO FINISH, one macro that you MIGHT wish to use in all your XMLIZED classes:
//******************************************************************************


//can be written as a single, opening macro in your CLASS HEADER, before the definition of function xml_ize (in the .h or in the .cc )
//Includes the invariant definition of function get_pointer_type_info (see (I) xmlClass )


#define XML_IZE_MACRO		\
const type_info & get_pointer_typeid ()	\
{		\
return typeid (this) ;		\
}	\
\
void xml_ize()

/*

ex:

class Toto
{
...

XML_IZE_MARCO
{
	...all xml_ize code...
}

};


or:


class Toto
{
...

XML_IZE_MACRO;

};

void Toto::xml_ize()
{
	...all xml_ize code...
}


*/




//******************************************************************************
//******************************************************************************
//**************     OK, now here comes the code !           *******************
//******************************************************************************
//******************************************************************************


//The ifndef is just a trick to define function xmlParam::delete_structure() in the code of xml_object_base.cc :
//need to include xml_parameters.h in xml_object_base.cc
//But if we include this file xml_parameters.h from xml_object_base.cc, we do not need all the following headers:

#ifndef XML_OBJECT_BASE_H

#include<xml_misc_tools.h>

#include<xml_object_base.h>
#include<xml_wrapper.h>
#include<xml_object.h>

#include<xml_find_create_functions.h>
#include<xml_parameters_template_code.h>	//the code for classes defined in this header.

//Specializations of xmlObject for pointers, and for stl containers:

#include<xml_factory.h>
#include<xml_object_pointer_specialisation.h>
#include<xml_object_container_specialisation.h>

#endif
#endif
