ThePEG  1.8.0
Tree.h
1 // -*- C++ -*-
2 //
3 // Tree.h is a part of ThePEG - Toolkit for HEP Event Generation
4 // Copyright (C) 1999-2011 Leif Lonnblad
5 //
6 // ThePEG is licenced under version 2 of the GPL, see COPYING for details.
7 // Please respect the MCnet academic guidelines, see GUIDELINES for details.
8 //
9 #ifndef LWH_Tree_H
10 #define LWH_Tree_H
11 //
12 // This is the declaration of the Tree class.
13 //
14 
15 #include "AITree.h"
16 #include "ManagedObject.h"
17 #include <fstream>
18 #include <iostream>
19 #include <vector>
20 #include <set>
21 #include <map>
22 #include <string>
23 
24 namespace LWH {
25 
26 using namespace AIDA;
27 
32 class Tree: public ITree {
33 
34 public:
35 
37  friend class AnalysisFactory;
38 
40  typedef std::vector<std::string> Path;
41 
43  typedef std::set<Path> PathSet;
44 
46  typedef std::map<std::string, IManagedObject *> ObjMap;
47 
48 public:
49 
53  Tree(std::string storename, bool xml = true)
54  : name(storename), flat(!xml), cwd("/"), overwrite(true) {
55  dirs.insert(Path());
56  }
57 
61  Tree(): name(""), flat(false), cwd("/") {
62  dirs.insert(Path());
63  }
64 
68  Tree(const Tree & dt)
69  : ITree(dt), name(dt.name), flat(dt.flat), dirs(dt.dirs),
70  objs(dt.objs), cwd(dt.cwd), overwrite(true) {}
71 
73  virtual ~Tree() {
74  for ( ObjMap::iterator it = objs.begin(); it != objs.end(); ++it )
75  delete it->second;
76  }
77 
82  std::string storeName() const {
83  return name;
84  }
85 
92  IManagedObject * find(const std::string & path) {
93  ObjMap::const_iterator it = objs.find(path);
94  return it == objs.end()? (IManagedObject *)0: it->second;
95  }
96 
101  ITree * findTree(const std::string &) {
102  return 0;
103  }
104 
111  bool cd(const std::string & dir) {
112  PathSet::iterator it = dirs.find(purgepath(str2pth(fullpath(sts(dir)))));
113  if ( it == dirs.end() ) return false;
114  cwd = pth2str(*it);
115  return true;
116  }
117 
121  bool insert(std::string str, IManagedObject * o) {
122  Path path = purgepath(str2pth(fullpath(str)));
123  if ( dirs.find(path) == dirs.end() ) {
124  std::string fullname = pth2str(path);
125  path.pop_back();
126  if ( dirs.find(path) != dirs.end() ) {
127  ObjMap::iterator old = objs.find(fullname);
128  if ( old == objs.end() || overwrite ) {
129  if ( old != objs.end() ) {
130  delete old->second;
131  objs.erase(old);
132  }
133  objs[fullname] = o;
134  return true;
135  }
136  }
137  }
138  return false;
139  }
140 
145  std::string pwd() const {
146  return cwd;
147  }
148 
154  bool ls(const std::string & = ".", bool = false,
155  std::ostream & = std::cout) const {
156  return false;
157  }
158 
162  std::vector<std::string> listObjectNames(const std::string & = ".",
163  bool = false) const {
164  return std::vector<std::string>();
165  }
166 
170  std::vector<std::string> listObjectTypes(const std::string & = ".",
171  bool = false) const {
172  return std::vector<std::string>();
173  }
174 
182  bool mkdir(const std::string & dir) {
183  Path p = purgepath(str2pth(fullpath(sts(dir))));
184  Path base = p;
185  base.pop_back();
186  if ( dirs.find(base) == dirs.end() ) return false;
187  dirs.insert(p);
188  return true;
189  }
190 
198  bool mkdirs(const std::string & dir) {
199  return mkdirs(purgepath(str2pth(fullpath(sts(dir)))));
200  }
201 
209  bool mkdirs(Path p) {
210  if ( dirs.find(p) != dirs.end() ) return true;
211  dirs.insert(p);
212  p.pop_back();
213  return mkdirs(p);
214  }
215 
222  bool rmdir(const std::string & dir) {
223  Path path = purgepath(str2pth(fullpath(sts(dir))));
224  if ( dirs.find(path) == dirs.end() ) return false;
225  for ( ObjMap::const_iterator it = objs.begin(); it != objs.end(); ++it )
226  if ( it->first.substr(0, dir.length()) == dir ) return false;
227  dirs.erase(path);
228  return true;
229  }
230 
237  bool rm(const std::string & path) {
238  ObjMap::iterator it = objs.find(fullpath(path));
239  if ( it == objs.end() ) return false;
240  delete it->second;
241  objs.erase(it);
242  return true;
243  }
244 
251  std::string findPath(const IManagedObject & o) const {
252  for ( ObjMap::const_iterator it = objs.begin(); it != objs.end(); ++it )
253  if ( it->second == &o ) return it->first;
254  return "";
255  }
256 
264  bool mv(const std::string & oldp, const std::string & newp) {
265  Path newpath = purgepath(str2pth(fullpath(sts(newp))));
266  std::string foldp = fullpath(oldp);
267  Path oldpath = purgepath(str2pth(foldp));
268  ObjMap::iterator it = objs.find(foldp);
269  if ( it == objs.end() ) return false;
270  if ( dirs.find(newpath) != dirs.end() ) return false;
271  newpath.push_back(oldpath.back());
272  if ( !insert(pth2str(newpath), it->second) ) return false;
273  objs.erase(foldp);
274  return true;
275  }
276 
281  bool commit() {
282  std::ofstream of(name.c_str());
283  if ( !of ) return false;
284  if ( !flat ) of
285  << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE aida SYSTEM "
286  << "\"http://aida.freehep.org/schemas/3.0/aida.dtd\">\n"
287  << "<aida version=\"3.0\">\n"
288  << "<implementation version=\"1.0\" package=\"FreeHEP\"/>" << std::endl;
289  for ( ObjMap::const_iterator it = objs.begin(); it != objs.end(); ++it ) {
290  ManagedObject * o = dynamic_cast<ManagedObject *>(it->second);
291  if ( !o ) continue;
292  std::string path = it->first.substr(0, it->first.rfind('/'));
293  std::string name = it->first.substr(it->first.rfind('/') + 1);
294  if ( flat )
295  o->writeFLAT(of, path, name);
296  else
297  o->writeXML(of, path, name);
298  }
299  if ( !flat ) of << "</aida>" << std::endl;
300  return of.good();
301  }
302 
306  void setOverwrite(bool o = true) {
307  overwrite = o;
308  }
309 
314  bool cp(const std::string &, const std::string &, bool = false) {
315  return false;
316  }
317 
322  bool symlink(const std::string &, const std::string &) {
323  return false;
324  }
325 
330  bool mount(const std::string &, ITree &, const std::string &) {
331  return false;
332  }
333 
338  bool unmount(const std::string &) {
339  return false;
340  }
341 
345  bool close() {
346  return commit();
347  }
348 
353  void * cast(const std::string &) const {
354  return 0;
355  }
356 
357 protected:
358 
360  std::string sts(std::string s) const {
361  if ( s[s.length() - 1] == '/' ) s = s.substr(0, s.length() - 1);
362  if ( s[s.length() - 1] == '/' ) return "";
363  return s;
364  }
365 
367  std::string stn(std::string s) const {
368  std::string::size_type slash = s.rfind('/');
369  return s.substr(0, slash);
370  }
371 
373  std::string fullpath(std::string d) const {
374  if ( d[0] != '/' ) d = cwd + "/" + d;
375  return pth2str(purgepath(str2pth(d)));
376  }
377 
379  Path str2pth(std::string s) const {
380  Path pth;
381  std::string::size_type i = s.find_first_not_of("/");
382  while ( i != std::string::npos ) {
383  s = s.substr(i);
384  i = s.find_first_of("/");
385  pth.push_back(s.substr(0, i));
386  if ( i == std::string::npos ) return pth;
387  s = s.substr(i);
388  i = s.find_first_not_of("/");
389  }
390  return pth;
391  }
392 
394  std::string pth2str(const Path & pth) const {
395  std::string str;
396  for ( int i = 0, N = pth.size(); i < N; ++i ) str += "/" + pth[i];
397  return str;
398  }
399 
401  Path purgepath(const Path & pth) const {
402  Path p;
403  for ( int i = 0, N = pth.size(); i < N; ++i ) {
404  if ( pth[i] == ".." ) p.pop_back();
405  else if ( pth[i] != "." ) p.push_back(pth[i]);
406  }
407  return p;
408  }
409 
410 private:
411 
413  std::string name;
414 
416  bool flat;
417 
420 
423 
425  std::string cwd;
426 
428  bool overwrite;
429 
430 };
431 
432 }
433 
434 #endif /* LWH_Tree_H */