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 return destination;
00093 }
00094
00095 private:
00096 Reflex::Type m_objectType;
00097 MappingElement& m_mapping;
00098 ContainerSchema& m_schema;
00099 DataElement m_localElement;
00100 SelectOperation m_query;
00101 DataElement* m_dataElement;
00102 std::auto_ptr<IRelationalReader> m_reader;
00103 };
00104
00105 class RelationalPtrLoader: public IPtrLoader {
00106 public:
00107 RelationalPtrLoader( OraPtrReadBuffer& buffer, const std::vector<int>& fullId ):
00108 m_buffer( buffer ),
00109 m_fullId( fullId ),
00110 m_valid( true ){
00111 }
00112
00113 virtual ~RelationalPtrLoader(){
00114 }
00115
00116 public:
00117 void* load() const {
00118 if(!m_valid){
00119 throwException("Ptr Loader has been invalidate.",
00120 "RelationalPtrLoader::load");
00121 }
00122 return m_buffer.read( m_fullId );
00123 }
00124
00125 void invalidate(){
00126 m_valid = false;
00127 }
00128
00129 bool isValid() const{
00130 return m_valid;
00131 }
00132
00133 private:
00134 OraPtrReadBuffer& m_buffer;
00135 std::vector<int> m_fullId;
00136 bool m_valid;
00137 };
00138 }
00139
00140 ora::OraPtrWriter::OraPtrWriter( const Reflex::Type& objectType,
00141 MappingElement& mapping,
00142 ContainerSchema& contSchema ):
00143 m_objectType( objectType ),
00144 m_mappingElement( mapping ),
00145 m_schema( contSchema ),
00146 m_localElement(),
00147 m_dataElement( 0 ),
00148 m_writer(){
00149 }
00150
00151 ora::OraPtrWriter::~OraPtrWriter(){
00152 }
00153
00154 bool ora::OraPtrWriter::build(DataElement& dataElement,
00155 IRelationalData& relationalData,
00156 RelationalBuffer& operationBuffer){
00157 m_dataElement = &dataElement;
00158 m_localElement.clear();
00159
00160
00161 Reflex::Type ptrType = m_objectType.TemplateArgumentAt(0);
00162 Reflex::Type ptrResolvedType = ClassUtils::resolvedType(ptrType);
00163
00164 if ( ! ptrType || !ptrResolvedType ) {
00165 throwException( "Missing dictionary information for the type of the pointer \"" +
00166 m_objectType.Name(Reflex::SCOPED|Reflex::FINAL) + "\"",
00167 "OraPtrWriter::build" );
00168 }
00169
00170 std::string ptrTypeName = ptrType.Name();
00171
00172 MappingElement::iterator iMe = m_mappingElement.find( ptrTypeName );
00173 if ( iMe == m_mappingElement.end() ) {
00174 throwException( "Item for \"" + ptrTypeName + "\" not found in the mapping element",
00175 "OraPtrWriter::build" );
00176 }
00177 RelationalStreamerFactory streamerFactory( m_schema );
00178 m_writer.reset( streamerFactory.newWriter( ptrResolvedType, iMe->second ));
00179 return m_writer->build( m_localElement, relationalData, operationBuffer );
00180 }
00181
00182 void ora::OraPtrWriter::setRecordId( const std::vector<int>& identity ){
00183 m_writer->setRecordId( identity );
00184 }
00185
00187 void ora::OraPtrWriter::write( int oid,
00188 const void* data ){
00189
00190 if(!m_dataElement){
00191 throwException("The streamer has not been built.",
00192 "OraPtrWriter::write");
00193 }
00194
00195 Reflex::Object ptrObject( m_objectType, m_dataElement->address( data ) );
00196
00197 ptrObject.Invoke("load",0);
00198
00199 void* ptrAddress = 0;
00200 ptrObject.Invoke("address",ptrAddress);
00201 m_writer->write( oid, ptrAddress );
00202 }
00203
00204 ora::OraPtrUpdater::OraPtrUpdater( const Reflex::Type& objectType,
00205 MappingElement& mapping,
00206 ContainerSchema& contSchema ):
00207 m_objectType( objectType ),
00208 m_mappingElement( mapping ),
00209 m_schema( contSchema ),
00210 m_localElement(),
00211 m_dataElement( 0 ),
00212 m_updater(){
00213 }
00214
00215 ora::OraPtrUpdater::~OraPtrUpdater(){
00216 }
00217
00218 bool ora::OraPtrUpdater::build(DataElement& dataElement,
00219 IRelationalData& relationalData,
00220 RelationalBuffer& operationBuffer){
00221 m_dataElement = &dataElement;
00222 m_localElement.clear();
00223
00224
00225 Reflex::Type ptrType = m_objectType.TemplateArgumentAt(0);
00226 Reflex::Type ptrResolvedType = ClassUtils::resolvedType(ptrType);
00227
00228 if ( ! ptrType || !ptrResolvedType ) {
00229 throwException( "Missing dictionary information for the type of the pointer \"" +
00230 m_objectType.Name(Reflex::SCOPED|Reflex::FINAL) + "\"",
00231 "OraPtrUpdater::build" );
00232 }
00233
00234 std::string ptrTypeName = ptrType.Name();
00235
00236 MappingElement::iterator iMe = m_mappingElement.find( ptrTypeName );
00237 if ( iMe == m_mappingElement.end() ) {
00238 throwException( "Item for \"" + ptrTypeName + "\" not found in the mapping element",
00239 "OraPtrUpdater::build" );
00240 }
00241 RelationalStreamerFactory streamerFactory( m_schema );
00242 m_updater.reset( streamerFactory.newUpdater( ptrResolvedType, iMe->second ) );
00243 return m_updater->build( m_localElement, relationalData, operationBuffer );
00244 }
00245
00246 void ora::OraPtrUpdater::setRecordId( const std::vector<int>& identity ){
00247 m_updater->setRecordId( identity );
00248 }
00249
00251 void ora::OraPtrUpdater::update( int oid,
00252 const void* data ){
00253 if(!m_dataElement){
00254 throwException("The streamer has not been built.",
00255 "OraPtrUpdater::update");
00256 }
00257 Reflex::Object ptrObject( m_objectType, m_dataElement->address( data ) );
00258
00259 ptrObject.Invoke("load",0);
00260 void* ptrAddress = 0;
00261 ptrObject.Invoke("address",ptrAddress);
00262 m_updater->update( oid, ptrAddress );
00263 }
00264
00265 ora::OraPtrReader::OraPtrReader( const Reflex::Type& objectType,
00266 MappingElement& mapping,
00267 ContainerSchema& contSchema ):
00268 m_objectType( objectType ),
00269 m_dataElement( 0 ),
00270 m_readBuffer(),
00271 m_loaders(),
00272 m_tmpIds(){
00273 m_readBuffer.reset( new OraPtrReadBuffer( objectType, mapping, contSchema ));
00274 }
00275
00276 ora::OraPtrReader::~OraPtrReader(){
00277 for(std::vector<boost::shared_ptr<IPtrLoader> >::const_iterator iL = m_loaders.begin();
00278 iL != m_loaders.end(); ++iL ){
00279 (*iL)->invalidate();
00280 }
00281 }
00282
00283 bool ora::OraPtrReader::build( DataElement& dataElement,
00284 IRelationalData& ){
00285 m_dataElement = &dataElement;
00286 m_tmpIds.clear();
00287 m_tmpIds.push_back(0);
00288 return m_readBuffer->build( dataElement );
00289 }
00290
00291 void ora::OraPtrReader::select( int oid ){
00292 if(!m_dataElement) throwException( "The streamer has not been built.","OraPtrReader::select");
00293 m_tmpIds[0] = oid;
00294 }
00295
00296 void ora::OraPtrReader::setRecordId( const std::vector<int>& identity ){
00297 m_tmpIds.resize( 1+identity.size() );
00298 for( size_t i=0;i<identity.size();i++){
00299 m_tmpIds[1+i] = identity[i];
00300 }
00301 }
00302
00304 void ora::OraPtrReader::read( void* data ){
00305 if(!m_dataElement){
00306 throwException("The streamer has not been built.",
00307 "OraPtrReader::read");
00308 }
00309
00310 Reflex::Member loaderMember = m_objectType.MemberByName("m_loader");
00311 DataElement& loaderElement = m_dataElement->addChild( loaderMember.Offset(), 0 );
00312 void* loaderAddress = loaderElement.address( data );
00313 boost::shared_ptr<IPtrLoader>* loaderPtr = static_cast<boost::shared_ptr<IPtrLoader>*>( loaderAddress );
00314
00315 boost::shared_ptr<IPtrLoader> newLoader( new RelationalPtrLoader( *m_readBuffer, m_tmpIds ) );
00316 m_loaders.push_back( newLoader );
00317
00318 *loaderPtr = newLoader;
00319 }
00320
00321 void ora::OraPtrReader::clear(){
00322 }
00323
00324
00325 ora::OraPtrStreamer::OraPtrStreamer( const Reflex::Type& objectType,
00326 MappingElement& mapping,
00327 ContainerSchema& contSchema ):
00328 m_objectType( objectType ),
00329 m_mapping( mapping ),
00330 m_schema( contSchema ){
00331 }
00332
00333 ora::OraPtrStreamer::~OraPtrStreamer(){
00334 }
00335
00336 ora::IRelationalWriter* ora::OraPtrStreamer::newWriter(){
00337 return new OraPtrWriter( m_objectType, m_mapping, m_schema );
00338 }
00339
00340 ora::IRelationalUpdater* ora::OraPtrStreamer::newUpdater(){
00341 return new OraPtrUpdater( m_objectType, m_mapping, m_schema );
00342 }
00343
00344 ora::IRelationalReader* ora::OraPtrStreamer::newReader(){
00345 return new OraPtrReader( m_objectType, m_mapping, m_schema );
00346 }
00347