interreality.org [VOS]
[Home] [About]
[Screenshots]
[Download]
[News]
[Community]
[Documentation] [Manual]
[Bugs & Requests] [Wiki]

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