Inverting Multiple Relations
Let us consider an object of type Route that uses a departure airport and an arrival airport:
class Route:
public IlsObject
{
public:
Route(AirportP dep, AirportP arr):
_departure(*this,dep),
_arrival(*this,arr)
{}
IlsUses<Route,Airport> _departure,_arrival;
};
Let us suppose that we want to maintain the list of the routes arriving at and departing from a given airport. We first have to declare a set of back pointers to the origins of the IlsUses relation—any number of routes can depart from or arrive at a given airport.
This set of back pointers is declared as an instance of the class template IlsInvertedRelationList:
class Airport:
public IlsObject
{
public
Airport():_routes(*this){}
IlsInvertedRelationList<Airport,Route> _routes;
};
Once the set of back pointers has been defined, you must add the callbacks
setContext and
unsetContext to the class
Airport as shown below. These callbacks are explained in
Inverting One Relation.
class Airport: public IlsObject
{
public:
Airport(): _routes(*this){}
void setContext(Route& route, void*, IlsRelationId){
_routes<<&route;
}
void unsetContext(Route& route, void*, IlsRelationId){
_routes>>&route;
}
IlsInvertedRelationList<Airport,Route> _routes;
};
Using Relation Identifiers with an Inverted List-Relation
You might want to maintain the routes arriving at a given airport and the routes departing from that airport in two separate lists. In this case, you have to make some changes in the class Airport:
class Airport:
public IlsObject
{
public:
typedef IlsInvertedRelationList<Airport,Route> ConnectedRoutes;
Airport();
void setContext(Route&, void*, IlsRelationId);
void unsetContext(Route&, void*, IlsRelationId);
private:
ConnectedRoutes arrivals,departures;
};
The data members arrivals and departures must be initialized in the constructor of Airport:
Airport::Airport():
arrivals(*this),
departures(*this)
{}
The functions setContext and unsetContext take the type IlsRelationId as their third argument. This argument is used to identify various relations of the same type with the same origin.
For example, to get the list of routes arriving at an airport separately from the list of routes departing from that airport, you need to specify identifiers which differentiate departures from arrivals. To do so, you declare an enumerated type containing the values DEPARTURE and ARRIVAL in the origin-class and you associate each relation with the corresponding value:
class Route:
public IlsObject
{
public:
enum{DEPARTURE,ARRIVAL};
Route(AirportP dep, AirportP arr):
departure(*this,dep,DEPARTURE),
arrival(*this,arr,ARRIVAL)
{}
IlsUses<Route,Airport> departure,arrival;
};
Then, you can define the setContext and unsetContext functions declared in the class Airport as follows.
void Airport::setContext(Route& l, void*, IlsRelationIdentifier id){
if (id==Route::DEPARTURE) departures<<&l;
else arrivals<<&l;
}
void Airport::unsetContext(Route& l, void*, IlsRelationIdentifier id){
if (id==Route::DEPARTURE) departures>>&l;
else arrivals>>&l;
}
Version 6.3
Copyright © 2018, Rogue Wave Software, Inc. All Rights Reserved.