// @(#)root/roostats:$Id$
// Author: Danilo Piparo   25/08/2009


/*************************************************************************
 * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//___________________________________________________
/*
BEGIN_HTML
<p>
HLFactory is an High Level model Factory allows you to
describe your models in a configuration file
(<i>datacards</i>) acting as an interface with the RooFactoryWSTool.
Moreover it provides tools for the combination of models and datasets.
</p>

END_HTML
*/

#include <iostream>
#include <fstream>

#include "RooStats/HLFactory.h"
#include "TFile.h"
#include "TObject.h"
#include "TObjArray.h"
#include "TObjString.h"

#include "RooSimultaneous.h"

using namespace std;

ClassImp(RooStats::HLFactory) ;


using namespace RooStats;
using namespace RooFit;

//_______________________________________________________
HLFactory::HLFactory(const char *name,
                     const char *fileName,
                     bool isVerbose):
    TNamed(name,name),
    fComboCat(0),
    fComboBkgPdf(0),
    fComboSigBkgPdf(0),
    fComboDataset(0),
    fCombinationDone(false),
    fVerbose(isVerbose),
    fInclusionLevel(0),
    fOwnWs(true){
    // Constructor with the name of the config file to interpret and the
    // verbosity flag. The extension for the config files is assumed to
    // be ".rs".

    TString wsName(name);
    wsName+="_ws";
    fWs = new RooWorkspace(wsName,true);

    fSigBkgPdfNames.SetOwner();
    fBkgPdfNames.SetOwner();
    fDatasetsNames.SetOwner();

    // Start the parsing
    fReadFile(fileName);
}

//_______________________________________________________
HLFactory::HLFactory(const char* name,
                     RooWorkspace* externalWs,
                     bool isVerbose):
    TNamed(name,name),
    fComboCat(0),
    fComboBkgPdf(0),
    fComboSigBkgPdf(0),
    fComboDataset(0),
    fCombinationDone(false),
    fVerbose(isVerbose),
    fInclusionLevel(0),
    fOwnWs(false){
    // Constructor without a card but with an exrernal workspace.

    fWs=externalWs;
    fSigBkgPdfNames.SetOwner();
    fBkgPdfNames.SetOwner();
    fDatasetsNames.SetOwner();

}

//_______________________________________________________
HLFactory::HLFactory():
    TNamed("hlfactory","hlfactory"),
    fComboCat(0),
    fComboBkgPdf(0),
    fComboSigBkgPdf(0),
    fComboDataset(0),
    fCombinationDone(false),
    fVerbose(false),
    fInclusionLevel(0),
    fOwnWs(true){

    fWs = new RooWorkspace("hlfactory_ws",true);

    fSigBkgPdfNames.SetOwner();
    fBkgPdfNames.SetOwner();
    fDatasetsNames.SetOwner();

    }

//_______________________________________________________
HLFactory::~HLFactory(){
    // destructor

    if (fComboSigBkgPdf!=NULL)
        delete fComboSigBkgPdf;
    if (fComboBkgPdf!=NULL)
        delete fComboBkgPdf;
    if (fComboDataset!=NULL)
        delete fComboDataset;
    if (fComboCat!=NULL)
        delete fComboCat;

    if (fOwnWs)
        delete fWs;
}

//_______________________________________________________
int HLFactory::AddChannel(const char* label,
                          const char* SigBkgPdfName,
                          const char* BkgPdfName,
                          const char* DatasetName){
    // Add a channel to the combination. The channel can be specified as:
    //  - A signal plus background pdf
    //  - A background only pdf
    //  - A dataset
    // Once the combination of the pdfs is done, no more channels should be
    // added.

    if (fCombinationDone){
        std::cerr << "Cannot add anymore channels. "
                  << "Combination already carried out.\n";
        return -1;
        }

    if (SigBkgPdfName!=0){
        if (fWs->pdf(SigBkgPdfName)==NULL){
            std::cerr << "Pdf " << SigBkgPdfName << " not found in workspace!\n";
            return -1;
            }
        TObjString* name = new TObjString(SigBkgPdfName);
        fSigBkgPdfNames.Add(name);
        }

    if (BkgPdfName!=0){
        if (fWs->pdf(BkgPdfName)==NULL){
            std::cerr << "Pdf " << BkgPdfName << " not found in workspace!\n";
            return -1;
            }
        TObjString* name = new TObjString(BkgPdfName);
        fBkgPdfNames.Add(name);
        }

    if (DatasetName!=0){
        if (fWs->data(DatasetName)==NULL){
            std::cerr << "Dataset " << DatasetName << " not found in workspace!\n";
            return -1;
            }
        TObjString* name = new TObjString(DatasetName);
        fDatasetsNames.Add(name);
        }

    if (label!=0){
        TObjString* name = new TObjString(label);
        fLabelsNames.Add(name);
        }
    return 0;

}

