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

apps/tutorials/vostut7hello.cc

Go to the documentation of this file.
00001 /* Seventh VOS tutorial.  Creating your own MetaObjects
00002 
00003    This tutorial covers:
00004 
00005    This file (vostut7hello.cc) is released into the public domain.  No
00006    restrictions are placed on its use, distribution or inclusion into
00007    other works.
00008 */
00009 
00010 #include "vostut7hello.hh"
00011 
00012 
00013 // The hello constructor.  Nice and simple :-)
00014 
00015 Hello::Hello(MetaObject* superobject)
00016     : MetaObject(superobject)
00017 {
00018 }
00019 
00020 
00021 // Return the VOS type
00022 
00023 const string Hello::getType()
00024 {
00025     return "tutorial:hello";
00026 }
00027 
00028 
00029 // This will be called by applications wishing to use the "Hello" extension.
00030 
00031 void Hello::registerExtenders()
00032 {
00033     /* Registering an extension consists of supplying a type string
00034        and a function to call to construct a new metaobject for that
00035        type.  Here we associate the new_LocalHello function for the
00036        abstract class, the local class, and the VOS type name, meaning
00037        the user can call LocalSite::createMetaObject() with any of
00038        these three strings and get an object with the LocalHello extension.
00039     */
00040     LocalSite::addLocalObjectExtension(typeid(Hello).name(), &LocalHello::new_LocalHello);
00041     LocalSite::addLocalObjectExtension(typeid(LocalHello).name(), &LocalHello::new_LocalHello);
00042     LocalSite::addLocalObjectExtension("tutorial:hello", &LocalHello::new_LocalHello);
00043 
00044     /* Note that for remote objects the VOS type name is extremely
00045        important: it is the VOS type name we get from the network, and
00046        we use it to automatically instantiate the correct extensions
00047        for the newly discovered object.
00048      */
00049     RemoteSite::addRemoteObjectExtension(typeid(Hello).name(), &RemoteHello::new_RemoteHello);
00050     RemoteSite::addRemoteObjectExtension(typeid(RemoteHello).name(), &RemoteHello::new_RemoteHello);
00051     RemoteSite::addRemoteObjectExtension("tutorial:hello", &RemoteHello::new_RemoteHello);
00052 }
00053 
00054 
00055 // That's it for the base class!
00056 
00057 
00058 // Now for RemoteHello.
00059 
00060 // Now the constructor for LocalHello.
00061 
00062 RemoteHello::RemoteHello(MetaObject* superobject)
00063     : Hello(superobject)
00064 { }
00065 
00066 
00067 // The client stub implementation of hello.
00068 
00069 string RemoteHello::hello(const string& s)
00070 {
00071     // will hold return value
00072     string ret;
00073 
00074     vRef<Message> m = new Message();
00075 
00076     /* RemoteVobject::initFields is a convenience function to
00077        initialize some of the fields on the message, including
00078        generating a nonce.  A "nonce" is a unique identifier
00079        associated with this message that will be used to match the
00080        reply message (which will bear the same nonce).  This function
00081        also returns the local site which is peered to this remote
00082        site, which we need if we want to wait for a reply.
00083     */
00084     vRef<LocalSite> ls = RemoteVobject::initFields(this, &m, "tutorial:hello", true);
00085 
00086     m->insertField(-1, "word", s);
00087 
00088     /* Send it off.  Note: since 'this' is a remote object, by sending
00089        a message to 'this' we are actualy causing the message to be
00090        delivered to the actual vobject over the network.
00091     */
00092     sendMessage(&m);
00093 
00094 
00095     // get our (remote) site
00096     vRef<RemoteSite> site = dynamic_cast<RemoteSite&>(getSite());
00097 
00098     /* The waitFor() method will wait until either a message is
00099        received on our local site from the supplied remote site
00100        bearing the given nonce, or time runs out.  It returns the
00101        message that matches the nonce, or throws a TimeoutError if we
00102        ran out of time.  In other words, the purpose of this method is
00103        for "waiting for" a reply to a message which we have just sent.
00104     */
00105     vRef<Message> n = ls->waitFor(m->getNonce(), &site);
00106 
00107     try {
00108 
00109         // We got a reply back.  Extract the answer from the "text" field.
00110         ret = n->getField("word").value;
00111 
00112     } catch(Message::NoSuchFieldError) {
00113 
00114         // Whoops.  There wasn't a "text" field.
00115         // We could perhaps throw an exception here.
00116 
00117         ret = "***site did not return a text field***";
00118     }
00119 
00120     // return our results.
00121     return ret;
00122 }
00123 
00124 
00125 // Constructs a RemoteHello object and returns it.  This is a hack
00126 // necessary since you can't take the address of a constructor and
00127 // call it like a normal function or method pointer.
00128 
00129 MetaObject* RemoteHello::new_RemoteHello(MetaObject* superobject, const string& type)
00130 {
00131     return new RemoteHello(superobject);
00132 }
00133 
00134 
00135 // All done with RemoteHello!
00136 
00137 
00138 // Now the constructor for LocalHello.
00139 
00140 LocalHello::LocalHello(MetaObject* superobject)
00141     : Hello(superobject)
00142 {
00143     /* Here we add a method to be called when this Vobject receives a
00144        message with specific method field.  The addMessageHandler
00145        method associates the message method ("tutorial:hello") with a
00146        C++ method to call (&LocalHello::handleHello) and a particular
00147        object to call in on (this).  It is a template method to keep
00148        C++'s type checking happy.
00149     */
00150     addMessageHandler<LocalHello>("tutorial:hello", this, &LocalHello::handleHello);
00151 }
00152 
00153 
00154 // The actual hello method.  Yes, all the trouble just to access this
00155 // method over a network :-)
00156 
00157 string LocalHello::hello(const string& s)
00158 {
00159     return ("Hello there!  You said \"" + s + "\"");
00160 }
00161 
00162 
00163 
00164 // This is the handler method registered with addMessageHandler() and
00165 // called by VOS when a message bearing the method "tutorial:hello" is
00166 // received by this object.
00167 
00168 void LocalHello::handleHello(Message* m)
00169 {
00170     // Somebody has said hello to us.  We will act upon the message
00171     // and send a reply.
00172 
00173     vRef<Message> reply = new Message();
00174 
00175     // LocalVobject has a convenience method which will set
00176     // up the reply for us, such as initializing with the
00177     // correct nonce. See API documentation for details.
00178 
00179     LocalVobject::initReply(this, &reply, m, "tutorial:hello-reply");
00180 
00181 
00182     try {
00183         // Now call hello() with the field called "word".
00184 
00185         string s = hello(m->getField("word").value);
00186 
00187 
00188         // The result goes into a field called "word" in the reply.
00189 
00190         reply->insertField(-1, "word", s);
00191 
00192     } catch(Message::NoSuchFieldError) {
00193 
00194         // oops!  The message we got didn't have the field we were looking for.
00195         reply->insertField(-1, "error", "need a field \"word\"");
00196 
00197     }
00198 
00199     try {
00200         // Get a handle on the object that sent this message to us
00201         // and send it the reply.
00202 
00203         vRef<Vobject> v = findObject(m->getFrom());
00204 
00205         v->sendMessage(&reply);
00206 
00207     } catch(NoSuchSiteError) {
00208     } catch(NoSuchObjectError) {
00209     } catch(AccessControlError) {
00210     } catch(RemoteError) {
00211     } catch(URL::BadURLError) {
00212     }
00213 }
00214 
00215 
00216 // Constructs a LocalHello object and returns it.  This is a hack
00217 // necessary since you can't take the address of a constructor and
00218 // call it like a normal function or method pointer.
00219 
00220 MetaObject* LocalHello::new_LocalHello(MetaObject* superobject, const string& type)
00221 {
00222     return new LocalHello(superobject);
00223 }

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