#include "QFramework/TQObservable.h"
#include "TTreeFormula.h"
#include "QFramework/TQStringUtils.h"
#include "QFramework/TQSample.h"
#include "QFramework/TQToken.h"
#include "QFramework/TQUtils.h"
#include "TTree.h"
#include "QFramework/TQIterator.h"
#include "QFramework/TQFilterObservable.h"

// #define _DEBUG_
#include "QFramework/TQLibrary.h"

#include <iostream>
#include <fstream>
#include <sstream>
#include <cstdlib>

/*@observable: [TQObservable] The TQObservable is an abstract base class for all Observables,
    i.e., it cannot be instantiated. It does, however, provide most of the backend functionality
    related to Observables, including a registry that both manually and automatically created
    Observables are added to such that the same instance of an Observable is used when encountering
    the same expression multiple times.
*/

TQObservable::Manager& TQObservable::getManager(){
	// return a reference to the manager
	return TQObservable::manager;
}

TQObservable::Manager::Manager(){
  // create an observable manager
  this->activeSet = new TFolder("default","default observable set");
  this->sets->Add(this->activeSet);
}
bool TQObservable::Manager::setActiveSet(const TString& name){
  // set/change the active set of observables that is currently used
  TFolder * set = dynamic_cast<TFolder*>(this->sets->FindObject(name));
  if(set) {
    this->activeSet = set;
    return true;
  } else {
    return false;
  }
}
void TQObservable::Manager::cloneActiveSet(const TString& newName){
  // clone the currently active observable set to a new instance with a new name
  this->createEmptySet(newName);
  TFolder* newset = dynamic_cast<TFolder*>(this->sets->FindObject(newName));
  TQObservableIterator itr(this->activeSet->GetListOfFolders());
  while(itr.hasNext()){
    TQObservable* obs = itr.readNext();
    if(!obs) continue;
    newset->Add(obs->getClone());
  }
}
void TQObservable::Manager::clearSet(const TString& name){
  // clear and empty the observable set with the given name
  TFolder* set = dynamic_cast<TFolder*>(this->sets->FindObject(name));
  TQObservableIterator itr(set->GetListOfFolders());
  while(itr.hasNext()){
    TQObservable* obs = itr.readNext();
    if(obs) delete obs;
  }
  this->sets->Remove(set);
  delete set;
}
void TQObservable::Manager::createEmptySet(const TString& name){
  // create a new empty set of observables with the given name
  this->sets->Add(new TFolder(name,name));
}
TCollection* TQObservable::Manager::listOfSets(){
  // retrieve the list of known sets
  return this->sets->GetListOfFolders();
}
TFolder* TQObservable::Manager::getActiveSet(){
	// retrieve the currently active set
	return this->activeSet;
}



TQObservable::Manager TQObservable::manager = TQObservable::Manager();
bool TQObservable::gAllowErrorMessages = false;




////////////////////////////////////////////////////////////////////////////////////////////////
//
// TQObservable
//
// The TQObservable class acts on a TQSample with the aim of extracting
// numerical data from a TTree inside the event loop.
//
// TQObservable itself is an abstract base class that is inherited from by
// different observable variants. The most notable ones are
//
// - TQTreeFormulaObservable: A wrapper around TTreeFormula, capable of
// evaluating arithmetic expressions on the TTree branches.
//
// - TQConstObservable: A trivial observable that has the same value for
// all events of a tree. While generally being of limited use, the existence
// of this observable type allows fast and convenient definition of cuts by
// providing an extremely fast way of implementing trivial cut or weight
// expressions.
//
// - TQMVATreeObservable: A more elaborate observable type that acts as a
// wrapper around a TMVA::Reader object and is capable of evaluating
// multivariate methods on the fly while only requiring a filepath to a
// valid TMVA weights.xml file as input.
//
// - TQMultiTreeObservable: A wrapper for an expression that consists of only
// constant values and names of other TQObservables, where the latter
// are required to be wrapped in brackets [...]. This observable type is
// required to cut on values provided by TQMVATreeObservable, but can also
// be used to combine outputs from different MVA methods or custom
// observable types.
//
// While any type of TQObservable may also be instantiated directly, it is
// generally advisable to use the factory functions
//
// TQObservable::getTreeObservable(name,expression): creates a
// TQObservable with the given name and expression. The type of
// observable created depends on the expression and may be indicated by a
// prefix if necessary (see function documentation of
// TQObservable::createObservable for details). The observable is
// automatically added to the observable database and is only created if
// necessary - if an observable with the same name and expression already
// exists, it is retrieved instead. If an observable with the same name, but
// a different expression exists, an error message is generated.
//
// TQObservable::getTreeObservable(expression): same as above, but the
// expression is also used as the name.
//
// The pure getter functions TQObservable::getTreeObservableByName(name)
// and TQObservable::getTreeObservableByExpression(expression) do not
// create observables, but only retrieve them from the central database.
//
// Defining Custom Observable Classes
//
// The TQObservable class can and should be used to define custom observable
// classes to implement a more complex behaviour. In order to have your custom
// observable class operate as expected, you need to implement the following
// methods:
//
// double getValue() const;
// This method returns the value of this observable. When implementing this
// method, please bear in mind that it will be called once for each event
// in all trees, possibly various times at each cut step. Try to implement
// this method as efficient as possible, even if this means spending more
// computation time in the other functions.
//
// bool initializeSelf();
// This method is supposed to initialize your observable in such a way that
// your getValue can safely be called. When this method is called, the
// values of the fields fSample, and fToken are already set and
// initialized, and you may access them in any way you seem fitting.
// If all went well, this method should return true. If an error occurred,
// you need to undo any changes performed previously and return false.
//
// bool finalizeSelf();
// This method is supposed to finalize your observable in such a way that
// all changes performed by initialzeSelf are undone and all data members
// allocated by initializeSelf are properly freed. The values of the
// fields fSample and fToken are still set and valid, and you
// may access them in any way you seem fitting. If all went well, this
// method should return true. In the unlikely case of an error, this method
// should return false.
//
// TObjArray* getBranchNames(TQSample* s) const;
// This method is supposed to return a TObjArray containing TObjStrings,
// each representing the name of a branch of a tree. The argument with
// which this function is called is a pointer to a TQSample object which
// contains the tree and possibly meta-information in the form of tags. A
// typical implementation of this method may look like this:
// TObjArray* getBranchNames(TQSample* s) const {
// return TQUtils::getBranchNames(this->getCompiledExpression(s));
// }
// Here, the called to TQObservable::getCompiledExpression produces the
// final expression string, taking into account all meta-information of the
// sample, and TQUtils::getBranchNames parses the expression to extract all
// literal strings that may represent branch names.
//
// Depending on the complexity of your observable class, it may be required to
// implement
// void setExpression(const TString&) as well. If you
// re-implement this method, you should call it in your constructor to ensure
// consistent behaviour of your class.
//
// For examples on how an actual implementation might look like, you may want
// to browse the source code of any of the aforementioned observable types.
//
// You may also choose to modify TQObservable::createObservable to be
// capable of creating your own observable type. For this purpose, you might
// choose a prefix string to help identifying your observable type.
//
// When you have implemented and created an instance of your class, you may use
// it as follows:
// - call TQObservable::printObservables() to see if it's in the database
// - add your observable to a cut by either of the following methods:
// - call TQCut::setCutObservableName or TQCut::setWeightObservableName
// with the name of your observable
// - call TQCut::setCutObservableName or TQCut::setWeightObservableName
// with the name of your observable
// - provide the name at construction time when creating via
// TQFolder::importFolder by setting the tags .cutObservableName or
// .weightObservableName of the folder in question
// - choose the name of your observable as CUTNAME_cut or CUTNAME_weight
// in the first place, where CUTNAME is the name of the cut in
// question
// - add your observable to a histogram, eventlist or anything else by
// providing the name or expression of the cut as an argument to the
// associated analysis job
//
// Of course, if you have modified TQObservable::createObservable to
// support your observable type, you don't have to add the observable yourself
// but can instead rely on automatic creation of your observable at the time it
// is requested by the analysis chain. You may, however, want to check if
// everything works as expected by calling
// TQObservable::printObservables()
// You may be surpised that the number of observables in the database is
// small. This is because most observables are only created when they are first
// requested. Usually, this happens when an analysis job is configured or when
// a cut is assigned to a sample visitor. In the case of the cut, however, you
// may force premature creation of the observables by calling
// TQCut::setupObservables() on the instance in question.
//
////////////////////////////////////////////////////////////////////////////////////////////////

