// ////////////////////////////////////////////////////////////////////////////
//
//  File:      TFGroupIterator.cpp
//
//  Version:   1.0
//
//  Author:    Reiner Rohlfs (GADC)
//
//  History:   1.0   12.08.03  first released version
//
// ////////////////////////////////////////////////////////////////////////////
#include <TList.h>

#include "TFGroup.h"
#include "TFError.h"

ClassImp(TFGroupIter)
ClassImp(TFSelector)

//_____________________________________________________________________________
// TFGroupIter:
//    A TFGroupIter should be used to get access to all children of any level
//    of a TFGroup. The Next() function returns kTRUE if there is a further 
//    TFIOElement in the group and kFALSE if there is no TFIOElement any more to
//    "point to". The operator * () and the operator ->() can be used to 
//    access the next TFIOElement of one of its derived classes like a TFTable
//    or a TFImage.
// 
//    The elements are opened "readOnly". To get elements for update call the
//    SetReadOnly() - function before calling the Next() function.
//
//    There are some possibilities to control the number of returned elements and
//    the order of the returned elements from the operator *() and operator ->():
//    A filter can be defined to filter rows of the first TFGroup depending on
//    other columns in the group ( see SetFilter() and Next() ). The rows of the 
//    first group can be sorted depending on the values of an other column of the 
//    group. ( see Sort() and Next() ). The returned elements can be selected by 
//    their names (see SetSelector() and Next() ).
//
// TFSelector:
//    TFSelector is an abstract base class to select pointers of a TFGroup. In the
//    current version there is one derived class to select the pointers depending
//    on the name of the element the group pointer points to. See TFNameSelector.



