// src/backend/serializer.hh - Copyright 2005, 2006, University
//               of Padova, dept. of Pure and Applied
//               Mathematics
//
// This file is part of SGPEMv2.
//
// This 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.
//
// SGPEMv2 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 SGPEMv2; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

#ifndef XML_SERIALIZER_HH
#define XML_SERIALIZER_HH 1

#include "config.h"
#include <sgpemv2/serializer.hh>

#include <glibmm/ustring.h>
#include <libxml/parser.h>
#include <libxml/xmlmemory.h>


namespace sgpem
{
  class XMLSerializerFactory;
}

namespace sgpem
{
  class XMLSerializer;

  /**
    \brief Loads and saves from/to XML
    
    Serialization should be done to temporary files, which are then moved in place when serialization has finished without errors.
    
    See mkstemp(3).
  */
  class XMLSerializer : public Serializer
  {
  public:
    XMLSerializer();
    virtual ~XMLSerializer();

    /**
      Tries to open filename for writing, else throws SerializerError.
      
      Respecting the SGPEMv2 DTD for the snapshots,
      creates a new XML document node and write to disk
      using a new xmlsave::XMLVisitor.
      Calls fill_doc to accomplish this task.
      
      \throws backend::SerializerError on error
     */
    virtual void save_snapshot(const Glib::ustring& filename, const History& hist) throw(SerializerError);

    /**
      \brief Re-initialize system status from a saved XML snapshot
      
      Tries to open filename for reading, else throws SerializerError.
      First validates file versus the SGPEMv2 DTD for snapshots, then reads it.
      Calls read_doc to relize the work.
      
      \throws backend::SerializerError
     */
    virtual void restore_snapshot(const Glib::ustring& filename, History& hist) throw(SerializerError);

    /**
      \return Constant string "xsgp"
     */
    virtual const Glib::ustring get_filename_extension();

    /**
      \return Constant string "SGPEMv2 XML savefile"
     */
    virtual const Glib::ustring get_filename_description();
  protected:
  private:
    /**
      \brief Create the document root and fill the data

      Create the document root and children "resources" and "schedulables",
      then calls fill_resources and fill_schedulables to fill all with data.
     */
    void fill_doc(xmlDocPtr doc, const History& hist);

    /**
      \brief Take a resources node and fill it with the data

      For each resource in hist create a "resource" node and fill with data.
      Uses an XMLVisitor object to do the task.
     */
    // void fill_resources(xmlNodePtr resources_node, const History& hist);

    /**
      \brief Take a schedulables node and fill it with the data

      For each resource in hist create a "schedulable" node and fill with data.
      Also all schedulable sub nodes are generated too.
      Uses an XMLVisitor object to do the task.
     */
    // void fill_schedulables(xmlNodePtr schedulables_node, const History& hist);


    /**
      \brief Restore the snapshot from the passed xml document

      Traverse the passed (previously readed) xml document and
      rebuild the correct image using the XMLSerializerFactory object.
     */
    void read_doc(xmlDocPtr doc, XMLSerializerFactory& fact) throw(SerializerError);

    /**
      \brief Restore all the resources from the passed xml node

      Traverse the passed (previously readed) xml node and
      rebuild the correct resources image using the XMLSerializerFactory
      object.
     */
    void read_resources(xmlNodePtr resources_node, XMLSerializerFactory& fact);

    /**
      \brief Restore all the schedulables (processes) from the passed xml node

      Traverse the passed (previously readed) xml node and
      rebuild the correct processes (and sub objects) images using the
      XMLSerializerFactory object.
     */
    void read_schedulables(xmlNodePtr schedulables_node, XMLSerializerFactory& fact);

    /**
      \brief Restore all threads from the passed xml node

      Traverse the passed (previously readed) xml node and
      rebuild the correct threads (and sub objects) images using the
      XMLSerializerFactory object.
     */
    void read_threads(xmlNodePtr schedulables_node, XMLSerializerFactory& fact);

    /**
      \brief Restore all the requests from the passed xml node

      Traverse the passed (previously readed) xml node and
      rebuild the correct requests (and sub objects) images using the
      XMLSerializerFactory object.
     */
    void read_requests(xmlNodePtr schedulables_node, XMLSerializerFactory& fact);

    /**
      \brief Restore all the subrequests from the passed xml node

      Traverse the passed (previously readed) xml node and
      rebuild the correct subrequests image using the
      XMLSerializerFactory object.
     */
    void read_subrequests(xmlNodePtr schedulables_node, XMLSerializerFactory& fact);
  };
}

#endif