//_______________________________________________________
RooAbsPdf* HLFactory::GetTotSigBkgPdf(){
    // Return the combination of the signal plus background channels.
    // The facory owns the object.

    if (fSigBkgPdfNames.GetSize()==0)
        return 0;

    if (fComboSigBkgPdf!=NULL)
        return fComboSigBkgPdf;

    if (!fNamesListsConsistent())
        return NULL;

    if (fSigBkgPdfNames.GetSize()==1){
        TString name(((TObjString*)fSigBkgPdfNames.At(0))->String());
        fComboSigBkgPdf=fWs->pdf(name);
        return fComboSigBkgPdf;
        }

    if (!fCombinationDone)
        fCreateCategory();

    RooArgList pdfs("pdfs");

    TIterator* it=fSigBkgPdfNames.MakeIterator();
    TObjString* ostring;
    TObject* obj;
    while ((obj = it->Next())){
        ostring=(TObjString*) obj;
        pdfs.add( *(fWs->pdf(ostring->String())) );
        }
    delete it;

    TString name(GetName());
    name+="_sigbkg";

    TString title(GetName());
    title+="_sigbkg";

    fComboSigBkgPdf=
      new RooSimultaneous(name,
                          title,
                          pdfs,
                          *fComboCat);

    return fComboSigBkgPdf;

    }
//_______________________________________________________
RooAbsPdf* HLFactory::GetTotBkgPdf(){
    // Return the combination of the background only channels.
    // If no background channel is specified a NULL pointer is returned.
    // The facory owns the object.

    if (fBkgPdfNames.GetSize()==0)
        return 0;

    if (fComboBkgPdf!=NULL)
        return fComboBkgPdf;

    if (!fNamesListsConsistent())
        return NULL;

    if (fBkgPdfNames.GetSize()==1){
        fComboBkgPdf=fWs->pdf(((TObjString*)fBkgPdfNames.First())->String());
        return fComboBkgPdf;
        }

    if (!fCombinationDone)
        fCreateCategory();

    RooArgList pdfs("pdfs");

    TIterator* it = fBkgPdfNames.MakeIterator();
    TObjString* ostring;
    TObject* obj;
    while ((obj = it->Next())){
        ostring=(TObjString*) obj;
        pdfs.add( *(fWs->pdf(ostring->String())) );
        }

    TString name(GetName());
    name+="_bkg";

    TString title(GetName());
    title+="_bkg";

    fComboBkgPdf=
      new RooSimultaneous(name,
                          title,
                          pdfs,
                          *fComboCat);

    return fComboBkgPdf;

}

//_______________________________________________________
RooDataSet* HLFactory::GetTotDataSet(){
   // Return the combination of the datasets.
   // If no dataset is specified a NULL pointer is returned.
   // The facory owns the object.

    if (fDatasetsNames.GetSize()==0)
        return 0;

    if (fComboDataset!=NULL)
        return fComboDataset;

    if (!fNamesListsConsistent())
        return NULL;

    if (fDatasetsNames.GetSize()==1){
        fComboDataset=(RooDataSet*)fWs->data(((TObjString*)fDatasetsNames.First())->String());
        return fComboDataset;
        }

    if (!fCombinationDone)
        fCreateCategory();


    TIterator* it = fDatasetsNames.MakeIterator();
    TObjString* ostring;
    TObject* obj = it->Next();
    ostring = (TObjString*) obj;
    fComboDataset = (RooDataSet*) fWs->data(ostring->String()) ;
    if (!fComboDataset) return NULL;
    fComboDataset->Print();
    TString dataname(GetName());
    fComboDataset = new RooDataSet(*fComboDataset,dataname+"_TotData");
    int catindex=0;
    fComboCat->setIndex(catindex);
    fComboDataset->addColumn(*fComboCat);
    while ((obj = it->Next())){
        ostring=(TObjString*) obj;
        catindex++;
        RooDataSet * data = (RooDataSet*)fWs->data(ostring->String());
        if (!data) return NULL;
        RooDataSet* dummy = new RooDataSet(*data,"");
        fComboCat->setIndex(catindex);
        fComboCat->Print();
        dummy->addColumn(*fComboCat);
        fComboDataset->append(*dummy);
        delete dummy;
    }

    delete it;
    return fComboDataset;

}

//_______________________________________________________
RooCategory* HLFactory::GetTotCategory(){
   // Return the category.
   // The facory owns the object.

    if (fComboCat!=NULL)
        return fComboCat;

    if (!fNamesListsConsistent())
        return NULL;

    if (!fCombinationDone)
        fCreateCategory();

    return fComboCat;

    }

//_______________________________________________________
int HLFactory::ProcessCard(const char* filename){
    // Process an additional configuration file
    return fReadFile(filename,0);
    }

