00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #define DBCNV_DBGENERICCONVERTER_CPP
00012
00013
00014 #include "GaudiDb/DbDefObject.h"
00015 #include "GaudiDb/DbContainerConverter.h"
00016
00017 #include "GaudiKernel/StreamBuffer.h"
00018 #include "GaudiKernel/ContainedObject.h"
00019 #include "GaudiKernel/ObjectContainerBase.h"
00020 #include "GaudiKernel/MsgStream.h"
00021 #include "GaudiKernel/IObjManager.h"
00022
00023
00024 #include <map>
00025
00027 typedef std::map<CLID,IContainedObjectFactory*> FactoryMap;
00028
00030 DbContainerConverter::DbContainerConverter(const CLID& clid, IOODataBase* db, ISvcLocator* svc)
00031 : DbGenericConverter( clid, db, svc )
00032 {
00033 m_factories = new FactoryMap();
00034 }
00035
00037 DbContainerConverter::~DbContainerConverter() {
00038 FactoryMap* factories = (FactoryMap*)m_factories;
00039 delete factories;
00040 }
00041
00042 IContainedObjectFactory* DbContainerConverter::objCreator(const CLID& clid) {
00043 FactoryMap* factories = (FactoryMap*)m_factories;
00044 FactoryMap::iterator it = factories->find( clid );
00045 if( it == factories->end() ) {
00046 IContainedObjectFactory* fac = locateCreator(clid);
00047 if ( 0 != fac ) {
00048 std::pair<FactoryMap::iterator, bool> p =
00049 factories->insert(FactoryMap::value_type(fac->clID(), fac) );
00050 return ( p.second ) ? fac : 0;
00051 }
00052 return fac;
00053 }
00054 return (*it).second;
00055 }
00056
00058 IContainedObjectFactory* DbContainerConverter::locateCreator(const CLID& clid) {
00059 IObjManager* m = m_helperServices.ObjManager;
00060 IObjManager::ObjIterator i, stop;
00061 for ( i = m->objBegin(), stop = m->objEnd(); i != stop; i++ ) {
00062 IFactory* f = const_cast<IFactory*>(*i);
00063 IContainedObjectFactory* fac = 0;
00064 StatusCode status = f->queryInterface(IID_IContainedObjectFactory, (void**)&fac);
00065 if ( status.isSuccess() ) {
00066 if ( fac->clID() == clid ) {
00067 return fac;
00068 }
00069 }
00070 }
00071 return 0;
00072 }
00073
00075 ContainedObject* DbContainerConverter::createContained(const CLID& clid) {
00076 IContainedObjectFactory* cr = objCreator(clid);
00077 if ( 0 != cr ) {
00078 return cr->instantiate();
00079 }
00080 return 0;
00081 }
00082
00084 StatusCode DbContainerConverter::checkObject( ContainedObject* pObj, const CLID& clid ) {
00085 if ( 0 == pObj ) {
00086 MsgStream log(messageService(),"DbContainerConverter");
00087 log << MSG::ERROR << "Cannot find Object factory for CLID:" << clid << endreq;
00088 return StatusCode::FAILURE;
00089 }
00090 else if ( pObj->clID() != clid ) {
00091 MsgStream log(messageService(),"DbContainerConverter");
00092 log << MSG::ERROR << "Cannot update an object of type " << pObj->clID()
00093 << " with data for an object of type " << clid << endreq;
00094 return StatusCode::FAILURE;
00095 }
00096 return StatusCode::SUCCESS;
00097 }
00098
00100 StatusCode DbContainerConverter::doPersistentUpdate( dbHandle<DbDefObject>& objH, const DataObject* pObject) {
00101 typedef std::vector<const ContainedObject*> ObjArray;
00102 typedef StreamBuffer::ContainedLinks CLinks;
00103 typedef StreamBuffer::IdentifiedLinks ILinks;
00104 try {
00105 StatusCode status = DbGenericConverter::doPersistentUpdate(objH, pObject);
00106 const ObjectContainerBase* pCont = dynamic_cast<const ObjectContainerBase*>(pObject);
00107 if ( status.isSuccess() && 0 != pCont ) {
00108 StreamBuffer& s = objH->streamBuffer();
00109 StreamBuffer tmp;
00110 unsigned char isunique = 1;
00111 CLID typ = CLID_NULL;
00112 CLinks& t_c = tmp.containedLinks();
00113 ILinks& t_i = tmp.identifiedLinks();
00114 CLinks& s_c = s.containedLinks();
00115 ILinks& s_i = s.identifiedLinks();
00116 std::vector<const ContainedObject*> objects;
00117 long numObj = pCont->numberOfObjects();
00118
00119 for (long j = 0; j < numObj; j++ ) {
00120 const ContainedObject* obj = pCont->containedObject(j);
00121 if ( typ == CLID_NULL ) {
00122 typ = obj->clID();
00123 }
00124 else if ( typ != obj->clID() ) {
00125 isunique = 0;
00126 }
00127 objects.push_back(obj);
00128 }
00129 s << numObj << isunique;
00130 if ( isunique ) {
00131 s << typ;
00132 }
00133 for ( ObjArray::iterator i=objects.begin(); i != objects.end(); i++ ) {
00134 tmp.setMode(StreamBuffer::WRITING);
00135 tmp.setBuffPointer(0);
00136 (*i)->serialize(tmp);
00137 s.extend(3*sizeof(long)+tmp.buffPointer());
00138 if ( !isunique ) {
00139 s << (*i)->clID();
00140 }
00141 for (ILinks::iterator ii = t_i.begin(); ii != t_i.end(); ii++ )
00142 s_i.push_back(*ii);
00143 for (CLinks::iterator jj = t_c.begin(); jj != t_c.end(); jj++ )
00144 s_c.push_back(*jj);
00145 s.writeBytes(tmp.data(), tmp.buffPointer());
00146 }
00147 return StatusCode::SUCCESS;
00148 }
00149 }
00150 catch(...) {
00151 }
00152 return StatusCode::FAILURE;
00153 }
00154
00156 StatusCode DbContainerConverter::doTransientUpdate( dbHandle<DbDefObject>& objH, DataObject* pObject) {
00157 try {
00158 StatusCode status = DbGenericConverter::doTransientUpdate(objH, pObject);
00159 ObjectContainerBase* pCont = dynamic_cast<ObjectContainerBase*>(pObject);
00160 if ( 0 != pCont && status.isSuccess() ) {
00161
00162 long i, num = 0, nObj, len = pCont->numberOfObjects();
00163 StreamBuffer& s = objH->streamBuffer();
00164 IContainedObjectFactory* cr = 0;
00165 unsigned char isunique = 1;
00166 ContainedObject* pObj;
00167
00168 CLID clid;
00169 s >> nObj >> isunique;
00170 if ( isunique ) {
00171 s >> clid;
00172 cr = objCreator(clid);
00173 if ( 0 == cr ) {
00174 return StatusCode::FAILURE;
00175 }
00176 }
00177 for ( i = 0; i < nObj; i++ ) {
00178 if ( !isunique ) {
00179 s >> clid;
00180 }
00181 s >> num;
00182 if ( i < len ) {
00183
00184
00185 }
00186 else {
00187 pObj = (isunique) ? cr->instantiate() : createContained(clid);
00188 pCont->add( pObj );
00189 }
00190 status = checkObject( pObj, clid );
00191 if ( !status.isSuccess() ) {
00192 return status;
00193 }
00194 pObj->serialize(s);
00195 }
00196 for ( num=pCont->numberOfObjects(); i < num; i++ ) {
00197 ContainedObject* obj = pCont->containedObject(i);
00198 pCont->release(obj);
00199 }
00200 return StatusCode::SUCCESS;
00201 }
00202 }
00203 catch(...) {
00204 }
00205 return StatusCode::FAILURE;
00206 }