/* 

                          Firewall Builder

                 Copyright (C) 2001 NetCitadel, LLC

  Author:  Vadim Zaliva lord@crocodile.org

  $Id: FWObjectDatabase.h,v 1.3 2004/09/09 05:35:58 vkurland Exp $

  This program is free software which we release under the GNU General Public
  License. You may redistribute and/or modify this program under the terms
  of that license as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This program 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.
 
  To get a copy of the GNU General Public License, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

*/


#ifndef __FWOBJECTDATABASE_HH_FLAG__
#define __FWOBJECTDATABASE_HH_FLAG__

#include <fwbuilder/FWObject.h>
#include <fwbuilder/FWException.h>
#include <fwbuilder/ThreadTools.h>
#include <fwbuilder/XMLTools.h>

#ifdef _WIN32
#  include <sys/timeb.h>
#endif

#include <time.h>   // for time_t

namespace libfwbuilder
{

    class Firewall;

class IDcounter {

 protected:
    long cntr;
    
 public:
    IDcounter();
    long get() { ++cntr; return cntr; }
};
    
/**
 * Database of objects.
 */
class FWObjectDatabase : public FWObject
{
    protected:

    static const std::string    DTD_FILE_NAME ;
    time_t                      lastModified;

    std::string data_file;

    Firewall* _findFirewallByNameRecursive(FWObject* db,const std::string &name) throw(FWException);

    public:

    DECLARE_FWOBJECT_SUBTYPE(FWObjectDatabase);

    /**
     * this constructor initializes singleton db
     */
    FWObjectDatabase();
    /**
     * this constructor makes a copy of entire tree and does not
     * intitialize db
     */
    FWObjectDatabase(FWObjectDatabase& d);

    virtual ~FWObjectDatabase() {};
    
    // --- XML import/export ---
    
    /**
     * This is the main "Create" method:
     * it creates instance of FWObject of given type
     *
     * if parameter 'create_with_root' is true, this method will create
     * objects using constructor that uses pointer to this as a parameter,
     * otherwise empty constructor is used
     */
    virtual FWObject *create(const std::string &type, bool create_with_root=false);

    /**
     * Creates instance of FWObject using its XML representation
     */
    virtual FWObject *createFromXML(xmlNodePtr data);

    virtual void       fromXML    (xmlNodePtr xml_parent_node) throw(FWException);
    virtual xmlNodePtr toXML(xmlNodePtr parent) throw(FWException);
    
    std::string generateUniqueId();

    time_t getTimeLastModified()           { return lastModified; }
    void   resetTimeLastModified(time_t t) { lastModified=t; }

    // --- Load/Save ---
    
    virtual void saveFile ( const std::string &filename) throw(FWException); 
    virtual void saveXML  ( xmlDocPtr                  ) throw(FWException); 
    virtual void load     ( const std::string &filename,
                            XMLTools::UpgradePredicate *upgrade,
                            const std::string &template_dir) throw(FWException);
    virtual void    setDirty(bool f);

    Firewall* findFirewallByName(const std::string &name) throw(FWException);

    FWObjectDatabase* exportSubtree( FWObject *lib );
    FWObjectDatabase* exportSubtree( const std::list<FWObject*> &libs );

    void recursivelyRemoveObjFromTree(FWObject* obj, bool remove_ref=false);

    /**
     * this predicate is used to hand control over to user in case
     * when a conflict is detected while merging trees. By default the
     * old object is overwritten with new one. 
     */
    class ConflictResolutionPredicate
    {
        public:

        virtual bool askUser(FWObject *o1,FWObject *o2) 
        { 
            return true;
        }
    };

    void merge( FWObjectDatabase *ndb , ConflictResolutionPredicate *mp=NULL);

    void setFileName (const std::string &filename);
    const std::string& getFileName ();
    const std::string  getFileDir ();

    // --- Standard object IDs ---

    static const std::string     getRootId()            { return "root";    }
    static const std::string     getAnyNetworkId()      { return "sysid0";  }
    static const std::string     getAnyIPServiceId()    { return "sysid1";  }
    static const std::string     getAnyIntervalId()     { return "sysid2";  }
    static const std::string     getDeletedObjectsId()  { return "sysid99"; }
        

    // singelton

    static FWObjectDatabase  *db;

};

}

#endif

