00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef LWH_Tree_H
00010 #define LWH_Tree_H
00011
00012
00013
00014
00015 #include "AITree.h"
00016 #include "ManagedObject.h"
00017 #include <fstream>
00018 #include <iostream>
00019 #include <vector>
00020 #include <set>
00021 #include <map>
00022 #include <string>
00023
00024 namespace LWH {
00025
00026 using namespace AIDA;
00027
00032 class Tree: public ITree {
00033
00034 public:
00035
00037 friend class AnalysisFactory;
00038
00040 typedef std::vector<std::string> Path;
00041
00043 typedef std::set<Path> PathSet;
00044
00046 typedef std::map<std::string, IManagedObject *> ObjMap;
00047
00048 public:
00049
00053 Tree(std::string storename, bool xml = true)
00054 : name(storename), flat(!xml), cwd("/"), overwrite(true) {
00055 dirs.insert(Path());
00056 }
00057
00061 Tree(): name(""), flat(false), cwd("/") {
00062 dirs.insert(Path());
00063 }
00064
00068 Tree(const Tree & dt)
00069 : ITree(dt), name(dt.name), flat(dt.flat), dirs(dt.dirs),
00070 objs(dt.objs), cwd(dt.cwd), overwrite(true) {}
00071
00073 virtual ~Tree() {
00074 for ( ObjMap::iterator it = objs.begin(); it != objs.end(); ++it )
00075 delete it->second;
00076 }
00077
00082 std::string storeName() const {
00083 return name;
00084 }
00085
00092 IManagedObject * find(const std::string & path) {
00093 ObjMap::const_iterator it = objs.find(path);
00094 return it == objs.end()? (IManagedObject *)0: it->second;
00095 }
00096
00101 ITree * findTree(const std::string &) {
00102 return 0;
00103 }
00104
00111 bool cd(const std::string & dir) {
00112 PathSet::iterator it = dirs.find(purgepath(str2pth(fullpath(sts(dir)))));
00113 if ( it == dirs.end() ) return false;
00114 cwd = pth2str(*it);
00115 return true;
00116 }
00117
00121 bool insert(std::string str, IManagedObject * o) {
00122 Path path = purgepath(str2pth(fullpath(str)));
00123 if ( dirs.find(path) == dirs.end() ) {
00124 std::string fullname = pth2str(path);
00125 path.pop_back();
00126 if ( dirs.find(path) != dirs.end() ) {
00127 ObjMap::iterator old = objs.find(fullname);
00128 if ( old == objs.end() || overwrite ) {
00129 if ( old != objs.end() ) {
00130 delete old->second;
00131 objs.erase(old);
00132 }
00133 objs[fullname] = o;
00134 return true;
00135 }
00136 }
00137 }
00138 return false;
00139 }
00140
00145 std::string pwd() const {
00146 return cwd;
00147 }
00148
00154 bool ls(const std::string & = ".", bool = false,
00155 std::ostream & = std::cout) const {
00156 return false;
00157 }
00158
00162 std::vector<std::string> listObjectNames(const std::string & = ".",
00163 bool = false) const {
00164 return std::vector<std::string>();
00165 }
00166
00170 std::vector<std::string> listObjectTypes(const std::string & = ".",
00171 bool = false) const {
00172 return std::vector<std::string>();
00173 }
00174
00182 bool mkdir(const std::string & dir) {
00183 Path p = purgepath(str2pth(fullpath(sts(dir))));
00184 Path base = p;
00185 base.pop_back();
00186 if ( dirs.find(base) == dirs.end() ) return false;
00187 dirs.insert(p);
00188 return true;
00189 }
00190
00198 bool mkdirs(const std::string & dir) {
00199 return mkdirs(purgepath(str2pth(fullpath(sts(dir)))));
00200 }
00201
00209 bool mkdirs(Path p) {
00210 if ( dirs.find(p) != dirs.end() ) return true;
00211 dirs.insert(p);
00212 p.pop_back();
00213 return mkdirs(p);
00214 }
00215
00222 bool rmdir(const std::string & dir) {
00223 Path path = purgepath(str2pth(fullpath(sts(dir))));
00224 if ( dirs.find(path) == dirs.end() ) return false;
00225 for ( ObjMap::const_iterator it = objs.begin(); it != objs.end(); ++it )
00226 if ( it->first.substr(0, dir.length()) == dir ) return false;
00227 dirs.erase(path);
00228 return true;
00229 }
00230
00237 bool rm(const std::string & path) {
00238 ObjMap::iterator it = objs.find(fullpath(path));
00239 if ( it == objs.end() ) return false;
00240 delete it->second;
00241 objs.erase(it);
00242 return true;
00243 }
00244
00251 std::string findPath(const IManagedObject & o) const {
00252 for ( ObjMap::const_iterator it = objs.begin(); it != objs.end(); ++it )
00253 if ( it->second == &o ) return it->first;
00254 return "";
00255 }
00256
00264 bool mv(const std::string & oldp, const std::string & newp) {
00265 Path newpath = purgepath(str2pth(fullpath(sts(newp))));
00266 std::string foldp = fullpath(oldp);
00267 Path oldpath = purgepath(str2pth(foldp));
00268 ObjMap::iterator it = objs.find(foldp);
00269 if ( it == objs.end() ) return false;
00270 if ( dirs.find(newpath) != dirs.end() ) return false;
00271 newpath.push_back(oldpath.back());
00272 if ( !insert(pth2str(newpath), it->second) ) return false;
00273 objs.erase(foldp);
00274 return true;
00275 }
00276
00281 bool commit() {
00282 std::ofstream of(name.c_str());
00283 if ( !of ) return false;
00284 if ( !flat ) of
00285 << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE aida SYSTEM "
00286 << "\"http://aida.freehep.org/schemas/3.0/aida.dtd\">\n"
00287 << "<aida version=\"3.0\">\n"
00288 << "<implementation version=\"1.0\" package=\"FreeHEP\"/>" << std::endl;
00289 for ( ObjMap::const_iterator it = objs.begin(); it != objs.end(); ++it ) {
00290 ManagedObject * o = dynamic_cast<ManagedObject *>(it->second);
00291 if ( !o ) continue;
00292 std::string path = it->first.substr(0, it->first.rfind('/'));
00293 std::string name = it->first.substr(it->first.rfind('/') + 1);
00294 if ( flat )
00295 o->writeFLAT(of, path, name);
00296 else
00297 o->writeXML(of, path, name);
00298 }
00299 if ( !flat ) of << "</aida>" << std::endl;
00300 return of.good();
00301 }
00302
00306 void setOverwrite(bool o = true) {
00307 overwrite = o;
00308 }
00309
00314 bool cp(const std::string &, const std::string &, bool = false) {
00315 return false;
00316 }
00317
00322 bool symlink(const std::string &, const std::string &) {
00323 return false;
00324 }
00325
00330 bool mount(const std::string &, ITree &, const std::string &) {
00331 return false;
00332 }
00333
00338 bool unmount(const std::string &) {
00339 return false;
00340 }
00341
00345 bool close() {
00346 return commit();
00347 }
00348
00353 void * cast(const std::string &) const {
00354 return 0;
00355 }
00356
00357 protected:
00358
00360 std::string sts(std::string s) const {
00361 if ( s[s.length() - 1] == '/' ) s = s.substr(0, s.length() - 1);
00362 if ( s[s.length() - 1] == '/' ) return "";
00363 return s;
00364 }
00365
00367 std::string stn(std::string s) const {
00368 std::string::size_type slash = s.rfind('/');
00369 return s.substr(0, slash);
00370 }
00371
00373 std::string fullpath(std::string d) const {
00374 if ( d[0] != '/' ) d = cwd + "/" + d;
00375 return pth2str(purgepath(str2pth(d)));
00376 }
00377
00379 Path str2pth(std::string s) const {
00380 Path pth;
00381 std::string::size_type i = s.find_first_not_of("/");
00382 while ( i != std::string::npos ) {
00383 s = s.substr(i);
00384 i = s.find_first_of("/");
00385 pth.push_back(s.substr(0, i));
00386 if ( i == std::string::npos ) return pth;
00387 s = s.substr(i);
00388 i = s.find_first_not_of("/");
00389 }
00390 return pth;
00391 }
00392
00394 std::string pth2str(const Path & pth) const {
00395 std::string str;
00396 for ( int i = 0, N = pth.size(); i < N; ++i ) str += "/" + pth[i];
00397 return str;
00398 }
00399
00401 Path purgepath(const Path & pth) const {
00402 Path p;
00403 for ( int i = 0, N = pth.size(); i < N; ++i ) {
00404 if ( pth[i] == ".." ) p.pop_back();
00405 else if ( pth[i] != "." ) p.push_back(pth[i]);
00406 }
00407 return p;
00408 }
00409
00410 private:
00411
00413 std::string name;
00414
00416 bool flat;
00417
00419 PathSet dirs;
00420
00422 ObjMap objs;
00423
00425 std::string cwd;
00426
00428 bool overwrite;
00429
00430 };
00431
00432 }
00433
00434 #endif