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

apps/tutorials/vostut4.cc

Go to the documentation of this file.
00001 /* Fourth VOS tutorial.  Linking Vobjects together.
00002 
00003    This tutorial covers:
00004    - Inserting, replacing and removing Vobjects as children of other
00005    Vobjects
00006    - Linking local and remote Vobjects
00007    - Finding specific a child by name
00008    - Vobject paths
00009    - Listing a Vobject's children
00010    - Listing a Vobject's parents
00011 
00012    This file (vostut4.cc) is released into the public domain.  No
00013    restrictions are placed on its use, distribution or inclusion into
00014    other works.
00015 */
00016 
00017 #include <vos/corelibs/vos/vos.hh>
00018 
00019 void listChildren(Vobject* vobject);
00020 void listParents(Vobject* vobject);
00021 
00022 // The server from tutorial 3 ("vostut3server") should be run before
00023 // running this tutorial.
00024 
00025 int main(int argc, char** argv)
00026 {
00027     cout << "VOS Tutorial 4\n\n";
00028 
00029     LocalSocketSite localsite(&NoAccessControl::static_);
00030     localsite.setTimeoutOnSelect(-1);
00031 
00032     /* We saw in the previous tutorial how one Vobject can access
00033        another.  We now look at how Vobjects may be linked together to
00034        create network-accessable data structures.  In this tutorial,
00035        we demonstrate how one might build a data structure describing
00036        a sphere with VOS.
00037 
00038        A Vobject may consist of a number of incoming "parent" links
00039        and outgoing "child" links.  The terms parent and child come
00040        from common computer science usage for describing hierarchical
00041        structures.  At the top level is the local site, which is a
00042        parent to all Vobjects it hosts (and therefore has each Vobject
00043        as a child).  When a Vobject is created, it is automatically
00044        made a child of its site.
00045     */
00046 
00047     // Create some objects to play with.
00048     vRef<Vobject> sphere = localsite.createMetaObject("sphere", 0);
00049     vRef<Vobject> tertius = localsite.createMetaObject("tertius", 0);
00050     vRef<Vobject> quartus = localsite.createMetaObject("quartus", 0);
00051     vRef<Vobject> quintus = localsite.createMetaObject("quintus", 0);
00052     vRef<Vobject> sextus = localsite.createMetaObject("sextus", 0);
00053     vRef<Vobject> septimus = localsite.createMetaObject("septimus", 0);
00054 
00055     listChildren(&localsite);
00056     cout << "\n";
00057 
00058     /* Each Vobject stores a list other Vobjects it links to. This is
00059        called the child list.  It is an ordered, associative list,
00060        where each position in the list consists of a string called the
00061        "contextual name" and a link to the Vobject it points to.
00062 
00063        Initially, the Vobject "sphere" does not have any children.
00064        The insertChild() method is used to add children.  The first
00065        parameter tells where in the list to insert the child, with the
00066        value "-1" used to append to the end of the child list.  The
00067        link is named "position", so in our example the the linked-to
00068        child vobject (tertius) describes the position of its parent
00069        (the sphere).
00070     */
00071     cout << "Appending tertius as \"position\"\n";
00072     sphere->insertChild(-1, "position", &tertius);
00073 
00074     /* For the moment, don't worry about how the value of position
00075         will be stored in the tertius Vobject. This is discussed in a
00076         later tutorial.  For this tutorial we are concentrating on the
00077         abstract structure.
00078      */
00079 
00080     /* Print out the children of the sphere and the parents of
00081        tertius.  Since tertius has been added as a child to sphere,
00082        sphere is now listed as a parent of tertius.
00083     */
00084     listChildren(&sphere);
00085     listParents(&tertius);
00086     cout << "\n";
00087 
00088 
00089     /* Now we add a few more vobjects to the sphere.  As demonstrated
00090        here, the child list can have more than one link to the same
00091        Vobject and you can have multiple entries with the same
00092        contextual name.
00093     */
00094     cout << "Appending quartus as \"orientation\"\n";
00095     sphere->insertChild(-1, "orientation", &quartus);
00096 
00097     cout << "Appending quintus as \"radius\"\n";
00098     sphere->insertChild(-1, "radius", &quintus);
00099 
00100     cout << "Appending quartus as \"position\"\n";
00101     sphere->insertChild(-1, "position", &quartus);
00102 
00103     listChildren(&sphere);
00104     listParents(&quartus);
00105     cout << "\n";
00106 
00107 
00108     /* Of course we can insert a new item anywhere. We'll add the
00109        Vobject "sextus" describing the color of our sphere so that it
00110        occupies position 2.  This shifts the rest of the list (from
00111        position 2 to the end) up one position to make room for the
00112        newly inserted child.  Note: position 0 inserts a child at the
00113        beginning of the list.
00114     */
00115     cout << "Inserting sextus as \"color\" into position 2\n";
00116     sphere->insertChild(2, "color", &sextus);
00117 
00118     listChildren(&sphere);
00119     cout << "\n";
00120 
00121 
00122     /* Oops!  We have two children named "position"!  The sphere can't
00123        very well be in two places at once, can it?  The setChild()
00124        method allows us to replace a child at one position with
00125        another, which is much more efficient than removing the old
00126        vobject and inserting the new one.  Here we replace the second
00127        "position" child (at list position 4 now) with a
00128        different object that will store our sphere's mass.
00129     */
00130     cout << "Replacing quartus in position 4 with septimus as \"mass\"\n";
00131     sphere->setChild(4, "mass", &septimus);
00132 
00133     listChildren(&sphere);
00134     cout << "\n";
00135 
00136     /* It's also sort of silly for a sphere to have an orientation,
00137        seeing as how it is perfectly round.  Let's remove the child
00138        storing the orientation.  The removeChild() method removes the
00139        list item at the given position and move everything above it
00140        down a notch to fill in the gap.
00141      */
00142     cout << "Removing quintus (\"orientation\") from position 1\n";
00143     sphere->removeChild(1);
00144 
00145     listChildren(&sphere);
00146     cout << "\n";
00147 
00148 
00149     /*  Some detail specifying a position in a child list: positive
00150         positions are counted from the beginning and negative
00151         positions are counted from the end.  The start of the list is
00152         always 0 and the end of the list is always -1.  This means
00153         that positions of -2 (second-to-last position), -3, -10 and so
00154         on are perfectly legal (provided the list is at least of that
00155         length).
00156      */
00157     cout << "Removing septimus (\"mass\") from the last position\n";
00158     sphere->removeChild(-1);
00159 
00160     listChildren(&sphere);
00161     cout << "\n";
00162 
00163     try {
00164         /* What makes parent-child linking of Vobjects really
00165            interesting is the fact that you can freely mix local and
00166            remote Vobjects.  Here we acquire a remote object running
00167            on a different site and manipulate it exactly the same way
00168            as if it were local.
00169          */
00170         vRef<Vobject> primus = Vobject::findObjectFromRoot("vop://localhost:4231/primus");
00171 
00172         cout << "Adding local vobject septimus to remote to remote vobject primus\n";
00173         primus->insertChild(-1, "septimus", &septimus);
00174 
00175         listChildren(&primus);
00176         listParents(&septimus);
00177         cout << "\n";
00178 
00179 
00180         cout << "Adding remote vobject primus to local vobject quartus\n";
00181         quartus->insertChild(-1, "primus", &primus);
00182 
00183         listChildren(&quartus);
00184         listParents(&primus);
00185         cout << "\n";
00186     } catch(runtime_error& e) {
00187         cerr << "An exception occured: " << e.what() << "\n";
00188     }
00189 
00190     /* Once we have created a VOS data structure, we want to be able
00191        to access it. One way is by iterating over the entire contents
00192        of the child list (which is demonstrated in the listChildren()
00193        function below).  The other is to use the findChild() and
00194        findObject() methods.
00195 
00196        The findChild() method returns the Vobject::ParentChildRelation
00197        structure describing the link with the given contextual name.
00198        If more than one link has the same contextual name, then the
00199        link with position closest to the beginning is returned. This
00200        simply consists of four fields, the parent, the child, and the
00201        position and contextual name in the parent's child list.
00202     */
00203     vRef<Vobject::ParentChildRelation> pcr = sphere->findChild("color");
00204     cout << "Results of findChild():\n";
00205     cout << " Parent: " << pcr->parent->getURL().getString() << "\n";
00206     cout << " Position: " << pcr->position << "\n";
00207     cout << " Contextual name: " << pcr->contextual_name << "\n";
00208     cout << " Child: " << pcr->child->getURL().getString() << "\n";
00209 
00210     /* The findObject() method returns just the Vobject itself, but
00211        can take a path going through several Vobjects.  A Vobject path
00212        is a slash-separated list of contextual names to follow to find
00213        the Vobject.  It is intended to resemble a familiar file system
00214        path and works essentially the same way, although the notation
00215        ".." is not available.  While directories in a filesystem only
00216        have one parent directory, Vobjects usually have two or more
00217        parent Vobjects!
00218     */
00219     vRef<Vobject> color = localsite.findObject("sphere/color");
00220 
00221     listParents(&color);
00222 
00223     /* One final method for accessing parent-child relationships:
00224        findParent() returns the parent-child relationship structure
00225        associated with a specific parent of this Vobject.
00226     */
00227     vRef<Vobject::ParentChildRelation> pcr2 = color->findParent(*sphere);
00228     cout << "Results of findParent():\n";
00229     cout << " Parent: " << pcr2->parent->getURL().getString() << "\n";
00230     cout << " Position: " << pcr2->position << "\n";
00231     cout << " Contextual name: " << pcr2->contextual_name << "\n";
00232     cout << " Child: " << pcr2->child->getURL().getString() << "\n";
00233 
00234 
00235     cout << "Going into runloop now.  Try connecting to " << localsite.getURL().getString() << " using \"mesh\"\n";
00236     cout << "to inspect the current vobject structure.\n";
00237 
00238     while(true) {
00239         localsite.flushIncomingBuffers();
00240     }
00241 }
00242 
00243 void listChildren(Vobject* vobject)
00244 {
00245     // getChildren() returns the child list for this Vobject.  This is
00246     // a list of Vobject::ParentChildRelation structures.  It is
00247     // intended for read only access and you should never ever modify
00248     // the contents of this list directly.
00249     const Vobject::ChildList& childlist = vobject->getChildren();
00250 
00251     cout << "Children of " << vobject->getURL().getString() << ":\n";
00252 
00253     // You can efficiently iterate over the list with an int:
00254     for(int i = 0; i < childlist.size(); i++) {
00255         Vobject::ParentChildRelation* pcr = childlist[i];
00256         cout << " #" << pcr->position << " " << pcr->contextual_name << " -> "
00257              << pcr->child->getURL().getString() << "\n";
00258     }
00259 }
00260 
00261 void listParents(Vobject* vobject)
00262 {
00263     // getParents returns an STL set storing the
00264     // Vobject::ParentChildRelation structures describing each link to
00265     // this Vobject in some Vobject's child list.  As with the child
00266     // list, this is for read only access and you should never modify
00267     // this set directly.
00268     const Vobject::ParentSet& parentset = vobject->getParents();
00269 
00270     cout << "Parents of " << vobject->getURL().getString() << ":\n";
00271 
00272     // Use an STL const_iterator to iterate over this set.
00273     for(Vobject::ParentSet::const_iterator i = parentset.begin(); i != parentset.end(); i++) {
00274         Vobject::ParentChildRelation* pcr = *i;
00275         cout << " " << pcr->parent->getURL().getString() << " linked as #"
00276              << pcr->position << " " << pcr->contextual_name << "\n";
00277     }
00278 }

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