coriolis/hurricane/doc/hurricane/DBo.dox

332 lines
12 KiB
C++

// -*- C++ -*-
namespace Hurricane {
/*! \class DBo
* \brief DataBase object root class (\b API).
*
* \section sDBoIntro Introduction
*
* All data base objects must be created explicitely by using
* the provided creation functions and not by calling directly
* the new operator (which anyway is not provided).
*
* On the same way, they must not be deleted with the delete
* operator but by calling the destruction function described
* below.
*
* Those objects can't, either, be duplicated : the copy
* constructor and the assignment operator are not available.
*
* Properties can be attached to those objects (the principles
* driving the properties management are detailed in the
* Property class).
*
* \section sDBoCreation Creation process
*
* The data base objects are strongly linked between them and
* some relations can't be set-up by the constructors themselves
* but must be established a posteriori. <b>Those objects must
* therefore be built by special functions which take care of
* that obscure work</b>.
*
* Indeed, let us imagine a <b>Go</b> type representing the
* category of graphic objects and two sub-classes
* <b>Rectangle</b> and <b>Line</b> having specific geometric
* attributes. For eficiency reasons those <b>Go</b> are stored
* in a fast access geometric data structure like a
* <b>QuadTree</b>. It would be ideal that the insertion of the
* <b>Go</b> within its <b>QuadTree</b> be automatic. This could
* be done in the <b>Go</b> constructor for instance. But, when
* this constructor is called upon (by the constructor of
* sub-classes) it is impossible to determine the bounding box
* of the object because all geometric characteristics are not
* yet assigned (making the insertion unfeasible).
*
* A possible solution would be to do nothing within the
* <b>Go</b> constructor and let the work be done by the
* sub-classes constructors wich could call upon the right
* insertion function. This solution is neither smart nor
* consistent because an omission can happen. If a sub-type of
* <b>Line</b> is created, the insertion being already done in
* the <b>Line</b> constructor, it must not be re-done for the
* derived class. Conversely if a new type of <b>Go</b> is
* created, insertion processing must not be forgotten. Code
* omissions or duplications are bound to happen and the code is
* not homogeneous.
*
* Therefore this insertion must be realized by the <b>Go</b>,
* but a posteriori, that is once the object has been fully
* built. In order to realize such an operation it must, once
* all derived classes constructors have been called, call upon
* a function <b>_postCreate</b> which realizes the additional
* work and then return the pointer on the new objects (let us
* recall that all member functions which must not be called
* directly are prefixed by an underscore).
*
* This process in two steps is realized by the <b>Create</b>
* function which is provided for each type of instanciable
* object. The following example shows its implementation for a
* net :
* \code{.cpp}
Net* Net::Create(Cell* cell, const Name& name)
{
Net* net = new Net(cell, name);
if (!net)
throw Error("Can't create Net : allocation failed");
net->_postCreate();
return net;
}
\endcode
*
* Within this function, the net is created in a first time
* thanks to the constructor spawn by the new operator. If
* everything goes right the function <b>_postCreate</b> is
* called upon the net. This one realizes the additional
* operations that the constructor couldn't realize and then
* calls the functions <b>_postCreate</b> upon the base
* classe. If everything goes right the net is returned, else an
* exception is thrown if something abnormal or illegal occurs
* (i.e. a net with the same name already exists). For the
* example of a <b>Line</b> : the different called constructors
* will fully characterize the line, then the <b>_postCreate</b>
* method on a line will do nothing else than call upon the
* <b>_postCreate</b> method of the <b>go</b> which will insert
* the line within the <b>QuadTree</b> (this is now feasible,
* the line geometry being fully characterized).
*
* \section sDBodestroy Deletion process
*
* <b>The destroy() member function :</b>
*
* Data base ojects can be destroyed only by calling upon this
* function and not by calling the C++ standard destructor
* (which indeed is not provided).
*
* A process similar but opposite to the creation process is
* required. A function <b>_preDestroy</b> must be called upon
* before the effective object destruction. As a matter of fact,
* if we take again the case of the <b>Line</b> for example, the
* line must be removed from the <b>QuadTree</b> before the
* destruction of its geometric characteristics (inverse of the
* previous phenomenon). Therefore the destroy function is
* implemented that way :
* \code
void DBo::destroy()
// ***************
{
_preDestroy();
delete this;
}
* \endcode
*
* \section sDBoExtentions Extentions
*
* For any new sub-type of DBo you must adhere to the same
* protocol. That is provide the methods _postCreate and
* _preDestroy calling the methods _postCreate and _preDestroy of
* their base class. Furthermore you must provide when this
* class is instantiable a creation function (caution : only the
* creation function, if any, must be \public (and \static) the
* others must be \protected).
*
* Extracted from the .h of a new type of cell.
* \code
class MyCell : public Cell {
public:
typedef Cell Inherit;
public:
// User-accessible creation method.
static MyCell* Create (Library* library, const Name& name);
protected:
// Internally used constructors & destructors.
MyCell (Library* library, const Name& name);
virtual void _postCreate ();
virtual void _preDestroy ();
};
* \endcode
* Extracted from the .cpp for this new type of cell.
* \code
MyCell::MyCell(Library* library, const Name&amp; name)
: Inherit(library, name)
{ }
MyCell* MyCell::Create(Library* library, const Name& name)
{
MyCell* myCell = new MyCell(library, name);
if (!myCell) throw Error("Can't create MyCell : allocation failed");
myCell->_postCreate(); // must not be forgotten!
return myCell;
}
void MyCell::_postCreate()
{
Inherit::_postCreate(); // must not be forgotten!
// complete here the post creation
}
void MyCell::_preDestroy()
{
Inherit::_preDestroy(); // must not be forgotten!
// complete here the pre-deletion.
}
* \endcode
*
* \remark The destructor, strictly speaking, is not defined because
* necessary operations are done within the method
* <b>_preDestroy</b>.
* In the implementation of the class <b>MyCell</b> we have only
* used the type <b>Inherit</b> (and never <b>Cell</b>). This opens
* the door to hierarchy changes without affecting the code already
* written.
*
* \section sDBoRemark Remark
*
* The construction and deletion process of property objects is the
* same. It is mandatory for any new type of property to adopt the
* same protocol.
*
*/
/*! \function void DBo::destroy ();
*
* The legal method to delete any DBo object (see \ref sDBodestroy).
*/
/*! \function Property* DBo::getProperty ( const Name& name ) const;
* \param name Name of the Property to return.
* \return The property of Name \e name attached to the object, if it exists, else \NULL.
*
* \remark When writting what follows :
* \code
forEach(DBo*, idbo, dbos) {
Property* property = idbo->getProperty("width");
if (property) {
// do something
}
}
* \endcode
*
* There is construction of a name (from a character string) for
* each visited dbo in order to find the property. It's more
* efficient to write :
* \code
Name width = "width";
forEach(DBo*, idbo, dbos) {
Property* property = idbo->getProperty(width);
if (property) {
// do something
}
}
* \endcode
* Or still better :
* \code
static Name WIDTH = "width";
forEach(DBo*, idbo, dbos) {
Property* property = idbo->getProperty(WIDTH);
if (property) {
// do something
}
}
* \endcode
* This remark applies each time you handle names.
*/
/*! \function Propertes DBo::getProperties () const;
* \return The property Collection associated to the object (possibly empty).
*/
/*! \function bool DBo::hasProperty () const;
* \return \true if the object has at least a property, else \false.
*/
/*! \function void DBo::put ( Property* property );
*
* Adds the Property \e property to the set of object
* properties. Properties being named, if an other one already
* exists in the set, with the same name, this last will be in a
* first step removed from the set.
*
* \remark Does nothing if the Property object is already attached to the
* object.
*
* \caution An exception is thrown if the Property pointer is \NULL.
*/
/*! \function void DBo::remove ( Property* property );
* removes the property \e property from the set of object properties.
*
* \remark Does nothing if the Property object is not attached to the object.
*
* \caution An exception is thrown if the Property pointer is \NULL.
*/
/*! \function void DBo::removeProperty ( const Name& name );
* removes the property of name \e name if it exists.
*/
/*! \function void DBo::clearProperties ();
* removes all properties attached to this object.
*/
//! \name DBo Collection
// \{
/*! \typedef typedef GenericCollection<DBo*> DBos;
* Generic collection representing a set of data base objects.
*/
/*! \typedef typedef GenericLocator<DBo*> DBoLocator;
* Generic locator for visiting a data base objects Collection.
*/
/*! \typedef typedef GenericFilter<DBo*> DBoFilter;
* Filter to selecting a subset of data base objects matching some criteria.
*/
/*! \def for_each_dbo(dbo,dbos)
* Macro for visiting all objects of a data base objects collection.
*/
// \}
}
/* \addtogroup getStringFunctions
*/
// \{
/* \function string getString ( const Hurricane::DBo& dbo );
* Convert any Hurricane::DBo object into a \string.
*/
/* \function inline ostream& operator<< ( ostream& o, const Hurricane::DBo& dbo );
* Print any Hurricane::DBo object into an output \stream.
*/
/* \function inline ostream& operator<< ( ostream& o, const Hurricane::DBo* dbo );
* Print any pointed Hurricane::DBo object into an output \stream.
*/
// \}