/* * World.hpp * * Created on: Feb 3, 2010 * Author: crueger */ #ifndef WORLD_HPP_ #define WORLD_HPP_ #include #include #include #include #include #include #include "defs.hpp" #include "Patterns/Observer.hpp" #include "Patterns/Cacheable.hpp" // forward declarations class periodentafel; class MoleculeListClass; class atom; class molecule; class AtomDescriptor; class AtomDescriptor_impl; class ManipulateAtomsProcess; template class AtomsCalculation; class World : public Observable { // necessary for coupling with descriptors friend class AtomDescriptor_impl; friend class AtomDescriptor; // Actions, calculations etc associated with the World friend class ManipulateAtomsProcess; template friend class AtomsCalculation; public: typedef std::map AtomSet; typedef std::map MoleculeSet; /***** getter and setter *****/ // reference to pointer is used for legacy reason... reference will be removed latter to keep encapsulation of World object /** * returns the periodentafel for the world. */ periodentafel *&getPeriode(); /** * returns the first atom that matches a given descriptor. * Do not rely on ordering for descriptors that match more than one atom. */ atom* getAtom(AtomDescriptor descriptor); /** * returns a vector containing all atoms that match a given descriptor */ std::vector getAllAtoms(AtomDescriptor descriptor); std::vector getAllAtoms(); /** * returns a calculation that calls a given function on all atoms matching a descriptor. * the calculation is not called at this point and can be used as an action, i.e. be stored in * menus, be kept around for later use etc. */ template AtomsCalculation* calcOnAtoms(boost::function,std::string,AtomDescriptor); template AtomsCalculation* calcOnAtoms(boost::function,std::string); /** * get the number of atoms in the World */ int numAtoms(); /** * get the number of molecules in the World */ int numMolecules(); /***** Methods to work with the World *****/ /** * create a new molecule. This method should be used whenever any kind of molecule is needed. Assigns a unique * ID to the molecule and stores it in the World for later retrieval. Do not create molecules directly. */ molecule *createMolecule(); void destroyMolecule(molecule*); void destroyMolecule(moleculeId_t); /** * Create a new atom. This method should be used whenever any atom is needed. Assigns a unique ID and stores * the atom in the World. If the atom is not destroyed it will automatically be destroyed when the world ends. */ atom *createAtom(); /** * Registers a Atom unknown to world. Needed in some rare cases, e.g. when cloning atoms, or in some unittests. * Do not re-register Atoms already known to the world since this will cause double-frees. */ int registerAtom(atom*); /** * Delete some atom and erase it from the world. Use this whenever you need to destroy any atom. Do not call delete on * atom directly since this will leave the pointer inside the world. */ void destroyAtom(atom*); /** * Delete some atom and erase it from the world. Use this whenever you need to destroy any atom. Do not call delete on * atom directly since this will leave the pointer inside the world. */ void destroyAtom(atomId_t); /** * Produces a process that calls a function on all Atoms matching a given descriptor. The process is not * called at this time, so it can be passed around, stored inside menuItems etc. */ ManipulateAtomsProcess* manipulateAtoms(boost::function,std::string,AtomDescriptor); ManipulateAtomsProcess* manipulateAtoms(boost::function,std::string); protected: /**** Iterators to use internal data structures */ class AtomIterator { public: AtomIterator(); AtomIterator(AtomDescriptor, World*); AtomIterator(const AtomIterator&); AtomIterator& operator=(const AtomIterator&); AtomIterator& operator++(); // prefix AtomIterator operator++(int); // postfix with dummy parameter bool operator==(const AtomIterator&); bool operator==(const AtomSet::iterator&); bool operator!=(const AtomIterator&); bool operator!=(const AtomSet::iterator&); atom* operator*(); int getCount(); protected: void advanceState(); AtomSet::iterator state; boost::shared_ptr descr; int index; World* world; }; /** * returns an iterator over all Atoms matching a given descriptor. * used for internal purposes, like AtomProcesses and AtomCalculations. */ AtomIterator getAtomIter(AtomDescriptor descr); /** * returns an iterator to the end of the AtomSet. Due to overloading this iterator * can be compared to iterators produced by getAtomIter (see the mis-matching types). * Thus it can be used to detect when such an iterator is at the end of the list. * used for internal purposes, like AtomProcesses and AtomCalculations. */ AtomSet::iterator atomEnd(); /******* Internal manipulation routines for double callback and Observer mechanism ******/ void doManipulate(ManipulateAtomsProcess *); private: periodentafel *periode; AtomSet atoms; atomId_t currAtomId; //!< stores the next available Id for atoms MoleculeSet molecules; moleculeId_t currMoleculeId; /***** singleton Stuff *****/ public: /** * get the currently active instance of the World. */ static World* get(); /** * destroy the currently active instance of the World. */ static void destroy(); /** * destroy the currently active instance of the World and immidiately * create a new one. Use this to reset while somebody is still Observing * the world and should reset the observed instance. All observers will be * sent the subjectKille() message from the old world. */ static World* reset(); private: /** * private constructor to ensure creation of the world using * the singleton pattern. */ World(); /** * private destructor to ensure destruction of the world using the * singleton pattern. */ virtual ~World(); static World *theWorld; // this mutex only saves the singleton pattern... // use other mutexes to protect internal data as well // this mutex handles access to the pointer, not to the object!!! static boost::mutex worldLock; /***** * some legacy stuff that is include for now but will be removed later *****/ public: MoleculeListClass *&getMolecules(); private: MoleculeListClass *molecules_deprecated; }; #endif /* WORLD_HPP_ */