CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/CondCore/ORA/src/RelationalMapping.cc

Go to the documentation of this file.
00001 #include "CondCore/ORA/interface/Exception.h"
00002 #include "CondCore/ORA/interface/Reference.h"
00003 #include "CondCore/ORA/interface/NamedRef.h"
00004 #include "RelationalMapping.h"
00005 #include "TableRegister.h"
00006 #include "MappingElement.h"
00007 #include "MappingRules.h"
00008 #include "ClassUtils.h"
00009 // externals 
00010 #include "Reflex/Reflex.h"
00011 #include "CoralBase/AttributeSpecification.h"
00012 
00013 size_t
00014 ora::RelationalMapping::sizeInColumns(const Reflex::Type& topLevelClassType ){
00015   size_t sz=0;
00016   bool hasDependencies = false;
00017   _sizeInColumns(topLevelClassType, sz, hasDependencies );
00018   return sz;
00019 }
00020 
00021 std::pair<bool,size_t>
00022 ora::RelationalMapping::sizeInColumnsForCArray(const Reflex::Type& topLevelClassType ){
00023   size_t sz=0;
00024   bool hasDependencies = false;
00025   _sizeInColumnsForCArray(topLevelClassType, sz, hasDependencies );
00026   return std::make_pair(hasDependencies,sz);
00027 }
00028 
00029 
00030 void
00031 ora::RelationalMapping::_sizeInColumns(const Reflex::Type& topLevelClassType,
00032                                        size_t& sz,
00033                                        bool& hasDependencies ){
00034   // resolve possible typedef chains
00035   Reflex::Type typ = ClassUtils::resolvedType( topLevelClassType );
00036   bool isOraPolyPointer = ora::ClassUtils::isTypeUniqueReference(typ);
00037   bool isPrimitive = ora::ClassUtils::isTypePrimitive( typ );
00038 
00039   // primitive and string
00040   if( isPrimitive || isOraPolyPointer || ora::ClassUtils::isTypeNamedReference( typ)) {
00041     ++sz;
00042   } else if (typ.IsArray()){
00043     size_t arraySize = 0;
00044     _sizeInColumnsForCArray( typ,arraySize, hasDependencies );
00045     if( arraySize < MappingRules::MaxColumnsForInlineCArray ) sz += arraySize;
00046     else hasDependencies = true;
00047   } else if (typ.TypeInfo() == typeid(ora::Reference) ||
00048              typ.HasBase( Reflex::Type::ByTypeInfo( typeid(ora::Reference) ) )){
00049     sz += 2;
00050   } else {
00051   
00052     bool isContainer =  ora::ClassUtils::isTypeNonAssociativeContainer(typ) ||
00053       ora::ClassUtils::isTypeAssociativeContainer(typ);
00054     bool isOraPointer = ora::ClassUtils::isTypeOraPointer(typ);
00055     if( !isContainer && !isOraPointer ){
00056       
00057       // loop over the data members
00058       typ.UpdateMembers();
00059       //std::vector<Reflex::Type> carrays;
00060       for ( size_t i=0; i< typ.DataMemberSize(); i++){
00061         Reflex::Member objMember = typ.DataMemberAt(i);
00062 
00063         // Skip the transient ones
00064         if ( objMember.IsTransient() ) continue;
00065 
00066         // Retrieve the field type
00067         Reflex::Type objMemberType = objMember.TypeOf();
00068 
00069         _sizeInColumns(objMemberType,sz, hasDependencies );
00070       }
00071     } else {
00072       hasDependencies = true;
00073     }    
00074   }
00075 }
00076 
00077 void
00078 ora::RelationalMapping::_sizeInColumnsForCArray(const Reflex::Type& topLevelClassType,
00079                                                 size_t& sz,
00080                                                 bool& hasDependencies){
00081   // resolve possible typedef chains
00082   Reflex::Type typ = ClassUtils::resolvedType( topLevelClassType );
00083   if( !typ.IsArray()){
00084     return;
00085   }
00086 
00087   size_t arraySize = typ.ArrayLength();
00088   Reflex::Type arrayType = typ.ToType();
00089   size_t arrayElementSize = 0;
00090   _sizeInColumns(arrayType, arrayElementSize, hasDependencies);
00091   size_t totSize = arraySize*arrayElementSize;
00092   sz += totSize;
00093 }
00094 
00095 
00096 ora::RelationalMappingFactory::RelationalMappingFactory( TableRegister& tableRegister ):
00097   m_tableRegister( tableRegister ){
00098 }
00099 
00100 ora::RelationalMappingFactory::~RelationalMappingFactory(){
00101 }
00102 
00103 ora::IRelationalMapping* ora::RelationalMappingFactory::newProcessor( const Reflex::Type& attributeType,
00104                                                                       bool blobStreaming ){
00105   if( blobStreaming ){
00106     return new BlobMapping( attributeType, m_tableRegister );
00107   }
00108   Reflex::Type resType = ClassUtils::resolvedType( attributeType );
00109   if ( ora::ClassUtils::isTypePrimitive(resType) ) {
00110     return new PrimitiveMapping( attributeType, m_tableRegister );
00111   }
00112   else if ( resType.IsArray() ){
00113     return new CArrayMapping( attributeType, m_tableRegister );
00114   }
00115   else if ( ora::ClassUtils::isTypeContainer( resType ) ) {
00116     return new ArrayMapping( attributeType, m_tableRegister );
00117   }
00118   else if ( resType.IsPointer() || resType.IsReference() ){
00119     return new EmptyMapping();
00120   }
00121   else if ( ora::ClassUtils::isTypeOraPointer( resType )){
00122     return new OraPtrMapping( attributeType, m_tableRegister );
00123   }
00124   else if ( ora::ClassUtils::isTypeUniqueReference( resType )){
00125     return new UniqueReferenceMapping( attributeType, m_tableRegister );
00126   }
00127   else if ( resType.TypeInfo() == typeid(ora::Reference) ||
00128             resType.HasBase( Reflex::Type::ByTypeInfo( typeid(ora::Reference) ) ) ){
00129     return new OraReferenceMapping( attributeType, m_tableRegister );
00130   }
00131   else if ( resType.TypeInfo() == typeid(ora::NamedReference) ||
00132             resType.HasBase( Reflex::Type::ByTypeInfo( typeid(ora::NamedReference) ) ) ){
00133     return new NamedRefMapping( attributeType, m_tableRegister );
00134   }
00135   else { // embeddedobject
00136     return new ObjectMapping( attributeType, m_tableRegister );
00137   } 
00138 }
00139 
00140 namespace ora {
00141   void processLeafElement( MappingElement& parentElement,
00142                            const std::string& elementType,
00143                            const std::string& typeName,
00144                            const std::string& attributeName,
00145                            const std::string& attributeNameForSchema,
00146                            const std::string& scopeNameForSchema,
00147                            TableRegister& tableRegister){
00148     if(!tableRegister.checkTable( parentElement.tableName())){
00149       throwException("Table \""+parentElement.tableName()+"\" has not been allocated.",
00150                      "processLeafElement");
00151     }
00152     ora::MappingElement& me = parentElement.appendSubElement( elementType, attributeName, typeName, parentElement.tableName() );
00153     std::string inputCol = ora::MappingRules::columnNameForVariable( attributeNameForSchema, scopeNameForSchema );
00154     std::string columnName(inputCol);
00155     unsigned int i=0;
00156     while(tableRegister.checkColumn(parentElement.tableName(),columnName)){
00157       columnName = ora::MappingRules::newNameForSchemaObject( inputCol, i, ora::MappingRules::MaxColumnNameLength );
00158       i++;
00159     }
00160     tableRegister.insertColumn(parentElement.tableName(),columnName);
00161     std::vector<std::string> cols;
00162     cols.push_back( columnName );
00163     // add metadata column for blobs 
00164     if( elementType == ora::MappingElement::blobMappingElementType() ){
00165       std::string metaDataColumnName = ora::MappingRules::columnNameForBlobMetadata( columnName );
00166       tableRegister.insertColumn(parentElement.tableName(),metaDataColumnName );
00167       cols.push_back( metaDataColumnName );      
00168     }
00169     me.setColumnNames( cols );
00170   }
00171 }
00172 
00173 ora::PrimitiveMapping::PrimitiveMapping( const Reflex::Type& attributeType, TableRegister& tableRegister ):
00174   m_type(attributeType),m_tableRegister( tableRegister ){
00175 }
00176 
00177 ora::PrimitiveMapping::~PrimitiveMapping(){
00178 }
00179 
00180 void ora::PrimitiveMapping::process( MappingElement& parentElement,
00181                                      const std::string& attributeName,
00182                                      const std::string& attributeNameForSchema,
00183                                      const std::string& scopeNameForSchema ){
00184   Reflex::Type t = ClassUtils::resolvedType( m_type );
00185   const std::type_info* attrType = &t.TypeInfo();
00186   if(t.IsEnum()) attrType = &typeid(int);
00187   //std::string tn = ClassUtils::demangledName(*attrType);
00188   if(ClassUtils::isTypeString( t )) attrType = &typeid(std::string);
00189   std::string typeName = coral::AttributeSpecification::typeNameForId(*attrType);
00190   
00191   processLeafElement(parentElement,
00192                      ora::MappingElement::primitiveMappingElementType(),
00193                      typeName,
00194                      attributeName,
00195                      attributeNameForSchema,
00196                      scopeNameForSchema,
00197                      m_tableRegister);  
00198 }
00199 
00200 ora::BlobMapping::BlobMapping( const Reflex::Type& attributeType, TableRegister& tableRegister ):
00201   m_type(attributeType),m_tableRegister( tableRegister ){
00202 }
00203 
00204 ora::BlobMapping::~BlobMapping(){
00205 }
00206 void ora::BlobMapping::process( MappingElement& parentElement,
00207                                 const std::string& attributeName,
00208                                 const std::string& attributeNameForSchema,
00209                                 const std::string& scopeNameForSchema ){
00210   std::string className = m_type.Name(Reflex::SCOPED);
00211   processLeafElement(parentElement,
00212                      ora::MappingElement::blobMappingElementType(),
00213                      className,
00214                      attributeName,
00215                      attributeNameForSchema,
00216                      scopeNameForSchema,
00217                      m_tableRegister);
00218 }
00219 
00220 ora::OraReferenceMapping::OraReferenceMapping( const Reflex::Type& attributeType, TableRegister& tableRegister ):
00221   m_type(attributeType),m_tableRegister( tableRegister ){
00222 }
00223 
00224 ora::OraReferenceMapping::~OraReferenceMapping(){
00225 }
00226 
00227 void ora::OraReferenceMapping::process( MappingElement& parentElement,
00228                                         const std::string& attributeName,
00229                                         const std::string& attributeNameForSchema,
00230                                         const std::string& scopeNameForSchema ){
00231   std::string className = m_type.Name(Reflex::SCOPED);
00232   std::string elementType = ora::MappingElement::OraReferenceMappingElementType();
00233   if(!m_tableRegister.checkTable( parentElement.tableName())){
00234     throwException("Table \""+parentElement.tableName()+"\" has not been allocated.",
00235                    "OraReferenceMapping::process");
00236   }
00237   ora::MappingElement& me = parentElement.appendSubElement( elementType, attributeName, className, parentElement.tableName() );
00238 
00239   std::vector<std::string> cols;
00240   for(unsigned int j=0;j<2;j++){
00241     std::string inputCol = ora::MappingRules::columnNameForOID( attributeNameForSchema, scopeNameForSchema, j );
00242     std::string columnName(inputCol);
00243     unsigned int i=0;
00244     while(m_tableRegister.checkColumn(parentElement.tableName(),columnName)){
00245       columnName = ora::MappingRules::newNameForSchemaObject( inputCol, i, ora::MappingRules::MaxColumnNameLength );
00246       i++;
00247     }
00248     m_tableRegister.insertColumn(parentElement.tableName(),columnName);
00249     cols.push_back( columnName );
00250   }
00251   me.setColumnNames( cols );
00252 }
00253 
00254 ora::UniqueReferenceMapping::UniqueReferenceMapping( const Reflex::Type& attributeType, TableRegister& tableRegister ):
00255   m_type(attributeType),m_tableRegister( tableRegister ){
00256 }
00257 
00258 ora::UniqueReferenceMapping::~UniqueReferenceMapping(){
00259 }
00260 
00261 void ora::UniqueReferenceMapping::process( MappingElement& parentElement,
00262                                            const std::string& attributeName,
00263                                            const std::string& attributeNameForSchema,
00264                                            const std::string& scopeNameForSchema ){
00265     
00266   std::string typeName = m_type.Name(Reflex::SCOPED);
00267   if(!m_tableRegister.checkTable( parentElement.tableName())){
00268     throwException("Table \""+parentElement.tableName()+"\" has not been allocated.",
00269                    "UniqueReferenceMapping::process");
00270   }
00271   ora::MappingElement& me = parentElement.appendSubElement( ora::MappingElement::uniqueReferenceMappingElementType(), attributeName, typeName, parentElement.tableName() );
00272 
00273   std::vector< std::string > cols;
00274   std::string inputCol = ora::MappingRules::columnNameForRefMetadata( attributeNameForSchema, scopeNameForSchema );
00275   std::string columnName(inputCol);
00276   unsigned int i=0;
00277   while(m_tableRegister.checkColumn(parentElement.tableName(),columnName)){
00278     columnName = ora::MappingRules::newNameForSchemaObject( inputCol, i, ora::MappingRules::MaxColumnNameLength );
00279     i++;
00280   }
00281   m_tableRegister.insertColumn(parentElement.tableName(),columnName);
00282   cols.push_back(columnName);
00283 
00284   std::string idCol = ora::MappingRules::columnNameForRefId( attributeNameForSchema, scopeNameForSchema);
00285   columnName = idCol;
00286   i=0;
00287   while(m_tableRegister.checkColumn(parentElement.tableName(),columnName)){
00288     columnName = ora::MappingRules::newNameForSchemaObject( inputCol, i, ora::MappingRules::MaxColumnNameLength );
00289     i++;
00290   }
00291   m_tableRegister.insertColumn(parentElement.tableName(),columnName);
00292   cols.push_back(columnName);
00293 
00294   me.setColumnNames( cols );
00295 }
00296 
00297 ora::OraPtrMapping::OraPtrMapping( const Reflex::Type& attributeType, TableRegister& tableRegister ):
00298   m_type(attributeType), m_tableRegister( tableRegister ){
00299 }
00300 
00301 ora::OraPtrMapping::~OraPtrMapping(){
00302 }
00303 
00304 void ora::OraPtrMapping::process( MappingElement& parentElement,
00305                                   const std::string& attributeName,
00306                                   const std::string& attributeNameForSchema,
00307                                   const std::string& scopeNameForSchema ){
00308   
00309   std::string typeName = m_type.Name(Reflex::SCOPED);
00310   ora::MappingElement& me = parentElement.appendSubElement( ora::MappingElement::OraPointerMappingElementType(), attributeName, typeName, parentElement.tableName() );
00311   me.setColumnNames( parentElement.columnNames() );
00312 
00313   Reflex::Type ptrType = m_type.TemplateArgumentAt(0);
00314   std::string ptrTypeName = ptrType.Name();
00315 
00316   RelationalMappingFactory factory( m_tableRegister );
00317   std::auto_ptr<IRelationalMapping> processor( factory.newProcessor( ptrType ) );
00318   processor->process( me, ptrTypeName, attributeNameForSchema, scopeNameForSchema );
00319 }
00320 
00321 ora::NamedRefMapping::NamedRefMapping( const Reflex::Type& attributeType, TableRegister& tableRegister ):
00322   m_type( attributeType ),
00323   m_tableRegister( tableRegister ){
00324 }
00325 
00326 ora::NamedRefMapping::~NamedRefMapping(){
00327 }
00328 
00329 void ora::NamedRefMapping::process( MappingElement& parentElement, 
00330                                     const std::string& attributeName,
00331                                     const std::string& attributeNameForSchema, 
00332                                     const std::string& scopeNameForSchema ){
00333   std::string typeName = m_type.Name(Reflex::SCOPED);
00334   ora::MappingElement& me = parentElement.appendSubElement( ora::MappingElement::namedReferenceMappingElementType(), attributeName, typeName, parentElement.tableName() );
00335 
00336   std::vector< std::string > cols;
00337   std::string inputCol = ora::MappingRules::columnNameForNamedReference( attributeNameForSchema, scopeNameForSchema );
00338   std::string columnName(inputCol);
00339   unsigned int i=0;
00340   while(m_tableRegister.checkColumn(parentElement.tableName(),columnName)){
00341     columnName = ora::MappingRules::newNameForSchemaObject( inputCol, i, ora::MappingRules::MaxColumnNameLength );
00342     i++;
00343   }
00344   m_tableRegister.insertColumn(parentElement.tableName(),columnName);
00345   cols.push_back(columnName);
00346 
00347   me.setColumnNames( cols );
00348   
00349 }
00350 
00351 ora::ArrayMapping::ArrayMapping( const Reflex::Type& attributeType, TableRegister& tableRegister ):
00352   m_type(attributeType), m_tableRegister( tableRegister ){
00353 }
00354 
00355 ora::ArrayMapping::~ArrayMapping(){
00356 }
00357 
00358 void ora::ArrayMapping::process( MappingElement& parentElement,
00359                                  const std::string& attributeName,
00360                                  const std::string& attributeNameForSchema,
00361                                  const std::string& scopeNameForSchema ){
00362   std::string tableName = parentElement.tableName();
00363   std::string initialTable(tableName);
00364 
00365   std::string arrayTable(initialTable);
00366   unsigned int i=0;
00367   while(m_tableRegister.checkTable(arrayTable)){
00368     arrayTable = ora::MappingRules::newNameForArraySchemaObject( initialTable, i, ora::MappingRules::MaxTableNameLength );
00369     i++;
00370   }
00371   m_tableRegister.insertTable(arrayTable);
00372 
00373   std::string className = m_type.Name(Reflex::SCOPED);
00374 
00375   std::string elementType = ora::MappingElement::arrayMappingElementType();
00376   if(ora::ClassUtils::isTypePVector(m_type) || ora::ClassUtils::isTypeQueryableVector(m_type)){
00377     elementType = ora::MappingElement::OraArrayMappingElementType();
00378   }
00379   ora::MappingElement& me = parentElement.appendSubElement( elementType,attributeName,className,arrayTable );
00380   const std::vector<std::string>& parentColumns = parentElement.columnNames();
00381   if( parentColumns.empty()){
00382     throwException( "No column name found in the parent mapping element.","ArrayMapping::process");
00383   }
00384   
00385   std::vector<std::string> columns;
00386   // always comes the oid first
00387   columns.push_back( ora::MappingRules::columnNameForId() );
00388   std::vector<std::string>::const_iterator iColumn = parentColumns.begin();
00389   // then copy the columns except the id...
00390   iColumn++;
00391   for ( ;iColumn != parentColumns.end(); iColumn++ ) {
00392     columns.push_back( ora::MappingRules::columnNameForId() + "_" + *iColumn );
00393   }
00394   // and finally add the position!
00395   columns.push_back( ora::MappingRules::columnNameForPosition() );
00396   
00397   me.setColumnNames( columns );
00398   m_tableRegister.insertColumns(arrayTable, columns );
00399 
00400   std::string arrayScopeNameForSchema = scopeNameForSchema;
00401   if( !arrayScopeNameForSchema.empty() ) arrayScopeNameForSchema +="_";
00402   arrayScopeNameForSchema += attributeNameForSchema;
00403 
00404   
00405   bool singleItemContainer =  ora::ClassUtils::isTypeNonAssociativeContainer(m_type);
00406   bool associativeContainer =  ora::ClassUtils::isTypeAssociativeContainer(m_type);
00407 
00408   Reflex::Type contentType;
00409   Reflex::Type keyType;
00410   
00411   if( singleItemContainer ){
00412     contentType = ClassUtils::containerValueType(m_type);
00413   }
00414   else if ( associativeContainer ) { // This is an associative container type
00415     contentType = ClassUtils::containerDataType( m_type );
00416     keyType = ClassUtils::containerKeyType( m_type );
00417     if( !keyType || !ClassUtils::resolvedType(keyType) ){
00418       throwException( "Cannot not resolve the type of the key item of container \""+m_type.Name(Reflex::SCOPED)+"\".",
00419                       "ArrayMapping::process");
00420     }
00421   }
00422   else {
00423     // Not supported container
00424       throwException( "Container type=\""+m_type.Name(Reflex::SCOPED)+"\".is not supported.",
00425                       "ArrayMapping::process");    
00426   }
00427 
00428   if( !contentType || !ClassUtils::resolvedType(contentType) ){
00429       throwException( "Cannot not resolve the type of the content item of container \""+m_type.Name(Reflex::SCOPED)+"\".",
00430                       "ArrayMapping::process");
00431   }
00432   RelationalMappingFactory mappingFactory( m_tableRegister );
00433   if ( keyType ) {
00434     std::string keyTypeName = keyType.Name();
00435     std::string keyTypeNameForSchema = MappingRules::variableNameForContainerKey();
00436     std::auto_ptr<IRelationalMapping> keyProcessor( mappingFactory.newProcessor( keyType ) );
00437     keyProcessor->process( me, keyTypeName, keyTypeNameForSchema, arrayScopeNameForSchema  );
00438   }
00439   std::string contentTypeName = contentType.Name();
00440   std::string contentTypeNameForSchema = MappingRules::variableNameForContainerValue();
00441   std::auto_ptr<IRelationalMapping> contentProcessor( mappingFactory.newProcessor( contentType ) );
00442   contentProcessor->process( me, contentTypeName, contentTypeNameForSchema, arrayScopeNameForSchema );
00443 }
00444 
00445 ora::CArrayMapping::CArrayMapping( const Reflex::Type& attributeType, TableRegister& tableRegister ):
00446   m_type(attributeType), m_tableRegister( tableRegister ){
00447 }
00448 
00449 ora::CArrayMapping::~CArrayMapping(){
00450 }
00451 
00452 void ora::CArrayMapping::process( MappingElement& parentElement,
00453                                   const std::string& attributeName,
00454                                   const std::string& attributeNameForSchema,
00455                                   const std::string& scopeNameForSchema ){
00456   Reflex::Type arrayElementType = m_type.ToType();
00457   if( !arrayElementType || !ClassUtils::resolvedType( arrayElementType ) ){
00458     throwException("Cannot resolve the type of the content of the array \""+m_type.Name(Reflex::SCOPED)+"\".",
00459                    "CArrayMapping::process");
00460   }
00461 
00462   if(!m_tableRegister.checkTable(parentElement.tableName())){
00463     throwException("Table \""+parentElement.tableName()+"\" has not been allocated.",
00464                    "CArrayMapping::process");
00465   }
00466   std::string className = m_type.Name(Reflex::SCOPED);
00467   RelationalMappingFactory mappingFactory( m_tableRegister );
00468 
00469   std::string arrayScopeNameForSchema = scopeNameForSchema;
00470   if( !arrayScopeNameForSchema.empty() ) arrayScopeNameForSchema +="_";
00471   arrayScopeNameForSchema += attributeNameForSchema;
00472 
00473   std::pair<bool,size_t> arraySizeInColumns = RelationalMapping::sizeInColumnsForCArray( m_type );
00474   if( !arraySizeInColumns.first && arraySizeInColumns.second < MappingRules::MaxColumnsForInlineCArray ) {
00475     size_t columnsInTable = m_tableRegister.numberOfColumns(parentElement.tableName()) + arraySizeInColumns.second;
00476     if( columnsInTable < MappingRules::MaxColumnsPerTable ){
00477       // Inline C-Array
00478       std::string mappingElementType = ora::MappingElement::inlineCArrayMappingElementType();
00479       ora::MappingElement& me = parentElement.appendSubElement( mappingElementType, attributeName, className, parentElement.tableName() );
00480       me.setColumnNames( parentElement.columnNames() );
00481       std::auto_ptr<IRelationalMapping> processor( mappingFactory.newProcessor( arrayElementType ) );
00482       for(size_t i=0;i<m_type.ArrayLength();i++){
00483         processor->process( me, MappingRules::variableNameForArrayIndex(attributeName,i), 
00484                             MappingRules::variableNameForArrayColumn(i), arrayScopeNameForSchema );
00485       }
00486       return;
00487     }
00488   }
00490   std::string tableName = parentElement.tableName();
00491   std::string initialTable(tableName);
00492 
00493   std::string arrayTable(initialTable);
00494   unsigned int i=0;
00495   while(m_tableRegister.checkTable(arrayTable)){
00496     arrayTable = ora::MappingRules::newNameForArraySchemaObject( initialTable, i, ora::MappingRules::MaxTableNameLength );
00497     i++;
00498   }
00499   m_tableRegister.insertTable(arrayTable);
00500   ora::MappingElement& me = parentElement.appendSubElement( ora::MappingElement::CArrayMappingElementType(),
00501                                                             attributeName, className, arrayTable );
00502   const std::vector<std::string>& parentColumns = parentElement.columnNames();
00503   if( parentColumns.empty()){
00504     throwException( "No column name found in the parent mapping element.","CArrayMapping::process");
00505   }
00506   std::vector<std::string> columns;
00507   // always comes the oid first
00508   columns.push_back( ora::MappingRules::columnNameForId() );
00509   std::vector<std::string>::const_iterator iColumn = parentColumns.begin();
00510   // then copy the columns except the id...
00511   iColumn++;
00512   for ( ;iColumn != parentColumns.end(); ++iColumn ) {
00513     columns.push_back( ora::MappingRules::columnNameForId() + "_" + *iColumn );
00514   }
00515   // and finally add the position!
00516   columns.push_back( ora::MappingRules::columnNameForPosition() );
00517   me.setColumnNames( columns );
00518   m_tableRegister.insertColumns(arrayTable, columns );
00519 
00520   std::string contentTypeName = arrayElementType.Name();
00521   std::string variableNameForSchema = MappingRules::variableNameForArrayColumn( m_type  );
00522   std::auto_ptr<IRelationalMapping> processor( mappingFactory.newProcessor( arrayElementType ) );
00523   processor->process( me, contentTypeName, variableNameForSchema, arrayScopeNameForSchema );
00524 }
00525 
00526 ora::ObjectMapping::ObjectMapping( const Reflex::Type& attributeType, TableRegister& tableRegister ):
00527   m_type(attributeType), m_tableRegister( tableRegister ){
00528 }
00529 
00530 ora::ObjectMapping::~ObjectMapping(){
00531 }
00532 
00533 namespace ora {
00534 
00535   bool isLoosePersistencyOnWriting( const Reflex::Member& dataMember ){
00536     std::string persistencyType("");
00537     Reflex::PropertyList memberProps = dataMember.Properties();
00538     if( memberProps.HasProperty(ora::MappingRules::persistencyPropertyNameInDictionary())){
00539        persistencyType = memberProps.PropertyAsString(ora::MappingRules::persistencyPropertyNameInDictionary());
00540     }
00541     return ora::MappingRules::isLooseOnWriting( persistencyType );
00542   }
00543   
00544   void processBaseClasses( MappingElement& mappingElement,
00545                            const Reflex::Type& objType,
00546                            const std::string& scopeNameForSchema,
00547                            TableRegister& tableRegister ){
00548     std::string className = objType.Name(Reflex::SCOPED);
00549     for ( size_t i=0; i< objType.BaseSize(); i++){
00550       Reflex::Base base = objType.BaseAt(i);
00551       Reflex::Type baseType = ClassUtils::resolvedType( base.ToType() );
00552       if(!baseType){
00553         throwException( "Class for base \""+base.Name()+"\" is not in the dictionary.","ObjectMapping::process");
00554       }
00555 
00556       // TO BE FIXED:: here there is still to fix the right scopeName to pass 
00557       processBaseClasses( mappingElement, baseType, scopeNameForSchema, tableRegister );
00558       for ( size_t j=0; j< baseType.DataMemberSize(); j++){
00559         Reflex::Member baseMember = baseType.DataMemberAt(j);
00560         // Skip the transient and the static ones
00561         if ( baseMember.IsTransient() || baseMember.IsStatic() || isLoosePersistencyOnWriting( baseMember ) ) continue;
00562         // Retrieve the data member type
00563         Reflex::Type type = ClassUtils::resolvedType( baseMember.TypeOf() );
00564         Reflex::Type declaringType = ClassUtils::resolvedType( baseMember.DeclaringType());
00565         std::string scope = declaringType.Name(Reflex::SCOPED);
00566         // Retrieve the field name
00567         std::string objectMemberName = ora::MappingRules::scopedVariableName( baseMember.Name(), scope );
00568         std::string objectMemberNameForSchema = ora::MappingRules::scopedVariableForSchemaObjects( baseMember.Name(), scope );
00569 
00570         std::string mappingType("");
00571         Reflex::PropertyList memberProps = baseMember.Properties();
00572         if( memberProps.HasProperty(ora::MappingRules::mappingPropertyNameInDictionary())){
00573           mappingType = memberProps.PropertyAsString(ora::MappingRules::mappingPropertyNameInDictionary());
00574         }
00575         bool blobStreaming = ora::MappingRules::isMappedToBlob( mappingType );
00576         
00577         RelationalMappingFactory mappingFactory( tableRegister );
00578         std::auto_ptr<IRelationalMapping> processor( mappingFactory.newProcessor( type, blobStreaming ) );
00579         processor->process( mappingElement, objectMemberName, objectMemberNameForSchema, scopeNameForSchema );
00580       }
00581     }
00582   }
00583 }
00584 
00585 void ora::ObjectMapping::process( MappingElement& parentElement,
00586                                   const std::string& attributeName,
00587                                   const std::string& attributeNameForSchema,
00588                                   const std::string& scopeNameForSchema ){
00589   std::string className = m_type.Name(Reflex::SCOPED);
00590   std::string elementType = ora::MappingElement::objectMappingElementType();
00591   ora::MappingElement& me = parentElement.appendSubElement( elementType, attributeName, className, parentElement.tableName() );
00592   me.setColumnNames( parentElement.columnNames() );
00593 
00594   // resolve possible typedef chains
00595   Reflex::Type objectType = ClassUtils::resolvedType(m_type);
00596   // process base class data members
00597   processBaseClasses( me, m_type, scopeNameForSchema, m_tableRegister );
00598   RelationalMappingFactory mappingFactory( m_tableRegister );
00599   std::string scope = attributeName;
00600   std::string objectScopeNameForSchema = scopeNameForSchema;
00601   if( !objectScopeNameForSchema.empty() ) objectScopeNameForSchema +="_";
00602   objectScopeNameForSchema += attributeNameForSchema;
00603 
00604   // loop over the data members 
00605   for ( size_t i=0; i< objectType.DataMemberSize(); i++){
00606 
00607     Reflex::Member objectMember = m_type.DataMemberAt(i);
00608     // Skip the transient and the static ones
00609     if ( objectMember.IsTransient() || objectMember.IsStatic() || isLoosePersistencyOnWriting( objectMember )) continue;
00610 
00611     // Retrieve the field type
00612     Reflex::Type type = ClassUtils::resolvedType( objectMember.TypeOf() );
00613     // Check for the existence of the dictionary information
00614     if ( !type ){
00615       throwException( "Type for data member \""+objectMember.Name()+"\" of class \""+className+
00616                       "\" has not been found in the dictionary.",
00617                       "ObjectMapping::process");
00618     }
00619     
00620     // check if the member is from a class in the inheritance tree
00621     Reflex::Type declaringType = ClassUtils::resolvedType( objectMember.DeclaringType());
00622     if( declaringType != objectType ){
00623       continue;
00624     }
00625     // Retrieve the field name
00626     std::string objectMemberName = objectMember.Name();
00627     std::string objectNameForSchema = objectMember.Name();
00628     
00629     std::string mappingType("");
00630     Reflex::PropertyList memberProps = objectMember.Properties();
00631     if( memberProps.HasProperty(ora::MappingRules::mappingPropertyNameInDictionary())){
00632       mappingType = memberProps.PropertyAsString(ora::MappingRules::mappingPropertyNameInDictionary());
00633     }
00634     bool blobStreaming = ora::MappingRules::isMappedToBlob( mappingType );
00635 
00636     std::auto_ptr<IRelationalMapping> processor( mappingFactory.newProcessor( type, blobStreaming ) );
00637     processor->process( me, objectMemberName, objectNameForSchema, objectScopeNameForSchema  );
00638   }
00639   
00640 }
00641 
00642 ora::EmptyMapping::EmptyMapping(){
00643 }
00644 
00645 ora::EmptyMapping::~EmptyMapping(){
00646 }
00647 
00648 void ora::EmptyMapping::process( MappingElement&,
00649                                  const std::string&,
00650                                  const std::string&,
00651                                  const std::string& ){
00652 }