ProjectionHandler.cc
Go to the documentation of this file.00001
00002 #include "Rivet/Rivet.hh"
00003 #include "Rivet/Tools/Logging.hh"
00004 #include "Rivet/ProjectionHandler.hh"
00005 #include "Rivet/Cmp.hh"
00006 #include <algorithm>
00007
00008 namespace Rivet {
00009
00010
00011
00012 ProjectionHandler* ProjectionHandler::_instance = 0;
00013
00014 ProjectionHandler& ProjectionHandler::getInstance() {
00015 if (!_instance) {
00016 _instance = new ProjectionHandler();
00017 Log::getLog("Rivet.ProjectionHandler")
00018 << Log::TRACE << "Created new ProjectionHandler at " << _instance << endl;
00019 }
00020 return *_instance;
00021 }
00022
00023
00024
00025
00026 Log& ProjectionHandler::getLog() const {
00027 return Log::getLog("Rivet.ProjectionHandler");
00028 }
00029
00030
00031 void ProjectionHandler::clear() {
00032 _projs.clear();
00033 _namedprojs.clear();
00034 }
00035
00036
00037
00038 ProjectionHandler::~ProjectionHandler() {
00039 clear();
00040 }
00041
00042
00043
00044
00045
00046
00047 const Projection& ProjectionHandler::registerProjection(const ProjectionApplier& parent,
00048 const Projection& proj,
00049 const string& name)
00050 {
00051 getLog() << Log::TRACE << "Trying to register"
00052 << " projection " << &proj << " (" << proj.name() << ")"
00053 << " for parent " << &parent << " (" << parent.name() << ")"
00054 << " with name '" << name << "'" << endl;
00055
00056
00057 const bool dupOk = _checkDuplicate(parent, proj, name);
00058 if (!dupOk) {
00059 cerr << "Duplicate name '" << name << "' in parent '" << parent.name() << "'." << endl;
00060 exit(1);
00061 }
00062
00063
00064 const Projection* p = _getEquiv(proj);
00065 if (p == 0) {
00066
00067 p = _clone(proj);
00068 }
00069
00070
00071 p = _register(parent, *p, name);
00072
00073
00074 return *p;
00075 }
00076
00077
00078
00079
00080
00081 const Projection* ProjectionHandler::registerProjection(const ProjectionApplier& parent,
00082 const Projection* proj,
00083 const string& name) {
00084 if (proj == 0) return 0;
00085 const Projection& p = registerProjection(parent, *proj, name);
00086 return &p;
00087 }
00088
00089
00090
00091
00092 const Projection* ProjectionHandler::_clone(const Projection& proj)
00093 {
00094
00095 getLog() << Log::TRACE << "Cloning projection " << proj.name() << " from " << &proj << endl;
00096 const Projection* newproj = proj.clone();
00097 getLog() << Log::TRACE << "Cloned projection " << proj.name() << " at " << newproj << endl;
00098 getLog() << Log::TRACE << "Clone types " << typeid(proj).name() << " -> " << typeid(newproj).name() << endl;
00099
00100
00101
00102 if (&proj != newproj) {
00103 NamedProjsMap::const_iterator nps = _namedprojs.find(&proj);
00104 if (nps != _namedprojs.end()) {
00105 getLog() << Log::TRACE << "Cloning registered projections list: "
00106 << &proj << " -> " << newproj << endl;
00107 _namedprojs[newproj] = nps->second;
00108 }
00109 }
00110
00111 return newproj;
00112 }
00113
00114
00115
00116
00117
00118
00119 const Projection* ProjectionHandler::_register(const ProjectionApplier& parent,
00120 const Projection& proj,
00121 const string& name)
00122 {
00123 ProjHandle ph(&proj);
00124 getLog() << Log::TRACE << "Registering new projection at " << ph << endl;
00125
00126
00127 _projs.insert(ph);
00128
00129
00130 _namedprojs[&parent][name] = ph;
00131
00132 return ph.get();
00133 }
00134
00135
00136
00137
00138
00139 const Projection* ProjectionHandler::_getEquiv(const Projection& proj) const
00140 {
00141
00142 const std::type_info& newtype = typeid(proj);
00143 getLog() << Log::TRACE << "RTTI type of " << &proj << " is " << newtype.name() << endl;
00144
00145
00146 getLog() << Log::TRACE << "Comparing " << &proj
00147 << " with " << _projs.size()
00148 << " registered projection" << (_projs.size() == 1 ? "" : "s") << endl;
00149 foreach (const ProjHandle& ph, _projs) {
00150
00151 const std::type_info& regtype = typeid(*ph);
00152 getLog() << Log::TRACE << "RTTI type comparison with " << ph << ": "
00153 << newtype.name() << " vs. " << regtype.name() << endl;
00154 if (newtype != regtype) continue;
00155 getLog() << Log::TRACE << "RTTI type matches with " << ph << endl;
00156
00157
00158 if (pcmp(*ph, proj) != EQUIVALENT) {
00159 getLog() << Log::TRACE << "Projections at "
00160 << &proj << " and " << ph << " are not equivalent" << endl;
00161 } else {
00162 getLog() << Log::TRACE << "MATCH! Projections at "
00163 << &proj << " and " << ph << " are equivalent" << endl;
00164 return ph.get();
00165 }
00166 }
00167
00168
00169 return 0;
00170 }
00171
00172
00173
00174 string ProjectionHandler::_getStatus() const {
00175 ostringstream msg;
00176 msg << "Current projection hierarchy:" << endl;
00177 foreach (const NamedProjsMap::value_type& nps, _namedprojs) {
00178
00179 msg << nps.first << endl;
00180 foreach (const NamedProjs::value_type& np, nps.second) {
00181 msg << " " << np.second << " (" << np.second->name()
00182 << ", locally called '" << np.first << "')" << endl;
00183 }
00184 msg << endl;
00185 }
00186 return msg.str();
00187 }
00188
00189
00190
00191
00192 bool ProjectionHandler::_checkDuplicate(const ProjectionApplier& parent,
00193 const Projection& proj,
00194 const string& name) const
00195 {
00196 NamedProjsMap::const_iterator ipnps = _namedprojs.find(&parent);
00197 if (ipnps != _namedprojs.end()) {
00198 const NamedProjs pnps = ipnps->second;
00199 const NamedProjs::const_iterator ipph = pnps.find(name);
00200 if (ipph != pnps.end()) {
00201 const ProjHandle pph = ipph->second;
00202 getLog() << Log::ERROR << "Projection clash! "
00203 << parent.name() << " (" << &parent << ") "
00204 << "is trying to overwrite its registered '" << name << "' "
00205 << "projection (" << pph << "="
00206 << pph->name() << ") with a non-equivalent projection "
00207 << "(" << &proj << "=" << proj.name() << ")" << endl;
00208 getLog() << Log::ERROR << _getStatus();
00209 return false;
00210 }
00211 }
00212 return true;
00213 }
00214
00215
00216
00217
00218 void ProjectionHandler::removeProjectionApplier(ProjectionApplier& parent) {
00219 NamedProjsMap::iterator npi = _namedprojs.find(&parent);
00220 if (npi != _namedprojs.end()) _namedprojs.erase(npi);
00221
00222 const Projection* parentprojptr = dynamic_cast<Projection*>(&parent);
00223 if (parentprojptr) {
00224 ProjHandle parentph(parentprojptr);
00225 ProjHandles::iterator pi = find(_projs.begin(), _projs.end(), parentph);
00226 if (pi != _projs.end()) _projs.erase(pi);
00227 }
00228 }
00229
00230
00231
00232
00233 set<const Projection*> ProjectionHandler::getChildProjections(const ProjectionApplier& parent,
00234 ProjDepth depth) const
00235 {
00236 set<const Projection*> toplevel;
00237 NamedProjs nps = _namedprojs.find(&parent)->second;
00238 foreach (NamedProjs::value_type& np, nps) {
00239 toplevel.insert(np.second.get());
00240 }
00241 if (depth == SHALLOW) {
00242
00243 return toplevel;
00244 } else {
00245
00246 set<const Projection*> alllevels = toplevel;
00247 foreach (const Projection* p, toplevel) {
00248 set<const Projection*> allsublevels = getChildProjections(*p, DEEP);
00249 alllevels.insert(allsublevels.begin(), allsublevels.end());
00250 }
00251 return alllevels;
00252 }
00253 }
00254
00255
00256
00257
00258 const Projection& ProjectionHandler::getProjection(const ProjectionApplier& parent,
00259 const string& name) const {
00260
00261
00262 NamedProjsMap::const_iterator nps = _namedprojs.find(&parent);
00263 if (nps == _namedprojs.end()) {
00264 ostringstream msg;
00265 msg << "No projections registered for parent " << &parent;
00266 throw Error(msg.str());
00267 }
00268 NamedProjs::const_iterator np = nps->second.find(name);
00269 if (np == nps->second.end()) {
00270 ostringstream msg;
00271 msg << "No projection '" << name << "' found for parent " << &parent;
00272 throw Error(msg.str());
00273 }
00274
00275
00276 return *(np->second);
00277 }
00278
00279
00280
00281 }