00001 #include "CondCore/ORA/interface/Exception.h"
00002 #include "CondCore/ORA/interface/Ptr.h"
00003 #include "OraPtrStreamer.h"
00004 #include "RelationalOperation.h"
00005 #include "MappingElement.h"
00006 #include "ContainerSchema.h"
00007 #include "ClassUtils.h"
00008 #include "RelationalStreamerFactory.h"
00009
00010 #include "CoralBase/Attribute.h"
00011 #include "Reflex/Object.h"
00012 #include "Reflex/Member.h"
00013
00014 namespace ora {
00015 class OraPtrReadBuffer {
00016 public:
00017 OraPtrReadBuffer( const Reflex::Type& objectType, MappingElement& mapping, ContainerSchema& contSchema ):
00018 m_objectType( objectType ),
00019 m_mapping( mapping ),
00020 m_schema( contSchema ),
00021 m_localElement(),
00022 m_query( mapping.tableName(), contSchema.storageSchema() ),
00023 m_dataElement( 0 ),
00024 m_reader(){
00025 }
00026
00027 ~OraPtrReadBuffer(){
00028 }
00029
00030 bool build( DataElement& dataElement ){
00031 m_dataElement = &dataElement;
00032 m_localElement.clear();
00033
00034 const std::vector<std::string>& columns = m_mapping.columnNames();
00035 size_t cols = columns.size();
00036 for( size_t i=0; i<cols; i++ ){
00037 m_query.addWhereId( columns[ i ] );
00038 }
00039
00040
00041 Reflex::Type ptrType = m_objectType.TemplateArgumentAt(0);
00042 Reflex::Type ptrResolvedType = ClassUtils::resolvedType(ptrType);
00043
00044 if ( ! ptrType || !ptrResolvedType ) {
00045 throwException( "Missing dictionary information for the type of the pointer \"" +
00046 m_objectType.Name(Reflex::SCOPED|Reflex::FINAL) + "\"",
00047 "OraPtrReadBuffer::build" );
00048 }
00049
00050 std::string ptrTypeName = ptrType.Name();
00051
00052 MappingElement::iterator iMe = m_mapping.find( ptrTypeName );
00053 if ( iMe == m_mapping.end() ) {
00054 throwException( "Item for \"" + ptrTypeName + "\" not found in the mapping element",
00055 "OraPtrReadBuffer::build" );
00056 }
00057 RelationalStreamerFactory streamerFactory( m_schema );
00058 m_reader.reset( streamerFactory.newReader( ptrResolvedType, iMe->second ) );
00059 return m_reader->build( m_localElement, m_query );
00060 }
00061
00062 void* read( const std::vector<int>& fullId ){
00063 if(!m_dataElement) throwException( "Read buffer has not been built.","OraPtrReadBuffer::read");
00064
00065 if(!fullId.size()) throwException( "Object id set is empty.","OraPtrReadBuffer::read");
00066
00067 coral::AttributeList& whereBuff = m_query.whereData();
00068 coral::AttributeList::iterator iCol = whereBuff.begin();
00069 size_t i=0;
00070 for( coral::AttributeList::iterator iCol = whereBuff.begin(); iCol != whereBuff.end(); ++iCol ){
00071 if( i<fullId.size() ){
00072 iCol->data<int>() = fullId[i];
00073 }
00074 i++;
00075 }
00076
00077 std::vector<int> recordId( fullId.size()-1 );
00078 for( size_t i=0; i<fullId.size()-1; i++ ){
00079 recordId[i] = fullId[i+1];
00080 ++i;
00081 }
00082
00083 m_query.execute();
00084 m_reader->select( fullId[0] );
00085 void* destination = 0;
00086 if( m_query.nextCursorRow() ){
00087 destination = ClassUtils::constructObject( m_objectType.TemplateArgumentAt(0) );
00088 m_reader->setRecordId( recordId );
00089 m_reader->read( destination );
00090 }
00091 m_query.clear();
00092 m_reader->clear();
00093 return destination;
00094 }
00095
00096 private:
00097 Reflex::Type m_objectType;
00098 MappingElement& m_mapping;
00099 ContainerSchema& m_schema;
00100 DataElement m_localElement;
00101 SelectOperation m_query;
00102 DataElement* m_dataElement;
00103 std::auto_ptr<IRelationalReader> m_reader;
00104 };
00105
00106 class RelationalPtrLoader: public IPtrLoader {
00107 public:
00108 RelationalPtrLoader( OraPtrReadBuffer& buffer, const std::vector<int>& fullId ):
00109 m_buffer( buffer ),
00110 m_fullId( fullId ),
00111 m_valid( true ){
00112 }
00113
00114 virtual ~RelationalPtrLoader(){
00115 }
00116
00117 public:
00118 void* load() const {
00119 if(!m_valid){
00120 throwException("Ptr Loader has been invalidate.",
00121 "RelationalPtrLoader::load");
00122 }
00123 return m_buffer.read( m_fullId );
00124 }
00125
00126 void invalidate(){
00127 m_valid = false;
00128 }
00129
00130 bool isValid() const{
00131 return m_valid;
00132 }
00133
00134 private:
00135 OraPtrReadBuffer& m_buffer;
00136 std::vector<int> m_fullId;
00137 bool m_valid;
00138 };
00139 }
00140
00141 ora::OraPtrWriter::OraPtrWriter( const Reflex::Type& objectType,
00142 MappingElement& mapping,
00143 ContainerSchema& contSchema ):
00144 m_objectType( objectType ),
00145 m_mappingElement( mapping ),
00146 m_schema( contSchema ),
00147 m_localElement(),
00148 m_dataElement( 0 ),
00149 m_writer(){
00150 }
00151
00152 ora::OraPtrWriter::~OraPtrWriter(){
00153 }
00154
00155 bool ora::OraPtrWriter::build(DataElement& dataElement,
00156 IRelationalData& relationalData,
00157 RelationalBuffer& operationBuffer){
00158 m_dataElement = &dataElement;
00159 m_localElement.clear();
00160
00161
00162 Reflex::Type ptrType = m_objectType.TemplateArgumentAt(0);
00163 Reflex::Type ptrResolvedType = ClassUtils::resolvedType(ptrType);
00164
00165 if ( ! ptrType || !ptrResolvedType ) {
00166 throwException( "Missing dictionary information for the type of the pointer \"" +
00167 m_objectType.Name(Reflex::SCOPED|Reflex::FINAL) + "\"",
00168 "OraPtrWriter::build" );
00169 }
00170
00171 std::string ptrTypeName = ptrType.Name();
00172
00173 MappingElement::iterator iMe = m_mappingElement.find( ptrTypeName );
00174 if ( iMe == m_mappingElement.end() ) {
00175 throwException( "Item for \"" + ptrTypeName + "\" not found in the mapping element",
00176 "OraPtrWriter::build" );
00177 }
00178 RelationalStreamerFactory streamerFactory( m_schema );
00179 m_writer.reset( streamerFactory.newWriter( ptrResolvedType, iMe->second ));
00180 return m_writer->build( m_localElement, relationalData, operationBuffer );
00181 }
00182
00183 void ora::OraPtrWriter::setRecordId( const std::vector<int>& identity ){
00184 m_writer->setRecordId( identity );
00185 }
00186
00188 void ora::OraPtrWriter::write( int oid,
00189 const void* data ){
00190
00191 if(!m_dataElement){
00192 throwException("The streamer has not been built.",
00193 "OraPtrWriter::write");
00194 }
00195
00196 Reflex::Object ptrObject( m_objectType, m_dataElement->address( data ) );
00197
00198 ptrObject.Invoke("load",0);
00199
00200 void* ptrAddress = 0;
00201 ptrObject.Invoke("address",ptrAddress);
00202 m_writer->write( oid, ptrAddress );
00203 }
00204
00205 ora::OraPtrUpdater::OraPtrUpdater( const Reflex::Type& objectType,
00206 MappingElement& mapping,
00207 ContainerSchema& contSchema ):
00208 m_objectType( objectType ),
00209 m_mappingElement( mapping ),
00210 m_schema( contSchema ),
00211 m_localElement(),
00212 m_dataElement( 0 ),
00213 m_updater(){
00214 }
00215
00216 ora::OraPtrUpdater::~OraPtrUpdater(){
00217 }
00218
00219 bool ora::OraPtrUpdater::build(DataElement& dataElement,
00220 IRelationalData& relationalData,
00221 RelationalBuffer& operationBuffer){
00222 m_dataElement = &dataElement;
00223 m_localElement.clear();
00224
00225
00226 Reflex::Type ptrType = m_objectType.TemplateArgumentAt(0);
00227 Reflex::Type ptrResolvedType = ClassUtils::resolvedType(ptrType);
00228
00229 if ( ! ptrType || !ptrResolvedType ) {
00230 throwException( "Missing dictionary information for the type of the pointer \"" +
00231 m_objectType.Name(Reflex::SCOPED|Reflex::FINAL) + "\"",
00232 "OraPtrUpdater::build" );
00233 }
00234
00235 std::string ptrTypeName = ptrType.Name();
00236
00237 MappingElement::iterator iMe = m_mappingElement.find( ptrTypeName );
00238 if ( iMe == m_mappingElement.end() ) {
00239 throwException( "Item for \"" + ptrTypeName + "\" not found in the mapping element",
00240 "OraPtrUpdater::build" );
00241 }
00242 RelationalStreamerFactory streamerFactory( m_schema );
00243 m_updater.reset( streamerFactory.newUpdater( ptrResolvedType, iMe->second ) );
00244 return m_updater->build( m_localElement, relationalData, operationBuffer );
00245 }
00246
00247 void ora::OraPtrUpdater::setRecordId( const std::vector<int>& identity ){
00248 m_updater->setRecordId( identity );
00249 }
00250
00252 void ora::OraPtrUpdater::update( int oid,
00253 const void* data ){
00254 if(!m_dataElement){
00255 throwException("The streamer has not been built.",
00256 "OraPtrUpdater::update");
00257 }
00258 Reflex::Object ptrObject( m_objectType, m_dataElement->address( data ) );
00259
00260 ptrObject.Invoke("load",0);
00261 void* ptrAddress = 0;
00262 ptrObject.Invoke("address",ptrAddress);
00263 m_updater->update( oid, ptrAddress );
00264 }
00265
00266 ora::OraPtrReader::OraPtrReader( const Reflex::Type& objectType,
00267 MappingElement& mapping,
00268 ContainerSchema& contSchema ):
00269 m_objectType( objectType ),
00270 m_dataElement( 0 ),
00271 m_readBuffer(),
00272 m_loaders(),
00273 m_tmpIds(){
00274 m_readBuffer.reset( new OraPtrReadBuffer( objectType, mapping, contSchema ));
00275 }
00276
00277 ora::OraPtrReader::~OraPtrReader(){
00278 for(std::vector<boost::shared_ptr<IPtrLoader> >::const_iterator iL = m_loaders.begin();
00279 iL != m_loaders.end(); ++iL ){
00280 (*iL)->invalidate();
00281 }
00282 }
00283
00284 bool ora::OraPtrReader::build( DataElement& dataElement,
00285 IRelationalData& ){
00286 m_dataElement = &dataElement;
00287 m_tmpIds.clear();
00288 m_tmpIds.push_back(0);
00289 return m_readBuffer->build( dataElement );
00290 }
00291
00292 void ora::OraPtrReader::select( int oid ){
00293 if(!m_dataElement) throwException( "The streamer has not been built.","OraPtrReader::select");
00294 m_tmpIds[0] = oid;
00295 }
00296
00297 void ora::OraPtrReader::setRecordId( const std::vector<int>& identity ){
00298 m_tmpIds.resize( 1+identity.size() );
00299 for( size_t i=0;i<identity.size();i++){
00300 m_tmpIds[1+i] = identity[i];
00301 }
00302 }
00303
00305 void ora::OraPtrReader::read( void* data ){
00306 if(!m_dataElement){
00307 throwException("The streamer has not been built.",
00308 "OraPtrReader::read");
00309 }
00310
00311 Reflex::Member loaderMember = m_objectType.MemberByName("m_loader");
00312 DataElement& loaderElement = m_dataElement->addChild( loaderMember.Offset(), 0 );
00313 void* loaderAddress = loaderElement.address( data );
00314 boost::shared_ptr<IPtrLoader>* loaderPtr = static_cast<boost::shared_ptr<IPtrLoader>*>( loaderAddress );
00315
00316 boost::shared_ptr<IPtrLoader> newLoader( new RelationalPtrLoader( *m_readBuffer, m_tmpIds ) );
00317 m_loaders.push_back( newLoader );
00318
00319 *loaderPtr = newLoader;
00320 }
00321
00322 void ora::OraPtrReader::clear(){
00323 }
00324
00325
00326 ora::OraPtrStreamer::OraPtrStreamer( const Reflex::Type& objectType,
00327 MappingElement& mapping,
00328 ContainerSchema& contSchema ):
00329 m_objectType( objectType ),
00330 m_mapping( mapping ),
00331 m_schema( contSchema ){
00332 }
00333
00334 ora::OraPtrStreamer::~OraPtrStreamer(){
00335 }
00336
00337 ora::IRelationalWriter* ora::OraPtrStreamer::newWriter(){
00338 return new OraPtrWriter( m_objectType, m_mapping, m_schema );
00339 }
00340
00341 ora::IRelationalUpdater* ora::OraPtrStreamer::newUpdater(){
00342 return new OraPtrUpdater( m_objectType, m_mapping, m_schema );
00343 }
00344
00345 ora::IRelationalReader* ora::OraPtrStreamer::newReader(){
00346 return new OraPtrReader( m_objectType, m_mapping, m_schema );
00347 }
00348