CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/OnlineDB/EcalCondDB/src/LMFUnique.cc

Go to the documentation of this file.
00001 #include "OnlineDB/EcalCondDB/interface/LMFUnique.h"
00002 #include <iomanip>
00003 
00004 using namespace std;
00005 using namespace oracle::occi;
00006 
00007 LMFUnique::~LMFUnique() {
00008 }
00009 
00010 std::string LMFUnique::sequencePostfix(Tm t) {
00011   std::string ts = t.str();
00012   return ts.substr(2, 2);
00013 }
00014 
00015 LMFUnique& LMFUnique::setString(std::string key, std::string value) {
00016   // check if this key exists
00017   std::map<std::string, std::string>::const_iterator i = 
00018     m_stringFields.find(key);
00019   if (i != m_stringFields.end()) {
00020     // the key exist: check if it changed: reset the ID of the object
00021     if (i->second != value) {
00022       m_stringFields[key] = value;
00023       m_ID = 0;
00024     }
00025   } else {
00026     // create this key and reset the ID of the object
00027     m_stringFields[key] = value;
00028     m_ID = 0;    
00029   }
00030   return *this;
00031 }
00032 
00033 LMFUnique& LMFUnique::setInt(std::string key, int value) {
00034   // check if this key exists
00035   std::map<std::string, int>::const_iterator i = m_intFields.find(key);
00036   if (i != m_intFields.end()) {
00037     // the key exist: check if it changed: reset the ID of the object
00038     if (i->second != value) {
00039       m_intFields[key] = value;
00040       m_ID = 0;
00041     }
00042   } else {
00043     // create this key and reset the ID of the object
00044     m_intFields[key] = value;
00045     m_ID = 0;    
00046   }
00047   return *this;
00048 }
00049 
00050 void LMFUnique::attach(std::string name, LMFUnique *u) {
00051   std::map<std::string, LMFUnique *>::const_iterator i = 
00052     m_foreignKeys.find(name);
00053   if (i != m_foreignKeys.end()) {
00054     if (i->second != u) {
00055       m_foreignKeys[name] = u;
00056       m_ID = 0;
00057     }
00058   } else {
00059     m_foreignKeys[name] = u;
00060     m_ID = 0;
00061   }
00062 }
00063 
00064 boost::ptr_list<LMFUnique> LMFUnique::fetchAll() const  
00065   throw(std::runtime_error)
00066 {
00067   /*
00068     Returns a list of pointers to DB objects
00069    */
00070   boost::ptr_list<LMFUnique> l;
00071   this->checkConnection();
00072 
00073   try {
00074     Statement* stmt = m_conn->createStatement();
00075     std::string sql = fetchAllSql(stmt);
00076     if (sql != "") {
00077       if (m_debug) {
00078         cout << m_className + ": Query " + sql << endl;
00079       }
00080       ResultSet* rset = stmt->executeQuery();
00081       while (rset->next()) {
00082         LMFUnique *o = createObject();
00083         if (m_debug) {
00084           o->debug();
00085         }
00086         if (o != NULL) {
00087           o->setByID(rset->getInt(1));
00088           if (m_debug) {
00089             o->dump();
00090           }
00091           l.push_back(o);
00092         }
00093       }
00094     }
00095     m_conn->terminateStatement(stmt);
00096   }
00097   catch (SQLException &e) {
00098     throw(std::runtime_error(m_className + "::fetchAll:  "+e.getMessage()));
00099   }
00100   if (m_debug) {
00101     cout << m_className << ": list size = " << l.size() << endl;
00102   }
00103   return l;
00104 }
00105 
00106 void LMFUnique::dump() const {
00107   dump(0);
00108 }
00109 
00110 void LMFUnique::dump(int n) const {
00111   /*
00112     This method is used to dump the content of an object 
00113     Indent data if the object is contained inside another object
00114   */
00115   std::string m_indent = "";
00116   std::string m_trail = "";
00117   m_trail.resize(70 - 31 - n * 2, '#');
00118   m_indent.resize(n*2, ' ');
00119   m_indent += "|";
00120   // start of object
00121   cout << m_indent << "#################" << setw(15) << m_className 
00122        << " " << m_trail << endl;
00123   cout << m_indent << "Address: " << this << endl;
00124   cout << m_indent << "Connection params : " << m_env << ", " << m_conn << endl;
00125   // object ID in the DB
00126   cout << m_indent << "ID" << setw(18) << ": " << m_ID;
00127   if (m_ID == 0) {
00128     cout << " *** NULL ID ***";
00129   }
00130   if (!isValid()) {
00131     cout << " INVALID ***";
00132   }
00133   cout << endl;
00134   // iterate over string fields
00135   std::map<std::string, std::string>::const_iterator is = 
00136     m_stringFields.begin();
00137   std::map<std::string, std::string>::const_iterator es = 
00138     m_stringFields.end();
00139   while (is != es) {
00140     std::string key = is->first;
00141     cout << m_indent << key << setw(20 - key.length()) << ": " << is->second
00142          << endl;
00143     is++;
00144   }
00145   // iterate over integer fields
00146   std::map<std::string, int>::const_iterator ii = m_intFields.begin();
00147   std::map<std::string, int>::const_iterator ei = m_intFields.end();
00148   while (ii != ei) {
00149     std::string key = ii->first;
00150     cout << m_indent << key << setw(20 - key.length()) << ": " << ii->second
00151          << endl;
00152     ii++;
00153   }
00154   cout << m_indent << "#################" << setw(15) << m_className 
00155        << " " << m_trail << endl;
00156   // iterate over foreign keys
00157   std::map<std::string, LMFUnique*>::const_iterator ik = m_foreignKeys.begin();
00158   std::map<std::string, LMFUnique*>::const_iterator ek = m_foreignKeys.end();
00159   m_indent.clear();
00160   m_indent.resize((n + 1) * 2, ' ');
00161   while (ik != ek) {
00162     cout << m_indent << "Foreign Key: " << ik->first << endl;
00163     ik->second->dump(n + 1);
00164     ik++;
00165   }
00166 }
00167 
00168 bool LMFUnique::exists() {
00169   fetchID();
00170   bool ret = false;
00171   if (m_ID > 0) {
00172     ret = true;
00173   }
00174   return ret;
00175 }
00176 
00177 std::string LMFUnique::fetchAllSql(Statement *stmt) const {
00178   /* this method should setup a Statement to select the unique IDs of the
00179      objects to return */
00180   return "";
00181 }
00182 
00183 LMFUnique* LMFUnique::createObject() const {
00184   /* this method should return a pointer to a newly created object */
00185   return NULL;
00186 }
00187 
00188 std::string LMFUnique::getString(std::string s) const {
00189   std::string rs = "";
00190   std::map<std::string, std::string>::const_iterator i = m_stringFields.find(s);
00191   if (i != m_stringFields.end()) {
00192     rs = i->second;
00193   }
00194   return rs;
00195 }
00196 
00197 int LMFUnique::getInt(std::string s) const {
00198   // this should be better defined
00199   int ret = 0;
00200   std::map<std::string, int>::const_iterator i = m_intFields.find(s);
00201   if (i != m_intFields.end()) {
00202     ret = i->second;
00203   }
00204   return ret;
00205 }
00206 
00207 int LMFUnique::fetchID()
00208   throw(std::runtime_error)
00209 {
00210   /*
00211     This method fetch the ID of the object from the database according
00212     to the given specifications.
00213 
00214     It is assumed that there is only one object in the database with the
00215     given specifications. In case more than one object can be retrieved
00216     this method throws an exception.
00217 
00218     Since not all the specifications can define completely the object
00219     itself, at the end, we setup the object based on its ID.
00220    */
00221   // Return tag from memory if available
00222   if (m_ID) {
00223     return m_ID;
00224   }
00225  
00226   this->checkConnection();
00227 
00228   // fetch this ID
00229   try {
00230     Statement* stmt = m_conn->createStatement();
00231     // prepare the sql query
00232     std::string sql = fetchIdSql(stmt);
00233     if (sql != "") {
00234       if (m_debug) {
00235         cout << m_className + ": Query " + sql << endl;
00236       }
00237       
00238       ResultSet* rset = stmt->executeQuery();
00239       if (rset->next()) {
00240         m_ID = rset->getInt(1);
00241       } else {
00242         m_ID = 0;
00243       }
00244       if (m_debug) {
00245         cout << m_className + ": ID set to " << m_ID << endl;
00246       }
00247       int n = rset->getNumArrayRows();
00248       if (m_debug) {
00249         cout << m_className + ": Returned " << n << " rows"  << endl;
00250       }
00251       if (n > 1) {
00252         throw(std::runtime_error(m_className + "::fetchID: too many rows returned " +
00253                             "executing query " + sql));
00254         m_ID = 0;
00255       }
00256     }
00257     m_conn->terminateStatement(stmt);
00258   } catch (SQLException &e) {
00259     throw(std::runtime_error(m_className + "::fetchID:  "+e.getMessage()));
00260   }
00261   // given the ID of this object setup it completely
00262   if (m_ID > 0) {
00263     setByID(m_ID);
00264   }
00265   // if foreignKeys are there, set these objects too
00266   map<string, LMFUnique*>::iterator i = m_foreignKeys.begin();
00267   map<string, LMFUnique*>::iterator e = m_foreignKeys.end();
00268   while (i != e) {
00269     if (i->second->getID() == 0) {
00270       i->second->fetchID();
00271     }
00272     i++;
00273   }
00274   if (m_debug) {
00275     cout << m_className << ": fetchID:: returning " << m_ID << endl;
00276   }
00277   return m_ID;
00278 }
00279 
00280 void LMFUnique::setByID(int id) 
00281   throw(std::runtime_error)
00282 {
00283   /*
00284     Given the ID of an object setup it
00285    */
00286   if (m_debug) {
00287     cout << m_className << ": Setting this object as ID = " << id << endl;
00288   }
00289   this->checkConnection();
00290   try {
00291     Statement* stmt = m_conn->createStatement();
00292     std::string sql = setByIDSql(stmt, id);
00293     if (sql == "") {
00294       throw(std::runtime_error(m_className + "::setByID: [empty sql])"));
00295     }
00296     if (m_debug) {
00297       cout << m_className + ": " + sql << endl;
00298     }
00299 
00300     ResultSet* rset = stmt->executeQuery();
00301     if (rset->next()) {
00302       // setup the concrete object
00303       getParameters(rset);
00304       m_ID = id;
00305       if (m_debug) {
00306         cout << m_className + ": Setting done. ID set to " << m_ID << endl;
00307       }
00308     } else {
00309       throw(std::runtime_error(m_className + "::setByID:  Given id is not in the database"));
00310     }
00311     m_conn->terminateStatement(stmt);
00312   } catch (SQLException &e) {
00313    throw(std::runtime_error(m_className + "::setByID:  "+e.getMessage()));
00314   }
00315 }
00316 
00317 int LMFUnique::writeForeignKeys() 
00318   throw(std::runtime_error)
00319 {
00320   std::map<std::string, LMFUnique*>::const_iterator i = m_foreignKeys.begin();
00321   std::map<std::string, LMFUnique*>::const_iterator e = m_foreignKeys.end();
00322   int count = 0;
00323   while (i != e) {
00324     if (i->second->getID() == 0) {
00325       i->second->writeDB();
00326       count++;
00327     }
00328     i++;
00329   }
00330   return count;
00331 }
00332 
00333 int LMFUnique::writeDB()
00334   throw(std::runtime_error)
00335 {
00336   clock_t start = 0;
00337   clock_t end = 0;
00338   if (_profiling) {
00339     start = clock();
00340   }
00341   // write the associated objects first (foreign keys must exist before use)
00342   writeForeignKeys();
00343   // see if this data is already in the DB
00344   if (!(this->fetchID())) { 
00345     // check the connectioin
00346     this->checkConnection();
00347     
00348     // write new tag to the DB
00349     std::string sql = "";
00350     try {
00351       Statement* stmt = m_conn->createStatement();
00352       
00353       sql = writeDBSql(stmt);
00354       if (sql != "") {
00355         if (m_debug) {
00356           cout << m_className + ": " + sql << endl;
00357         }
00358         stmt->executeUpdate();
00359       }
00360       m_conn->commit();
00361       m_conn->terminateStatement(stmt);
00362     } catch (SQLException &e) {
00363       debug();
00364       dump();
00365       throw(std::runtime_error(m_className + "::writeDB:  " + e.getMessage() +
00366                                " while executing query " + sql));
00367     }
00368     // now get the id
00369     if (this->fetchID() == 0) {
00370       throw(std::runtime_error(m_className + "::writeDB:  Failed to write"));
00371     }
00372   }
00373   if (_profiling) {
00374     end = clock();
00375     if (m_debug) {
00376       std::cout << m_className << ":: Spent time in writeDB:" << 
00377         ((double) (end - start)) / CLOCKS_PER_SEC << " s" << endl;
00378     }
00379   }
00380   return m_ID;
00381 }
00382