00001 #include "CondCore/ORA/interface/Exception.h"
00002 #include "CondCore/ORA/interface/UniqueRef.h"
00003 #include "UniqueRefStreamer.h"
00004 #include "RelationalOperation.h"
00005 #include "MappingElement.h"
00006 #include "MappingRules.h"
00007 #include "ContainerSchema.h"
00008 #include "ClassUtils.h"
00009 #include "RelationalStreamerFactory.h"
00010
00011 #include "CoralBase/Attribute.h"
00012 #include "Reflex/Object.h"
00013 #include "Reflex/Member.h"
00014
00015 namespace ora {
00016
00017 class DependentClassWriter {
00018 public:
00019
00020 DependentClassWriter( ):
00021 m_dataElement(),
00022 m_writer(),
00023 m_depInsert( 0 ){
00024 }
00025
00026 void build( const Reflex::Type& objectType, MappingElement& mapping,
00027 ContainerSchema& contSchema, RelationalBuffer& operationBuffer ){
00028
00029 m_depInsert = &operationBuffer.newInsert( mapping.tableName());
00030 const std::vector<std::string> columns = mapping.columnNames();
00031 for( std::vector<std::string>::const_iterator iC = columns.begin();
00032 iC != columns.end(); ++iC){
00033 m_depInsert->addId( *iC );
00034 }
00035
00036 MappingElement::iterator iMe = mapping.find( objectType.Name(Reflex::SCOPED) );
00037
00038 if( iMe == mapping.end()){
00039 throwException("Could not find a mapping element for class \""+
00040 objectType.Name(Reflex::SCOPED)+"\"",
00041 "DependentClassWriter::write");
00042 }
00043 RelationalStreamerFactory streamerFactory( contSchema );
00044 m_writer.reset( streamerFactory.newWriter( objectType, iMe->second ) );
00045 m_writer->build( m_dataElement, *m_depInsert, operationBuffer );
00046 }
00047
00048 ~DependentClassWriter(){
00049 }
00050
00051 void write( int oId, int refId, const void* data ){
00052 if( !m_depInsert ){
00053 throwException( "DependentClassWriter has not been built.",
00054 "DependentClassWriter::write");
00055 }
00056
00057 coral::AttributeList& dataBuff = m_depInsert->data();
00058 coral::AttributeList::iterator iData = dataBuff.begin();
00059 iData->data<int>()= oId;
00060 ++iData;
00061 iData->data<int>()= refId;
00062
00063 std::vector<int> recordId(1,refId);
00064 m_writer->setRecordId( recordId);
00065 m_writer->write( oId, data );
00066 }
00067
00068 private:
00069 DataElement m_dataElement;
00070 std::auto_ptr<IRelationalWriter> m_writer;
00071 InsertOperation* m_depInsert;
00072 };
00073
00074 class DependentClassReader {
00075 public:
00076 DependentClassReader():
00077 m_dataElement(),
00078 m_type(),
00079 m_reader(),
00080 m_depQuery(){
00081 }
00082
00083 void build( const Reflex::Type& objectType, MappingElement& depMapping, ContainerSchema& contSchema ){
00084
00085 m_type = objectType;
00086 m_depQuery.reset( new SelectOperation( depMapping.tableName(), contSchema.storageSchema()));
00087 m_depQuery->addWhereId( depMapping.columnNames()[ 1 ] );
00088 MappingElement::iterator iMap = depMapping.find( m_type.Name(Reflex::SCOPED) );
00089
00090 if( iMap == depMapping.end()){
00091 throwException("Could not find a mapping element for class \""+
00092 m_type.Name(Reflex::SCOPED)+"\"",
00093 "DependentClassReadBuffer::ReadBuffer");
00094 }
00095 MappingElement& mapping = iMap->second;
00096 RelationalStreamerFactory streamerFactory( contSchema );
00097 m_reader.reset( streamerFactory.newReader( m_type, mapping )) ;
00098 m_reader->build( m_dataElement , *m_depQuery );
00099 }
00100
00101 ~DependentClassReader(){
00102 }
00103
00104 void* read( int refId ){
00105 if( !m_depQuery.get() ){
00106 throwException( "DependentClassReader has not been built.",
00107 "DependentClassReader::read");
00108 }
00109 coral::AttributeList& whereData = m_depQuery->whereData();
00110 coral::AttributeList::iterator iWData = whereData.begin();
00111 iWData->data<int>() = refId;
00112 m_depQuery->execute();
00113 m_reader->select( refId );
00114 void* destination = 0;
00115 if( m_depQuery->nextCursorRow() ){
00116 destination = ClassUtils::constructObject( m_type );
00117 m_reader->read( destination );
00118 }
00119 m_depQuery->clear();
00120 m_reader->clear();
00121 return destination;
00122 }
00123
00124 private:
00125 DataElement m_dataElement;
00126 Reflex::Type m_type;
00127 std::auto_ptr<IRelationalReader> m_reader;
00128 std::auto_ptr<SelectOperation> m_depQuery;
00129 };
00130
00131 class RelationalRefLoader: public IPtrLoader {
00132 public:
00133 explicit RelationalRefLoader( int refId ):
00134 m_reader(),
00135 m_refId( refId ),
00136 m_valid( false ){
00137 }
00138
00139 virtual ~RelationalRefLoader(){
00140 }
00141
00142 public:
00143 void build( const Reflex::Type& objectType, MappingElement& mapping, ContainerSchema& contSchema ){
00144 m_reader.build( objectType, mapping, contSchema );
00145 m_valid = true;
00146 }
00147
00148 void* load() const {
00149 if(!m_valid){
00150 throwException("Ref Loader has been invalidate.",
00151 "RelationalRefLoader::load");
00152 }
00153 return m_reader.read( m_refId );
00154 }
00155
00156 void invalidate(){
00157 m_valid = false;
00158 }
00159
00160 bool isValid() const{
00161 return m_valid;
00162 }
00163
00164 private:
00165 mutable DependentClassReader m_reader;
00166 int m_refId;
00167 bool m_valid;
00168 };
00169 }
00170
00171 ora::UniqueRefWriter::UniqueRefWriter( const Reflex::Type& objectType,
00172 MappingElement& mapping,
00173 ContainerSchema& contSchema ):
00174 m_objectType( objectType ),
00175 m_mappingElement( mapping ),
00176 m_schema( contSchema ),
00177 m_dataElement( 0 ),
00178 m_relationalData( 0 ),
00179 m_operationBuffer( 0 ){
00180 m_columnIndexes[0]=-1;
00181 m_columnIndexes[1]=-1;
00182 }
00183
00184 std::string ora::uniqueRefNullLabel(){
00185 static std::string nullLabel("ora::UniqueRef::Null");
00186 return nullLabel;
00187 }
00188
00189 ora::UniqueRefWriter::~UniqueRefWriter(){
00190 }
00191
00192 bool ora::UniqueRefWriter::build(DataElement& dataElement,
00193 IRelationalData& relationalData,
00194 RelationalBuffer& buffer){
00195 m_dataElement = &dataElement;
00196
00197 const std::vector<std::string>& columns = m_mappingElement.columnNames();
00198 if( columns.size() < 2 ){
00199 throwException("Expected column names have not been found in the mapping.",
00200 "UniqueRefWriter::build");
00201 }
00202
00203 m_columnIndexes[0] = relationalData.addData( columns[0],typeid(std::string) );
00204
00205 m_columnIndexes[1] = relationalData.addData( columns[1],typeid(int) );
00206 m_relationalData = &relationalData;
00207 m_operationBuffer = &buffer;
00208 return true;
00209 }
00210
00211 void ora::UniqueRefWriter::setRecordId( const std::vector<int>& ){
00212 }
00213
00215 void ora::UniqueRefWriter::write( int oid,
00216 const void* data ){
00217
00218 if(!m_dataElement){
00219 throwException("The streamer has not been built.",
00220 "UniqueRefWriter::write");
00221 }
00222
00223 void* refAddress = m_dataElement->address( data );
00224
00225 Reflex::Object refObj( m_objectType, const_cast<void*>(refAddress));
00226
00227 bool isNull;
00228 refObj.Invoke("operator!",isNull);
00229
00230 int refId = 0;
00231 std::string className = uniqueRefNullLabel();
00232
00233 if(!isNull){
00234
00235 std::type_info* refTypeInfo = 0;
00236 refObj.Invoke("typeInfo",refTypeInfo);
00237 Reflex::Type refType = ClassUtils::lookupDictionary(*refTypeInfo);
00238 className = refType.Name(Reflex::SCOPED);
00239
00240
00241 MappingElement& depMapping = m_schema.mappingForDependentClass( refType, true );
00242
00243
00244 refId = m_schema.containerSequences().getNextId( MappingRules::sequenceNameForDependentClass( m_schema.containerName(),className ));
00245
00246 DependentClassWriter writer;
00247 writer.build( refType, depMapping, m_schema, m_operationBuffer->addVolatileBuffer() );
00248 void* refData;
00249 refObj.Invoke("operator*",refData);
00250 writer.write( oid, refId, refData );
00251
00252 }
00253
00254 coral::AttributeList& parentData = m_relationalData->data();
00255 parentData[m_columnIndexes[0]].data<std::string>()=className;
00256 parentData[m_columnIndexes[1]].data<int>()=refId;
00257 }
00258
00259 ora::UniqueRefUpdater::UniqueRefUpdater( const Reflex::Type& objectType,
00260 MappingElement& mapping,
00261 ContainerSchema& contSchema ):
00262 m_writer( objectType, mapping, contSchema ){
00263 }
00264
00265 ora::UniqueRefUpdater::~UniqueRefUpdater(){
00266 }
00267
00268 bool ora::UniqueRefUpdater::build(DataElement& dataElement,
00269 IRelationalData& relationalData,
00270 RelationalBuffer& operationBuffer){
00271 return m_writer.build( dataElement, relationalData, operationBuffer );
00272 }
00273
00274 void ora::UniqueRefUpdater::setRecordId( const std::vector<int>& identity ){
00275 m_writer.setRecordId( identity );
00276 }
00277
00279 void ora::UniqueRefUpdater::update( int oid,
00280 const void* data ){
00281 m_writer.write( oid, data );
00282 }
00283
00284 ora::UniqueRefReader::UniqueRefReader( const Reflex::Type& objectType,
00285 MappingElement& mapping,
00286 ContainerSchema& contSchema ):
00287 m_objectType( objectType ),
00288 m_mappingElement( mapping ),
00289 m_schema( contSchema ),
00290 m_dataElement( 0 ),
00291 m_relationalData( 0 ),
00292 m_loaders(){
00293 m_columnIndexes[0]=-1;
00294 m_columnIndexes[1]=-1;
00295 }
00296
00297 ora::UniqueRefReader::~UniqueRefReader(){
00298 for(std::vector<boost::shared_ptr<RelationalRefLoader> >::const_iterator iL = m_loaders.begin();
00299 iL != m_loaders.end(); ++iL ){
00300 (*iL)->invalidate();
00301 }
00302 }
00303
00304 bool ora::UniqueRefReader::build( DataElement& dataElement,
00305 IRelationalData& relationalData){
00306 m_dataElement = &dataElement;
00307 const std::vector<std::string>& columns = m_mappingElement.columnNames();
00308 if( columns.size() < 2 ){
00309 throwException("Expected column names have not been found in the mapping.",
00310 "UniqueRefReader::build");
00311 }
00312
00313 m_columnIndexes[0] = relationalData.addData( columns[0],typeid(std::string) );
00314
00315 m_columnIndexes[1] = relationalData.addData( columns[1],typeid(int) );
00316 m_relationalData = &relationalData;
00317 return true;
00318 }
00319
00320 void ora::UniqueRefReader::select( int ){
00321 }
00322
00323 void ora::UniqueRefReader::setRecordId( const std::vector<int>& ){
00324 }
00325
00327 void ora::UniqueRefReader::read( void* data ){
00328 if(!m_dataElement){
00329 throwException("The streamer has not been built.",
00330 "UniqueRefReader::read");
00331 }
00332 coral::AttributeList& row = m_relationalData->data();
00333 std::string className = row[m_columnIndexes[0]].data<std::string>();
00334 int refId = row[m_columnIndexes[1]].data<int>();
00335
00336 Reflex::Type refType = ClassUtils::lookupDictionary(className);
00337
00338
00339 MappingElement& depMapping = m_schema.mappingForDependentClass( refType );
00340
00341
00342 Reflex::Member loaderMember = m_objectType.MemberByName("m_loader");
00343 DataElement& loaderElement = m_dataElement->addChild( loaderMember.Offset(), 0 );
00344 void* loaderAddress = loaderElement.address( data );
00345 boost::shared_ptr<IPtrLoader>* loaderPtr = static_cast<boost::shared_ptr<IPtrLoader>*>( loaderAddress );
00346
00347 boost::shared_ptr<RelationalRefLoader> newLoader( new RelationalRefLoader( refId ) );
00348 newLoader->build( refType, depMapping, m_schema );
00349 m_loaders.push_back( newLoader );
00350
00351 boost::shared_ptr<IPtrLoader> tmp( newLoader );
00352 *loaderPtr = tmp;
00353 }
00354
00355 void ora::UniqueRefReader::clear(){
00356 }
00357
00358 ora::UniqueRefStreamer::UniqueRefStreamer( const Reflex::Type& objectType,
00359 MappingElement& mapping,
00360 ContainerSchema& contSchema ):
00361 m_objectType( objectType ),
00362 m_mapping( mapping ),
00363 m_schema( contSchema ){
00364 }
00365
00366 ora::UniqueRefStreamer::~UniqueRefStreamer(){
00367 }
00368
00369 ora::IRelationalWriter* ora::UniqueRefStreamer::newWriter(){
00370 return new UniqueRefWriter( m_objectType, m_mapping, m_schema );
00371 }
00372
00373 ora::IRelationalUpdater* ora::UniqueRefStreamer::newUpdater(){
00374 return new UniqueRefUpdater( m_objectType, m_mapping, m_schema );
00375 }
00376
00377 ora::IRelationalReader* ora::UniqueRefStreamer::newReader(){
00378 return new UniqueRefReader( m_objectType, m_mapping, m_schema );
00379 }
00380