ClassImp(TQObservable)

//______________________________________________________________________________________________

void TQObservable::clearAll(){
  TQIterator itr(getManager().listOfSets());
	while(itr.hasNext()){
		TFolder* set = dynamic_cast<TFolder*>(itr.readNext());
		if(!set) continue;
		TQObservableIterator obsitr(set->GetListOfFolders());
		while(obsitr.hasNext()){
			TQObservable* obs = obsitr.readNext();
			if(obs){
				set->Remove(obs);
				delete obs;
			}
		}
	}
}

//______________________________________________________________________________________________

TQObservable::TQObservable() :
  TNamed("TQObservable","TQObservable")
{
  DEBUGclass("default constructor called");
  // default constructor, setting name and title
}

//______________________________________________________________________________________________

TQObservable::TQObservable(const TString& expression) :
  TQObservable()
{
  // constructor setting the name and expression
  DEBUGclass("constructor called with expression '%s'",expression.Data());
  this->SetName(TQObservable::makeObservableName(expression));
}

//______________________________________________________________________________________________

void TQObservable::Manager::registerFactory(const TQObservable::FactoryBase* factory, bool putFirst){
  // add a new factory to the TQObservable manager
  if(putFirst){
    this->observableFactories.insert(this->observableFactories.begin(),factory);
  } else {
    this->observableFactories.push_back(factory);
  }
}

//______________________________________________________________________________________________

void TQObservable::Manager::clearFactories(){
  // clear all factories from the list
  this->observableFactories.clear();
}

#include <typeinfo>

void TQObservable::Manager::printFactories(){
  for(size_t i=0; i<this->observableFactories.size(); ++i){
    std::cout << this->observableFactories[i]->className() << std::endl;
  }
}


#include "QFramework/TQMultiObservable.h"
#include "QFramework/TQMVAObservable.h"
#include "QFramework/TQConstObservable.h"
#include "QFramework/TQTreeFormulaObservable.h"
#include "QFramework/TQHistogramObservable.h"
#include "QFramework/TQVectorAuxObservable.h"

//______________________________________________________________________________________________

bool TQObservableFactory::setupDefault(){
  // clear all factories from the list
  TQObservable::manager.clearFactories();
  TQObservable::manager.registerFactory(TQConstObservable::getFactory(),false);
  TQObservable::manager.registerFactory(TQHistogramObservable<TH3>::getFactory(),false);
  TQObservable::manager.registerFactory(TQHistogramObservable<TH2>::getFactory(),false);
  TQObservable::manager.registerFactory(TQHistogramObservable<TH1>::getFactory(),false);
  TQObservable::manager.registerFactory(TQFilterObservable::getFactory(),false);
  TQObservable::manager.registerFactory(TQVectorAuxObservable::getFactory(),false);
  TQObservable::manager.registerFactory(TQMultiObservable::getFactory(),false);
  TQObservable::manager.registerFactory(TQMVAObservable::getFactory(),false);
  TQObservable::manager.registerFactory(TQTreeFormulaObservable::getFactory(),false);
  return true;
}

namespace {
  const bool _TQObservableFactory__setupDefault = TQObservableFactory::setupDefault();
}

//______________________________________________________________________________________________

TQObservable* TQObservable::Manager::createObservable(TString expression, TQTaggable* tags){
  // this is a factory function for TQObservables.
  //  TQStringUtils::removeLeadingBlanks(expression);
  //  TQStringUtils::removeTrailingBlanks(expression);
  expression = TQObservable::unreplaceBools(TQObservable::compileExpression(expression,tags,true));

  TQStringUtils::removeLeadingBlanks(expression);
  TQStringUtils::removeTrailingBlanks(expression);
  for(size_t i=0; i<this->observableFactories.size(); ++i){
    TQObservable* obs = this->observableFactories[i]->tryCreateInstance(expression);
    if(obs){
      TString obsname(TQObservable::makeObservableName(expression));
      TQObservable* other = (TQObservable*)(this->activeSet->FindObject(obsname));
      if(other){
        ERRORclass("These are the tags used when attempting to create a new observable instance:");
        tags->printTags();
        ERRORclass("These are the already existing observables:");
        TQObservable::printObservables();
        ERRORclass("An observable was created via its factory from expression '%s'. However, there is already another observable with the same name in the current set of observables. The list of already existing observables has been printed above. The duplicate name is '%s'. if this happens with the latest version of QFramework pease report it to qframework-users@cern.ch and try to provide a test case to reproduce the issue!", expression.Data(), obsname.Data());
        throw std::runtime_error(TString::Format("Internal Error: cannot add observable with name '%s' (generated from expression '%s') to set '%s' -- name is already in use, observable has expression '%s'!",obsname.Data(),expression.Data(),this->activeSet->GetName(),other->getExpression().Data()).Data());
      } else {
        DEBUG(TString::Format("adding observable '%s' to set '%s'",obsname.Data(),this->activeSet->GetName()).Data());
        obs->SetName(obsname);
        this->activeSet->Add(obs);
      }
      return obs;
    }
  }
  return NULL;
}

//______________________________________________________________________________________________

bool TQObservable::addObservable(TQObservable* obs){
  // add an existing tree observable to the pool
  if(!obs) return false;
  if(dynamic_cast<TQObservable*>(TQObservable::manager.activeSet->FindObject(obs->GetName()))){
    WARNclass("Failed to add observable '%s': an observable with this name already present",obs->GetName());
    return false;
  }
  TQObservable::manager.activeSet->Add(obs);
  obs->fIsManaged = true;
  return true;
}

//______________________________________________________________________________________________

bool TQObservable::addObservable(TQObservable* obs, const TString& name){
  // add an existing tree observable to the pool
  // giving it a new name
  if(!obs) return false;
  if(dynamic_cast<TQObservable*>(TQObservable::manager.activeSet->FindObject(name))){
    WARNclass("Failed to add observable '%s': an observable with this name already present",name.Data());
    return false;
  }
  obs->SetName(name);
  TQObservable::manager.activeSet->Add(obs);
  obs->fIsManaged = true;
  return true;
}

//______________________________________________________________________________________________

void TQObservable::printObservables(const TString& filter){
  // retrieve a TQObservable by expression
  // create it if necessary
  int width = TQLibrary::getConsoleWidth();
  TQIterator itr(TQObservable::manager.listOfSets());
  while(itr.hasNext()){
    TFolder* f = dynamic_cast<TFolder*>(itr.readNext());
    TQObservableIterator obsitr(f->GetListOfFolders());
    std::cout << TQStringUtils::makeBoldWhite(TQStringUtils::fixedWidth(f->GetName(),.2*width,"l")) << " " << TQStringUtils::makeBoldWhite(TQStringUtils::fixedWidth("name",.3*width,"l")) << " " << TQStringUtils::makeBoldWhite("expression") << std::endl;
    std::cout << TQStringUtils::makeBoldWhite(TQStringUtils::repeat("=",width)) << std::endl;
    while(obsitr.hasNext()){
      TQObservable* obs = obsitr.readNext();
      if(!obs) continue;
      if(!TQStringUtils::matches(obs->GetName(),filter)) continue;
      std::cout << TQStringUtils::makeBoldBlue(TQStringUtils::fixedWidth(obs->IsA()->GetName(),.2*width,"l"));
      std::cout << " ";
      std::cout << TQStringUtils::makeBoldWhite(TQStringUtils::fixedWidth(obs->GetName(),.3*width,"l"));
      std::cout << " ";
      std::cout << TQStringUtils::fixedWidth(obs->isInitialized() ? TQStringUtils::makeBoldRed(obs->getActiveExpression()) : obs->getExpression(),.5*width,"l.");
      std::cout << std::endl;
    }
  }
}

