Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members | Related Pages | Examples

vos/corelibs/vos/metaobject.hh

Go to the documentation of this file.
00001 /*
00002     This file is part of the Virtual Object System of
00003     the Interreality project (http://interreality.org).
00004 
00005     Copyright (C) 2001-2003 Peter Amstutz
00006 
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Lesser General Public
00009     License as published by the Free Software Foundation; either
00010     version 2 of the License, or (at your option) any later version.
00011 
00012     This library is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     Lesser General Public License for more details.
00016 
00017     You should have received a copy of the GNU Lesser General Public
00018     License along with this library; if not, write to the Free Software
00019     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00020 
00021     Peter Amstutz <tetron@interreality.org>
00022 */
00023 #ifndef _METAOBJECT_HH_
00024 #define _METAOBJECT_HH_
00025 
00026 #include <stdexcept>
00027 #include <typeinfo>
00028 #include <vos/corelibs/vos/vosdefs.hh>
00029 #include <vos/corelibs/vos/vobject.hh>
00030 
00031 namespace VOS
00032 {
00033 /** @class MetaObject metaobject.hh vos/corelibs/vos/metaobject.hh
00034   
00035     This class is responsible for managing a group of object
00036     extensions under a single logical Vobject.  Messages sent to it
00037     using sendMessage() and sendUpdateMessage() are propagated to any
00038     extension plugins which have been attached to it.  Metaobjects
00039     allow you to switch between multiple interfaces using meta_cast,
00040     allowing you to request a certain C++ class interface such as
00041     Property or Talkative from a given Vobject, if the Vobject has
00042     that type.
00043  */
00044 class VOS_API MetaObject : public virtual Vobject
00045 {
00046 private:
00047     std::deque<MetaObject*> typehandlers;    ///< Type extensions for this metaobject.
00048     std::set<std::string> touchedNonces;
00049 protected:
00050     MetaObject(MetaObject* superobject);
00051     MetaObject* superobject;
00052 
00053     /** This is where you put type-handler specific save state code.
00054         @param output The messageblock to append your messages to
00055         @param types The types for the object that should be output as
00056         part of this save state. Some save state handlers may want to
00057         modify this.
00058         @see Vobject::saveState
00059     */
00060     virtual void doSaveState(MessageBlock& output, std::set<std::string>& types, bool portable);
00061 
00062     /** This is where you put type-handler specific code to respond to an excise().
00063         It will be called exactly once.
00064     */
00065     virtual void doExcise();
00066 
00067 public:
00068     /** destructor */
00069     virtual ~MetaObject();
00070 
00071     /** Add an instantiated extension object to this metaobject.  End
00072         users generally shouldn't need to do this, use
00073         MetaFactory::extendLocalObject() instead.
00074         @note Extension object is @em deleted when the destructor for
00075         this metaobject is called.
00076         @param moe the metaobject to be added
00077     */
00078     virtual void addObjectExtension(MetaObject* moe);
00079 
00080     /** @returns the specific MOS type name that represents the MOS
00081         interface this object is supplying.
00082     */
00083     virtual const std::string getType();
00084 
00085     /** Get the superobject (the object immediately
00086         containing this metaobject)
00087         @returns the superobject
00088     */
00089     MetaObject* getSuperObject();
00090 
00091     /** Get the 'top' superobject, that is, the root of the metaobject tree.
00092         @returns the top superobject
00093     */
00094     MetaObject* getTopObject();
00095 
00096     /** Get a vector of the extension object contained in this metaobject.
00097         @returns a list of extensions
00098      */
00099     const std::deque<MetaObject*>& getTypeHandlers();
00100 
00101     /** Initialize the security policy of a newly created local metaobject.
00102         @param requester the object that requested the creation of this type extension
00103      */
00104     virtual void initializeSecurity(Vobject& requester);
00105 
00106     virtual const std::string& getName();
00107     virtual Site& getSite();
00108     virtual const URL& getURL();
00109     virtual bool isLocal();
00110     virtual bool isRemote();
00111     virtual const TypeSet& getTypes() throw (AccessControlError, RemoteError);
00112     virtual void addType(const std::string& s);
00113     virtual const ParentSet& getParents()
00114         throw (AccessControlError, RemoteError);
00115     virtual const ChildList& getChildren()
00116         throw (AccessControlError, RemoteError);
00117 
00118     virtual void sendMessage(Message* m);
00119     virtual void sendMessage(MessageBlock* m);
00120     virtual Message* receiveMessage() throw (MessageQueueEmptyError);
00121     virtual bool hasMessageAvailable();
00122 
00123     virtual void sendUpdateMessage(Message* m);
00124     virtual Message* receiveUpdateMessage() throw (MessageQueueEmptyError);
00125     virtual bool hasUpdateMessageAvailable();
00126 
00127     virtual Vobject& findObject(const std::string& path)
00128         throw (NoSuchSiteError, NoSuchObjectError, URL::BadURLError, AccessControlError, RemoteError);
00129     virtual ParentChildRelation& findChild(const std::string& path)
00130         throw (NoSuchObjectError, AccessControlError, RemoteError);
00131     virtual Vobject::ParentChildRelation& findParent(Vobject& parent)
00132         throw (NoSuchObjectError, AccessControlError, RemoteError);
00133     virtual void setChild(int position, const std::string& contextual_name, Vobject* child)
00134         throw (AccessControlError, RemoteError);
00135     virtual void insertChild(int position, const std::string& contextual_name, Vobject* child)
00136         throw (AccessControlError, RemoteError);
00137     virtual void removeChild(int position)
00138         throw (AccessControlError, RemoteError);
00139 
00140     virtual void addTypeListener(TypeChangeListener* tl, bool notifyImmediately = true);
00141     virtual void addParentListener(ParentChangeListener* pl, bool notifyImmediately = true);
00142     virtual void addChildListener(ChildChangeListener* cl, bool notifyImmediately = true);
00143     virtual void removeTypeListener(TypeChangeListener* tl);
00144     virtual void removeParentListener(ParentChangeListener* pl);
00145     virtual void removeChildListener(ChildChangeListener* cl);
00146 
00147     virtual void saveState(MessageBlock& output, std::set<std::string>& types, bool portable);
00148 
00149     virtual void addFlag(const std::string& flag);
00150     virtual void removeFlag(const std::string& flag);
00151     virtual bool checkFlag(const std::string& flag);
00152 
00153     /** @note Important: this is delegated to the top object, and
00154         means you want the entire logical Vobject to go away!  If
00155         called on an object with no superobject, it calls doExcise() on its type
00156         handlers.  Type implementation specific cleanup code (such as
00157         calling excise on certain children no longer needed) should
00158         override doExcise().
00159     */
00160     virtual void excise();
00161 
00162     /** Note that this means you have a handle on the entire logical object! */
00163     virtual void acquire();
00164 
00165     /** Note that this means you are releasing the entire logical object! */
00166     virtual void release();
00167 
00168     /** Note that this counts for the entire logical object! */
00169     virtual int getCount();
00170 
00171     /** Some MetaObject subclasses provide an initialize method to
00172      * create required subobjects with default values, to set a default
00173      * property access control policy, etc.
00174      * Calling this method on a top level MetaObject will call initialize()
00175      * on each of it's type extensions. e.g.:
00176      * @code
00177      * MetaObject* foo = site->createMetaObject("foo", typeid(A3DL::Cube).name(), typeid(Hypercard).name(), 0);
00178      * foo->initialize();
00179      *                       // calls A3DL::Cube::initialize() and  Hypercard::initialize()
00180      * MetaObject::meta_cast<Hypercard*>(foo)->initialize();
00181      *                       // just call Hypercard::initialize().
00182      * @endcode
00183      */
00184     virtual void initialize();
00185 
00186     /** A specialized cast allowing you to switch between different
00187         extension plugins in the same logical object.  It first attempts to
00188         dynamic_cast the Vobject into a MetaObject, and then searches the
00189         metaobject type tree of this for an instance of an extension
00190         that satisfied the requested type.
00191         @param v the object to be cast
00192     */
00193     template<class C> static C meta_cast(Vobject* v)
00194         {
00195             if(C ret = dynamic_cast<C>(v)) return ret;
00196             else if(MetaObject* m = dynamic_cast<MetaObject*>(v)) return meta_cast<C>(m);
00197             else return 0;
00198         }
00199 
00200     /** A specialized cast allowing you to switch between different
00201         extension plugins in the same logical object.  It first attempts to
00202         dynamic_cast the Vobject into a MetaObject, and then searches the
00203         metaobject type tree of this for an instance of an extension
00204         that satisfied the requested type.
00205         @param v the object to be cast
00206     */
00207     template<class C> static C meta_cast(Vobject& v) throw (bad_cast) 
00208     {
00209         try {
00210             C ret = dynamic_cast<C>(v);
00211             return ret;
00212         } catch(bad_cast) {
00213             MetaObject& m = dynamic_cast<MetaObject&>(v);
00214             return meta_cast<C>(m);
00215         }
00216     }
00217 
00218     /** A specialized cast allowing you to switch between different
00219         extension plugins in the same logical object. It searches the
00220         metaobject type tree of this for an instance of an extension
00221         that satisfied the requested type.  You can cast any member of
00222         a logical object to any other member.  For example:
00223         @code
00224         LocalMetaObject* l = MetaFactory::createLocalMetaObject(mysite,
00225                                                                 typeid(Property).name(),
00226                                                                 typeid(World).name(),
00227                                                                 0);
00228         Property* p = MetaObject::meta_cast<Property*>(l);
00229         World* w = MetaObject::meta_cast<World*>(p);
00230         @endcode
00231         @param v the object to be cast
00232         @param fromsuper Whether this search invocation started from
00233         the root, to avoid backtracking.  You don't (and shouldn't) need to specify this.
00234     */
00235     template<class C> static C meta_cast(MetaObject* v, bool fromsuper=false)
00236         {
00237             if(!fromsuper && v->superobject != 0) return meta_cast<C>(v->superobject, false);
00238             if(C ret = dynamic_cast<C>(v)) {
00239                 return ret;
00240             } else {
00241                 for(std::deque<MetaObject*>::iterator i=v->typehandlers.begin();
00242                     i != v->typehandlers.end();
00243                     i++) {
00244                     if(C ret = meta_cast<C>(*i, true)) return ret;
00245                 }
00246             }
00247             return 0;
00248         }
00249 
00250     /** A specialized cast allowing you to switch between different
00251         extension plugins in the same logical object.  It searches the
00252         metaobject type tree of this for an instance of an extension
00253         that satisfied the requested type.  You can cast any member of
00254         a logical object to any other member.  For example:
00255         @code
00256         LocalMetaObject* l = MetaFactory::createLocalMetaObject(mysite, typeid(Property).name(),
00257                                                                 typeid(World).name(), 0);
00258         Property& p = MetaObject::meta_cast<Property&>(*l);
00259         World& w = MetaObject::meta_cast<World&>(p);
00260         @endcode
00261         @param v the object to be cast
00262         @param fromsuper Whether this search invocation started from
00263         the root, to avoid backtracking.  You don't (and shouldn't) need to specify this.  */
00264     template<class C> static C meta_cast(MetaObject& v, bool fromsuper=false) throw (bad_cast)
00265     {
00266         if(!fromsuper && v.superobject != 0) {
00267              return meta_cast<C>(*(v.superobject), false);
00268         }
00269         try {
00270             return dynamic_cast<C>(v);
00271         } catch(bad_cast) {
00272             for(std::deque<MetaObject*>::iterator i=v.typehandlers.begin();
00273                 i != v.typehandlers.end();
00274                 i++) {
00275                 try {
00276                     return meta_cast<C>(**i, true);
00277                 } catch(bad_cast){
00278                 }
00279             }
00280         } catch(runtime_error) {
00281         } catch(...) {
00282         }
00283         throw bad_cast();
00284     }
00285 
00286     template<class T> void addMessageHandler(const std::string& method, T* theobj,
00287                                              void (T::* MessageHandler)(Message*),
00288                                              bool addExHandler = false)
00289         {
00290             dynamic_cast<VobjectImplementation*>(getTopObject())->addMessageHandler<T>(method, theobj,
00291                                                                                        MessageHandler, addExHandler);
00292         };
00293     template<class T> void addUpdateHandler(const std::string& method, T* theobj,
00294                                             void (T::* MessageHandler)(Message*),
00295                                             bool addExHandler = false)
00296         {
00297             dynamic_cast<VobjectImplementation*>(getTopObject())->addUpdateHandler<T>(method, theobj,
00298                                                                                       MessageHandler, addExHandler);
00299         };
00300     template<class T> void removeMessageHandler(const std::string& method, T* theobj,
00301                                                 void (T::* MessageHandler)(Message*))
00302         {
00303             dynamic_cast<VobjectImplementation*>(getTopObject())->removeMessageHandler<T>(method, theobj, MessageHandler);
00304         };
00305     template<class T> void removeUpdateHandler(const std::string& method, T* theobj,
00306                                                void (T::* MessageHandler)(Message*))
00307         {
00308             dynamic_cast<VobjectImplementation*>(getTopObject())->removeUpdateHandler<T>(method, theobj, MessageHandler);
00309         };
00310 };
00311 
00312 /** This is a macro for the convenience of lazy typists. Note, it can only create
00313     objects with one type.  
00314     @deprecated Don't use this, use LocalSite::createMetaObject<TYPE>(name, ac).
00315     @param SITE A pointer or vRef to a Site
00316     @param CLASS Class to cast to and to use in creating the new object.
00317 */
00318 #define CREATE_METAOBJECT(SITE, CLASS) VOS::MetaObject::meta_cast<CLASS*>((SITE)->createMetaObject(#CLASS, typeid(CLASS).name(), 0))
00319 
00320 }
00321 
00322 #endif

Generated on Tue Aug 12 03:55:40 2003 for Interreality Project - VOS by doxygen 1.3.2