diff --git a/Interface/RefVector.cc b/Interface/RefVector.cc --- a/Interface/RefVector.cc +++ b/Interface/RefVector.cc @@ -1,259 +1,262 @@ // -*- C++ -*- // // RefVector.cc is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 1999-2011 Leif Lonnblad // // ThePEG is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the RefVector class. // #include "InterfacedBase.h" #include "RefVector.h" #include "RefVector.xh" #include "ThePEG/Utilities/HoldFlag.h" #include "ThePEG/Utilities/Rebinder.h" #include "ThePEG/Repository/BaseRepository.h" #include "ThePEG/Repository/EventGenerator.h" using namespace ThePEG; RefVectorBase:: RefVectorBase(string newName, string newDescription, string newClassName, const type_info & newTypeInfo, string newRefClassName, const type_info & newRefTypeInfo, int newSize, bool depSafe, bool readonly, bool norebind, bool nullable, bool defnull) : RefInterfaceBase(newName, newDescription, newClassName, newTypeInfo, newRefClassName, newRefTypeInfo, depSafe, readonly, norebind, nullable, defnull), theSize(newSize) {} IVector RefVectorBase::getReferences(const InterfacedBase & i) const { return get(i); } string RefVectorBase::exec(InterfacedBase & i, string action, string arguments) const { istringstream arg(arguments.c_str()); int place = -1; if ( !( arg >> place ) ) place = -1; ostringstream ret; if ( action == "get" ) { IVector refvec = get(i); if ( place >= 0 && unsigned(place) < refvec.size() ) { if ( refvec[place] ) return refvec[place]->fullName(); else return "*** NULL Reference ***"; } for ( IVector::size_type j = 0; j < refvec.size(); ++j ) { if ( j != 0 ) ret << ", "; if ( refvec[j] ) ret << refvec[j]->fullName(); else ret << "*** NULL Reference ***"; } } else if ( action == "erase" ) { erase(i, place); } + else if ( action == "clear" ) { + clear(i); + } else if ( action == "set" || action == "insert" || action == "newdef" || action == "setdef" ) { string refname; arg >> refname; if ( action == "setdef" ) { if ( objectDefaults(i).find(tag(place)) == objectDefaults(i).end() ) return "Error: No default value defined for this object."; refname = objectDefaults(i)[tag(place)]; } IBPtr ip; if ( refname.size() && refname != "NULL") { Interfaced * ii = dynamic_cast<Interfaced *>(&i); if ( ii && ii->generator() ) ip = ii->generator()->getObject<Interfaced>(refname); else ip = BaseRepository::TraceObject(refname); } if ( action == "insert" ) insert(i, ip, place); else set(i, ip, place); if ( action == "newdef" ) { IVector refvec = get(i); if ( place >= 0 && unsigned(place) < refvec.size() ) objectDefaults(i)[tag(place)] = refvec[place]? refvec[place]->fullName(): string("NULL"); } } else if ( action == "notdef" ) { IVector refvec = get(i); for ( place = 0; unsigned(place) < refvec.size(); ++place ) { if ( objectDefaults(i).find(tag(place)) == objectDefaults(i).end() ) continue; string refname = refvec[place]? refvec[place]->fullName(): string("NULL"); if ( refname == objectDefaults(i)[tag(place)] ) continue; ret << "[" << place << "] " << refname << " (" << objectDefaults(i)[tag(place)] << ") "; } } else throw InterExUnknown(*this, i); return ret.str(); } string RefVectorBase::fullDescription(const InterfacedBase & ib) const { ostringstream os; os << InterfaceBase::fullDescription(ib) << ( noNull()? "nevernull\n": "nullable\n" ) << ( defaultIfNull()? "defnull\n": "nodefnull\n" ); IVector refs = get(ib); os << size() << '\n' << refs.size() << '\n'; for ( int i = 0, N = refs.size(); i < N; ++i ) if ( !refs[i] ) os << "NULL\n"; else os << refs[i]->fullName() << '\n'; return os.str(); } string RefVectorBase::type() const { return string("V<") + refClassName() + ">"; } string RefVectorBase::doxygenType() const { ostringstream os; if ( size() <= 0 ) os << "Varying size "; else os << "Fixed size (" << size() << ") "; os << "vector of references to objects of class " << refClassName(); return os.str(); } void RefVectorBase:: rebind(InterfacedBase & i, const TranslationMap & trans, const IVector & defs) const { if ( noRebind() ) return; IVector oldrefs = get(i); IVector newRefs; for ( unsigned int ir = 0; ir < oldrefs.size(); ++ir ) { IBPtr oldref = oldrefs[ir];; IBPtr newref; if ( oldref ) { newref = trans.translate(oldref); if ( !dependencySafe() && newref->fullName() != oldref->fullName() ) i.touch(); } else if ( defaultIfNull() ) { for ( IVector::const_iterator p = defs.begin(); p != defs.end(); ++p ) { try { if ( *p && check(i, *p, ir) ) { newref = *p; i.touch(); break; } } catch ( ... ) {} } } newRefs.push_back(newref); } HoldFlag<> depflag(isDependencySafe); HoldFlag<> roflag(isReadOnly, false); if ( size() <= 0 ) for ( IVector::size_type j = oldrefs.size(); j > 0; --j ) erase(i, j - 1); for ( IVector::size_type j = 0; j < oldrefs.size(); ++j ) if ( size() > 0 ) set(i, newRefs[j], j, false); else insert(i, newRefs[j], j, false); } RefVExRefClass::RefVExRefClass(const RefInterfaceBase & i, const InterfacedBase & o, cIBPtr r, const char * s) { theMessage << "Could not " << s << " the object \"" << (r? r->name().c_str(): "<NULL>") << "\" in the reference vector \"" << i.name() << "\" for the object \"" << o.name() << "\" because it is not of the required class (" << i.refClassName() << ")."; severity(setuperror); } RefVExSetUnknown::RefVExSetUnknown(const RefInterfaceBase & i, const InterfacedBase & o, cIBPtr r, int j, const char * s) { theMessage << "Could not " << s << " the object \"" << (r? r->name().c_str(): "<NULL>") << " at position " << j << " in the reference vector \"" << i.name() << "\" for the object \"" << o.name() << "\" because the " << s << " function threw an unknown exception."; severity(setuperror); } RefVExSetUnfound::RefVExSetUnfound(const InterfaceBase & i, const InterfacedBase & o, string n) { theMessage << "Could not set the object named \"" << n << " in the reference vector \"" << i.name() << "\" of \"" << o.name() << "\"because the object was not found."; severity(setuperror); } RefVExIndex::RefVExIndex(const InterfaceBase & i, const InterfacedBase & o, int j) { theMessage << "Could not access element " << j << " of the reference vector \"" << i.name() << "\" for the object \"" << o.name() << "\" because the index was outside of the allowed range."; severity(setuperror); } RefVExFixed::RefVExFixed(const InterfaceBase & i, const InterfacedBase & o) { theMessage << "Cannot insert or delete in the reference vector \"" << i.name() << "\" for the object \"" << o.name() << "\" since the vector is of fixed size."; severity(setuperror); } RefVExDelUnknown::RefVExDelUnknown(const InterfaceBase & i, const InterfacedBase & o, int j) { theMessage << "Could not delete the value at position " << j << " from the reference vector \"" << i.name() << "\" for the object \"" << o.name() << "\" because the delete function threw an unknown exception."; severity(setuperror); } RefVExGetUnknown::RefVExGetUnknown(const InterfaceBase & i, const InterfacedBase & o) { theMessage << "Could not get the reference vector \"" << i.name() << "\" for the object \"" << o.name() << "\" because the get function threw an unknown exception."; severity(setuperror); } RefVExNoSet::RefVExNoSet(const InterfaceBase & i, const InterfacedBase & o) { theMessage << "Could not set an object in the reference vector \"" << i.name() << "\" for the object \"" << o.name() << "\" because no set function has been specified."; severity(setuperror); } RefVExNoIns::RefVExNoIns(const InterfaceBase & i, const InterfacedBase & o) { theMessage << "Could not insert an object in the reference vector \"" << i.name() << "\" for the object \"" << o.name() << "\" because no insert function has been specified."; severity(setuperror); } RefVExNoDel::RefVExNoDel(const InterfaceBase & i, const InterfacedBase & o) { theMessage << "Could not erase an object in the reference vector \"" << i.name() << "\" for the object \"" << o.name() << "\" because no erase function has been specified."; severity(setuperror); } diff --git a/Interface/RefVector.h b/Interface/RefVector.h --- a/Interface/RefVector.h +++ b/Interface/RefVector.h @@ -1,432 +1,444 @@ // -*- C++ -*- // // RefVector.h is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 1999-2011 Leif Lonnblad // // ThePEG is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_RefVector_H #define ThePEG_RefVector_H // This is the declaration of the RefVector and RefVectorBase classes. #include "ThePEG/Config/ThePEG.h" #include "InterfaceBase.h" #include "RefVector.xh" #include "RefVector.fh" namespace ThePEG { /** * The RefVector and its base class RefVectorBase defines an interface * to a class derived from the InterfacedBase, through which vectors * (or any other container) of pointers to other InterfacedBase * objects may be manipulated. RefVector is templated on the type of * the class and the class of the objects pointed to, and is derived * from the InterfaceBase class via RefVectorBase and * RefInterfaceBase. * * For each InterfacedBase class exactly one static RefVector object * should created for each member variable of container type which * should be interfaced. This object will automatically register * itself with the BaseRepository class. * * @see InterfacedBase * @see InterfaceBase * */ class RefVectorBase: public RefInterfaceBase { public: /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newClassName the name of the corresponding class. * * @param newTypeInfo the type_info object of the corresponding * class. * * @param newRefClassName the name of the class pointed to. * * @param newRefTypeInfo the type_info object of the class pointed * to. * * @param newSize the size of the container or -1 if varying. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. * * @param norebind if set to true, this interface is not responsible * for the rebinding of corresponding objects. * * @param nullable if set to true this corresponding references may * be null. * * @param defnull if set to true and a corresponding reference is * null it may be given a a default value in the initialization of * an EventGenerator. */ RefVectorBase(string newName, string newDescription, string newClassName, const type_info & newTypeInfo, string newRefClassName, const type_info & newRefTypeInfo, int newSize, bool depSafe, bool readonly, bool norebind, bool nullable, bool defnull); /** * The general interface method overriding the one in * InterfaceBase. For this class, \a action can be any of "set", * "get", "erase" and "insert" and \a argument should be a something * which can be read into an integer while the rest of \a argument * should correspond to the name of an InterfacedBase object in the * BaseRepository. */ virtual string exec(InterfacedBase & ib, string action, string arguments) const; /** * Return a complete description of this reference vector. */ virtual string fullDescription(const InterfacedBase & ib) const; /** * Return a code for the type of this reference. */ virtual string type() const; /** * Return a string describing the type of interface to be included * in the Doxygen documentation. */ virtual string doxygenType() const; /** * Set the \a i'th element of a container of pointers of \a ib * to \a ip. */ virtual void set(InterfacedBase & ib, IBPtr ip, int i, bool chk = true) const = 0; /** * Insert a new pointer before the \a i'th element of a container of * pointers of \a ib and set it to \a ip. */ virtual void insert(InterfacedBase & ib, IBPtr ip, int i, bool chk = true) const = 0; /** * Remove the \a i'th element of a container of pointers of \a ib. */ virtual void erase(InterfacedBase & ib, int i) const = 0; /** + * Clear the container of pointers of \a ib. + */ + virtual void clear(InterfacedBase & ib) + const = 0; + + /** * Return a vector of pointers corresponding to the container of * pointers of \a ib. */ virtual IVector get(const InterfacedBase & ib) const = 0; /** * Check if set(ib, ip, i) will be successfull but do not do * anything. */ virtual bool check(const InterfacedBase & ib, cIBPtr ip, int i) const = 0; /** * In the object \a ib, replace all pointers to objects in this * interface with the translated ones provided by \a trans. If a * pointer is null, and defaultIfNull() is true, replace it with * the first alowed object found in \a defs. */ virtual void rebind(InterfacedBase & ib, const TranslationMap & trans, const IVector & defs) const; /** * Return pointers to other objects in \a ib. */ virtual IVector getReferences(const InterfacedBase & ib) const; /** * Get the size of the container being interfaced. If the size() is * less than 0, the size is allowed to vary. */ int size() const { return theSize; } /** * Set the size of the container being interfaced. If the size is * less than 0, the size is allowed to vary. */ void setSize(int sz) { theSize = sz; } /** * Set the size of the container being interfaced to -1, i.e. the * size is allowed to vary. */ void setVariableSize() { theSize = 0; } private: /** * The size of the container being interfaced. */ int theSize; }; /** * The RefVector and its base class RefVectorBase defines an interface * to a class derived from the InterfacedBase, through which vectors * (or any other container) of pointers to other InterfacedBase * objects may be manipulated. RefVector is templated on the type of * the class and the class of the objects pointed to, and is derived * from the InterfaceBase class via RefVectorBase and * RefInterfaceBase. * * For each InterfacedBase class exactly one static RefVector object * should created for each member variable of container type which * should be interfaced. This object will automatically register * itself with the BaseRepository class. * * @see InterfacedBase * @see InterfaceBase * */ template <class T, class R> class RefVector: public RefVectorBase { public: /** A pointer to the class of objects referred to. */ typedef typename Ptr<R>::pointer RefPtr; /** A const pointer to the class of objects referred to. */ typedef typename Ptr<R>::const_pointer cRefPtr; /** A pointer to a menberfunction to be used for the 'set' action. */ typedef void (T::*SetFn)(RefPtr, int); /** A pointer to a menberfunction to be used for the 'insert' action. */ typedef void (T::*InsFn)(RefPtr, int); /** A pointer to a menberfunction to be used for the 'erase' action. */ typedef void (T::*DelFn)(int); /** A pointer to a menberfunction to be used for the 'check' action. */ typedef bool (T::*CheckFn)(cRefPtr, int) const; /** A pointer to a menberfunction to be used for the 'get' action. */ typedef vector<RefPtr> (T::*GetFn)() const; /** * Declaration of a direct pointer to the member variable in case it * is a vector. */ typedef vector<RefPtr> T::* Member; public: /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newMember a pointer to a Member which is a TypeVector. May * be null, in which case the pointers to member functions must be * specified. * * @param newSize the size of the container or -1 if varying. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. * * @param rebind if set to true, this interface is responsible * for the rebinding of corresponding objects. * * @param nullable if set to true this corresponding references may * be null. * * @param newSetFn optional pointer to member function for the 'set' * action. * * @param newInsFn optional pointer to member function for the * 'insert' action. * * @param newDelFn optional pointer to member function for the * 'erase' action. * * @param newGetFn optional pointer to member function for the * 'get' action. * * @param newCheckFn optional pointer to member function for the * 'check' action. */ RefVector(string newName, string newDescription, Member newMember, int newSize, bool depSafe = false, bool readonly = false, bool rebind = true, bool nullable = true, SetFn newSetFn = 0, InsFn newInsFn = 0, DelFn newDelFn = 0, GetFn newGetFn = 0, CheckFn newCheckFn = 0); /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newMember a pointer to a Member which is a TypeVector. May * be null, in which case the pointers to member functions must be * specified. * * @param newSize the size of the container or -1 if varying. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. * * @param rebind if set to true, this interface is responsible * for the rebinding of corresponding objects. * * @param nullable if set to true this corresponding references may * be null. * * @param defnull if set to true and a corresponding reference is * null it may be given a a default value in the initialization of * an EventGenerator. * * @param newSetFn optional pointer to member function for the 'set' * action. * * @param newInsFn optional pointer to member function for the * 'insert' action. * * @param newDelFn optional pointer to member function for the * 'erase' action. * * @param newGetFn optional pointer to member function for the * 'get' action. * * @param newCheckFn optional pointer to member function for the * 'check' action. */ RefVector(string newName, string newDescription, Member newMember, int newSize, bool depSafe, bool readonly, bool rebind, bool nullable, bool defnull, SetFn newSetFn = 0, InsFn newInsFn = 0, DelFn newDelFn = 0, GetFn newGetFn = 0, CheckFn newCheckFn = 0); /** * Set the \a i'th element of a container of pointers of \a ib * to \a ip. */ virtual void set(InterfacedBase & ib, IBPtr ip, int i, bool chk = true) const; /** * Insert a new pointer before the \a i'th element of a container of * pointers of \a ib and set it to \a ip. */ virtual void insert(InterfacedBase & ib, IBPtr ip, int i, bool chk = true) const; /** * Remove the \a i'th element of a container of pointers of \a ib. */ virtual void erase(InterfacedBase & ib, int i) const; /** + * Clear the container of pointers of \a ib. + */ + virtual void clear(InterfacedBase & ib) + const; + + /** * Return a vector of pointers corresponding to the container of * pointers of \a ib. */ virtual IVector get(const InterfacedBase & ib) const ; /** * Check if set(ib, ip, i) will be successfull but do not do * anything. */ virtual bool check(const InterfacedBase & ib, cIBPtr, int i) const ; /** * Give a pointer to a member function to be used by 'set()'. */ void setSetFunction(SetFn sf) { theSetFn = sf; } /** * Give a pointer to a member function to be used by 'insert()'. */ void setInsertFunction(InsFn ifn) { theInsFn = ifn; } /** * Give a pointer to a member function to be used by 'get()'. */ void setGetFunction(GetFn gf) { theGetFn = gf; } /** * Give a pointer to a member function to be used by 'erase()'. */ void setEraseFunction(DelFn df) { theDelFn = df; } /** * Give a pointer to a member function to be used by 'check()'. */ void setCheckFunction(CheckFn cf) { theCheckFn = cf; } private: /** * The pointer to the member variable. */ Member theMember; /** * A pointer to a member function to be used by 'set()'. */ SetFn theSetFn; /** * Give a pointer to a member function to be used by 'insert()'. */ InsFn theInsFn; /** * Give a pointer to a member function to be used by 'erase()'. */ DelFn theDelFn; /** * Give a pointer to a member function to be used by 'get()'. */ GetFn theGetFn; /** * Give a pointer to a member function to be used by 'check()'. */ CheckFn theCheckFn; }; } #include "RefVector.tcc" #endif /* ThePEG_RefVector_H */ diff --git a/Interface/RefVector.tcc b/Interface/RefVector.tcc --- a/Interface/RefVector.tcc +++ b/Interface/RefVector.tcc @@ -1,143 +1,155 @@ // -*- C++ -*- // // RefVector.tcc is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 1999-2011 Leif Lonnblad // // ThePEG is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined templated member // functions of the RefVector class. // namespace ThePEG { template <class T, class R> RefVector<T,R>:: RefVector(string newName, string newDescription, Member newMember, int newSize, bool depSafe, bool readonly, bool rebind, bool nullable, SetFn newSetFn, InsFn newInsFn, DelFn newDelFn, GetFn newGetFn, CheckFn newCheckFn) : RefVectorBase(newName, newDescription, ClassTraits<T>::className(), typeid(T), ClassTraits<R>::className(), typeid(R), newSize, depSafe, readonly, !rebind, nullable, false), theMember(newMember), theSetFn(newSetFn), theInsFn(newInsFn), theDelFn(newDelFn), theGetFn(newGetFn), theCheckFn(newCheckFn) {} template <class T, class R> RefVector<T,R>:: RefVector(string newName, string newDescription, Member newMember, int newSize, bool depSafe, bool readonly, bool rebind, bool nullable, bool defnull, SetFn newSetFn, InsFn newInsFn, DelFn newDelFn, GetFn newGetFn, CheckFn newCheckFn) : RefVectorBase(newName, newDescription, ClassTraits<T>::className(), typeid(T), ClassTraits<R>::className(), typeid(R), newSize, depSafe, readonly, !rebind, nullable, defnull), theMember(newMember), theSetFn(newSetFn), theInsFn(newInsFn), theDelFn(newDelFn), theGetFn(newGetFn), theCheckFn(newCheckFn) {} template <class T, class R> void RefVector<T,R>:: set(InterfacedBase & i, IBPtr newRef, int place, bool chk) const { if ( readOnly() ) throw InterExReadOnly(*this, i); T * t = dynamic_cast<T *>(&i); if ( !t ) throw InterExClass(*this, i); if ( noNull() && !newRef ) throw InterExNoNull(*this, i); RefPtr r = dynamic_ptr_cast<RefPtr>(newRef); if ( !r && newRef ) throw RefVExRefClass(*this, i, newRef, "set"); IVector oldVector = get(i); if ( theSetFn && ( chk || !theMember ) ) { try { (t->*theSetFn)(r, place); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw RefVExSetUnknown(*this, i, r, place, "set"); } } else { if ( !theMember ) throw RefVExNoSet(*this, i); if ( place < 0 || static_cast<unsigned long>(place) >= (t->*theMember).size() ) throw RefVExIndex(*this, i, place); (t->*theMember)[place] = r; } if ( !InterfaceBase::dependencySafe() && oldVector != get(i) ) i.touch(); } template <class T, class R> void RefVector<T,R>:: insert(InterfacedBase & i, IBPtr newRef, int place, bool chk) const { if ( readOnly() ) throw InterExReadOnly(*this, i); if ( size() > 0 ) throw RefVExFixed(*this, i); T * t = dynamic_cast<T *>(&i); if ( !t ) throw InterExClass(*this, i); if ( noNull() && !newRef ) throw InterExNoNull(*this, i); RefPtr r = dynamic_ptr_cast<RefPtr>(newRef); if ( !r && newRef ) throw RefVExRefClass(*this, i, newRef, "insert"); IVector oldVector = get(i); if ( theInsFn && ( chk || !theMember ) ) { try { (t->*theInsFn)(r, place); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw RefVExSetUnknown(*this, i, r, place, "insert"); } } else { if ( !theMember ) throw RefVExNoIns(*this, i); if ( place < 0 || static_cast<unsigned long>(place) > (t->*theMember).size() ) throw RefVExIndex(*this, i, place); (t->*theMember).insert((t->*theMember).begin()+place, r); } if ( !InterfaceBase::dependencySafe() && oldVector != get(i) ) i.touch(); } template <class T, class R> void RefVector<T,R>::erase(InterfacedBase & i, int place) const { if ( readOnly() ) throw InterExReadOnly(*this, i); if ( size() > 0 ) throw RefVExFixed(*this, i); T * t = dynamic_cast<T *>(&i); if ( !t ) throw InterExClass(*this, i); IVector oldVector = get(i); if ( theDelFn ) { try { (t->*theDelFn)(place); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw RefVExDelUnknown(*this, i, place); } } else { if ( !theMember ) throw RefVExNoDel(*this, i); if ( place < 0 || static_cast<unsigned long>(place) >= (t->*theMember).size() ) throw RefVExIndex(*this, i, place); (t->*theMember).erase((t->*theMember).begin()+place); } if ( !InterfaceBase::dependencySafe() && oldVector != get(i) ) i.touch(); } template <class T, class R> +void RefVector<T,R>::clear(InterfacedBase & i) const + { + if ( readOnly() ) throw InterExReadOnly(*this, i); + if ( size() > 0 ) throw RefVExFixed(*this, i); + T * t = dynamic_cast<T *>(&i); + if ( !t ) throw InterExClass(*this, i); + if ( !theMember ) throw RefVExNoDel(*this, i); + (t->*theMember).clear(); + if ( !InterfaceBase::dependencySafe() ) i.touch(); +} + +template <class T, class R> IVector RefVector<T,R>::get(const InterfacedBase & i) const { const T * t = dynamic_cast<const T *>(&i); if ( !t ) throw InterExClass(*this, i); if ( theGetFn ) { try { vector<RefPtr> ret = (t->*theGetFn)(); return IVector(ret.begin(), ret.end()); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw RefVExGetUnknown(*this, i); } } if ( theMember ) return IVector((t->*theMember).begin(), (t->*theMember).end()); throw InterExSetup(*this, i); } template <class T, class R> bool RefVector<T,R>::check(const InterfacedBase & i, cIBPtr ir, int place) const { const T * t = dynamic_cast<const T *>(&i); if ( !t ) throw InterExClass(*this, i); if ( noNull() && !ir ) return false; cRefPtr r = dynamic_ptr_cast<cRefPtr>(ir); if ( !r && ir ) return false; if ( theCheckFn ) return (t->*theCheckFn)(r, place); if ( !theMember ) return true; return place >= 0 && static_cast<unsigned long>(place) <= (t->*theMember).size(); } } diff --git a/Repository/BaseRepository.cc b/Repository/BaseRepository.cc --- a/Repository/BaseRepository.cc +++ b/Repository/BaseRepository.cc @@ -1,941 +1,941 @@ // -*- C++ -*- // // BaseRepository.cc is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 1999-2011 Leif Lonnblad // // ThePEG is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the BaseRepository class. // // macro is passed in from -D compile flag #ifndef THEPEG_PKGDATADIR #error Makefile.am needs to define THEPEG_PKGDATADIR #endif #include "BaseRepository.h" #include "ThePEG/Config/algorithm.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/InterfaceBase.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Utilities/ClassDescription.h" #include "ThePEG/Utilities/DescriptionList.h" #include "ThePEG/Utilities/HoldFlag.h" #include "ThePEG/Utilities/TypeInfo.h" #include "ThePEG/Utilities/DynamicLoader.h" #include "ThePEG/Utilities/StringUtils.h" #include "ThePEG/Utilities/Throw.h" #include "ThePEG/PDT/DecayMode.h" #ifdef ThePEG_TEMPLATES_IN_CC_FILE #include "BaseRepository.tcc" #endif using namespace ThePEG; ostream *& BaseRepository::coutp() { static ostream * theCout = &std::cout; return theCout; } ostream *& BaseRepository::cerrp() { static ostream * theCerr = &std::cerr; return theCerr; } ostream *& BaseRepository::clogp() { static ostream * theClog = &std::clog; return theClog; } bool & BaseRepository::updating() { static bool theBool = false; return theBool; } ObjectMap & BaseRepository::objects() { static ObjectMap theObjectMap; return theObjectMap; } ObjectSet & BaseRepository::allObjects() { static ObjectSet theObjectSet; return theObjectSet; } BaseRepository::TypeInterfaceMap & BaseRepository::interfaces() { static TypeInterfaceMap theInterfaceMap; return theInterfaceMap; } BaseRepository::TypeDocumentationMap & BaseRepository::documentations() { static TypeDocumentationMap theDocumentationMap; return theDocumentationMap; } BaseRepository::DirectorySet & BaseRepository::directories() { static char root[1][2] = {"/"}; static DirectorySet theDirectories(root, root+1); return theDirectories; } vector<string> & BaseRepository::globalLibraries() { static vector<string> theGlobalLibraries; return theGlobalLibraries; } stack<string> & BaseRepository::currentReadDirStack() { static stack<string> theCurrentReadDirStack; if ( theCurrentReadDirStack.empty() ) theCurrentReadDirStack.push(""); return theCurrentReadDirStack; } vector<string> & BaseRepository::readDirs() { // macro is passed in from -D compile flag static vector<string> theReadDirs(1, THEPEG_PKGDATADIR); return theReadDirs; } void BaseRepository::prependReadDir(string dir) { readDirs().insert(readDirs().begin(), dir); } void BaseRepository::appendReadDir(string dir) { readDirs().push_back(dir); } BaseRepository::StringVector & BaseRepository::directoryStack() { static StringVector theDirectoryStack(1, "/"); return theDirectoryStack; } void BaseRepository::Register(const InterfaceBase & ib, const type_info & i) { const ClassDescriptionBase * db = DescriptionList::find(i); if ( db ) interfaces()[db].insert(&ib); } void BaseRepository:: Register(const ClassDocumentationBase & cd, const type_info & i) { const ClassDescriptionBase * db = DescriptionList::find(i); if ( db ) documentations()[db] = &cd; } void BaseRepository::Register(IBPtr ip, string newName) { DirectoryAppend(newName); ip->name(newName); Register(ip); } void BaseRepository::Register(IBPtr ip) { if ( !ip || member(allObjects(), ip) ) return; while ( member(objects(), ip->fullName()) ) ip->name(ip->fullName() + "#"); objects()[ip->fullName()] = ip; allObjects().insert(ip); ip->clear(); ip->update(); ip->touch(); } void BaseRepository::DirectoryAppend(string & name) { if ( name == "." ) name = directoryStack().back(); if ( name[0] != '/' ) name = directoryStack().back() + name; } void BaseRepository::CreateDirectory(string name) { DirectoryAppend(name); if ( name[name.size()-1] != '/' ) name += "/"; if ( member(directories(), name) ) return; directories().insert(name); name = name.substr(0, name.size() - 1); name = name.substr(0, name.rfind('/')); if ( name.size() ) CreateDirectory(name); } void BaseRepository::CheckObjectDirectory(string name) { if ( name[name.size() - 1] != '/' ) name = name.substr(0, name.rfind('/') + 1); CheckDirectory(name); } void BaseRepository::CheckDirectory(string name) { DirectoryAppend(name); if ( name[name.size()-1] != '/' ) name += "/"; if ( member(directories(), name) ) return; throw RepositoryNoDirectory(name); } void BaseRepository::ChangeDirectory(string name) { DirectoryAppend(name); if ( name[name.size()-1] != '/' ) name += "/"; if ( member(directories(), name) ) { directoryStack().back() = name; return; } throw RepositoryNoDirectory(name); } void BaseRepository::PushDirectory(string name) { DirectoryAppend(name); if ( name[name.size()-1] != '/' ) name += "/"; if ( member(directories(), name) ) { directoryStack().push_back(name); return; } throw RepositoryNoDirectory(name); } void BaseRepository::PopDirectory() { if ( directoryStack().size() > 1 ) directoryStack().pop_back(); } IBPtr BaseRepository::GetPointer(string name) { ObjectMap::iterator it = objects().find(name); return it == objects().end()? IBPtr(): it->second; } IVector BaseRepository::SearchDirectory(string name, string className) { IVector ret; DirectoryAppend(name); const ClassDescriptionBase * cdb = 0; if ( className.size() ) { cdb = DescriptionList::find(className); if ( !cdb ) return ret; } if ( name[name.size()-1] != '/' ) name += "/"; string::size_type size = name.size(); for ( ObjectMap::const_iterator i = objects().begin(); i != objects().end(); ++i ) { if ( cdb && !DescriptionList::find(typeid(*(i->second)))->isA(*cdb) ) continue; if ( i->first.substr(0, size) == name ) ret.push_back(i->second); } return ret; } IVector BaseRepository::GetObjectsReferringTo(IBPtr obj) { IVector ret; for ( ObjectMap::const_iterator i = objects().begin(); i != objects().end(); ++i ) { if ( obj == i->second ) continue; IVector ov = DirectReferences(i->second); if ( member(ov, obj) ) ret.push_back(i->second); } return ret; } IVector BaseRepository::DirectReferences(IBPtr obj) { IVector ov = obj->getReferences(); InterfaceMap interfaceMap = getInterfaces(typeid(*obj)); for ( InterfaceMap::iterator iit = interfaceMap.begin(); iit != interfaceMap.end(); ++iit ) { IVector ovi = iit->second->getReferences(*obj); ov.insert(ov.end(), ovi.begin(), ovi.end()); } return ov; } void BaseRepository:: addReferences(tIBPtr obj, ObjectSet & refs) { if ( !obj ) return; refs.insert(obj); IVector ov = obj->getReferences(); for ( IVector::const_iterator it = ov.begin(); it != ov.end(); ++it ) if ( !member(refs, *it) ) addReferences(*it, refs); InterfaceMap interfaceMap = getInterfaces(typeid(*obj)); for ( InterfaceMap::iterator iit = interfaceMap.begin(); iit != interfaceMap.end(); ++iit ) { IVector ov = iit->second->getReferences(*obj); for ( IVector::const_iterator it = ov.begin(); it != ov.end(); ++it ) if ( !member(refs, *it) ) addReferences(*it, refs); } } void BaseRepository:: addInterfaces(const ClassDescriptionBase & db, InterfaceMap & interfaceMap, bool all) { for ( ClassDescriptionBase::DescriptionVector::const_iterator it = db.descriptions().begin(); it != db.descriptions().end(); ++it ) if ( *it ) addInterfaces(**it, interfaceMap, all); TypeInterfaceMap::const_iterator cit = interfaces().find(&db); if ( cit == interfaces().end() ) return; for ( InterfaceSet::const_iterator iit = (cit->second).begin(); iit != (cit->second).end(); ++iit ) { string n = (**iit).name(); while ( all && member(interfaceMap, n) ) n = "+" + n; interfaceMap[n] = *iit; } } InterfaceMap BaseRepository::getInterfaces(const type_info & ti, bool all) { InterfaceMap interfaceMap; const ClassDescriptionBase * db = DescriptionList::find(ti); if ( !db ) return interfaceMap; addInterfaces(*db, interfaceMap, all); return interfaceMap; } void BaseRepository:: rebind(InterfacedBase & i, const TranslationMap & trans, const IVector & defaults) { InterfaceMap interfaceMap = getInterfaces(typeid(i), true); for ( InterfaceMap::iterator iit = interfaceMap.begin(); iit != interfaceMap.end(); ++iit ) iit->second->rebind(i, trans, defaults); i.rebind(trans); } void BaseRepository::update() { for_each(allObjects(), mem_fun(&InterfacedBase::update)); clearAll(allObjects()); } template <typename Set1, typename Set2> bool overlap(const Set1 & s1, const Set2 & s2) { typename Set1::const_iterator i1 = s1.begin(); typename Set2::const_iterator i2 = s2.begin(); while ( i1 != s1.end() && i2 != s2.end() ) { if ( *i1 == *i2 ) return true; if ( *i1 < *i2 ) { i1 = s1.lower_bound(*i2); if ( *i1 == *i2 ) return true; ++i1; } else { i2 = s2.lower_bound(*i1); if ( *i1 == *i2 ) return true; ++i2; } } return false; } void BaseRepository::remove(tIBPtr ip) { ObjectMap::iterator it = objects().find(ip->fullName()); if ( it == objects().end() || ip != it->second ) return; objects().erase(it); allObjects().erase(ip); } string BaseRepository::remove(const ObjectSet & rmset) { ObjectSet refset; for ( ObjectSet::const_iterator oi = rmset.begin(); oi != rmset.end(); ++oi ) { IVector ov = GetObjectsReferringTo(*oi); refset.insert(ov.begin(), ov.end()); } for ( ObjectSet::iterator oi = rmset.begin(); oi != rmset.end(); ++oi ) refset.erase(*oi); if ( refset.empty() ) { for ( ObjectSet::iterator oi = rmset.begin(); oi != rmset.end(); ++oi ) remove(*oi); return ""; } string ret = "Error: cannot remove the objects because the following " "objects refers to some of them:\n"; for ( ObjectSet::iterator oi = refset.begin(); oi != refset.end(); ++oi ) ret += (**oi).fullName() + "\n"; return ret; } void BaseRepository::rename(tIBPtr ip, string newName) { ObjectSet::iterator it = allObjects().find(ip); if ( it == allObjects().end() ) { Register(ip, newName); return; } ObjectMap::iterator mit = objects().find(ip->fullName()); if ( mit == objects().end() || mit->second != ip ) throw RepoNameException(ip->fullName()); objects().erase(mit); ip->name(newName); while ( member(objects(), ip->fullName()) ) ip->name(ip->fullName() + "#"); objects()[ip->fullName()] = ip; } const InterfaceBase * BaseRepository::FindInterface(IBPtr ip, string name) { InterfaceMap imap = getInterfaces(typeid(*ip), false); InterfaceMap::iterator it = imap.find(name); return it == imap.end()? 0: it->second; } const ClassDocumentationBase * BaseRepository::getDocumentation(tcIBPtr ip) { TypeDocumentationMap::const_iterator cdoc = documentations().find(DescriptionList::find(typeid(*ip))); return cdoc != documentations().end()? cdoc->second: 0; } string BaseRepository::getModelDescription(tcIBPtr ip) { const ClassDocumentationBase * cd = getDocumentation(ip); return cd? cd->modelDescription(): string(""); } string BaseRepository::getModelReferences(tcIBPtr ip) { const ClassDocumentationBase * cd = getDocumentation(ip); return cd? cd->modelReferences(): string(""); } IBPtr BaseRepository::TraceObject(string path) { DirectoryAppend(path); string::size_type colon = path.find(':'); IBPtr ip = GetPointer(path.substr(0, colon)); if ( !ip ) { // Do special check if this is a decay mode. string name = path.substr(0, colon); string::size_type slash = name.rfind('/'); if ( slash != string::npos ) name = name.substr(slash + 1); if ( name.find("->") != string::npos && name[name.length() - 1] == ';' ) { vector<DMPtr> save; DMPtr dm = DecayMode::constructDecayMode(name, &save); if ( dm ) ip = dynamic_ptr_cast<DMPtr>(GetPointer(path.substr(0, slash + 1) + dm->tag())); if ( ip ) Throw<Exception>() << "Warning: rewriting DecayMode name '" << path.substr(0, colon).substr(slash + 1) << "' to '" << ip->name() << Exception::warning; } } while ( colon != string::npos ) { if ( !ip ) throw RepositoryNotFound(path); path = path.substr(colon+1); colon = path.find(':'); string::size_type bra = path.find('['); const InterfaceBase * ifb = FindInterface(ip, path.substr(0, min(colon, bra))); const ReferenceBase * rb = dynamic_cast<const ReferenceBase *>(ifb); if ( rb ) { ip = rb->get(*ip); continue; } const RefVectorBase * rvb = dynamic_cast<const RefVectorBase *>(ifb); if ( rvb ) { unsigned int place = 0; if ( bra < colon ) { string::size_type ket = path.find(']'); place = atoi(path.substr(bra + 1,ket - bra - 1).c_str()); } IVector iv = rvb->get(*ip); if ( place >= iv.size() ) throw RepositoryNotFound(path); ip = iv[place]; continue; } const CommandBase * cb = dynamic_cast<const CommandBase *>(ifb); if ( cb ) { string::size_type ket = path.find(']'); string newobj = cb->cmd(*ip, path.substr(bra + 1,ket - bra - 1)); ip = GetPointer(newobj); continue; } throw RepositoryNotFound(path); } if ( !ip ) throw RepositoryNotFound(path); return ip; } IBPtr BaseRepository::getObjectFromNoun(string noun) { string::size_type colon = noun.rfind(':'); return TraceObject(noun.substr(0, colon)); } string BaseRepository::getInterfaceFromNoun(string noun) { string::size_type colon = noun.rfind(':'); string interface = noun.substr(colon+1); string::size_type bra = interface.find('['); if ( bra != string::npos ) return interface.substr(0, bra); else return interface; } string BaseRepository::getPosArgFromNoun(string noun) { string::size_type colon = noun.rfind(':'); string interface = noun.substr(colon+1); string::size_type bra = interface.find('['); if ( bra != string::npos ) { string::size_type ket = interface.find(']'); return interface.substr(bra + 1,ket - bra - 1); } return ""; } string BaseRepository:: GetInterfacedBaseClasses(const ClassDescriptionBase * cdb) { if ( !cdb || cdb->name() == "ThePEG::Interfaced" || cdb->name() == "ThePEG::InterfacedBase" ) return ""; string ret = cdb->name() + "\n"; for ( int i = 0, N = cdb->descriptions().size(); i < N; ++i ) ret += GetInterfacedBaseClasses(cdb->descriptions()[i]); return ret; } struct InterfaceOrder { bool operator()(const InterfaceBase * x, const InterfaceBase * y) const { return x->rank() > y->rank() || ( x->rank() == y->rank() && x->name() < y->name() ); } }; void BaseRepository::readSetup(tIBPtr ip, istream & is) { ip->setup(is); } string BaseRepository::exec(string command, ostream &) { string verb = StringUtils::car(command); command = StringUtils::cdr(command); if ( verb.empty() || verb[0] == '#' ) return ""; try { if ( verb == "DISABLEREADONLY" ) { InterfaceBase::NoReadOnly = true; return ""; } if ( verb == "ENABLEREADONLY" ) { InterfaceBase::NoReadOnly = false; return ""; } if ( verb == "cd" || verb == "pushd" || verb == "mkdir") { string dir = StringUtils::car(command); if ( verb == "cd" ) ChangeDirectory(dir); else if ( verb == "pushd" ) PushDirectory(dir); else CreateDirectory(dir); return ""; } if ( verb == "popd" ) { PopDirectory(); return ""; } if ( verb == "pwd" ) return directoryStack().back(); if ( verb == "dirs" ) { string ret; for ( StringVector::reverse_iterator it = directoryStack().rbegin(); it != directoryStack().rend(); ++it ) ret += *it; return ret; } if ( verb == "cp" || verb == "mv" ) { string oldname = StringUtils::car(command); DirectoryAppend(oldname); IBPtr obj = GetPointer(oldname); if ( !obj ) return "Error: No object named '" + oldname + "' available."; command = StringUtils::cdr(command); string newname = StringUtils::car(command); DirectoryAppend(newname); if ( newname[newname.size() - 1] == '/' ) newname += obj->name(); if ( verb == "cp" ) obj = obj->fullclone(); rename(obj, newname); return ""; } if ( verb == "check" ) { string name = StringUtils::car(command); if ( directories().find(name) != directories().end() ) return name; if ( objects().find(name) != objects().end() ) return name; return "Not found"; } if ( verb == "ls" ) { string className; string dir = StringUtils::car(command); if ( dir.size() ) { PushDirectory(dir); command = StringUtils::cdr(command); className = StringUtils::car(command); } string ret; string thisdir = directoryStack().back(); for ( DirectorySet::iterator it = directories().begin(); it != directories().end(); ++it ) { string d = *it; if ( d.size() <= thisdir.size() ) continue; string d0 = d.substr(0, thisdir.size()); string d1 = d.substr(thisdir.size()); if ( d0 == thisdir && d1.find('/') == d1.size() - 1 ) { if ( className.size() && SearchDirectory(d, className).empty() ) continue; ret += (dir.size()? d: d1) + "\n"; } } for ( ObjectMap::iterator it = objects().begin(); it != objects().end(); ++it ) { if ( className.size() ) { const ClassDescriptionBase * cdb = DescriptionList::find(className); if ( cdb && !DescriptionList::find(typeid(*(it->second)))->isA(*cdb) ) continue; } if ( thisdir + it->second->name() == it->first ) ret += (dir.size()? it->first: it->second->name()) + '\n'; } if ( dir.size() ) PopDirectory(); return ret; } if ( verb == "library" ) { string library = StringUtils::car(command); if ( library.empty() ) return "Error: No library specified."; if ( !DynamicLoader::load(library) ) return "Error: Could not load library " + library + "\n - " + DynamicLoader::lastErrorMessage; return ""; } if ( verb == "globallibrary" ) { string library = StringUtils::car(command); if ( library.empty() ) return "Error: No library specified."; if ( !DynamicLoader::load(library) ) return "Error: Could not load library " + library + "\n - " + DynamicLoader::lastErrorMessage; globalLibraries().push_back(library); return ""; } if ( verb == "rmgloballibrary" ) { string library = StringUtils::car(command); if ( library.empty() ) return "Error: No library specified."; vector<string>::iterator it; while ( (it = find(globalLibraries(), library)) != globalLibraries().end() ) globalLibraries().erase(it); return ""; } if ( verb == "appendpath" ) { string path = StringUtils::car(command); if ( !path.empty() ) DynamicLoader::appendPath(path); return ""; } if ( verb == "lspaths" ) { string paths; for ( int i = 0, N = DynamicLoader::allPaths().size(); i < N; ++i ) paths += DynamicLoader::allPaths()[i] + "\n"; return paths; } if ( verb == "prependpath" ) { string path = StringUtils::car(command); if ( !path.empty() ) DynamicLoader::prependPath(path); return ""; } if ( verb == "create" ) { string className = StringUtils::car(command); command = StringUtils::cdr(command); string name = StringUtils::car(command); const ClassDescriptionBase * db = DescriptionList::find(className); command = StringUtils::cdr(command); while ( !db && command.length() ) { string library = StringUtils::car(command); command = StringUtils::cdr(command); DynamicLoader::load(library); db = DescriptionList::find(className); } if ( !db ) { string msg = "Error: " + className + ": No such class found."; if ( !DynamicLoader::lastErrorMessage.empty() ) msg += "\nerror message from dynamic loader:\n" + DynamicLoader::lastErrorMessage; return msg; } IBPtr obj = dynamic_ptr_cast<IBPtr>(db->create()); if ( !obj ) return "Error: Could not create object of class "+className; if ( name.empty() ) return "Error: No name specified."; Register(obj, name); return ""; } if ( verb == "setup" ) { string name = StringUtils::car(command); DirectoryAppend(name); IBPtr obj = GetPointer(name); if ( !obj ) return "Error: Could not find object named " + name; istringstream is(StringUtils::cdr(command)); readSetup(obj, is); return ""; } if ( verb == "rm" ) { ObjectSet rmset; while ( !command.empty() ) { string name = StringUtils::car(command); DirectoryAppend(name); IBPtr obj = GetPointer(name); if ( !obj ) return "Error: Could not find object named " + name; rmset.insert(obj); command = StringUtils::cdr(command); } return remove(rmset); } if ( verb == "rmdir" || verb == "rrmdir" ) { string dir = StringUtils::car(command); DirectoryAppend(dir); if ( dir[dir.size() - 1] != '/' ) dir += '/'; if ( !member(directories(), dir) ) return verb == "rmdir"? "Error: No such directory.": ""; IVector ov = SearchDirectory(dir); if ( ov.size() && verb == "rmdir" ) return "Error: Cannot remove a non-empty directory. " "(Use rrmdir do remove all object and subdirectories.)"; ObjectSet rmset(ov.begin(), ov.end()); string ret = remove(rmset); if ( !ret.empty() ) return ret; StringVector dirs(directories().begin(), directories().end()); for ( int i = 0, N = dirs.size(); i < N; ++ i ) if ( dirs[i].substr(0, dir.size()) == dir ) directories().erase(dirs[i]); for ( int i = 0, N = directoryStack().size(); i < N; ++i ) if ( directoryStack()[i].substr(0, dir.size()) == dir ) directoryStack()[i] = '/'; return ""; } if ( verb == "rcp" ) { string name = StringUtils::car(command); DirectoryAppend(name); string newName = StringUtils::car(StringUtils::cdr(command)); if ( newName.empty() ) return "Error: No destination directory specified."; DirectoryAppend(newName); CreateDirectory(newName); if ( newName[newName.size() - 1] != '/' ) newName += '/'; IBPtr obj = GetPointer(name); if ( name[name.size() - 1] != '/' ) name += '/'; IVector ov = SearchDirectory(name); ov.push_back(obj); if ( ov.empty() ) return "Error: No such object or directory."; ObjectSet toclone; for ( IVector::iterator i = ov.begin(); i != ov.end(); ++i ) { toclone.insert(*i); addReferences(*i, toclone); } for ( ObjectSet::iterator i = toclone.begin(); i != toclone.end(); ++i ) Register((**i).clone(), newName + (**i).name()); return ""; } if ( verb == "doxygendump" ) { string spacename = StringUtils::car(command); command = StringUtils::cdr(command); string filename = StringUtils::car(command); ofstream os(filename.c_str()); for ( TypeDocumentationMap::const_iterator it = documentations().begin(); it != documentations().end(); ++it ) { const ClassDescriptionBase & db = *(it->first); string classname = db.name(); if ( classname.substr(0, spacename.length()) != spacename ) continue; string briefname = classname.substr(spacename.length()); os << "/** \\page " << briefname << "Interfaces " << "Interfaces defined for the " << classname << " class.\n\n" << "\\par Brief class description:\n"; string doc = it->second->documentation(); if ( doc.substr(0,25) == "There is no documentation" ) os << "See " << classname << "\n\n"; else os << doc << "<br>See also " << classname << "\n\n"; TypeInterfaceMap::const_iterator isit = interfaces().find(it->first); if ( isit == interfaces().end() || isit->second.empty() ) { os << "There are no interfaces declared for this class.\n\n"; } else { const InterfaceSet & ints = isit->second; for ( InterfaceSet::const_iterator iit = ints.begin(); iit != ints.end(); ++iit ) (**iit).doxygenDescription(os); } string baserefs = ""; int nbases = 0; for ( int ib = 0, N = db.descriptions().size(); ib < N; ++ib ) { if ( documentations().find(db.descriptions()[ib]) == documentations().end() ) continue; const ClassDescriptionBase & bdb = *db.descriptions()[ib]; if ( nbases ) baserefs += " and "; string briefname = bdb.name().substr(bdb.name().rfind("::") + 2); baserefs += "\\ref " + briefname + "Interfaces \"" + bdb.name() + "\""; ++nbases; } if ( nbases == 1 ) os << "<hr>There may be interfaces inherited from the " << baserefs << " class."; else if ( nbases > 1 ) os << "<hr>There may be interfaces inherited from the " << "following classes: " << baserefs << "."; os << "\n\n*/\n\n"; } return ""; } if ( verb == "mset" || verb == "msetdef" || verb == "minsert" || verb == "mdo" || verb == "mget" || verb == "mdef" || verb == "mmin" || verb == "mmax" || verb == "merase" || verb == "msend" ) { if ( verb == "msend" ) verb = "mdo"; string dir = StringUtils::car(command); command = StringUtils::cdr(command); string className = StringUtils::car(command); command = StringUtils::cdr(command); string interface = StringUtils::car(command); string arguments = StringUtils::cdr(command); string::size_type bra = interface.find('['); if ( bra != string::npos ) { string::size_type ket = interface.find(']'); arguments = interface.substr(bra + 1,ket - bra - 1) + " " + arguments; interface = interface.substr(0, bra); } IVector ov = SearchDirectory(dir, className); if ( ov.empty() ) return "Error: no matching objects found."; string ret; verb = verb.substr(1); for ( IVector::size_type i = 0; i < ov.size(); ++i ) { const InterfaceBase * ifb = FindInterface(ov[i], interface); if ( !ifb ) continue; string mess = ifb->exec(*ov[i], verb, arguments); if ( !mess.empty() ) ret += ov[i]->fullName() + ": " + mess + "\n"; } return ret.substr(0, ret.size() - 1); } if ( verb == "set" || verb == "setdef" || verb == "insert" || verb == "do" || verb == "get" || verb == "def" || verb == "min" || verb == "max" || verb == "describe" || verb == "fulldescribe" || - verb == "erase" || verb == "send" || verb == "newdef" ) { + verb == "erase" || verb == "clear" || verb == "send" || verb == "newdef" ) { if ( verb == "send" ) verb = "do"; if ( verb == "newdef" && !InterfaceBase::NoReadOnly ) return "Error: The default value of an interface is a read-only " "entity. Use the command 'DISABLEREADONLY' to override."; string noun = StringUtils::car(command); string arguments = getPosArgFromNoun(noun) + " " + StringUtils::cdr(command); IBPtr ip = getObjectFromNoun(noun); const InterfaceBase * ifb = FindInterface(ip, getInterfaceFromNoun(noun)); if ( !ifb && verb != "describe" && verb != "fulldescribe" ) { string ret = "Error: The interface '" + noun + "' was not found.\n"; ret += "Valid interfaces:\n"; InterfaceMap imap = getInterfaces(typeid(*ip)); for ( InterfaceMap::iterator it = imap.begin(); it != imap.end(); ++it ) ret += "* " + it->second->name() + "\n"; return ret; } if ( verb == "describe" ) { if ( ifb ) return ifb->description(); const ClassDescriptionBase * cd = DescriptionList::find(typeid(*ip)); string ret = "Object '" + ip->name() + "' of class '" + cd->name() + "':\n"; TypeDocumentationMap::const_iterator cdoc = documentations().find(cd); if ( cdoc != documentations().end() ) ret += cdoc->second->documentation() + "\n"; ret +="Interfaces:\n"; InterfaceMap imap = getInterfaces(typeid(*ip)); for ( InterfaceMap::iterator it = imap.begin(); it != imap.end(); ++it ) ret += "* " + it->second->name() + "\n"; return ret; } else if ( verb == "fulldescribe" ) { if ( ifb ) return ifb->fullDescription(*ip); ostringstream ret; const ClassDescriptionBase * cd = DescriptionList::find(typeid(*ip)); TypeDocumentationMap::const_iterator cdoc = documentations().find(cd); ret << ip->fullName() << endl << cd->name() << endl; if ( cdoc != documentations().end() ) ret << cdoc->second->documentation() << endl; ret << "Interfaces:" << endl; InterfaceMap imap = getInterfaces(typeid(*ip)); typedef set<const InterfaceBase *, InterfaceOrder> InterfaceSet; InterfaceSet iset; for ( InterfaceMap::iterator it = imap.begin(); it != imap.end(); ++it ) iset.insert(it->second); double rank = 1.0; for ( InterfaceSet::iterator it = iset.begin(); it != iset.end(); ++it ) { if ( rank >= 0.0 && (**it).rank() < 0.0 ) ret << "0" << endl; rank = (**it).rank(); ret << (**it).type() << " " << (**it).name() << endl; } return ret.str(); } else return ifb->exec(*ip, verb, arguments); } if ( verb == "baseclasses" ) { string className = StringUtils::car(command); const ClassDescriptionBase * cdb = 0; if ( className.size() ) { cdb = DescriptionList::find(className); if ( !cdb ) return "Error: no class '" + className + "' found."; } return GetInterfacedBaseClasses(cdb); } if ( verb == "describeclass" ) { string className = StringUtils::car(command); const ClassDescriptionBase * cdb = 0; if ( className.size() ) { cdb = DescriptionList::find(className); if ( !cdb ) return "Error: no class '" + className + "' found."; } TypeDocumentationMap::const_iterator cdoc = documentations().find(cdb); if ( cdoc != documentations().end() ) return cdoc->second->documentation() + "\n"; else return ""; } if ( verb == "lsclass" ) { string className = StringUtils::car(command); const ClassDescriptionBase * cdb = 0; if ( className.size() ) { cdb = DescriptionList::find(className); if ( !cdb ) return "Error: no class '" + className + "' found."; } vector<const ClassDescriptionBase *> classes; if ( cdb && !cdb->abstract() ) classes.push_back(cdb); for ( DescriptionList::DescriptionMap::const_iterator it = DescriptionList::all().begin(); it != DescriptionList::all().end(); ++it ) { if ( it->second == cdb || it->second->abstract() ) continue; if ( cdb && !it->second->isA(*cdb) ) continue; classes.push_back(it->second); } if ( classes.empty() ) return "Error: no classes found."; string ret; for ( int i = 0, N = classes.size(); i < N; ++i ) ret += classes[i]->name() + "\n"; return ret; } } catch (const Exception & e) { e.handle(); return "Error: " + e.message(); } return "Error: Unrecognized command '" + verb + "'."; } BadClassClone::BadClassClone(const InterfacedBase & o) { theMessage << "Could not clone the object '" << o.name() << "' of class '" << TypeInfo::name(o) << "' because the class does not" << " implement a working 'clone' method."; severity(abortnow); } BadClone::BadClone(const InterfacedBase & o) { theMessage << "Could not clone the object '" << o.name() << "' of class '" << TypeInfo::name(o) << "' because the clone method threw an unknown exception."; severity(abortnow); } RepoNameException::RepoNameException(string name) { theMessage << "The object '" << name << "' is present in the Repository but " << "under a different name. This means that the name of the " << "object has been illegally changed outside of the Repository."; severity(abortnow); } RepositoryNoDirectory::RepositoryNoDirectory(string name) { theMessage << "The directory '" << name << "' does not exist."; severity(warning); } RepositoryNotFound::RepositoryNotFound(string name) { theMessage << "There was no object named '" << name << "' in the repository."; severity(warning); } RepositoryClassMisMatch:: RepositoryClassMisMatch(const InterfacedBase & o, string name) { theMessage << "The requested object '" << o.fullName() << "' was not of the " << "specified type (" << name << ")."; severity(warning); }