//______________________________________________________________________________________________

bool TQObservable::matchExpressions(const TString& ex1, const TString& ex2, bool requirePrefix){
  DEBUGclass("trying to match expressions '%s' and '%s'. Prefix matching: %s",ex1.Data(),ex2.Data(),requirePrefix?"required":"ignored");
  //simple parsing
  if(ex1.Length() == ex2.Length()) return TQStringUtils::equal(ex1,ex2);

  //try matching without prefix. Originally intended to match expressions like 'Multi:[x]+[y]' and '[x]+[y]'. Can be disabled (requirePrefix=true) as it can cause infinite recursions for observables which explicity require a prefix, e.g. VecAND:x. Prefix requirement is controled by the observable instance a user-expression is compared against:
  if (requirePrefix) {
    DEBUGclass("prefix is required but lengths don't match. Expressions do not match.");
    return false;
  }

  if(ex1.Length() > ex2.Length()){
    int first = ex1.First(":");
    DEBUGclass("comparing: '%s' vs '%s'",ex1(first+1,ex1.Length()-first-1).Data(),ex2.Data());
    return (first < .5*ex1.Length()) && TQStringUtils::isValidIdentifier(ex1(0,first),TQStringUtils::alphanum) && TQStringUtils::equal(ex1(first+1,ex1.Length()-first-1),ex2);
  }
  if(ex1.Length() < ex2.Length()){
    int first = ex2.First(":");
    DEBUGclass("comparing: '%s' vs '%s'",ex2(first+1,ex2.Length()-first-1).Data(),ex1.Data());
    return (first < .5*ex2.Length()) && TQStringUtils::isValidIdentifier(ex2(0,first),TQStringUtils::alphanum) && TQStringUtils::equal(ex2(first+1,ex2.Length()-first-1),ex1);
  }
  DEBUGclass("finished matching, no attempt succeeded");
  return false;
}

//______________________________________________________________________________________________

TQObservable* TQObservable::getObservable(const TString& origexpr, TQTaggable* tags){
  // retrieve an incarnation of a TQObservable
  // the observable is identified by its name 'expression'
  // also, the incarnation of this observable needs to match the compiled expression
  // retrieved by compiling expression using the tags provided
  DEBUGclass("trying to obtain observable with origexpr '%s'",origexpr.Data());
  TString incarnation = TQObservable::unreplaceBools(TQObservable::compileExpression(origexpr,tags,true));
  if(incarnation.Contains("$")){
    tags->printTags();
    ERRORclass("there seem to be unresolved aliases/tags in expression '%s', available aliases are listed above.",incarnation.Data());
    return NULL;
  }
  TString expression(origexpr);
  expression.ReplaceAll("\\","");
  TString obsname(TQObservable::makeObservableName(expression));
  TString incname(TQObservable::makeObservableName(incarnation));
  DEBUGclass("attempting to retrieve observable '%s' (raw name)/'%s' (compiled name) with expression '%s'",obsname.Data(),incname.Data(),incarnation.Data());
  if(obsname.IsNull()) {ERRORclass("Failed to retrieve observable: Observable name is empty! Original expression was '%s'",expression.Data()); return NULL;}
  TQObservableIterator itr(TQObservable::manager.activeSet->GetListOfFolders());
  while(itr.hasNext()){
    TQObservable* obs = itr.readNext();
    if(!obs) continue;

    DEBUGclass("next object is: '%s' ",obs->GetName());

    if(TQObservable::matchExpressions(obs->GetName(),incname, obs->isPrefixRequired() )){
      DEBUGclass("found perfect match '%s' for '%s'",obs->GetName(),incname.Data());
      return obs;
    }

    DEBUGclass("comparing '%s' vs. '%s' with expression=%d, initialized=%d",obs->getActiveExpression().Data(),incarnation.Data(),obs->hasExpression(),obs->isInitialized());

    if(obs->hasExpression()){
      if(obs->isInitialized() && TQObservable::matchExpressions(TQObservable::unreplaceBools(obs->getActiveExpression()),incarnation,obs->isPrefixRequired() )){
        DEBUGclass("found pre-initialized match '%s' for '%s'",obs->getActiveExpression().Data(),incarnation.Data());
        return obs;
      }
      if(!obs->isInitialized() && TQObservable::matchExpressions(TQObservable::unreplaceBools(obs->getExpression()),expression,obs->isPrefixRequired() )){
        DEBUGclass("found free match '%s' for '%s'",obs->getExpression().Data(),expression.Data());
        return obs;
      }
    }
  }
  itr.reset();
  TQObservable* match = NULL;
  size_t rating = -1;
  while(itr.hasNext()){
    TQObservable* obs = itr.readNext();
    if(!obs) continue;
    DEBUGclass("comparing observable's compiled expression to incarnation: '%s' vs. '%s'",TQObservable::unreplaceBools(obs->getCompiledExpression(tags)).Data(),incarnation.Data());
    if(TQObservable::matchExpressions(TQObservable::unreplaceBools(obs->getCompiledExpression(tags)),incarnation,obs->isPrefixRequired())){
      size_t obsrating = TQStringUtils::countText(obs->getExpression(),"$");//TODO: improve! this is mostly useless, since the default (i.e. non-overridden) implementation of getExpression returns the name of the observable. Some observables' names do not contain "$" anymore since (correctly) TQObservable::makeObservableName is used before setting fName. For now we need this, e.g., for HWWEventWeight with systematics where getExpression() is overridden.
      DEBUGclass("found general match '%s' for '%s' with rating %d (expression is '%s')",obs->GetName(),incname.Data(),(int)(obsrating),obs->getExpression().Data());
      if(!match || obsrating < rating){
        match = obs;
        rating = obsrating;
      }
    }
  }
  if(match){
    if(match->isInitialized()){
      if(!(match->hasFactory())){
        TQObservable* clone = match->getClone();
        if(!clone){
          throw std::runtime_error(TString::Format("tried to retrieve observable '%s' with expression '%s' in incarnation '%s' and found a near match '%s' that can't be cloned...",obsname.Data(),expression.Data(),incarnation.Data(),match->getActiveExpression().Data()).Data());
        }
        clone->SetName(incname);
        clone->fIsManaged = true;
        clone->finalize();
        TQObservable::manager.activeSet->Add(clone);
        DEBUGclass("cloned '%s' for '%s'",match->GetName(),clone->GetName());
        return clone;
      }
      DEBUGclass("existing observable '%s' is initialized but factory exists",match->GetName());
    } else {
      DEBUGclass("returning unused match with name '%s' and compiled expression '%s'",match->GetName(),match->getCompiledExpression(NULL).Data());
      return match;
    }
  }
  DEBUGclass("no match found for '%s' in set '%s' -- creating new observable from expression '%s' (incarnation is '%s')",obsname.Data(),TQObservable::manager.activeSet->GetName(),expression.Data(),incarnation.Data());

  TQObservable* retObs = TQObservable::manager.createObservable(origexpr, tags);
  if (!retObs) {
    tags->printTags();
    ERRORclass("Failed to get observable from expression '%s'. Tags/aliases used have been printed above.",origexpr.Data());
    ERRORclass("The following steps have been attempted:");
    ERRORclass("1) Trying to find a) existing observable with name matching '%s' or",incname.Data());
    ERRORclass("                  b) already existing and initialized observable with activeExpression matching '%s' or",incarnation.Data());
    ERRORclass("                  c) already existing and UNinitialized observable expression matching '%s' or",expression.Data());
    ERRORclass("2) Trying to find existing observable instances which would yield a compiledExpression matching '%s' if initialized with the provided tags (tags see above). either such an observable was not found or the best match has a factory (in which case we do not clone an existing instance but ask the factory to create a new instance.",incarnation.Data());
    ERRORclass("3) No factory managed to produce a working observable instance");
  }
  return retObs;

}

//______________________________________________________________________________________________

bool TQObservable::hasFactory() const {
  return false;
}

//______________________________________________________________________________________________

