/* massXpert - the true massist's program.
   --------------------------------------
   Copyright(C) 2006,2007 Filippo Rusconi

   http://www.massxpert.org/massXpert

   This file is part of the massXpert project.

   The massxpert project is the successor to the "GNU polyxmass"
   project that is an official GNU project package(see
   www.gnu.org). The massXpert project is not endorsed by the GNU
   project, although it is released ---in its entirety--- under the
   GNU General Public License. A huge part of the code in massXpert
   is actually a C++ rewrite of code in GNU polyxmass. As such
   massXpert was started at the Centre National de la Recherche
   Scientifique(FRANCE), that granted me the formal authorization to
   publish it under this Free Software License.

   This software is free software; you can redistribute it and/or
   modify it under the terms of the GNU  General Public
   License version 3, as published by the Free Software Foundation.


   This software 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 software; if not, write to the

   Free Software Foundation, Inc.,

   51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/


#ifndef PROP_HPP
#define PROP_HPP


/////////////////////// Qt includes
#include <QObject>
#include <QString>
#include <QDomElement>


namespace massXpert
{

  class PolChemDef;


  //////////////////////// Prop ////////////////////////


  //! The Prop class provides a property.
  /*! Properties are massXpert's way of extending the capabilities of
    objects. A property is merely an encapsulation of:

    \li a name(a QString);

    \li a pointer to data specifically allocated for this property to
    become their owner(the member data pointer is a void *);

    In order to perform tasks in the derived classes using dynamic
    binding, virtual functions are available to derived classes to
    perform:

    \li XML string formatting(formatXmlElement());

    \li XML element rendering(renderXmlElement());

    \li data destruction(deleteData()).

    Derived classes should be named according the following scheme:
    XxxYyyZzzzProp, like StringProp or MonomerProp or
    ModifProp.

    \attention When a derived class is created, it should register
    itself to the system by registering its name in the
    propAllocator(const QString &) function. This function will be able
    to allocate a property using the proper constructor based on the
    property name that is passed as argument. It returns a pointer to
    the newly allocated instance.

    \sa StringProp.
  */
  class Prop
  {
  protected:

    //! Name.
    QString m_name;

    //! Pointer to data.
    /*! These data belong to us and are freed upon destruction.
     */
    void *mpa_data;

  public:
    Prop();

    virtual ~Prop();
    virtual void deleteData() = 0;

    virtual void *clone() const = 0;
    virtual void cloneOut(void *) const = 0;
    virtual void cloneIn(const void *) = 0;

    void setName(QString &);
    const QString &name();

    void setData(void *);
    void *data();

    virtual bool renderXmlElement(const QDomElement &, int = 1) = 0;
    virtual QString *formatXmlElement(int,
                                      const QString & = QString("  ")) = 0;
  };



  //////////////////////// StringProp ////////////////////////

  //! The StringProp class provides a string-only property.
  /*! A StringProp property is a simple property in which the data
    is a pointer to an allocated QString.

  */
  class StringProp : public Prop
  {
  public:
    StringProp(const QString & = QString(), const QString & = QString());
    StringProp(const QString & = QString(), QString * = 0);
    ~StringProp();
    void deleteData();

    virtual void *clone() const;
    virtual void cloneOut(void *) const;
    virtual void cloneIn(const void *);

    bool renderXmlElement(const QDomElement &, int = 1);
    QString *formatXmlElement(int, const QString & = QString("  "));
  };



  //////////////////////// IntProp ////////////////////////

  //! The IntProp class provides a integer property.
  /*! A IntProp property is a simple property in which the data
    is a pointer to an allocated int.

  */
  class IntProp : public Prop
  {
  public:
    IntProp(const QString & = QString(), int = 0);
    ~IntProp();
    void deleteData();

    virtual void *clone() const;
    virtual void cloneOut(void *) const;
    virtual void cloneIn(const void *);

    bool renderXmlElement(const QDomElement &, int = 1);
    QString *formatXmlElement(int, const QString & = QString("  "));
  };




  //////////////////////// DoubleProp ////////////////////////

  //! The DoubleProp class provides a double property.
  /*! A DoubleProp property is a simple property in which the data
    is a pointer to an allocated double.

  */
  class DoubleProp : public Prop
  {
  public:
    DoubleProp(const QString & = QString(), double = 0);
    ~DoubleProp();
    void deleteData();

    virtual void *clone() const;
    virtual void cloneOut(void *) const;
    virtual void cloneIn(const void *);

    bool renderXmlElement(const QDomElement &, int = 1);
    QString *formatXmlElement(int, const QString & = QString("  "));
  };



  /////////////////// NoDeletePointerProp ///////////////////

  //! The NoDeletePointerProp class provides a pointer property.
  /*! A NoDeletePointerProp property is a simple property in which
    the data is a pointer to an allocated instance, but which may never
    be destroyed by the property itself. This property is regarded as a
    simple "message-containing property". The message is nothing but the
    name of the property.

  */
  class NoDeletePointerProp : public Prop
  {
  public:
    NoDeletePointerProp(const QString & = QString(), void * = 0);
    ~NoDeletePointerProp();
    void deleteData();

    virtual void *clone() const;
    virtual void cloneOut(void *) const;
    virtual void cloneIn(const void *);

    bool renderXmlElement(const QDomElement &, int = 1);
    QString *formatXmlElement(int, const QString & = QString("  "));
  };




  //////////////////////// Utility Functions ////////////////////////
  Prop *propAllocator(const QString &, const PolChemDef * = 0);

} // namespace massXpert


#endif // PROP_HPP