TFGroupIter::TFGroupIter(TFGroup * group, std::set<TFElementIdPtr> * done, 
                                 TList * select,Bool_t readOnly)
   : fCol((TFGroupCol&)group->GetColumn(GROUP_COL_NAME)), fRowIter(group)
{
// private constructor used by this class only

   fGroup      = group;
   fList       = NULL;
   fReadOnly   = readOnly;
   fLast       = NULL;
   fDone       = done;
   fStart      = kFALSE;
   fSelect     = select;
}
//_____________________________________________________________________________
TFGroupIter::TFGroupIter(TFGroup * group)
   : fCol((TFGroupCol&)group->GetColumn(GROUP_COL_NAME)), fRowIter(group)
{
// private constructor. Use TFGroup::MakeGroupIterator() to create a TFGroupIter

   fGroup      = group;
   fList       = NULL;
   fReadOnly   = kTRUE;
   fLast       = NULL;
   fDone       = new std::set<TFElementIdPtr>;
   fStart      = kTRUE;
   fSelect     = new TList;
}
//_____________________________________________________________________________
TFGroupIter::TFGroupIter(const TFGroupIter & groupIter) 
   : fCol(groupIter.fCol), fRowIter(groupIter.fGroup) 
{
   fGroup         = groupIter.fGroup;
   fReadOnly      = groupIter.fReadOnly;
   fList          = NULL;
   fLast          = NULL;
   fDone          = new std::set<TFElementIdPtr>;
   fStart         = kTRUE;
   fSelect        = new TList;
}
//_____________________________________________________________________________
TFGroupIter::~TFGroupIter()
{
   if (fList)
      {
      delete fList->fGroup;
      delete fList;
      }

   if (fStart)
      {
      delete fDone;

      fSelect->Delete();
      delete fSelect;
      }

   delete fLast;
}
//_____________________________________________________________________________
Bool_t  TFGroupIter::Next()
{
// "Moves" this iterator to the next TFIOElement or one of a dervied class of 
// TFIOElement in a group. After the first time the TFGroupIter "points" to
// the first TFIOElement. This function returns kTRUE as long as there is a
// further TFIOElement in the group. It returns kFALSE if it has already 
// "pointed" to all TFIOElements of the group. The operator *() and the 
// operator->() can be used to access the actual TFIOELement this iterator
// "points to". 
// All elements in all branches of the group are returned but never the same
// element twice. Assume that a child of the group is a group with some 
// children and again some groups as children and so on. All elements that are 
// child of any child - group of this group are searched and returned if they
// pass the selection criteria and the filter.
// Therefore this TFGroupIter never atually "points" to a TFGroup.
//
// Before calling the first time Next() a filter can be set (SetFilter). For more
// information on setting a filter see class TFRowIterator and its member function
// TFRowIterator::SetFilter() This function is directly called by the SetFilter()
// function of this TFGroupIter class. But in any case the filter is only 
// applied to the first TFGroup and not to its children groups.
//
// The order of the returned elements can be sorted with the Sort() function. For
// more information how to sort the rows of a group see class TFRowIterator and its
// member function TFRowIterator::Sort(). This function is directly called by the
// Sort() function of this TFGroupIter class. But in any case only the rows of
// the first TFGroup are sorted not the rows of its children groups.
//
// Further it is possible to select elements the iterator "points to"  by
// the name of the elements. Call one or several times the SetSelector() function to
// define the names of returned elements. For more information how to set the 
// selected element names see class description of TFNameSelector. 

   if (fList)
      {
      if (fList->Next())
         return kTRUE;
      delete fList->fGroup;
      delete fList;            
      fList = NULL;
      }
   
   // delete the element returned at the previous call of this function   
   delete fLast;
   fLast = NULL;

   TIter selectIter(fSelect);

   while ( fRowIter.Next() )
      {
      TFElementIdPtr item( fCol[*fRowIter], fGroup->GetFileName());

      if (item.IsGroup())
         {
         if (fDone->insert(item).second == false)
            // we processed this element already
            continue;
                  
         // we found a group. Go into it and iterate their children
         TFErrorType errT = TFError::GetErrorType();
         TFError::SetErrorType(kNoErr);
         TFGroup * group = TFReadGroup(item.GetFileName(), item.GetElementName(), 
                                       item.GetCycle() );
         TFError::SetErrorType(errT);
         if (!group)
            continue;
         // make a new iterator for the new group and get the next
         // element from this group
         errT = TFError::GetErrorType();
         TFError::SetErrorType(kExceptionErr);
         try {
            TFError::SetErrorType(errT);
            fList = new TFGroupIter(group, fDone, fSelect, fReadOnly);
            if (fList->Next())
               {
               return kTRUE;
               }
            }
         catch (TFException) 
            {
            TFError::SetErrorType(errT);
            }
         

         if (fList) delete fList->fGroup;
         delete fList;            
         fList = NULL;
         continue;
         }

      // check if this element passes the selection criteria
      Bool_t notSelect = kFALSE;
      while (TFSelector * selector = (TFSelector*)selectIter())
         {
         if (!(selector->Select(item)))
            {
            notSelect = kTRUE;
            break;
            }
         }
      selectIter.Reset();
      if (notSelect)
         continue;

      // don't return the same element twice
      if (fDone->insert(item).second == false)
         // we processed this element already
         continue;

      // the next element is not a group, but a normal table or image or ..
      // try to open it
      TFIOElement * element = TFRead(item.GetFileName(), item.GetElementName(), 
                                     item.GetCycle(), fReadOnly ? kFRead : kFReadWrite);
      if (element)
         {
         fLast = element;
         return kTRUE;
         }
      }

  // we are at the end
  return kFALSE;
}
//_____________________________________________________________________________
void TFGroupIter::Reset()
{
// resets the iterator, but not the filter, not the sorting and not the selection
// criteria. The Next() function can be used again to iterate through all 
// TFIOElements.

   delete fList;
   fList = NULL;

   fDone->clear();
   
   fRowIter.Reset();
}
//_____________________________________________________________________________
void TFGroupIter::SetReadOnly(Bool_t readOnly) 
{
// As default the elements returned from the operator * () and the 
// operator->() are opened in readOnly mode. To open them in update 
// mode set readOnly to kFALSE.
   fReadOnly = readOnly;
   if (fList)
      fList->SetReadOnly(readOnly);
}
//_____________________________________________________________________________
void TFGroupIter::ClearSelectors()
{
// clears all selectors set by the SetSelector() function
   if (fStart)
      fSelect->Delete();
}
//_____________________________________________________________________________
void TFGroupIter::SetSelector(TFSelector * select)
{
// Set one selector. The number of elements this iterator "points to" 
// depend on select. For more information see TFNameSelector and the Next() 
// function. 
// select is adapted by this class and will be deleted by this TFGroupIter class.
   fSelect->Add(select);
}

Last update: Fri Mar 14 13:55:23 2008

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.