TString TQObservable::makeObservableName(const TString& name){
  // convert a string into a valid observable name
  TString tmpname(name);
  tmpname.ReplaceAll("!","NOT");
  tmpname.ReplaceAll("&&","AND");
  tmpname.ReplaceAll("||","OR");
  tmpname.ReplaceAll("[","_");
  tmpname.ReplaceAll("]","_");
  tmpname.ReplaceAll("(","_");
  tmpname.ReplaceAll(")","_");
  tmpname.ReplaceAll("/",":");
  return TQStringUtils::makeValidIdentifier(tmpname,"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890._*+-><=:/");
}

//______________________________________________________________________________________________

bool TQObservable::initialize(TQSample * sample){
  // initialize this observable
  if(this->isInitialized()) return true;
  if (fSample){
    // we can't do anything if we already have a sample
    if(fSample == sample) return true;
    else throw std::runtime_error(TString::Format("observable '%s' already initialized to sample '%s'",this->GetName(),fSample->getPath().Data()).Data());
  }

  // the sample to use has to be valid
  if(!sample) return false;
  fSample = sample;

  if(!this->initializeSelf()){
    this->fIsInitialized = false;
    this->fSample = NULL;
    throw std::runtime_error(TString::Format("unable to initialize observable '%s'",this->GetName()).Data());
  }

  this->fIsInitialized = true;
  return true;
}

//______________________________________________________________________________________________

bool TQObservable::isInitialized() const {
  // return true if this observable is initialized, false otherwise
  return this->fIsInitialized;
}

//______________________________________________________________________________________________

bool TQObservable::finalize() {
  // finalize this observable, return the tree token
  DEBUGclass("finalizing '%s'",this->GetName());
  if(!this->isInitialized()){
    return true;
  }

  if (!this->fSample){
    ERRORclass("no sample assigned to this observable: '%s'",this->GetName());
    return false;
  }

  this->fIsInitialized = !(this->finalizeSelf());
  if(this->fIsInitialized){
    ERRORclass("unable to finalize observable '%s'",this->GetName());
  }

  this->fSample = 0;

  return (!this->fIsInitialized);
}


//______________________________________________________________________________________________

TQObservable::~TQObservable() {
  // standard destructor
  if(this->fIsManaged){
    TQObservable::manager.activeSet->Remove(this);
  }
}

//______________________________________________________________________________________________

void TQObservable::print() const {
  // print the contents of this observable and its associated branches
  std::cout << TQStringUtils::makeBoldYellow(this->getExpression()) << std::endl;
}

//______________________________________________________________________________________________

TString TQObservable::getCompiledExpression(TQTaggable* tags) const {
  // retrieve the expression string
  return this->compileExpression(getExpression(),tags);
}

//______________________________________________________________________________________________

TString TQObservable::replaceBools(TString expression){
  expression = TQStringUtils::replaceEnclosed(expression,"true", "(1==1)"," /*+-?!|&\n\t ()[]{}=:");
  expression = TQStringUtils::replaceEnclosed(expression,"false","(1==0)"," /*+-?!|&\n\t ()[]{}=:");
  return expression;
}

//______________________________________________________________________________________________

TString TQObservable::unreplaceBools(TString expression){
  expression.ReplaceAll("(1==1)","true");
  expression.ReplaceAll("(1==0)","false");
  return expression;
}

//______________________________________________________________________________________________

TString TQObservable::compileExpression(const TString& input, TQTaggable* tags, bool replaceBools) {
  // compile an expression, evaluating all evaluable expressions beforehand
  // the following examples document the behaviour of this function:
  //
  // - newlines and tabs, and double spaces are removed, e.g.
  // "Mjj > 600."
  // becomes
  // "Mjj > 600."
  //
  // - placeholders are replaced by their respective values based on the
  // instance of TQTaggable provided as second argument and all its base
  // objects, e.g.
  // "$(bTagWeightName)"
  // becomes
  // "bTagEventWeight"
  // if the TQTaggable object or any of its parent objects carries the tag
  // bTagWeightName = bTagEventWeight
  //
  // - boolean strings are replaced by their numerical equivalents, i.e.
  // "true" is replaced by "1."
  // "false" is replaced by "0."
  //
  // - inline conditionals in curly braces are evaluated if possible, e.g.
  // "{ $(channel) == 'ee' ? true : false }"
  // becomes "1." if the tag "channel" has the value "ee", false otherwise.
  // if evaluation is not possible because the conditional contains
  // unresolved strings, the curly braces are replaced by round ones.
  //
  // - single quotes are replaced by double quotes, e.g.
  // "{ $(channel) == "ee" ? true : false }"
  // is identical to
  // "{ $(channel) == 'ee' ? true : false }"
  //
  // if the compilation fails and the result still contains unresolved
  // variables (or any dollar signs, to that extend) an error is thrown.
  //
  if(input.IsNull()) return input;
  TString expression = tags ? tags->replaceInTextRecursive(input,"~",false) : input;
  expression.ReplaceAll("'","\"");
  if(replaceBools){
    expression = TQObservable::replaceBools(expression);
  }

  //  DEBUGclass("input is '%s', obtained from '%s'",expression.Data(),input.Data());

  TString retval("");
  while (!expression.IsNull()) {
    // loop over the expressions '{ ... }' until end of string is reached
    //    DEBUGclass("next iteration, remainder is '%s'",expression.Data());
    TQStringUtils::readUpTo(expression,retval,"{");

    if(expression.Length() < 1) return TQStringUtils::minimize(retval);

    size_t endpos = TQStringUtils::findParenthesisMatch(expression,0,"{","}");
    if(endpos > (size_t)expression.Length()){
      ERRORclass("parenthesis mismatch in expression '%s'",expression.Data());
      return "";
    }

    size_t posIf = TQStringUtils::find(expression,"?");
    if (posIf < (size_t)expression.Length()){
      // if the expression contains '?', we assume it's an if-statement
      //      DEBUGclass("found sub-expression: '%s'",TString(expression(0,endpos+1)).Data());
      TString ifExpr(expression(1, posIf-1));
      if(TQStringUtils::hasUnquotedStrings(ifExpr)){
        // if there are unquoted strings, we can't compile it
        // for now, we assume that they are branch names
        // we replace the curly braces with round ones and skip evaluation
        // the TTreeFormula will hopefully deal with it
        //        DEBUGclass("'if'-statement '%s' seems to have unquoted strings, skipping",ifExpr.Data());
        retval.Append("(");
        TString subExpr(expression(1,endpos-1));
        retval.Append(compileExpression(subExpr,NULL,replaceBools));
        retval.Append(")");
      } else {
        // we have found something valid that we can evaluate
        //        DEBUGclass("testing 'if'-statement: '%s'",ifExpr.Data());
        TFormula formula("if", ifExpr);
        TString thenExpr, elseExpr;
        size_t posElse = posIf;
        while(posElse == posIf || expression[posElse-1] == '\\'){
          posElse = TQStringUtils::findFree(expression,":","{}()[]",posElse+1);
        }
        if (posElse < (size_t)expression.Length()) {
          // we have found an ':', indicating an "else"-block
          thenExpr = expression(posIf+1, posElse-posIf-1);
          elseExpr = expression(posElse+1, endpos-posElse-1);
          //          DEBUGclass("found 'then' and 'else' statements: '%s'/'%s'",thenExpr.Data(),elseExpr.Data());
        } else {
          // no "else"-block was found, only "then"
          thenExpr = expression(posIf+1,endpos-posIf-1);
          elseExpr = "";
          //          DEBUGclass("found 'then'-statement: '%s'",thenExpr.Data());
        }
        if (formula.Eval(0.)){
          // the formula evaluated to "true" - we can use the "then"-block
          //          DEBUGclass("using THEN statement");
          retval.Append(compileExpression(thenExpr,NULL,replaceBools));
        } else {
          // the formula evaluated to "false" - we should use the "else"-block
          //          DEBUGclass("using ELSE statement");
          retval.Append(compileExpression(elseExpr,NULL,replaceBools));
        }
      }
    } else {
      // this is odd - we have curly braces, but nothing that looks like an if-statement
      // we assume that the user meant to use round braces instead
      // we replace them and continue
      retval.Append("(");
      TString subExpr(expression(1,endpos-1));
      retval.Append(compileExpression(subExpr,NULL,replaceBools));
      retval.Append(")");
    }

    expression.Remove(0,endpos+1);
    TQStringUtils::removeLeadingBlanks(expression);
  }

  if(retval.Index("$") != kNPOS){
    size_t start = retval.Index("$");
    size_t stop;
    if(retval[start+1] == '('){
      stop = TQStringUtils::findParenthesisMatch(retval,start+1,"(",")")+1;
    } else {
      stop = TQStringUtils::findFirstNotOf(retval,TQStringUtils::defaultIDchars,start+1);
    }
    TString var(retval(start,stop-start));
    TString err = TString::Format("unresolved variable '%s' in expression '%s'!",var.Data(),retval.Data());
    if(tags){
      ERRORclass(err+" Available tags are listed above.");
      tags->printTags("l");
    }
    throw std::runtime_error(err.Data());
  }

  //  DEBUGclass("expression compilation complete");
  retval.ReplaceAll("\\","");
  return TQStringUtils::minimize(retval);
}

