#ifndef _TOBJECT_H_
#define _TOBJECT_H_

#include <string>

using namespace std;

/**
 * \brief Base class for all project classes.
 * 
 * Handles reference counting, type checking, provides virtual methods
 * for cloning, comparing and text dump.
 *
 * For valid type-checking should all subclasses declare static member type
 * and override getType method like this :
 * \code
 *
 * class MyClass:public TObject {
 * public:
 *    static const char* type;
 *    const char* getType() const {
 *       return type;
 *    }
 * };
 *
 * const char* MyClass::type="MyClass";
 * 
 * \endcode
 *
 * \date 01-13-2006
 *
 * \author Ondrej Svejdar
 *
 * \todo 
 *
 * \bug 
 *
 */
class TObject
{
	mutable int refCount;
public:
	static const char* type;

	/**
	 * \brief Return type of class.
	 * \return type of class
	 */
	virtual const char* getType() const;
	
	/**
	 * \brief Check if class is inherited from class named className.
     *
	 * We're using pointer comparation, so typicall usage should be
	 * like this :
	 * \code
	 * bool isInheritedFromMyClass=hasParent(MyClass::type)
	 * \endcode
	 * \param className pointer to type of class
	 * \return true, if this instance is inherited from class named className
	 */
	virtual bool hasParent(const char* className) const;


	/**
	 * \brief Compare two objects.
	 * \note If method is not overriden it throws ExceptionNoImplementation when called.
	 * \param object pointer to another object
	 * \return true if object are equal
	 */
	virtual bool compareTo(TObject* object) const;

	/**
	 * \brief Simple text dump.
	 * \return if not overriden, it returns type of class
	 */
	virtual const string& toString() const;

	/**
	 * \brief Create deep-clone of object.
	 * \return deep-clone of object
	 */
	virtual TObject* clone();


	/**
	 * \brief Check if this instance is of type "type".
	 * \note we're using pointer comparation
	 * \param type pointer to type of class
	 * \return true, if this instance is instance of class named type
	 */
	inline bool typeOf(const char* type) const
	{
		return getType()==type;
	}

	TObject()
	{
		refCount=0;
	}

	/**
	 * \brief Increase number of refences count.
	 * Do not call directly, use Ptr class instead.
	 * \see Ptr
	 */
	void upcount() const 
	{
		refCount++;
	}

	/**
	 * \brief Decrease number of refences count.
	 * Do not call directly, use Ptr class instead.
	 * \see Ptr
	 */
	void downcount() const
	{
		refCount--;
		if (refCount==0) delete this;
	}
  
};

#endif/*_TOBJECT_H_*/