//_______________________________________________________
int HLFactory::fReadFile(const char*fileName, bool is_included){
    // Parses the configuration file. The objects can be specified following
    // the rules of the RooFactoryWSTool, plus some more flexibility.
    //
    // The official format for the datacards is ".rs".
    //
    // All the instructions end with a ";" (like in C++).
    //
    // Carriage returns and white lines are irrelevant but adviced since they
    // improve readability (like in C++).
    //
    // The (Roo)ClassName::objname(description) can be replaced with the more
    // "pythonic" objname = (Roo)ClassName(description).
    //
    // The comments can be specified with a "//" if on a single line or with
    // /* */ if on multiple lines (like in C++).
    //
    // The "#include path/to/file.rs" statement triggers the inclusion of a
    // configuration fragment.
    //
    // The "import myobject:myworkspace:myrootfile" will add to the Workspace
    // the object myobject located in myworkspace recorded in myrootfile.
    // Alternatively, one could choose the "import myobject:myrootfile" in case
    // no Workspace is present.
    //
    // The "echo" statement prompts a message on screen.

    // Check the deepness of the inclusion
    if (is_included)
        fInclusionLevel+=1;
    else
        fInclusionLevel=0;

    const int maxDeepness=50;
    if (fInclusionLevel>maxDeepness){
        TString warning("The inclusion stack is deeper than ");
        warning+=maxDeepness;
        warning+=". Is this a recursive inclusion?";
        Warning("fReadFile", "%s", warning.Data());
        }


    // open the config file and go through it
    std::ifstream ifile(fileName);

    if(ifile.fail()){
        TString error("File ");
        error+=fileName;
        error+=" could not be opened.";
        Error("fReadFile", "%s", error.Data());
        return -1;
        }

    TString ifileContent("");
    ifileContent.ReadFile(ifile);
    ifile.close();

    // Tokenise the file using the "\n" char and parse it line by line to strip
    // the comments.
    TString ifileContentStripped("");

    TObjArray* lines_array = ifileContent.Tokenize("\n");
    TIterator* lineIt=lines_array->MakeIterator();

    bool in_comment=false;
    TString line;
    TObject* line_o;

    while((line_o=(*lineIt)())){ // Start iteration on lines array
        line = (static_cast<TObjString*>(line_o))->GetString();

        // Are we in a multiline comment?
        if (in_comment)
            if (line.EndsWith("*/")){
                in_comment=false;
                if (fVerbose) Info("fReadFile","Out of multiline comment ...");

                continue;
                }

        // Was line a single line comment?

        if ((line.BeginsWith("/*") && line.EndsWith("*/")) ||
            line.BeginsWith("//")){
            if (fVerbose) Info("fReadFile","In single line comment ...");
            continue;
            }

        // Did a multiline comment just begin?
        if (line.BeginsWith("/*")){
            in_comment=true;
            if (fVerbose) Info("fReadFile","In multiline comment ...");
            continue;
            }

        ifileContentStripped+=line+"\n";
        }

    delete lines_array;
    delete lineIt;

    // Now proceed with the parsing of the stripped file

    lines_array = ifileContentStripped.Tokenize(";");
    lineIt=lines_array->MakeIterator();
    in_comment=false;

    const int nNeutrals=2;
    TString neutrals[nNeutrals]={"\t"," "};

    while((line_o=(*lineIt)())){

        line = (static_cast<TObjString*>(line_o))->GetString();

        // Strip spaces at the beginning and the end of the line
        line.Strip(TString::kBoth,' ');

        // Put the single statement in one single line
        line.ReplaceAll("\n","");

        // Do we have an echo statement? "A la RooFit"
        if (line.BeginsWith("echo")){
            line = line(5,line.Length()-1);
            if (fVerbose)
              std::cout << "Echoing line " << line.Data() << std::endl;
            std::cout << "[" << GetName() << "] echo: "
                      << line.Data() << std::endl;
            continue;
            }

        // Spaces and tabs at this point are not needed.
        for (int i=0;i<nNeutrals;++i)
            line.ReplaceAll(neutrals[i],"");


        if (fVerbose) Info("fReadFile","Reading --> %s <--", line.Data());

        // Was line a white space?
        if (line == ""){
            if (fVerbose) Info("fReadFile", "%s", "Empty line: skipping ...");
            continue;
            }

        // Do we have an include statement?
        // We treat this recursively.
        if (line.BeginsWith("#include")){
            line.ReplaceAll("#include","");
            if (fVerbose) Info("fReadFile","Reading included file...");
            fReadFile(line,true);
            continue;
            }

        // We parse the line
        if (fVerbose) Info("fReadFile","Parsing the line...");
        fParseLine(line);
        }

    delete lineIt;
    delete lines_array;

    return 0;
}


//_______________________________________________________
void HLFactory::fCreateCategory(){
    // Builds the category necessary for the mutidimensional models. Its name
    // will be <HLFactory name>_category and the types are specified by the
    // model labels.

    fCombinationDone=true;

    TString name(GetName());
    name+="_category";

    TString title(GetName());
    title+="_category";

    fComboCat=new RooCategory(name,title);

    TIterator* it=fLabelsNames.MakeIterator();
    TObjString* ostring;
    TObject* obj;
    while ((obj = it->Next())){
        ostring=(TObjString*) obj;
        fComboCat->defineType(ostring->String());
        }

    }

