/***************************************************************************
**
**  This file is part of QGpCoreTools.
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Lesser General Public
**  License as published by the Free Software Foundation; either
**  version 2.1 of the License, or (at your option) any later version.
**
**  This file 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 Lesser General Public
**  License for more details.
**
**  You should have received a copy of the GNU Lesser General Public
**  License along with this library; if not, write to the Free Software
**  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2004-11-27
**  Copyright: 2004-2019
**    Marc Wathelet
**    Marc Wathelet (ULg, Liège, Belgium)
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#ifndef XMLCLASSFACTORY_H
#define XMLCLASSFACTORY_H

#include <QtCore>

#include "CoreApplication.h"
#include "QGpCoreToolsDLLExport.h"

namespace QGpCoreTools {

  class XMLClass;
  class XMLClassCreator;

  class QGPCORETOOLS_EXPORT XMLClassFactory
  {
  public:
    XMLClassFactory() {_nextId=0;}
    ~XMLClassFactory();

    int id(const QString& tag) const;
    XMLClass * create(const QString& tag) const;
    XMLClass * create(int id) const;
    XMLClassCreator * creator(const QString& tag) const;
    XMLClassCreator * creator(int id) const;

    QStringList registeredTags() const;
    QList<int> registeredIds() const;

    int registerClass(const QString& tag, XMLClassCreator * creator);
    void registerTag(const QString& tag, int id);
    void registerTag(const QString& tag, const QString& destTag);

    static void registerFactory(XMLClassFactory * f);
    static void clearFactories();
  protected:
    int newId() {return _nextId++;}
  private:
    QMap<int, XMLClassCreator *> _registeredClasses;
    QMap<QString, int> _registeredTags;
    int _nextId;

    static QList<XMLClassFactory *> _factories;
  };

  class QGPCORETOOLS_EXPORT XMLClassCreator
  {
  public:
    virtual ~XMLClassCreator() {}

    virtual XMLClass * create() const;
  };

  #define XMLREGISTER_HEAD(_factory_, _creator_, _className_, _tagName_) \
    class _className_##XMLClassCreator : public _creator_ \
    { \
    public: \
      _className_##XMLClassCreator() \
      { \
        _factory_::init(); \
        _factory_::instance()->registerClass(_tagName_, this); \
      }


  #define XMLREGISTER_TAIL(_className_) \
    private: \
      virtual XMLClass * create() const {return new _className_;} \
    }; \
    static _className_##XMLClassCreator register##_className_;

  #define XMLSYNONYM(_factory_, _synName_, _tagName_) \
    class _synName_##XMLClassSynonym \
    { \
    public: \
      _synName_##XMLClassSynonym() { \
        _factory_::instance()->registerTag(# _synName_, _tagName_); \
      } \
    }; \
    static _synName_##XMLClassSynonym register##_synName_;

} // namespace QGpCoreTools

#endif // XMLCLASSFACTORY_H
