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 return destination;
00121 }
00122
00123 private:
00124 DataElement m_dataElement;
00125 Reflex::Type m_type;
00126 std::auto_ptr<IRelationalReader> m_reader;
00127 std::auto_ptr<SelectOperation> m_depQuery;
00128 };
00129
00130 class RelationalRefLoader: public IPtrLoader {
00131 public:
00132 explicit RelationalRefLoader( int refId ):
00133 m_reader(),
00134 m_refId( refId ),
00135 m_valid( false ){
00136 }
00137
00138 virtual ~RelationalRefLoader(){
00139 }
00140
00141 public:
00142 void build( const Reflex::Type& objectType, MappingElement& mapping, ContainerSchema& contSchema ){
00143 m_reader.build( objectType, mapping, contSchema );
00144 m_valid = true;
00145 }
00146
00147 void* load() const {
00148 if(!m_valid){
00149 throwException("Ref Loader has been invalidate.",
00150 "RelationalRefLoader::load");
00151 }
00152 return m_reader.read( m_refId );
00153 }
00154
00155 void invalidate(){
00156 m_valid = false;
00157 }
00158
00159 bool isValid() const{
00160 return m_valid;
00161 }
00162
00163 private:
00164 mutable DependentClassReader m_reader;
00165 int m_refId;
00166 bool m_valid;
00167 };
00168 }
00169
00170 ora::UniqueRefWriter::UniqueRefWriter( const Reflex::Type& objectType,
00171 MappingElement& mapping,
00172 ContainerSchema& contSchema ):
00173 m_objectType( objectType ),
00174 m_mappingElement( mapping ),
00175 m_schema( contSchema ),
00176 m_dataElement( 0 ),
00177 m_relationalData( 0 ),
00178 m_operationBuffer( 0 ){
00179 }
00180
00181 std::string ora::uniqueRefNullLabel(){
00182 static std::string nullLabel("ora::UniqueRef::Null");
00183 return nullLabel;
00184 }
00185
00186 ora::UniqueRefWriter::~UniqueRefWriter(){
00187 }
00188
00189 bool ora::UniqueRefWriter::build(DataElement& dataElement,
00190 IRelationalData& relationalData,
00191 RelationalBuffer& buffer){
00192 m_dataElement = &dataElement;
00193
00194 const std::vector<std::string>& columns = m_mappingElement.columnNames();
00195
00196 relationalData.addData( columns[0],typeid(std::string) );
00197
00198 relationalData.addData( columns[1],typeid(int) );
00199 m_relationalData = &relationalData;
00200 m_operationBuffer = &buffer;
00201 return true;
00202 }
00203
00204 void ora::UniqueRefWriter::setRecordId( const std::vector<int>& ){
00205 }
00206
00208 void ora::UniqueRefWriter::write( int oid,
00209 const void* data ){
00210
00211 if(!m_dataElement){
00212 throwException("The streamer has not been built.",
00213 "UniqueRefWriter::write");
00214 }
00215
00216 void* refAddress = m_dataElement->address( data );
00217
00218 Reflex::Object refObj( m_objectType, const_cast<void*>(refAddress));
00219
00220 bool isNull;
00221 refObj.Invoke("operator!",isNull);
00222
00223 int refId = 0;
00224 std::string className = uniqueRefNullLabel();
00225
00226 if(!isNull){
00227
00228 std::type_info* refTypeInfo = 0;
00229 refObj.Invoke("typeInfo",refTypeInfo);
00230 Reflex::Type refType = ClassUtils::lookupDictionary(*refTypeInfo);
00231 className = refType.Name(Reflex::SCOPED);
00232
00233
00234 refId = m_schema.containerSequences().getNextId( MappingRules::sequenceNameForDependentClass( m_schema.containerName(),className ));
00235
00236
00237 MappingElement& depMapping = m_schema.mappingForDependentClass( refType, true );
00238
00239 DependentClassWriter writer;
00240 writer.build( refType, depMapping, m_schema, m_operationBuffer->addVolatileBuffer() );
00241 void* refData;
00242 refObj.Invoke("operator*",refData);
00243 writer.write( oid, refId, refData );
00244
00245 }
00246
00247 coral::AttributeList& parentData = m_relationalData->data();
00248 parentData[m_mappingElement.columnNames()[0]].data<std::string>()=className;
00249 parentData[m_mappingElement.columnNames()[1]].data<int>()=refId;
00250 }
00251
00252 ora::UniqueRefUpdater::UniqueRefUpdater( const Reflex::Type& objectType,
00253 MappingElement& mapping,
00254 ContainerSchema& contSchema ):
00255 m_writer( objectType, mapping, contSchema ){
00256 }
00257
00258 ora::UniqueRefUpdater::~UniqueRefUpdater(){
00259 }
00260
00261 bool ora::UniqueRefUpdater::build(DataElement& dataElement,
00262 IRelationalData& relationalData,
00263 RelationalBuffer& operationBuffer){
00264 return m_writer.build( dataElement, relationalData, operationBuffer );
00265 }
00266
00267 void ora::UniqueRefUpdater::setRecordId( const std::vector<int>& identity ){
00268 m_writer.setRecordId( identity );
00269 }
00270
00272 void ora::UniqueRefUpdater::update( int oid,
00273 const void* data ){
00274 m_writer.write( oid, data );
00275 }
00276
00277 ora::UniqueRefReader::UniqueRefReader( const Reflex::Type& objectType,
00278 MappingElement& mapping,
00279 ContainerSchema& contSchema ):
00280 m_objectType( objectType ),
00281 m_mappingElement( mapping ),
00282 m_schema( contSchema ),
00283 m_dataElement( 0 ),
00284 m_relationalData( 0 ),
00285 m_loaders(){
00286 }
00287
00288 ora::UniqueRefReader::~UniqueRefReader(){
00289 for(std::vector<boost::shared_ptr<RelationalRefLoader> >::const_iterator iL = m_loaders.begin();
00290 iL != m_loaders.end(); ++iL ){
00291 (*iL)->invalidate();
00292 }
00293 }
00294
00295 bool ora::UniqueRefReader::build( DataElement& dataElement,
00296 IRelationalData& relationalData){
00297 m_dataElement = &dataElement;
00298 const std::vector<std::string>& columns = m_mappingElement.columnNames();
00299
00300 relationalData.addData( columns[0],typeid(std::string) );
00301
00302 relationalData.addData( columns[1],typeid(int) );
00303 m_relationalData = &relationalData;
00304 return true;
00305 }
00306
00307 void ora::UniqueRefReader::select( int ){
00308 }
00309
00310 void ora::UniqueRefReader::setRecordId( const std::vector<int>& ){
00311 }
00312
00314 void ora::UniqueRefReader::read( void* data ){
00315 if(!m_dataElement){
00316 throwException("The streamer has not been built.",
00317 "UniqueRefReader::read");
00318 }
00319 coral::AttributeList& row = m_relationalData->data();
00320 std::string className = row[m_mappingElement.columnNames()[0]].data<std::string>();
00321 int refId = row[m_mappingElement.columnNames()[1]].data<int>();
00322
00323 Reflex::Type refType = ClassUtils::lookupDictionary(className);
00324
00325
00326 MappingElement& depMapping = m_schema.mappingForDependentClass( refType );
00327
00328
00329 Reflex::Member loaderMember = m_objectType.MemberByName("m_loader");
00330 DataElement& loaderElement = m_dataElement->addChild( loaderMember.Offset(), 0 );
00331 void* loaderAddress = loaderElement.address( data );
00332 boost::shared_ptr<IPtrLoader>* loaderPtr = static_cast<boost::shared_ptr<IPtrLoader>*>( loaderAddress );
00333
00334 boost::shared_ptr<RelationalRefLoader> newLoader( new RelationalRefLoader( refId ) );
00335 newLoader->build( refType, depMapping, m_schema );
00336 m_loaders.push_back( newLoader );
00337
00338 boost::shared_ptr<IPtrLoader> tmp( newLoader );
00339 *loaderPtr = tmp;
00340 }
00341
00342 void ora::UniqueRefReader::clear(){
00343 }
00344
00345 ora::UniqueRefStreamer::UniqueRefStreamer( const Reflex::Type& objectType,
00346 MappingElement& mapping,
00347 ContainerSchema& contSchema ):
00348 m_objectType( objectType ),
00349 m_mapping( mapping ),
00350 m_schema( contSchema ){
00351 }
00352
00353 ora::UniqueRefStreamer::~UniqueRefStreamer(){
00354 }
00355
00356 ora::IRelationalWriter* ora::UniqueRefStreamer::newWriter(){
00357 return new UniqueRefWriter( m_objectType, m_mapping, m_schema );
00358 }
00359
00360 ora::IRelationalUpdater* ora::UniqueRefStreamer::newUpdater(){
00361 return new UniqueRefUpdater( m_objectType, m_mapping, m_schema );
00362 }
00363
00364 ora::IRelationalReader* ora::UniqueRefStreamer::newReader(){
00365 return new UniqueRefReader( m_objectType, m_mapping, m_schema );
00366 }
00367