//__________________________________________________________________________________|___________

TString TQObservable::getName() const {
  // retrieve the name of this object
  return this->fName;
}

//__________________________________________________________________________________|___________

void TQObservable::setName(const TString& newName) {
  // set the name of this object
  this->fName = newName;
}

//__________________________________________________________________________________|___________

const TString& TQObservable::getNameConst() const {
  // retrieve a const reference to the name of this object
  return this->fName;
}


//__________________________________________________________________________________|___________

bool TQObservable::isSetup() const {
  // return true if this observable is setup and ready to initialize
  // false otherwise
  return true;
}

//__________________________________________________________________________________|___________

void TQObservable::allowErrorMessages(bool val){
  TQObservable::gAllowErrorMessages = val;
}

//______________________________________________________________________________________________

const TString& TQObservable::getExpression() const {
  // retrieve the expression associated with this observable
  return this->fName;
}

//______________________________________________________________________________________________

bool TQObservable::hasExpression() const {
  // check if this observable type knows expressions (default false)
  DEBUGclass("doesn't know expressions");
  return false;
}

//______________________________________________________________________________________________

TQObservable* TQObservable::getClone() const {
  // retrieve a clone of this observable
  TQObservable* obs = NULL;
  if(this->hasExpression()){
    obs = this->tryCreateInstanceVirtual(this->getExpression());
  }
  if(!obs){
    obs = (TQObservable*)(this->Clone());
  }
  if(obs->isInitialized()) obs->finalize();
  return obs;
}

//______________________________________________________________________________________________

void TQObservable::setExpression(const TString&/*expr*/){
  // set the expression to a given string
  // not implemented for the base class
  ERRORclass("this function is not implemented. did you forget to implement 'virtual void YOURCLASS::setExpression(const TString)'?");
}

//______________________________________________________________________________________________

TQObservable* TQObservable::tryCreateInstanceVirtual (const TString&) const {
  // this is the factory function for each observable type
  // in the default implementation, this always returns NULL
  // because there is no fully general observable factory
  return NULL;
}

//______________________________________________________________________________________________

TString TQObservable::getActiveExpression() const {
  // retrieve the expression string
  return this->getExpression();
}

//______________________________________________________________________________________________

