// $Id: IDataLink.hxx,v 1.1 2010/09/07 18:29:48 mcgrew Exp $ // // The base class for Event Data. // #ifndef T_DATALINK_HXX #define T_DATALINK_HXX #include #include "IDatum.hxx" namespace COMET { OA_EXCEPTION(EBadLink,EDatum); class IDataLink; } #define TDATALINK_TITLE "IDatum Reference" /// The IDataLink class provides a way to reference a IDatum object in a IData /// tree without having the IData become the parent (in other words, a "weak /// reference"). This is conceptually similar to a hard link in a unix file /// system. This prevents IHandle loops. /// /// The IDataLink class should be used when one object in an event wants to /// reference another. An example might be when two tracks share some hits, /// and the reconstruction wants to record the relationship between the /// tracks. In this case, both tracks will be owned by a /// IReconObjectContainer, but each of the tracks needs to have a reference to /// the other. This reference would be done using a IDataLink. For example: /// /// \code /// trk1 = COMET::IHandle(new COMET::IReconTrack); /// objectContainer->push_back(trk1); /// /// trk2 = COMET::IHandle(new COMET::IReconTrack); /// objectContainer->push_back(trk2); /// /// trk1->AddDatum(new IDataLink("otherTrack",trk2); /// trk2->AddDatum(new IDataLink("otherTrack",trk1); /// \endcode /// /// will mean that the "otherTrack" can be accessed using /// /// \code /// COMET::IHandle otherTrack /// = trk1->Get("otherTrack") /// \endcode /// /// where this will return a handle to trk2. class COMET::IDataLink : public COMET::IDatum { private: /// The datum which this is a link too. IDatum *fLink; protected: /// A virtual function that can be used to have "special" Get<> behavior. /// This is mostly used by the TDatumLink class so that it can have a weak /// reference to IDatum elsewhere in the hierarchy, and have a Get<> /// method that refers transparently to the linked object. The GetThis() /// method should be used wherever the link indirection might be desired. /// Notice that this will follow the link all the way to the real object /// (even if there are several links along the way. virtual const IDatum *GetThis(void) const { if (!fLink) throw EBadLink(); return fLink->GetThis(); } virtual IDatum *GetThis(void) { if (!fLink) throw EBadLink(); return fLink->GetThis(); } public: IDataLink() : IDatum("",TDATALINK_TITLE) { }; /// Create a new IDataLink. A IDataLink inherits two fields from IDatum, /// "Name" and "Title". The name is the handle that is used to find /// "this" in IData objects. It can only contain alphanumeric characters /// (no "/" or spaces) and *should* be unique with in any level of the /// IData hierarchy. For instance, to get a particular datum out of a /// IData object you use data->Get("thename"). The title is /// a discription of a particular type of datum. As an example, the MC /// interaction data might be named "interaction" and titled "MC /// Interaction Data". The default title is "Event Datum". explicit IDataLink(const char* name, COMET::IHandle link) : IDatum(name,TDATALINK_TITLE) { if (!link) return; fLink = GetPointer(link); } virtual ~IDataLink(); /// Set the IDatum that is being linked. virtual void SetLink(COMET::IDatum *link) {fLink = link;} /// Set the IDatum that is being linked. virtual void SetLink(COMET::IHandle link) { fLink = GetPointer(link); } /// Print the datum information. virtual void ls(Option_t* opt = "") const { IDatum::ls(opt); TROOT::IncreaseDirLevel(); TROOT::IndentLevel(); std::cout << "-> " << fLink->GetThis()->ClassName() << "(" << fLink->GetThis() << ")::" << "Name = " << fLink->GetThis()->GetFullName(); if (strstr(opt,"title")) { std::cout << " Title = " << fLink->GetThis()->GetTitle(); } std::cout << std::endl; TROOT::DecreaseDirLevel(); }; /// Check if this link is to a browsable class. virtual Bool_t IsFolder(void) const; /// Call the browser for the linked class. virtual void Browse(TBrowser* b); protected: ClassDef(IDataLink,1); }; #endif