//_______________________________________________________
bool HLFactory::fNamesListsConsistent(){
    // Check the number of entries in each list. If not the same and the list
    // is not empty prompt an error.

    if ((fSigBkgPdfNames.GetEntries()==fBkgPdfNames.GetEntries() || fBkgPdfNames.GetEntries()==0) &&
        (fSigBkgPdfNames.GetEntries()==fDatasetsNames.GetEntries() || fDatasetsNames.GetEntries()==0) &&
        (fSigBkgPdfNames.GetEntries()==fLabelsNames.GetEntries() || fLabelsNames.GetEntries()==0))
        return true;
    else{
        std::cerr << "The number of datasets and models added as channels "
                  << " is not the same!\n";
        return false;
        }
    }

//_______________________________________________________
int HLFactory::fParseLine(TString& line){
    // Parse a single line and puts the content in the RooWorkSpace

    if (fVerbose) Info("fParseLine", "Parsing line: %s", line.Data());

    TString new_line("");

    const int nequals = line.CountChar('=');

    // Build with the factory a var or cat, or pipe the command directly.

    if (line.Contains("::") || // It is a ordinary statement
        nequals==0 || //it is a RooRealVar or cat with 0,1,2,3.. indexes
        (line.Contains("[") &&
         line.Contains("]") &&
         nequals>0 &&    // It is a cat like "tag[B0=1,B0bar=-1]"
         ! line.Contains("(") &&
         ! line.Contains(")"))) {
      fWs->factory(line);
      return 0;
      }

    // Transform the line o_name = o_class(o_descr) in o_class::o_name(o_descr)
    if (nequals==1 ||
        (nequals > 1 &&  line.Contains("SIMUL"))){

        // Divide the line in 3 components: o_name,o_class and o_descr
        // assuming that o_name=o_class(o_descr)
        const int equal_index=line.First('=');
        const int par_index=line.First('(');
        TString o_name(line(0,equal_index));
        TString o_class(line(equal_index+1,par_index-equal_index-1));
        TString o_descr(line(par_index+1,line.Length()-par_index-2));

        if (fVerbose) Info("fParseLine", "o_name=%s o_class=%s o_descr=%s",
                           o_name.Data(), o_class.Data(), o_descr.Data());

        // Now two cases either we wanna produce an object or import something
        // under a new name.
        if (o_class =="import"){// import a generic TObject into the WS
        // Now see if we have a workspace or not, according to the number of
        // entries in the description..

        TObjArray* descr_array = o_descr.Tokenize(",");

        const int n_descr_parts=descr_array->GetEntries();

        if (n_descr_parts<2 || n_descr_parts>3)
          Error("fParseLine","Import wrong syntax: cannot process %s", o_descr.Data());

        TString obj_name (static_cast<TObjString*>(descr_array->At(n_descr_parts-1))->GetString());
        TString ws_name("");
        TString rootfile_name (static_cast<TObjString*>(descr_array->At(0))->GetString());

        TFile* ifile=TFile::Open(rootfile_name);
        if (ifile==0)
            return 1;

        if (n_descr_parts==3){// in presence of a Ws
          o_descr.ReplaceAll(",",":");
          fWs->import(o_descr);
          }
        else if(n_descr_parts==2){ // in presence of an object in rootfile
          if (fVerbose)
            Info("fParseLine","Importing %s from %s under the name of %s",
                 obj_name.Data(), rootfile_name.Data(), o_name.Data());
          TObject* the_obj=ifile->Get(obj_name);
          fWs->import(*the_obj,o_name);
          }
        delete ifile;
        return 0;
        } // end of import block

        new_line=o_class+"::"+o_name+"("+o_descr+")";

        if (fVerbose){
            std::cout << "DEBUG: line: " << line.Data() << std::endl;
            std::cout << "DEBUG: new_line: " << new_line.Data() << std::endl;
            }

        fWs->factory(new_line);

        return 0;
        }

    else { // In case we do not know what to do we pipe it..
        fWs->factory(line);
        }

    return 0;

}




 HLFactory.cxx:1
 HLFactory.cxx:2
 HLFactory.cxx:3
 HLFactory.cxx:4
 HLFactory.cxx:5
 HLFactory.cxx:6
 HLFactory.cxx:7
 HLFactory.cxx:8
 HLFactory.cxx:9
 HLFactory.cxx:10
 HLFactory.cxx:11
 HLFactory.cxx:12
 HLFactory.cxx:13
 HLFactory.cxx:14
 HLFactory.cxx:15
 HLFactory.cxx:16
 HLFactory.cxx:17
 HLFactory.cxx:18
 HLFactory.cxx:19
 HLFactory.cxx:20
 HLFactory.cxx:21
 HLFactory.cxx:22
 HLFactory.cxx:23
 HLFactory.cxx:24
 HLFactory.cxx:25
 HLFactory.cxx:26
 HLFactory.cxx:27
 HLFactory.cxx:28
 HLFactory.cxx:29
 HLFactory.cxx:30
 HLFactory.cxx:31
 HLFactory.cxx:32
 HLFactory.cxx:33
 HLFactory.cxx:34
 HLFactory.cxx:35
 HLFactory.cxx:36
 HLFactory.cxx:37
 HLFactory.cxx:38
 HLFactory.cxx:39
 HLFactory.cxx:40
 HLFactory.cxx:41
 HLFactory.cxx:42
 HLFactory.cxx:43
 HLFactory.cxx:44
 HLFactory.cxx:45
 HLFactory.cxx:46
 HLFactory.cxx:47
 HLFactory.cxx:48
 HLFactory.cxx:49
 HLFactory.cxx:50
 HLFactory.cxx:51
 HLFactory.cxx:52
 HLFactory.cxx:53
 HLFactory.cxx:54
 HLFactory.cxx:55
 HLFactory.cxx:56
 HLFactory.cxx:57
 HLFactory.cxx:58
 HLFactory.cxx:59
 HLFactory.cxx:60
 HLFactory.cxx:61
 HLFactory.cxx:62
 HLFactory.cxx:63
 HLFactory.cxx:64
 HLFactory.cxx:65
 HLFactory.cxx:66
 HLFactory.cxx:67
 HLFactory.cxx:68
 HLFactory.cxx:69
 HLFactory.cxx:70
 HLFactory.cxx:71
 HLFactory.cxx:72
 HLFactory.cxx:73
 HLFactory.cxx:74
 HLFactory.cxx:75
 HLFactory.cxx:76
 HLFactory.cxx:77
 HLFactory.cxx:78
 HLFactory.cxx:79
 HLFactory.cxx:80
 HLFactory.cxx:81
 HLFactory.cxx:82
 HLFactory.cxx:83
 HLFactory.cxx:84
 HLFactory.cxx:85
 HLFactory.cxx:86
 HLFactory.cxx:87
 HLFactory.cxx:88
 HLFactory.cxx:89
 HLFactory.cxx:90
 HLFactory.cxx:91
 HLFactory.cxx:92
 HLFactory.cxx:93
 HLFactory.cxx:94
 HLFactory.cxx:95
 HLFactory.cxx:96
 HLFactory.cxx:97
 HLFactory.cxx:98
 HLFactory.cxx:99
 HLFactory.cxx:100
 HLFactory.cxx:101
 HLFactory.cxx:102
 HLFactory.cxx:103
 HLFactory.cxx:104
 HLFactory.cxx:105
 HLFactory.cxx:106
 HLFactory.cxx:107
 HLFactory.cxx:108
 HLFactory.cxx:109
 HLFactory.cxx:110
 HLFactory.cxx:111
 HLFactory.cxx:112
 HLFactory.cxx:113
 HLFactory.cxx:114
 HLFactory.cxx:115
 HLFactory.cxx:116
 HLFactory.cxx:117
 HLFactory.cxx:118
 HLFactory.cxx:119
 HLFactory.cxx:120
 HLFactory.cxx:121
 HLFactory.cxx:122
 HLFactory.cxx:123
 HLFactory.cxx:124
 HLFactory.cxx:125
 HLFactory.cxx:126
 HLFactory.cxx:127
 HLFactory.cxx:128
 HLFactory.cxx:129
 HLFactory.cxx:130
 HLFactory.cxx:131
 HLFactory.cxx:132
 HLFactory.cxx:133
 HLFactory.cxx:134
 HLFactory.cxx:135
 HLFactory.cxx:136
 HLFactory.cxx:137
 HLFactory.cxx:138
 HLFactory.cxx:139
 HLFactory.cxx:140
 HLFactory.cxx:141
 HLFactory.cxx:142
 HLFactory.cxx:143
 HLFactory.cxx:144
 HLFactory.cxx:145
 HLFactory.cxx:146
 HLFactory.cxx:147
 HLFactory.cxx:148
 HLFactory.cxx:149
 HLFactory.cxx:150
 HLFactory.cxx:151
 HLFactory.cxx:152
 HLFactory.cxx:153
 HLFactory.cxx:154
 HLFactory.cxx:155
 HLFactory.cxx:156
 HLFactory.cxx:157
 HLFactory.cxx:158
 HLFactory.cxx:159
 HLFactory.cxx:160
 HLFactory.cxx:161
 HLFactory.cxx:162
 HLFactory.cxx:163
 HLFactory.cxx:164
 HLFactory.cxx:165
 HLFactory.cxx:166
 HLFactory.cxx:167
 HLFactory.cxx:168
 HLFactory.cxx:169
 HLFactory.cxx:170
 HLFactory.cxx:171
 HLFactory.cxx:172
 HLFactory.cxx:173
 HLFactory.cxx:174
 HLFactory.cxx:175
 HLFactory.cxx:176
 HLFactory.cxx:177
 HLFactory.cxx:178
 HLFactory.cxx:179
 HLFactory.cxx:180
 HLFactory.cxx:181
 HLFactory.cxx:182
 HLFactory.cxx:183
 HLFactory.cxx:184
 HLFactory.cxx:185
 HLFactory.cxx:186
 HLFactory.cxx:187
 HLFactory.cxx:188
 HLFactory.cxx:189
 HLFactory.cxx:190
 HLFactory.cxx:191
 HLFactory.cxx:192
 HLFactory.cxx:193
 HLFactory.cxx:194
 HLFactory.cxx:195
 HLFactory.cxx:196
 HLFactory.cxx:197
 HLFactory.cxx:198
 HLFactory.cxx:199
 HLFactory.cxx:200
 HLFactory.cxx:201
 HLFactory.cxx:202
 HLFactory.cxx:203
 HLFactory.cxx:204
 HLFactory.cxx:205
 HLFactory.cxx:206
 HLFactory.cxx:207
 HLFactory.cxx:208
 HLFactory.cxx:209
 HLFactory.cxx:210
 HLFactory.cxx:211
 HLFactory.cxx:212
 HLFactory.cxx:213
 HLFactory.cxx:214
 HLFactory.cxx:215
 HLFactory.cxx:216
 HLFactory.cxx:217
 HLFactory.cxx:218
 HLFactory.cxx:219
 HLFactory.cxx:220
 HLFactory.cxx:221
 HLFactory.cxx:222
 HLFactory.cxx:223
 HLFactory.cxx:224
 HLFactory.cxx:225
 HLFactory.cxx:226
 HLFactory.cxx:227
 HLFactory.cxx:228
 HLFactory.cxx:229
 HLFactory.cxx:230
 HLFactory.cxx:231
 HLFactory.cxx:232
 HLFactory.cxx:233
 HLFactory.cxx:234
 HLFactory.cxx:235
 HLFactory.cxx:236
 HLFactory.cxx:237
 HLFactory.cxx:238
 HLFactory.cxx:239
 HLFactory.cxx:240
 HLFactory.cxx:241
 HLFactory.cxx:242
 HLFactory.cxx:243
 HLFactory.cxx:244
 HLFactory.cxx:245
 HLFactory.cxx:246
 HLFactory.cxx:247
 HLFactory.cxx:248
 HLFactory.cxx:249
 HLFactory.cxx:250
 HLFactory.cxx:251
 HLFactory.cxx:252
 HLFactory.cxx:253
 HLFactory.cxx:254
 HLFactory.cxx:255
 HLFactory.cxx:256
 HLFactory.cxx:257
 HLFactory.cxx:258
 HLFactory.cxx:259
 HLFactory.cxx:260
 HLFactory.cxx:261
 HLFactory.cxx:262
 HLFactory.cxx:263
 HLFactory.cxx:264
 HLFactory.cxx:265
 HLFactory.cxx:266
 HLFactory.cxx:267
 HLFactory.cxx:268
 HLFactory.cxx:269
 HLFactory.cxx:270
 HLFactory.cxx:271
 HLFactory.cxx:272
 HLFactory.cxx:273
 HLFactory.cxx:274
 HLFactory.cxx:275
 HLFactory.cxx:276
 HLFactory.cxx:277
 HLFactory.cxx:278
 HLFactory.cxx:279
 HLFactory.cxx:280
 HLFactory.cxx:281
 HLFactory.cxx:282
 HLFactory.cxx:283
 HLFactory.cxx:284
 HLFactory.cxx:285
 HLFactory.cxx:286
 HLFactory.cxx:287
 HLFactory.cxx:288
 HLFactory.cxx:289
 HLFactory.cxx:290
 HLFactory.cxx:291
 HLFactory.cxx:292
 HLFactory.cxx:293
 HLFactory.cxx:294
 HLFactory.cxx:295
 HLFactory.cxx:296
 HLFactory.cxx:297
 HLFactory.cxx:298
 HLFactory.cxx:299
 HLFactory.cxx:300
 HLFactory.cxx:301
 HLFactory.cxx:302
 HLFactory.cxx:303
 HLFactory.cxx:304
 HLFactory.cxx:305
 HLFactory.cxx:306
 HLFactory.cxx:307
 HLFactory.cxx:308
 HLFactory.cxx:309
 HLFactory.cxx:310
 HLFactory.cxx:311
 HLFactory.cxx:312
 HLFactory.cxx:313
 HLFactory.cxx:314
 HLFactory.cxx:315
 HLFactory.cxx:316
 HLFactory.cxx:317
 HLFactory.cxx:318
 HLFactory.cxx:319
 HLFactory.cxx:320
 HLFactory.cxx:321
 HLFactory.cxx:322
 HLFactory.cxx:323
 HLFactory.cxx:324
 HLFactory.cxx:325
 HLFactory.cxx:326
 HLFactory.cxx:327
 HLFactory.cxx:328
 HLFactory.cxx:329
 HLFactory.cxx:330
 HLFactory.cxx:331
 HLFactory.cxx:332
 HLFactory.cxx:333
 HLFactory.cxx:334
 HLFactory.cxx:335
 HLFactory.cxx:336
 HLFactory.cxx:337
 HLFactory.cxx:338
 HLFactory.cxx:339
 HLFactory.cxx:340
 HLFactory.cxx:341
 HLFactory.cxx:342
 HLFactory.cxx:343
 HLFactory.cxx:344
 HLFactory.cxx:345
 HLFactory.cxx:346
 HLFactory.cxx:347
 HLFactory.cxx:348
 HLFactory.cxx:349
 HLFactory.cxx:350
 HLFactory.cxx:351
 HLFactory.cxx:352
 HLFactory.cxx:353
 HLFactory.cxx:354
 HLFactory.cxx:355
 HLFactory.cxx:356
 HLFactory.cxx:357
 HLFactory.cxx:358
 HLFactory.cxx:359
 HLFactory.cxx:360
 HLFactory.cxx:361
 HLFactory.cxx:362
 HLFactory.cxx:363
 HLFactory.cxx:364
 HLFactory.cxx:365
 HLFactory.cxx:366
 HLFactory.cxx:367
 HLFactory.cxx:368
 HLFactory.cxx:369
 HLFactory.cxx:370
 HLFactory.cxx:371
 HLFactory.cxx:372
 HLFactory.cxx:373
 HLFactory.cxx:374
 HLFactory.cxx:375
 HLFactory.cxx:376
 HLFactory.cxx:377
 HLFactory.cxx:378
 HLFactory.cxx:379
 HLFactory.cxx:380
 HLFactory.cxx:381
 HLFactory.cxx:382
 HLFactory.cxx:383
 HLFactory.cxx:384
 HLFactory.cxx:385
 HLFactory.cxx:386
 HLFactory.cxx:387
 HLFactory.cxx:388
 HLFactory.cxx:389
 HLFactory.cxx:390
 HLFactory.cxx:391
 HLFactory.cxx:392
 HLFactory.cxx:393
 HLFactory.cxx:394
 HLFactory.cxx:395
 HLFactory.cxx:396
 HLFactory.cxx:397
 HLFactory.cxx:398
 HLFactory.cxx:399
 HLFactory.cxx:400
 HLFactory.cxx:401
 HLFactory.cxx:402
 HLFactory.cxx:403
 HLFactory.cxx:404
 HLFactory.cxx:405
 HLFactory.cxx:406
 HLFactory.cxx:407
 HLFactory.cxx:408
 HLFactory.cxx:409
 HLFactory.cxx:410
 HLFactory.cxx:411
 HLFactory.cxx:412
 HLFactory.cxx:413
 HLFactory.cxx:414
 HLFactory.cxx:415
 HLFactory.cxx:416
 HLFactory.cxx:417
 HLFactory.cxx:418
 HLFactory.cxx:419
 HLFactory.cxx:420
 HLFactory.cxx:421
 HLFactory.cxx:422
 HLFactory.cxx:423
 HLFactory.cxx:424
 HLFactory.cxx:425
 HLFactory.cxx:426
 HLFactory.cxx:427
 HLFactory.cxx:428
 HLFactory.cxx:429
 HLFactory.cxx:430
 HLFactory.cxx:431
 HLFactory.cxx:432
 HLFactory.cxx:433
 HLFactory.cxx:434
 HLFactory.cxx:435
 HLFactory.cxx:436
 HLFactory.cxx:437
 HLFactory.cxx:438
 HLFactory.cxx:439
 HLFactory.cxx:440
 HLFactory.cxx:441
 HLFactory.cxx:442
 HLFactory.cxx:443
 HLFactory.cxx:444
 HLFactory.cxx:445
 HLFactory.cxx:446
 HLFactory.cxx:447
 HLFactory.cxx:448
 HLFactory.cxx:449
 HLFactory.cxx:450
 HLFactory.cxx:451
 HLFactory.cxx:452
 HLFactory.cxx:453
 HLFactory.cxx:454
 HLFactory.cxx:455
 HLFactory.cxx:456
 HLFactory.cxx:457
 HLFactory.cxx:458
 HLFactory.cxx:459
 HLFactory.cxx:460
 HLFactory.cxx:461
 HLFactory.cxx:462
 HLFactory.cxx:463
 HLFactory.cxx:464
 HLFactory.cxx:465
 HLFactory.cxx:466
 HLFactory.cxx:467
 HLFactory.cxx:468
 HLFactory.cxx:469
 HLFactory.cxx:470
 HLFactory.cxx:471
 HLFactory.cxx:472
 HLFactory.cxx:473
 HLFactory.cxx:474
 HLFactory.cxx:475
 HLFactory.cxx:476
 HLFactory.cxx:477
 HLFactory.cxx:478
 HLFactory.cxx:479
 HLFactory.cxx:480
 HLFactory.cxx:481
 HLFactory.cxx:482
 HLFactory.cxx:483
 HLFactory.cxx:484
 HLFactory.cxx:485
 HLFactory.cxx:486
 HLFactory.cxx:487
 HLFactory.cxx:488
 HLFactory.cxx:489
 HLFactory.cxx:490
 HLFactory.cxx:491
 HLFactory.cxx:492
 HLFactory.cxx:493
 HLFactory.cxx:494
 HLFactory.cxx:495
 HLFactory.cxx:496
 HLFactory.cxx:497
 HLFactory.cxx:498
 HLFactory.cxx:499
 HLFactory.cxx:500
 HLFactory.cxx:501
 HLFactory.cxx:502
 HLFactory.cxx:503
 HLFactory.cxx:504
 HLFactory.cxx:505
 HLFactory.cxx:506
 HLFactory.cxx:507
 HLFactory.cxx:508
 HLFactory.cxx:509
 HLFactory.cxx:510
 HLFactory.cxx:511
 HLFactory.cxx:512
 HLFactory.cxx:513
 HLFactory.cxx:514
 HLFactory.cxx:515
 HLFactory.cxx:516
 HLFactory.cxx:517
 HLFactory.cxx:518
 HLFactory.cxx:519
 HLFactory.cxx:520
 HLFactory.cxx:521
 HLFactory.cxx:522
 HLFactory.cxx:523
 HLFactory.cxx:524
 HLFactory.cxx:525
 HLFactory.cxx:526
 HLFactory.cxx:527
 HLFactory.cxx:528
 HLFactory.cxx:529
 HLFactory.cxx:530
 HLFactory.cxx:531
 HLFactory.cxx:532
 HLFactory.cxx:533
 HLFactory.cxx:534
 HLFactory.cxx:535
 HLFactory.cxx:536
 HLFactory.cxx:537
 HLFactory.cxx:538
 HLFactory.cxx:539
 HLFactory.cxx:540
 HLFactory.cxx:541
 HLFactory.cxx:542
 HLFactory.cxx:543
 HLFactory.cxx:544
 HLFactory.cxx:545
 HLFactory.cxx:546
 HLFactory.cxx:547
 HLFactory.cxx:548
 HLFactory.cxx:549
 HLFactory.cxx:550
 HLFactory.cxx:551
 HLFactory.cxx:552
 HLFactory.cxx:553
 HLFactory.cxx:554
 HLFactory.cxx:555
 HLFactory.cxx:556
 HLFactory.cxx:557
 HLFactory.cxx:558
 HLFactory.cxx:559
 HLFactory.cxx:560
 HLFactory.cxx:561
 HLFactory.cxx:562
 HLFactory.cxx:563
 HLFactory.cxx:564
 HLFactory.cxx:565
 HLFactory.cxx:566
 HLFactory.cxx:567
 HLFactory.cxx:568
 HLFactory.cxx:569
 HLFactory.cxx:570
 HLFactory.cxx:571
 HLFactory.cxx:572
 HLFactory.cxx:573
 HLFactory.cxx:574
 HLFactory.cxx:575
 HLFactory.cxx:576
 HLFactory.cxx:577
 HLFactory.cxx:578
 HLFactory.cxx:579
 HLFactory.cxx:580
 HLFactory.cxx:581
 HLFactory.cxx:582
 HLFactory.cxx:583
 HLFactory.cxx:584
 HLFactory.cxx:585
 HLFactory.cxx:586
 HLFactory.cxx:587
 HLFactory.cxx:588
 HLFactory.cxx:589
 HLFactory.cxx:590
 HLFactory.cxx:591
 HLFactory.cxx:592
 HLFactory.cxx:593
 HLFactory.cxx:594
 HLFactory.cxx:595
 HLFactory.cxx:596
 HLFactory.cxx:597
 HLFactory.cxx:598
 HLFactory.cxx:599
 HLFactory.cxx:600
 HLFactory.cxx:601
 HLFactory.cxx:602
 HLFactory.cxx:603
 HLFactory.cxx:604
 HLFactory.cxx:605
 HLFactory.cxx:606
 HLFactory.cxx:607
 HLFactory.cxx:608
 HLFactory.cxx:609
 HLFactory.cxx:610
 HLFactory.cxx:611
 HLFactory.cxx:612
 HLFactory.cxx:613
 HLFactory.cxx:614
 HLFactory.cxx:615
 HLFactory.cxx:616
 HLFactory.cxx:617
 HLFactory.cxx:618
 HLFactory.cxx:619
 HLFactory.cxx:620
 HLFactory.cxx:621
 HLFactory.cxx:622
 HLFactory.cxx:623
 HLFactory.cxx:624
 HLFactory.cxx:625
 HLFactory.cxx:626
 HLFactory.cxx:627
 HLFactory.cxx:628
 HLFactory.cxx:629
 HLFactory.cxx:630
 HLFactory.cxx:631
 HLFactory.cxx:632
 HLFactory.cxx:633
 HLFactory.cxx:634
 HLFactory.cxx:635
 HLFactory.cxx:636
 HLFactory.cxx:637
 HLFactory.cxx:638
 HLFactory.cxx:639
 HLFactory.cxx:640
 HLFactory.cxx:641
 HLFactory.cxx:642
 HLFactory.cxx:643
 HLFactory.cxx:644
 HLFactory.cxx:645
 HLFactory.cxx:646
 HLFactory.cxx:647
 HLFactory.cxx:648
 HLFactory.cxx:649
 HLFactory.cxx:650
 HLFactory.cxx:651
 HLFactory.cxx:652
 HLFactory.cxx:653
 HLFactory.cxx:654
 HLFactory.cxx:655
 HLFactory.cxx:656
 HLFactory.cxx:657
 HLFactory.cxx:658
 HLFactory.cxx:659
 HLFactory.cxx:660
 HLFactory.cxx:661
 HLFactory.cxx:662
 HLFactory.cxx:663
 HLFactory.cxx:664
 HLFactory.cxx:665