Introduction

GALILEI is a research and development platform in the field of information science.

Main classes

The main classes are:

A new application using the GALILEI platform should define a class inheriting from GGALILEIApp. This class will manage the plug-ins and their configurations. A global variable GALILEIApp is created.

To work on a given "world" (a given set of documents, users and profiles), the application should create a session through GALILEIApp.CreateSession. To delete the session, GALILEIApp.DeleteSession should be called.

The GSession is a complex class that inherits from several other classes that represent all the objects that are managed. These include :

Pseudo-parameter

Several member methods, in particular in GSession (and parent classes), use a pseudo-parameter as first argument. This parameter, a constant pointer, is needed to differentiate different methods with the same name but working on different objects. Several constant variables are declared to be used as pseudo-parameter (pDoc, pProfile, etc.). The following code explains their usage:

void PrintInfo(GSession* session)
{
cout<<"Name of the session: "<<session->GetName()<<endl;
cout<<"Number of documents: "<<session->GetNbObjs(pDoc)<<endl;
cout<<"Number of users: "<<session->GetNbObjs(pUser)<<endl;
cout<<"Number of profiles: "<<session->GetNbObjs(pProfile)<<endl;
cout<<"Number of concept types: "<<session->GetNbObjs(pConceptType)<<endl;
cout<<"Number of concepts: "<<session->GetNbObjs(pConcept)<<endl;
}

Here, the method GObjects::GetNbObjs returns the number of objects of a given type (documents, users, profiles, etc.). The pseudo-parameter (pDoc, pUser, pProfile, etc.) specifies which type is concerned.

The choice to use a pseudo-paramter for several methods was motivated for programming constraints (since GSession inherits several types from the same template class, it is necessary to distinct the methods) and to ensure the coherence of the API.

Notifications

The GALILEI platform uses the notification mechanism provided by the R Core library through the inheritance of the R::RObject class.

The notifications are used by the GALILEI platform to communicate some events to modules (plug-ins, application, etc.). A typical example is to inform that the current description of a document is changed : a first notification will be emitted before its replacement to specify that the description will be deleted, and a second one will be emitted after the new description assignment to inform that a new description id added. Typically, a plug-in proposing a similarity measure will observe the second notification to know that all the measures concerning that particular document are outdated.

Several notifications are send by the objects at different moment. They are declared by a series of arrays:

  1. The tObjEvent enumeration that defines a list of possible events generated by the objects.
  2. Several arrays of notifications (hDocs, hProfiles, etc.) using tObjEvent as indexer.

GSession sends a notification GALILEI::hReInit each time it forces the computations on objects of a given type. An example is to force a new analysis of the documents. In this case, all their descriptions will be cleared and, rather than to send a notification for each document, the session send one notification.

GPlugInList sends also a notification GALILEI::hCurrentPlugIn each time a plug-in becomes its current one. This can be useful because plug-ins may have dependencies. For example, a measure plug-in computing a similarity between two documents may rely on a measure plug-in proposing a weighting schema for the document descriptions.

When programming modules, in particular plug-ins, developers should carefully choose the notifications to observe.

The following code defines a plug-in that will print information on the status of the descriptions of documents.

class MyPlugIn : public RObject, public GMeasure
{
public:
MyPlugIn(GSession* session,GPlugInFactory* fac);
virtual void Init(void);
void HandleAddDoc(const R::RNotification& notification);
void HandleDelDoc(const R::RNotification& notification);
void HandleReInit(const R::RNotification& notification);
void HandleCurrentPlugIn(const R::RNotification& notification);
};
MyPlugIn::MyPlugIn(GSession* session,GPlugInFactory* fac)
: RObject(fac->GetName()), GMeasure(session,fac)
{
InsertObserver(HANDLER(MyPlugIn::HandleAddDoc),hDocs[oeUpdated]);
InsertObserver(HANDLER(MyPlugIn::HandleDelDoc),hDocs[oeAboutToBeUpdated]);
InsertObserver(HANDLER(MyPlugIn::HandleDelDoc),hDocs[oeAboutToBeDeleted]);
InsertObserver(HANDLER(MyPlugIn::HandleReInit),hReInit,session);
}
void MyPlugIn::Init(void)
{
// The insertion must be done here since the order of the creation of the
// plug-ins are unknown.
InsertObserver(HANDLER(MyPlugIn::HandleCurrentPlugIn),hCurrentPlugIn,GALILEIApp->GetManager("Measures")->GetPlugInList("Features Evaluation"));
}
void MyPlugIn::HandleAddDoc(const RNotification& notification)
{
// Verify that the sender is a document
GDoc* Doc(dynamic_cast<GDoc*>(notification.GetSender()));
if(Doc)
cout<<"Document "<<Doc->GetId()<<" has a new description"<<endl;
}
void MyPlugIn::HandleDelDoc(const RNotification& notification)
{
// Verify that the sender is a document
GDoc* Doc(dynamic_cast<GDoc*>(notification.GetSender()));
if(Doc)
cout<<"The description of document "<<Doc->GetId()<<" will be deleted"<<endl;
}
void MyPlugIn::HandleReInit(const R::RNotification& notification)
{
GSessionMsg& Msg(GetData<GSessionMsg&>(notification));
if(Msg.GetType()==otDoc)
cout<<"The description of all documents will be deleted"<<endl;
}
void MyPlugIn::HandleCurrentPlugIn(const R::RNotification& notification)
{
GMeasure* Weighting(dynamic_cast<GMeasure*>(GetData<GPlugIn*>(notification)));
cout<<Weighting->GetName()<<endl;
}

For safety raesons, the methods HandleAddDoc and HandleDelDoc verifies that the sender of the notification is a document.