/* * World.hpp * * Created on: Feb 3, 2010 * Author: crueger */ #ifndef WORLD_HPP_ #define WORLD_HPP_ #include #include #include #include #include #include #include "types.hpp" #include "Patterns/Observer.hpp" #include "Patterns/Cacheable.hpp" #include "Patterns/Singleton.hpp" // forward declarations class periodentafel; class MoleculeListClass; class atom; class molecule; class AtomDescriptor; class AtomDescriptor_impl; class MoleculeDescriptor; class MoleculeDescriptor_impl; class ManipulateAtomsProcess; template class AtomsCalculation; class World : public Singleton, public Observable { // Make access to constructor and destructor possible from inside the singleton friend class Singleton; // necessary for coupling with descriptors friend class AtomDescriptor_impl; friend class AtomDescriptor; friend class MoleculeDescriptor_impl; friend class MoleculeDescriptor; // Actions, calculations etc associated with the World friend class ManipulateAtomsProcess; template friend class AtomsCalculation; public: // Types for Atom and Molecule structures 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(); /** * returns the first molecule that matches a given descriptor. * Do not rely on ordering for descriptors that match more than one molecule. */ molecule *getMolecule(MoleculeDescriptor descriptor); /** * returns a vector containing all molecules that match a given descriptor */ std::vector getAllMolecules(MoleculeDescriptor descriptor); /** * 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); /** * used when changing an atom Id. * Unless you are calling this method from inside an atom don't fiddle with the third parameter. * * Return value indicates wether the change could be done or not. */ bool changeAtomId(atomId_t oldId, atomId_t newId, atom* target=0); /** * 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 */ // Atoms class AtomIterator : public std::iterator::difference_type, std::iterator_traits::value_type, std::iterator_traits::pointer, std::iterator_traits::reference> { public: typedef AtomSet::iterator _Iter; typedef _Iter::value_type value_type; typedef _Iter::difference_type difference_type; typedef _Iter::pointer pointer; typedef _Iter::reference reference; typedef _Iter::iterator_category iterator_category; 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(); // Molecules class MoleculeIterator : public std::iterator::difference_type, std::iterator_traits::value_type, std::iterator_traits::pointer, std::iterator_traits::reference> { public: typedef MoleculeSet::iterator _Iter; typedef _Iter::value_type value_type; typedef _Iter::difference_type difference_type; typedef _Iter::pointer pointer; typedef _Iter::reference reference; typedef _Iter::iterator_category iterator_category; MoleculeIterator(); MoleculeIterator(MoleculeDescriptor, World*); MoleculeIterator(const MoleculeIterator&); MoleculeIterator& operator=(const MoleculeIterator&); MoleculeIterator& operator++(); // prefix MoleculeIterator operator++(int); // postfix with dummy parameter bool operator==(const MoleculeIterator&); bool operator==(const MoleculeSet::iterator&); bool operator!=(const MoleculeIterator&); bool operator!=(const MoleculeSet::iterator&); molecule* operator*(); int getCount(); protected: void advanceState(); MoleculeSet::iterator state; boost::shared_ptr descr; int index; World* world; }; /** * returns an iterator over all Molecules matching a given descriptor. * used for internal purposes, like MoleculeProcesses and MoleculeCalculations. */ MoleculeIterator getMoleculeIter(MoleculeDescriptor descr); /** * returns an iterator to the end of the MoleculeSet. Due to overloading this iterator * can be compared to iterators produced by getMoleculeIter (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 MoleculeProcesses and MoleculeCalculations. */ MoleculeSet::iterator moleculeEnd(); /******* Internal manipulation routines for double callback and Observer mechanism ******/ void doManipulate(ManipulateAtomsProcess *); private: atomId_t getNextAtomId(); void releaseAtomId(atomId_t); bool reserveAtomId(atomId_t); periodentafel *periode; AtomSet atoms; std::set atomIdPool; //