double TQObservable::getValueAt(int index) const {
  // retrieve the value at the given index
  if (index!=0) {throw std::runtime_error("Attempt to retrieve value from illegal index in observable."); return -999.;} else return this->getValue();
}

 TQObservable.cxx:1
 TQObservable.cxx:2
 TQObservable.cxx:3
 TQObservable.cxx:4
 TQObservable.cxx:5
 TQObservable.cxx:6
 TQObservable.cxx:7
 TQObservable.cxx:8
 TQObservable.cxx:9
 TQObservable.cxx:10
 TQObservable.cxx:11
 TQObservable.cxx:12
 TQObservable.cxx:13
 TQObservable.cxx:14
 TQObservable.cxx:15
 TQObservable.cxx:16
 TQObservable.cxx:17
 TQObservable.cxx:18
 TQObservable.cxx:19
 TQObservable.cxx:20
 TQObservable.cxx:21
 TQObservable.cxx:22
 TQObservable.cxx:23
 TQObservable.cxx:24
 TQObservable.cxx:25
 TQObservable.cxx:26
 TQObservable.cxx:27
 TQObservable.cxx:28
 TQObservable.cxx:29
 TQObservable.cxx:30
 TQObservable.cxx:31
 TQObservable.cxx:32
 TQObservable.cxx:33
 TQObservable.cxx:34
 TQObservable.cxx:35
 TQObservable.cxx:36
 TQObservable.cxx:37
 TQObservable.cxx:38
 TQObservable.cxx:39
 TQObservable.cxx:40
 TQObservable.cxx:41
 TQObservable.cxx:42
 TQObservable.cxx:43
 TQObservable.cxx:44
 TQObservable.cxx:45
 TQObservable.cxx:46
 TQObservable.cxx:47
 TQObservable.cxx:48
 TQObservable.cxx:49
 TQObservable.cxx:50
 TQObservable.cxx:51
 TQObservable.cxx:52
 TQObservable.cxx:53
 TQObservable.cxx:54
 TQObservable.cxx:55
 TQObservable.cxx:56
 TQObservable.cxx:57
 TQObservable.cxx:58
 TQObservable.cxx:59
 TQObservable.cxx:60
 TQObservable.cxx:61
 TQObservable.cxx:62
 TQObservable.cxx:63
 TQObservable.cxx:64
 TQObservable.cxx:65
 TQObservable.cxx:66
 TQObservable.cxx:67
 TQObservable.cxx:68
 TQObservable.cxx:69
 TQObservable.cxx:70
 TQObservable.cxx:71
 TQObservable.cxx:72
 TQObservable.cxx:73
 TQObservable.cxx:74
 TQObservable.cxx:75
 TQObservable.cxx:76
 TQObservable.cxx:77
 TQObservable.cxx:78
 TQObservable.cxx:79
 TQObservable.cxx:80
 TQObservable.cxx:81
 TQObservable.cxx:82
 TQObservable.cxx:83
 TQObservable.cxx:84
 TQObservable.cxx:85
 TQObservable.cxx:86
 TQObservable.cxx:87
 TQObservable.cxx:88
 TQObservable.cxx:89
 TQObservable.cxx:90
 TQObservable.cxx:91
 TQObservable.cxx:92
 TQObservable.cxx:93
 TQObservable.cxx:94
 TQObservable.cxx:95
 TQObservable.cxx:96
 TQObservable.cxx:97
 TQObservable.cxx:98
 TQObservable.cxx:99
 TQObservable.cxx:100
 TQObservable.cxx:101
 TQObservable.cxx:102
 TQObservable.cxx:103
 TQObservable.cxx:104
 TQObservable.cxx:105
 TQObservable.cxx:106
 TQObservable.cxx:107
 TQObservable.cxx:108
 TQObservable.cxx:109
 TQObservable.cxx:110
 TQObservable.cxx:111
 TQObservable.cxx:112
 TQObservable.cxx:113
 TQObservable.cxx:114
 TQObservable.cxx:115
 TQObservable.cxx:116
 TQObservable.cxx:117
 TQObservable.cxx:118
 TQObservable.cxx:119
 TQObservable.cxx:120
 TQObservable.cxx:121
 TQObservable.cxx:122
 TQObservable.cxx:123
 TQObservable.cxx:124
 TQObservable.cxx:125
 TQObservable.cxx:126
 TQObservable.cxx:127
 TQObservable.cxx:128
 TQObservable.cxx:129
 TQObservable.cxx:130
 TQObservable.cxx:131
 TQObservable.cxx:132
 TQObservable.cxx:133
 TQObservable.cxx:134
 TQObservable.cxx:135
 TQObservable.cxx:136
 TQObservable.cxx:137
 TQObservable.cxx:138
 TQObservable.cxx:139
 TQObservable.cxx:140
 TQObservable.cxx:141
 TQObservable.cxx:142
 TQObservable.cxx:143
 TQObservable.cxx:144
 TQObservable.cxx:145
 TQObservable.cxx:146
 TQObservable.cxx:147
 TQObservable.cxx:148
 TQObservable.cxx:149
 TQObservable.cxx:150
 TQObservable.cxx:151
 TQObservable.cxx:152
 TQObservable.cxx:153
 TQObservable.cxx:154
 TQObservable.cxx:155
 TQObservable.cxx:156
 TQObservable.cxx:157
 TQObservable.cxx:158
 TQObservable.cxx:159
 TQObservable.cxx:160
 TQObservable.cxx:161
 TQObservable.cxx:162
 TQObservable.cxx:163
 TQObservable.cxx:164
 TQObservable.cxx:165
 TQObservable.cxx:166
 TQObservable.cxx:167
 TQObservable.cxx:168
 TQObservable.cxx:169
 TQObservable.cxx:170
 TQObservable.cxx:171
 TQObservable.cxx:172
 TQObservable.cxx:173
 TQObservable.cxx:174
 TQObservable.cxx:175
 TQObservable.cxx:176
 TQObservable.cxx:177
 TQObservable.cxx:178
 TQObservable.cxx:179
 TQObservable.cxx:180
 TQObservable.cxx:181
 TQObservable.cxx:182
 TQObservable.cxx:183
 TQObservable.cxx:184
 TQObservable.cxx:185
 TQObservable.cxx:186
 TQObservable.cxx:187
 TQObservable.cxx:188
 TQObservable.cxx:189
 TQObservable.cxx:190
 TQObservable.cxx:191
 TQObservable.cxx:192
 TQObservable.cxx:193
 TQObservable.cxx:194
 TQObservable.cxx:195
 TQObservable.cxx:196
 TQObservable.cxx:197
 TQObservable.cxx:198
 TQObservable.cxx:199
 TQObservable.cxx:200
 TQObservable.cxx:201
 TQObservable.cxx:202
 TQObservable.cxx:203
 TQObservable.cxx:204
 TQObservable.cxx:205
 TQObservable.cxx:206
 TQObservable.cxx:207
 TQObservable.cxx:208
 TQObservable.cxx:209
 TQObservable.cxx:210
 TQObservable.cxx:211
 TQObservable.cxx:212
 TQObservable.cxx:213
 TQObservable.cxx:214
 TQObservable.cxx:215
 TQObservable.cxx:216
 TQObservable.cxx:217
 TQObservable.cxx:218
 TQObservable.cxx:219
 TQObservable.cxx:220
 TQObservable.cxx:221
 TQObservable.cxx:222
 TQObservable.cxx:223
 TQObservable.cxx:224
 TQObservable.cxx:225
 TQObservable.cxx:226
 TQObservable.cxx:227
 TQObservable.cxx:228
 TQObservable.cxx:229
 TQObservable.cxx:230
 TQObservable.cxx:231
 TQObservable.cxx:232
 TQObservable.cxx:233
 TQObservable.cxx:234
 TQObservable.cxx:235
 TQObservable.cxx:236
 TQObservable.cxx:237
 TQObservable.cxx:238
 TQObservable.cxx:239
 TQObservable.cxx:240
 TQObservable.cxx:241
 TQObservable.cxx:242
 TQObservable.cxx:243
 TQObservable.cxx:244
 TQObservable.cxx:245
 TQObservable.cxx:246
 TQObservable.cxx:247
 TQObservable.cxx:248
 TQObservable.cxx:249
 TQObservable.cxx:250
 TQObservable.cxx:251
 TQObservable.cxx:252
 TQObservable.cxx:253
 TQObservable.cxx:254
 TQObservable.cxx:255
 TQObservable.cxx:256
 TQObservable.cxx:257
 TQObservable.cxx:258
 TQObservable.cxx:259
 TQObservable.cxx:260
 TQObservable.cxx:261
 TQObservable.cxx:262
 TQObservable.cxx:263
 TQObservable.cxx:264
 TQObservable.cxx:265
 TQObservable.cxx:266
 TQObservable.cxx:267
 TQObservable.cxx:268
 TQObservable.cxx:269
 TQObservable.cxx:270
 TQObservable.cxx:271
 TQObservable.cxx:272
 TQObservable.cxx:273
 TQObservable.cxx:274
 TQObservable.cxx:275
 TQObservable.cxx:276
 TQObservable.cxx:277
 TQObservable.cxx:278
 TQObservable.cxx:279
 TQObservable.cxx:280
 TQObservable.cxx:281
 TQObservable.cxx:282
 TQObservable.cxx:283
 TQObservable.cxx:284
 TQObservable.cxx:285
 TQObservable.cxx:286
 TQObservable.cxx:287
 TQObservable.cxx:288
 TQObservable.cxx:289
 TQObservable.cxx:290
 TQObservable.cxx:291
 TQObservable.cxx:292
 TQObservable.cxx:293
 TQObservable.cxx:294
 TQObservable.cxx:295
 TQObservable.cxx:296
 TQObservable.cxx:297
 TQObservable.cxx:298
 TQObservable.cxx:299
 TQObservable.cxx:300
 TQObservable.cxx:301
 TQObservable.cxx:302
 TQObservable.cxx:303
 TQObservable.cxx:304
 TQObservable.cxx:305
 TQObservable.cxx:306
 TQObservable.cxx:307
 TQObservable.cxx:308
 TQObservable.cxx:309
 TQObservable.cxx:310
 TQObservable.cxx:311
 TQObservable.cxx:312
 TQObservable.cxx:313
 TQObservable.cxx:314
 TQObservable.cxx:315
 TQObservable.cxx:316
 TQObservable.cxx:317
 TQObservable.cxx:318
 TQObservable.cxx:319
 TQObservable.cxx:320
 TQObservable.cxx:321
 TQObservable.cxx:322
 TQObservable.cxx:323
 TQObservable.cxx:324
 TQObservable.cxx:325
 TQObservable.cxx:326
 TQObservable.cxx:327
 TQObservable.cxx:328
 TQObservable.cxx:329
 TQObservable.cxx:330
 TQObservable.cxx:331
 TQObservable.cxx:332
 TQObservable.cxx:333
 TQObservable.cxx:334
 TQObservable.cxx:335
 TQObservable.cxx:336
 TQObservable.cxx:337
 TQObservable.cxx:338
 TQObservable.cxx:339
 TQObservable.cxx:340
 TQObservable.cxx:341
 TQObservable.cxx:342
 TQObservable.cxx:343
 TQObservable.cxx:344
 TQObservable.cxx:345
 TQObservable.cxx:346
 TQObservable.cxx:347
 TQObservable.cxx:348
 TQObservable.cxx:349
 TQObservable.cxx:350
 TQObservable.cxx:351
 TQObservable.cxx:352
 TQObservable.cxx:353
 TQObservable.cxx:354
 TQObservable.cxx:355
 TQObservable.cxx:356
 TQObservable.cxx:357
 TQObservable.cxx:358
 TQObservable.cxx:359
 TQObservable.cxx:360
 TQObservable.cxx:361
 TQObservable.cxx:362
 TQObservable.cxx:363
 TQObservable.cxx:364
 TQObservable.cxx:365
 TQObservable.cxx:366
 TQObservable.cxx:367
 TQObservable.cxx:368
 TQObservable.cxx:369
 TQObservable.cxx:370
 TQObservable.cxx:371
 TQObservable.cxx:372
 TQObservable.cxx:373
 TQObservable.cxx:374
 TQObservable.cxx:375
 TQObservable.cxx:376
 TQObservable.cxx:377
 TQObservable.cxx:378
 TQObservable.cxx:379
 TQObservable.cxx:380
 TQObservable.cxx:381
 TQObservable.cxx:382
 TQObservable.cxx:383
 TQObservable.cxx:384
 TQObservable.cxx:385
 TQObservable.cxx:386
 TQObservable.cxx:387
 TQObservable.cxx:388
 TQObservable.cxx:389
 TQObservable.cxx:390
 TQObservable.cxx:391
 TQObservable.cxx:392
 TQObservable.cxx:393
 TQObservable.cxx:394
 TQObservable.cxx:395
 TQObservable.cxx:396
 TQObservable.cxx:397
 TQObservable.cxx:398
 TQObservable.cxx:399
 TQObservable.cxx:400
 TQObservable.cxx:401
 TQObservable.cxx:402
 TQObservable.cxx:403
 TQObservable.cxx:404
 TQObservable.cxx:405
 TQObservable.cxx:406
 TQObservable.cxx:407
 TQObservable.cxx:408
 TQObservable.cxx:409
 TQObservable.cxx:410
 TQObservable.cxx:411
 TQObservable.cxx:412
 TQObservable.cxx:413
 TQObservable.cxx:414
 TQObservable.cxx:415
 TQObservable.cxx:416
 TQObservable.cxx:417
 TQObservable.cxx:418
 TQObservable.cxx:419
 TQObservable.cxx:420
 TQObservable.cxx:421
 TQObservable.cxx:422
 TQObservable.cxx:423
 TQObservable.cxx:424
 TQObservable.cxx:425
 TQObservable.cxx:426
 TQObservable.cxx:427
 TQObservable.cxx:428
 TQObservable.cxx:429
 TQObservable.cxx:430
 TQObservable.cxx:431
 TQObservable.cxx:432
 TQObservable.cxx:433
 TQObservable.cxx:434
 TQObservable.cxx:435
 TQObservable.cxx:436
 TQObservable.cxx:437
 TQObservable.cxx:438
 TQObservable.cxx:439
 TQObservable.cxx:440
 TQObservable.cxx:441
 TQObservable.cxx:442
 TQObservable.cxx:443
 TQObservable.cxx:444
 TQObservable.cxx:445
 TQObservable.cxx:446
 TQObservable.cxx:447
 TQObservable.cxx:448
 TQObservable.cxx:449
 TQObservable.cxx:450
 TQObservable.cxx:451
 TQObservable.cxx:452
 TQObservable.cxx:453
 TQObservable.cxx:454
 TQObservable.cxx:455
 TQObservable.cxx:456
 TQObservable.cxx:457
 TQObservable.cxx:458
 TQObservable.cxx:459
 TQObservable.cxx:460
 TQObservable.cxx:461
 TQObservable.cxx:462
 TQObservable.cxx:463
 TQObservable.cxx:464
 TQObservable.cxx:465
 TQObservable.cxx:466
 TQObservable.cxx:467
 TQObservable.cxx:468
 TQObservable.cxx:469
 TQObservable.cxx:470
 TQObservable.cxx:471
 TQObservable.cxx:472
 TQObservable.cxx:473
 TQObservable.cxx:474
 TQObservable.cxx:475
 TQObservable.cxx:476
 TQObservable.cxx:477
 TQObservable.cxx:478
 TQObservable.cxx:479
 TQObservable.cxx:480
 TQObservable.cxx:481
 TQObservable.cxx:482
 TQObservable.cxx:483
 TQObservable.cxx:484
 TQObservable.cxx:485
 TQObservable.cxx:486
 TQObservable.cxx:487
 TQObservable.cxx:488
 TQObservable.cxx:489
 TQObservable.cxx:490
 TQObservable.cxx:491
 TQObservable.cxx:492
 TQObservable.cxx:493
 TQObservable.cxx:494
 TQObservable.cxx:495
 TQObservable.cxx:496
 TQObservable.cxx:497
 TQObservable.cxx:498
 TQObservable.cxx:499
 TQObservable.cxx:500
 TQObservable.cxx:501
 TQObservable.cxx:502
 TQObservable.cxx:503
 TQObservable.cxx:504
 TQObservable.cxx:505
 TQObservable.cxx:506
 TQObservable.cxx:507
 TQObservable.cxx:508
 TQObservable.cxx:509
 TQObservable.cxx:510
 TQObservable.cxx:511
 TQObservable.cxx:512
 TQObservable.cxx:513
 TQObservable.cxx:514
 TQObservable.cxx:515
 TQObservable.cxx:516
 TQObservable.cxx:517
 TQObservable.cxx:518
 TQObservable.cxx:519
 TQObservable.cxx:520
 TQObservable.cxx:521
 TQObservable.cxx:522
 TQObservable.cxx:523
 TQObservable.cxx:524
 TQObservable.cxx:525
 TQObservable.cxx:526
 TQObservable.cxx:527
 TQObservable.cxx:528
 TQObservable.cxx:529
 TQObservable.cxx:530
 TQObservable.cxx:531
 TQObservable.cxx:532
 TQObservable.cxx:533
 TQObservable.cxx:534
 TQObservable.cxx:535
 TQObservable.cxx:536
 TQObservable.cxx:537
 TQObservable.cxx:538
 TQObservable.cxx:539
 TQObservable.cxx:540
 TQObservable.cxx:541
 TQObservable.cxx:542
 TQObservable.cxx:543
 TQObservable.cxx:544
 TQObservable.cxx:545
 TQObservable.cxx:546
 TQObservable.cxx:547
 TQObservable.cxx:548
 TQObservable.cxx:549
 TQObservable.cxx:550
 TQObservable.cxx:551
 TQObservable.cxx:552
 TQObservable.cxx:553
 TQObservable.cxx:554
 TQObservable.cxx:555
 TQObservable.cxx:556
 TQObservable.cxx:557
 TQObservable.cxx:558
 TQObservable.cxx:559
 TQObservable.cxx:560
 TQObservable.cxx:561
 TQObservable.cxx:562
 TQObservable.cxx:563
 TQObservable.cxx:564
 TQObservable.cxx:565
 TQObservable.cxx:566
 TQObservable.cxx:567
 TQObservable.cxx:568
 TQObservable.cxx:569
 TQObservable.cxx:570
 TQObservable.cxx:571
 TQObservable.cxx:572
 TQObservable.cxx:573
 TQObservable.cxx:574
 TQObservable.cxx:575
 TQObservable.cxx:576
 TQObservable.cxx:577
 TQObservable.cxx:578
 TQObservable.cxx:579
 TQObservable.cxx:580
 TQObservable.cxx:581
 TQObservable.cxx:582
 TQObservable.cxx:583
 TQObservable.cxx:584
 TQObservable.cxx:585
 TQObservable.cxx:586
 TQObservable.cxx:587
 TQObservable.cxx:588
 TQObservable.cxx:589
 TQObservable.cxx:590
 TQObservable.cxx:591
 TQObservable.cxx:592
 TQObservable.cxx:593
 TQObservable.cxx:594
 TQObservable.cxx:595
 TQObservable.cxx:596
 TQObservable.cxx:597
 TQObservable.cxx:598
 TQObservable.cxx:599
 TQObservable.cxx:600
 TQObservable.cxx:601
 TQObservable.cxx:602
 TQObservable.cxx:603
 TQObservable.cxx:604
 TQObservable.cxx:605
 TQObservable.cxx:606
 TQObservable.cxx:607
 TQObservable.cxx:608
 TQObservable.cxx:609
 TQObservable.cxx:610
 TQObservable.cxx:611
 TQObservable.cxx:612
 TQObservable.cxx:613
 TQObservable.cxx:614
 TQObservable.cxx:615
 TQObservable.cxx:616
 TQObservable.cxx:617
 TQObservable.cxx:618
 TQObservable.cxx:619
 TQObservable.cxx:620
 TQObservable.cxx:621
 TQObservable.cxx:622
 TQObservable.cxx:623
 TQObservable.cxx:624
 TQObservable.cxx:625
 TQObservable.cxx:626
 TQObservable.cxx:627
 TQObservable.cxx:628
 TQObservable.cxx:629
 TQObservable.cxx:630
 TQObservable.cxx:631
 TQObservable.cxx:632
 TQObservable.cxx:633
 TQObservable.cxx:634
 TQObservable.cxx:635
 TQObservable.cxx:636
 TQObservable.cxx:637
 TQObservable.cxx:638
 TQObservable.cxx:639
 TQObservable.cxx:640
 TQObservable.cxx:641
 TQObservable.cxx:642
 TQObservable.cxx:643
 TQObservable.cxx:644
 TQObservable.cxx:645
 TQObservable.cxx:646
 TQObservable.cxx:647
 TQObservable.cxx:648
 TQObservable.cxx:649
 TQObservable.cxx:650
 TQObservable.cxx:651
 TQObservable.cxx:652
 TQObservable.cxx:653
 TQObservable.cxx:654
 TQObservable.cxx:655
 TQObservable.cxx:656
 TQObservable.cxx:657
 TQObservable.cxx:658
 TQObservable.cxx:659
 TQObservable.cxx:660
 TQObservable.cxx:661
 TQObservable.cxx:662
 TQObservable.cxx:663
 TQObservable.cxx:664
 TQObservable.cxx:665
 TQObservable.cxx:666
 TQObservable.cxx:667
 TQObservable.cxx:668
 TQObservable.cxx:669
 TQObservable.cxx:670
 TQObservable.cxx:671
 TQObservable.cxx:672
 TQObservable.cxx:673
 TQObservable.cxx:674
 TQObservable.cxx:675
 TQObservable.cxx:676
 TQObservable.cxx:677
 TQObservable.cxx:678
 TQObservable.cxx:679
 TQObservable.cxx:680
 TQObservable.cxx:681
 TQObservable.cxx:682
 TQObservable.cxx:683
 TQObservable.cxx:684
 TQObservable.cxx:685
 TQObservable.cxx:686
 TQObservable.cxx:687
 TQObservable.cxx:688
 TQObservable.cxx:689
 TQObservable.cxx:690
 TQObservable.cxx:691
 TQObservable.cxx:692
 TQObservable.cxx:693
 TQObservable.cxx:694
 TQObservable.cxx:695
 TQObservable.cxx:696
 TQObservable.cxx:697
 TQObservable.cxx:698
 TQObservable.cxx:699
 TQObservable.cxx:700
 TQObservable.cxx:701
 TQObservable.cxx:702
 TQObservable.cxx:703
 TQObservable.cxx:704
 TQObservable.cxx:705
 TQObservable.cxx:706
 TQObservable.cxx:707
 TQObservable.cxx:708
 TQObservable.cxx:709
 TQObservable.cxx:710
 TQObservable.cxx:711
 TQObservable.cxx:712
 TQObservable.cxx:713
 TQObservable.cxx:714
 TQObservable.cxx:715
 TQObservable.cxx:716
 TQObservable.cxx:717
 TQObservable.cxx:718
 TQObservable.cxx:719
 TQObservable.cxx:720
 TQObservable.cxx:721
 TQObservable.cxx:722
 TQObservable.cxx:723
 TQObservable.cxx:724
 TQObservable.cxx:725
 TQObservable.cxx:726
 TQObservable.cxx:727
 TQObservable.cxx:728
 TQObservable.cxx:729
 TQObservable.cxx:730
 TQObservable.cxx:731
 TQObservable.cxx:732
 TQObservable.cxx:733
 TQObservable.cxx:734
 TQObservable.cxx:735
 TQObservable.cxx:736
 TQObservable.cxx:737
 TQObservable.cxx:738
 TQObservable.cxx:739
 TQObservable.cxx:740
 TQObservable.cxx:741
 TQObservable.cxx:742
 TQObservable.cxx:743
 TQObservable.cxx:744
 TQObservable.cxx:745
 TQObservable.cxx:746
 TQObservable.cxx:747
 TQObservable.cxx:748
 TQObservable.cxx:749
 TQObservable.cxx:750
 TQObservable.cxx:751
 TQObservable.cxx:752
 TQObservable.cxx:753
 TQObservable.cxx:754
 TQObservable.cxx:755
 TQObservable.cxx:756
 TQObservable.cxx:757
 TQObservable.cxx:758
 TQObservable.cxx:759
 TQObservable.cxx:760
 TQObservable.cxx:761
 TQObservable.cxx:762
 TQObservable.cxx:763
 TQObservable.cxx:764
 TQObservable.cxx:765
 TQObservable.cxx:766
 TQObservable.cxx:767
 TQObservable.cxx:768
 TQObservable.cxx:769
 TQObservable.cxx:770
 TQObservable.cxx:771
 TQObservable.cxx:772
 TQObservable.cxx:773
 TQObservable.cxx:774
 TQObservable.cxx:775
 TQObservable.cxx:776
 TQObservable.cxx:777
 TQObservable.cxx:778
 TQObservable.cxx:779
 TQObservable.cxx:780
 TQObservable.cxx:781
 TQObservable.cxx:782
 TQObservable.cxx:783
 TQObservable.cxx:784
 TQObservable.cxx:785
 TQObservable.cxx:786
 TQObservable.cxx:787
 TQObservable.cxx:788
 TQObservable.cxx:789
 TQObservable.cxx:790
 TQObservable.cxx:791
 TQObservable.cxx:792
 TQObservable.cxx:793
 TQObservable.cxx:794
 TQObservable.cxx:795
 TQObservable.cxx:796
 TQObservable.cxx:797
 TQObservable.cxx:798
 TQObservable.cxx:799
 TQObservable.cxx:800
 TQObservable.cxx:801
 TQObservable.cxx:802
 TQObservable.cxx:803
 TQObservable.cxx:804
 TQObservable.cxx:805
 TQObservable.cxx:806
 TQObservable.cxx:807
 TQObservable.cxx:808
 TQObservable.cxx:809
 TQObservable.cxx:810
 TQObservable.cxx:811
 TQObservable.cxx:812
 TQObservable.cxx:813
 TQObservable.cxx:814
 TQObservable.cxx:815
 TQObservable.cxx:816
 TQObservable.cxx:817
 TQObservable.cxx:818
 TQObservable.cxx:819
 TQObservable.cxx:820
 TQObservable.cxx:821
 TQObservable.cxx:822
 TQObservable.cxx:823
 TQObservable.cxx:824
 TQObservable.cxx:825
 TQObservable.cxx:826
 TQObservable.cxx:827
 TQObservable.cxx:828
 TQObservable.cxx:829
 TQObservable.cxx:830
 TQObservable.cxx:831
 TQObservable.cxx:832
 TQObservable.cxx:833
 TQObservable.cxx:834
 TQObservable.cxx:835
 TQObservable.cxx:836
 TQObservable.cxx:837
 TQObservable.cxx:838
 TQObservable.cxx:839
 TQObservable.cxx:840
 TQObservable.cxx:841
 TQObservable.cxx:842
 TQObservable.cxx:843
 TQObservable.cxx:844
 TQObservable.cxx:845
 TQObservable.cxx:846
 TQObservable.cxx:847
 TQObservable.cxx:848
 TQObservable.cxx:849
 TQObservable.cxx:850
 TQObservable.cxx:851
 TQObservable.cxx:852
 TQObservable.cxx:853
 TQObservable.cxx:854
 TQObservable.cxx:855
 TQObservable.cxx:856
 TQObservable.cxx:857
 TQObservable.cxx:858
 TQObservable.cxx:859
 TQObservable.cxx:860
 TQObservable.cxx:861
 TQObservable.cxx:862
 TQObservable.cxx:863
 TQObservable.cxx:864
 TQObservable.cxx:865
 TQObservable.cxx:866
 TQObservable.cxx:867
 TQObservable.cxx:868
 TQObservable.cxx:869
 TQObservable.cxx:870
 TQObservable.cxx:871
 TQObservable.cxx:872
 TQObservable.cxx:873
 TQObservable.cxx:874
 TQObservable.cxx:875
 TQObservable.cxx:876
 TQObservable.cxx:877
 TQObservable.cxx:878
 TQObservable.cxx:879
 TQObservable.cxx:880
 TQObservable.cxx:881
 TQObservable.cxx:882
 TQObservable.cxx:883
 TQObservable.cxx:884
 TQObservable.cxx:885
 TQObservable.cxx:886
 TQObservable.cxx:887
 TQObservable.cxx:888
 TQObservable.cxx:889
 TQObservable.cxx:890
 TQObservable.cxx:891
 TQObservable.cxx:892
 TQObservable.cxx:893
 TQObservable.cxx:894
 TQObservable.cxx:895