source: JEM-EUSO/esaf_cc_at_lal/packages/common/base/src/Config.cc @ 114

Last change on this file since 114 was 114, checked in by moretto, 11 years ago

actual version of ESAF at CCin2p3

File size: 13.0 KB
Line 
1// ESAF : Euso Simulation and Analysis Framework
2// $Id: Config.cc 2956 2011-06-28 18:54:32Z mabl $
3// Author: Daniel De Marco    Jan, 25 2002
4// M.Pallavicini - added Standard configuration handling 1/10/02
5
6/*****************************************************************************
7 * ESAF: Euso Simulation and Analysis Framework                              *
8 *                                                                           *
9 *  Id: EsafMsgDispatcher                                                    *
10 *  Package: Base                                                            *
11 *  Coordinator: Marco.Pallavicini                                           *
12 *                                                                           *
13 *****************************************************************************/
14
15//______________________________________________________________________________
16//
17//  Configuration Manager
18//  ====================
19//
20//
21
22
23#include "Config.hh"
24#include "StringsFileParser.hh"
25#include "EsafSys.hh"
26
27#include <TSystem.h>
28#include <fstream>
29
30ClassImp(Config)
31
32Config *Config::fMe = 0;
33
34//______________________________________________________________________________
35Config::Config() {
36    //
37    // Ctor
38    //
39    fCurrentConfig = "None";
40
41    if ( !gEsafSys )
42        gEsafSys = new EsafSys();
43
44    fStdConfigList = ConfigFileParser::GetCfgDir();
45        fStdConfigList += "/Standard/StandardConfigs.lst";
46    fCfgDump  = "./output/ConfigDump.cfg";
47}
48
49//______________________________________________________________________________
50Config::~Config() {
51    //
52    // Dtor
53    //
54}
55
56//______________________________________________________________________________
57Config* Config::Get() {
58    //
59    // Instance
60    //
61    if ( fMe == 0 )
62        fMe = new Config();
63    return fMe;
64}
65
66//______________________________________________________________________________
67void Config::SetCfgDump( const char* name ) {
68    //
69    //
70    //
71
72    if ( !name ) return;
73
74    string ext = ".cfg";
75
76    fCfgDump = name;
77
78    if (fCfgDump.rfind(ext) != (fCfgDump.size()-ext.size()))
79        fCfgDump += ext;
80}
81
82//______________________________________________________________________________
83void Config::SaveConfig( const char* name ) {
84    //
85    // Save the current configuration in a single "standard config file"
86    //
87
88    TString fname = name ? name : fCfgDump.c_str();
89
90    if ( fname[0] != '/' )
91       gSystem->ExpandPathName(fname);
92
93    Msg(EsafMsg::Debug) << "Saving config on file " << fname << MsgDispatch;
94        ofstream of(fname.Data(),ios::out);
95
96    if (!of) {
97        Msg(EsafMsg::Error) << "Failed to open file " << fname << " to save the config" << MsgDispatch;
98        return;
99    }
100
101    if ( IsStandardConfigDefined() ) {
102                of << "## Standard config " << fCurrentConfig << " is being used." << endl;
103                of << "## user defined variables dump" << endl;
104        map<string, vector<string>*>::iterator jt;
105        for(jt=fUserDef.begin(); jt != fUserDef.end(); jt++) {
106            of << "## Dump for class name " << jt->first << endl;
107
108            vector<string>::iterator jt2;
109            for(jt2 = jt->second->begin(); jt2 != jt->second->end(); jt2++)
110                of << (*jt2) << endl;
111
112            of << "## End of dump for class name " << jt->first << endl;
113        }
114                of.close();
115                return;
116        }
117        of << "## config file dump generated by ESAF \n\n";
118        map<string, ConfigFileParser*>::const_iterator it;
119        for(it=fCfs.begin(); it!=fCfs.end(); it++) {
120                ConfigFileParser &cfp = *(it->second);
121                of << "## Dump for class name " << it->first << endl;
122                map<string,double>::const_iterator it2;
123                for(it2=cfp.fNumbers.begin(); it2!=cfp.fNumbers.end(); it2++) {
124                        of << it2->first << " = " << it2->second << endl;
125                }
126                map<string,string>::const_iterator it3;
127                for(it3=cfp.fChars.begin(); it3!=cfp.fChars.end(); it3++) {
128                        of << it3->first << " = " << it3->second << endl;
129                }
130                of << "## End of dump for class name " << it->first << endl;
131        }
132        of.close();
133}
134
135//______________________________________________________________________________
136ConfigFileParser *Config::GetCF(const string &ClassType, const string &ClassName,
137                                const string &path ) {
138    //
139    // if ClassName is name of a parent class whose real instance is a child, the
140    // file corresponding to the child is returned
141    //
142
143        // if a standard config is defined, use it
144        if ( IsStandardConfigDefined() )  {
145                return fStandards[fCurrentConfig];
146        }
147
148        // check if this class has a child
149        string child_name;
150        if ( fChildTable.count( ClassName ) == 0 )
151        child_name = ClassName;
152        else
153                child_name = *(fChildTable[ClassName]);
154
155    map<string, string*>::iterator cit=fChildTable.begin(),
156                                   cend=fChildTable.end();
157    string parent_name;
158    for ( ; cit!=cend; cit++ ) {
159        if ( *(cit->second) == ClassName ) {
160            parent_name = cit->first;
161            break;
162        }
163    }
164
165// create the ConfigFileParser if needed, and override parameters if required
166    if ( fCfs.count(child_name) == 0 ) {
167                fCfs[child_name] = new ConfigFileParser(ClassType,child_name,path);
168        if ( fUserDef.count( child_name ) != 0 ) {
169            vector<string>::iterator dummy;
170            for( dummy = fUserDef[child_name]->begin();
171                 dummy != fUserDef[child_name]->end() ;dummy++){
172                fCfs[child_name]->Replace( *dummy );
173            }
174        }
175
176        if ( parent_name.length()>0 ){
177            if ( fUserDef.count( parent_name ) != 0 ) {
178                vector<string>::iterator dummy;
179                for( dummy = fUserDef[parent_name]->begin();
180                    dummy != fUserDef[parent_name]->end() ;dummy++){
181                    fCfs[child_name]->Replace( *dummy );
182                }
183            }
184        }
185        }
186
187        // return ConfigFileParser
188        return fCfs[child_name];
189}
190
191// handling standard configuration
192// The file config/Standard/StandardConfigs.lst contains the names of the "Standard"
193// configurations, i.e. files with all ESAF parameters.
194// Each file will be also kept in the same directory
195
196
197//______________________________________________________________________________
198Bool_t Config::UseConfig(const string& name) {
199    //
200    // Define a new config with the current configuration files
201    // to be implemented
202    //
203
204    if ( fStandards.count(name) == 0 ) {
205        Msg(EsafMsg::Warning) << name << " is not defined as standard configuration in "
206            << fStdConfigList<< MsgDispatch;
207        return kFALSE;
208    }
209
210    Msg(EsafMsg::Info) << "Using standard configuration " << name << MsgDispatch;
211    fCurrentConfig = name;
212    return kTRUE;
213}
214
215//______________________________________________________________________________
216ConfigFileParser *Config::GetStandardConfig() {
217    //
218    // Get the current standard config if defined
219    // returns NULL if not (no exception thrown)
220    //
221    if ( IsStandardConfigDefined() ) {
222        if ( fStandards.find(fCurrentConfig) == fStandards.end() ) {
223            Msg(EsafMsg::Warning) << "Standard config "+fCurrentConfig+" does not exist!!!" << MsgDispatch;
224            return NULL;
225        } else
226            return fStandards[fCurrentConfig];
227    }
228    return (ConfigFileParser*)NULL;
229}
230
231//______________________________________________________________________________
232void Config::LoadStandardConfigs() {
233    //
234    // Load the list of defined standard configs
235    //
236
237        // open file
238        ifstream in(fStdConfigList.c_str());
239        if(!in) FatalError("Can't open file "+fStdConfigList);
240
241        // get list from file
242        // each line not beginning with # is considered a standard config name
243        string dummy;
244        while(getline(in, dummy)) {
245                size_t pos;
246
247        // erase comments
248        pos=dummy.find('#');
249        if(pos!=string::npos) dummy.erase(pos);
250
251        // swallow spaces
252        dummy=ltrim(dummy);
253
254        // skip blank lines
255        if(dummy.empty()) continue;
256
257        // now ready with name
258        string cfgName = dummy;
259        //FIXME: conflict with EsafMsgDispatcher building
260        //Messages can't be used here
261        //Msg(EsafMsg::Info) << "Reading standard config " << cfgName << MsgDispatch;
262        Msg(EsafMsg::Info) << "Reading standard config " << cfgName << MsgDispatch;
263
264                // build the ConfigFileParser object and put it into the map
265                if ( fStandards.find(cfgName) == fStandards.end() ) {
266                        fStandards[cfgName] = new ConfigFileParser("Standard",cfgName);
267
268                        // override parameters if required
269                        // iterate on map elements
270                        map<string, vector<string>* >::iterator m_iter;
271                        for(m_iter = fUserDef.begin(); m_iter != fUserDef.end(); m_iter++) {
272                                // iterate on vector elements
273                                vector<string>::iterator v_iter;
274                                for(v_iter = m_iter->second->begin();
275                                                v_iter != m_iter->second->end(); v_iter++) {
276                                        fStandards[cfgName]->Replace(*v_iter);
277                                }
278                        }
279                }
280        else {
281            //FIXME: conflict with EsafMsgDispatcher building
282            //Messages can't be used here
283            Msg(EsafMsg::Panic) << "Duplicate name "+cfgName+" in ./config/Standard/Config.cfg" << MsgDispatch;
284        }
285        }
286}
287
288//______________________________________________________________________________
289void Config::Reset(Bool_t user) {
290    //
291    // Reset the config
292    //
293
294    // FIXME: check for memory leak here.
295    // Does map destroy the elements it points to ?
296        map<string,ConfigFileParser*>::iterator dummy;
297        if (fCfs.size() != 0)
298        for (dummy = fCfs.begin(); dummy != fCfs.end(); ++dummy)
299                delete dummy->second;
300        fCfs.clear();
301
302    if ( user )
303        ResetUserDef();
304}
305
306//______________________________________________________________________________
307void Config::ResetUserDef() {
308    //
309        // Reset User settings
310    //
311        map<string, vector<string>* >::iterator dummy;
312        if (fUserDef.size() != 0)
313        for (dummy = fUserDef.begin(); dummy != fUserDef.end(); ++dummy)
314                delete dummy->second;
315        fUserDef.clear();
316}
317
318//______________________________________________________________________________
319void Config::AssociateParent(const string& c_name, const string& p_name) {
320    //
321    // associate class name and parent name
322    //
323    if ( fChildTable.count(p_name) == 0 ) {
324        fChildTable[p_name] = new string(c_name);
325    }
326    else {
327        if ( (*(fChildTable[p_name])) == c_name ) return;
328        Msg(EsafMsg::Warning) << c_name << " is being associated to "
329            << p_name << endl;
330        Msg(EsafMsg::Warning) <<  *(fChildTable[p_name]) << MsgDispatch;
331    }
332}
333
334//______________________________________________________________________________
335void Config::AddUserDefinition(const string &c_name, const string &expr) {
336    //
337    // Overrides a parameter of the config files.
338    // Syntax:
339    //  Config::Get()->AddUserDefinition( "classname","parameter=value")
340    //
341
342    string s = expr;
343    s = ltrim( s );
344    if ( s.empty() )
345        FatalError("invalid expr: "+expr);
346
347    if ( fUserDef.count(c_name) == 0)
348        fUserDef[c_name] = new vector<string>;
349
350    fUserDef[c_name]->push_back(expr);
351
352        if ( IsStandardConfigDefined() &&  fUserDef.count( c_name ) != 0 )
353        fStandards[fCurrentConfig]->Replace( expr, kTRUE );
354
355    MsgForm(EsafMsg::Debug,"UserDef added: class=%s, expr=%s",c_name.c_str(), expr.c_str());
356}
357
358//______________________________________________________________________________
359Bool_t Config::LoadUserConfig( const char* name ) {
360    //
361    // Load a set of user definitions from file
362    //
363    // The definitions MUST have the following format
364    // Classname.VarName=Value
365    //
366
367    TString fname = name;
368    gSystem->ExpandPathName(fname);
369    StringsFileParser parser( fname.Data() );
370    if ( parser.IsZombie() )
371        MsgForm(EsafMsg::Panic,"File %s not found",name);
372
373
374    list< list<string> >& lines = parser.GetLines();
375
376    size_t nlines = lines.size();
377    size_t n(0);
378    vector<string> keys(nlines);
379    vector<string> expr(nlines);
380
381    list<string>::const_iterator jt;
382    list< list<string> >::const_iterator it;
383
384    for( it = lines.begin(); it != lines.end(); it++ ) {
385        // rebuild the line with 1 space
386        string line;
387        for (jt=it->begin(); jt != it->end();jt++ ) {
388            if ( jt != it->begin() ) line += " ";
389            line += *(jt);
390        }
391
392
393        if ( it->size() != 3 ) {
394            MsgForm(EsafMsg::Warning,"Wrong number of elements in file %s at line:",name);
395            Msg(EsafMsg::Panic) << line << "  " << it->size() << MsgDispatch;
396            return kFALSE;
397        }
398
399        // keyword
400        jt = it->begin();
401        size_t pos = jt->find('.');
402
403        if ( pos == string::npos ) {
404            MsgForm(EsafMsg::Warning,"Corrupted file %s at line:",name);
405            Msg(EsafMsg::Panic) << line << "  " << it->size() << MsgDispatch;
406            return kFALSE;
407        }
408
409        keys[n] = jt->substr(0,pos);
410
411        // check on the '='
412        jt++;
413        if ( *(jt) != "=" ) {
414            MsgForm(EsafMsg::Warning,"Corrupted file %s at line:",name);
415            Msg(EsafMsg::Panic) << line << "  " << it->size() << MsgDispatch;
416            return kFALSE;
417        }
418
419        expr[n] = line;
420
421        n++;
422    }
423
424    MsgForm(EsafMsg::Info,"UserConfig %s loaded.", name);
425    for (size_t i(0); i<n; i++)
426        AddUserDefinition(keys[i],expr[i]);
427
428    return kTRUE;
429}
Note: See TracBrowser for help on using the repository browser.