Tutorial: Building an Rogue Wave Server Application > Designing the Server Object Model > Inverting Relations > Inverting a Single Relation
 
Inverting a Single Relation
In the previous section, you defined a relation where a domain owns one or more nodes. Let us assume now that you want to know the domain to which a given node belongs. First, you declare a back pointer (an instance of the Rogue Wave® Server class IlsInvertedRelation) to the class Domain in the class Node.
Then, you use the setContext and unsetContext functions provided with Rogue Wave Server. These functions automatically maintain the back pointer to the origin of the relation.
Adding a Back Pointer
1. In the file network.h, add a back pointer to the class Domain in the class Node using the class template IlsInvertedRelation and add the following lines with public access:
class Node:
public IlsObject
{
public:
   Node();
   void setContext(Domain& d, void*, IlsRelationId){domain=&d;}
   void unsetContext(Domain&, void*, IlsRelationId){domain=0;}
   void setContext(IlsRefCounted&, void*, IlsRelationId){}
   void unsetContext(IlsRefCounted&, void*, IlsRelationId){}
   DomainP getDomain(){return domain;}
private:
   IlsInvertedRelation<Node,Domain> domain;
}
Once they have been defined, the functions setContext and unsetContext are automatically called by Rogue Wave Server. The function setContext is called when the relation is established. The function unsetContext is called when the relation is broken off.
An application should never try to modify the value of the inverted relation directly.
A reference to the origin object is passed as a first argument to the setContext and unsetContext callbacks. If you declare at least one pair of set/unsetContext functions, you need to add a pair of default callbacks, like this:
void setContext(IlsRefCounted&, void*, IlsRelationId);
void unsetContext(IlsRefCounted&, void*, IlsRelationId);
This pair of functions will be called for all relations that do not need to be inverted.
Since any origin class transitively derives from IlsRefCounted, these callbacks work regardless of the kind of relation. In our example, these callbacks are used when a relation between Line and Node is established or broken.
Initializing the Inverse Relation
2. To initialize the inverse relation, you must first add a constructor for the class Node, then pass a reference (*this) to the holder type (Domain). This reference will automatically be set to zero. No other argument is needed.
Node::Node():
   domain(*this) // automatically initialized to zero
{
}
When the relation is established, the setContext function is called and the pointer points to the domain. When the relation is broken off, the function unsetContext is called and the pointer is set to 0.
Note: The setContext and unsetContext functions do not need to be inline in network.h.
Repeat the same steps to inverse the ownership relation between a domain and its lines if you want to be able to know to what domain a line belongs.
Testing the Inverted Relations
It is time now to test the inverted relations you have just defined. To do so, you will:
*modify your main.cpp file to check that the back pointer from n1 to the domain is properly maintained.
*verify that the pointer is set back to zero when n1 is removed from the domain.
3. Add the following lines to your main.cpp file and compile it.
int
main()
{
   // ...
   if (n1->getDomain()) {
      cout<<"n1 is in domain"<<endl;
   }
   d->nodes>>n1;
   if (!n1->getDomain()){
      cout<<"n1 removed from domain"<<endl;
   }
   return 0;
}
First, this program prints that the node n1 is in the domain. Then, node n1 being removed from the list of nodes, the program prints the message saying that the node has been removed from the domain:
n1 is in domain
n1 removed from domain

Version 5.7
Copyright © 2013, Rogue Wave Software, Inc. All Rights Reserved.