CMS 3D CMS Logo

CMSSW_4_4_3_patch1/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     me.setColumnNames( std::vector< std::string >( 1, columnName ) );
00162   }
00163 }
00164 
00165 ora::PrimitiveMapping::PrimitiveMapping( const Reflex::Type& attributeType, TableRegister& tableRegister ):
00166   m_type(attributeType),m_tableRegister( tableRegister ){
00167 }
00168 
00169 ora::PrimitiveMapping::~PrimitiveMapping(){
00170 }
00171 
00172 void ora::PrimitiveMapping::process( MappingElement& parentElement,
00173                                      const std::string& attributeName,
00174                                      const std::string& attributeNameForSchema,
00175                                      const std::string& scopeNameForSchema ){
00176   Reflex::Type t = ClassUtils::resolvedType( m_type );
00177   const std::type_info* attrType = &t.TypeInfo();
00178   if(t.IsEnum()) attrType = &typeid(int);
00179   //std::string tn = ClassUtils::demangledName(*attrType);
00180   if(ClassUtils::isTypeString( t )) attrType = &typeid(std::string);
00181   std::string typeName = coral::AttributeSpecification::typeNameForId(*attrType);
00182   
00183   processLeafElement(parentElement,
00184                      ora::MappingElement::primitiveMappingElementType(),
00185                      typeName,
00186                      attributeName,
00187                      attributeNameForSchema,
00188                      scopeNameForSchema,
00189                      m_tableRegister);  
00190 }
00191 
00192 ora::BlobMapping::BlobMapping( const Reflex::Type& attributeType, TableRegister& tableRegister ):
00193   m_type(attributeType),m_tableRegister( tableRegister ){
00194 }
00195 
00196 ora::BlobMapping::~BlobMapping(){
00197 }
00198 void ora::BlobMapping::process( MappingElement& parentElement,
00199                                 const std::string& attributeName,
00200                                 const std::string& attributeNameForSchema,
00201                                 const std::string& scopeNameForSchema ){
00202   std::string className = m_type.Name(Reflex::SCOPED);
00203   processLeafElement(parentElement,
00204                      ora::MappingElement::blobMappingElementType(),
00205                      className,
00206                      attributeName,
00207                      attributeNameForSchema,
00208                      scopeNameForSchema,
00209                      m_tableRegister);
00210 }
00211 
00212 ora::OraReferenceMapping::OraReferenceMapping( const Reflex::Type& attributeType, TableRegister& tableRegister ):
00213   m_type(attributeType),m_tableRegister( tableRegister ){
00214 }
00215 
00216 ora::OraReferenceMapping::~OraReferenceMapping(){
00217 }
00218 
00219 void ora::OraReferenceMapping::process( MappingElement& parentElement,
00220                                         const std::string& attributeName,
00221                                         const std::string& attributeNameForSchema,
00222                                         const std::string& scopeNameForSchema ){
00223   std::string className = m_type.Name(Reflex::SCOPED);
00224   std::string elementType = ora::MappingElement::OraReferenceMappingElementType();
00225   if(!m_tableRegister.checkTable( parentElement.tableName())){
00226     throwException("Table \""+parentElement.tableName()+"\" has not been allocated.",
00227                    "OraReferenceMapping::process");
00228   }
00229   ora::MappingElement& me = parentElement.appendSubElement( elementType, attributeName, className, parentElement.tableName() );
00230 
00231   std::vector<std::string> cols;
00232   for(unsigned int j=0;j<2;j++){
00233     std::string inputCol = ora::MappingRules::columnNameForOID( attributeNameForSchema, scopeNameForSchema, j );
00234     std::string columnName(inputCol);
00235     unsigned int i=0;
00236     while(m_tableRegister.checkColumn(parentElement.tableName(),columnName)){
00237       columnName = ora::MappingRules::newNameForSchemaObject( inputCol, i, ora::MappingRules::MaxColumnNameLength );
00238       i++;
00239     }
00240     m_tableRegister.insertColumn(parentElement.tableName(),columnName);
00241     cols.push_back( columnName );
00242   }
00243   me.setColumnNames( cols );
00244 }
00245 
00246 ora::UniqueReferenceMapping::UniqueReferenceMapping( const Reflex::Type& attributeType, TableRegister& tableRegister ):
00247   m_type(attributeType),m_tableRegister( tableRegister ){
00248 }
00249 
00250 ora::UniqueReferenceMapping::~UniqueReferenceMapping(){
00251 }
00252 
00253 void ora::UniqueReferenceMapping::process( MappingElement& parentElement,
00254                                            const std::string& attributeName,
00255                                            const std::string& attributeNameForSchema,
00256                                            const std::string& scopeNameForSchema ){
00257     
00258   std::string typeName = m_type.Name(Reflex::SCOPED);
00259   if(!m_tableRegister.checkTable( parentElement.tableName())){
00260     throwException("Table \""+parentElement.tableName()+"\" has not been allocated.",
00261                    "UniqueReferenceMapping::process");
00262   }
00263   ora::MappingElement& me = parentElement.appendSubElement( ora::MappingElement::uniqueReferenceMappingElementType(), attributeName, typeName, parentElement.tableName() );
00264 
00265   std::vector< std::string > cols;
00266   std::string inputCol = ora::MappingRules::columnNameForRefMetadata( attributeNameForSchema, scopeNameForSchema );
00267   std::string columnName(inputCol);
00268   unsigned int i=0;
00269   while(m_tableRegister.checkColumn(parentElement.tableName(),columnName)){
00270     columnName = ora::MappingRules::newNameForSchemaObject( inputCol, i, ora::MappingRules::MaxColumnNameLength );
00271     i++;
00272   }
00273   m_tableRegister.insertColumn(parentElement.tableName(),columnName);
00274   cols.push_back(columnName);
00275 
00276   std::string idCol = ora::MappingRules::columnNameForRefId( attributeNameForSchema, scopeNameForSchema);
00277   columnName = idCol;
00278   i=0;
00279   while(m_tableRegister.checkColumn(parentElement.tableName(),columnName)){
00280     columnName = ora::MappingRules::newNameForSchemaObject( inputCol, i, ora::MappingRules::MaxColumnNameLength );
00281     i++;
00282   }
00283   m_tableRegister.insertColumn(parentElement.tableName(),columnName);
00284   cols.push_back(columnName);
00285 
00286   me.setColumnNames( cols );
00287 }
00288 
00289 ora::OraPtrMapping::OraPtrMapping( const Reflex::Type& attributeType, TableRegister& tableRegister ):
00290   m_type(attributeType), m_tableRegister( tableRegister ){
00291 }
00292 
00293 ora::OraPtrMapping::~OraPtrMapping(){
00294 }
00295 
00296 void ora::OraPtrMapping::process( MappingElement& parentElement,
00297                                   const std::string& attributeName,
00298                                   const std::string& attributeNameForSchema,
00299                                   const std::string& scopeNameForSchema ){
00300   
00301   std::string typeName = m_type.Name(Reflex::SCOPED);
00302   ora::MappingElement& me = parentElement.appendSubElement( ora::MappingElement::OraPointerMappingElementType(), attributeName, typeName, parentElement.tableName() );
00303   me.setColumnNames( parentElement.columnNames() );
00304 
00305   Reflex::Type ptrType = m_type.TemplateArgumentAt(0);
00306   std::string ptrTypeName = ptrType.Name();
00307 
00308   RelationalMappingFactory factory( m_tableRegister );
00309   std::auto_ptr<IRelationalMapping> processor( factory.newProcessor( ptrType ) );
00310   processor->process( me, ptrTypeName, attributeNameForSchema, scopeNameForSchema );
00311 }
00312 
00313 ora::NamedRefMapping::NamedRefMapping( const Reflex::Type& attributeType, TableRegister& tableRegister ):
00314   m_type( attributeType ),
00315   m_tableRegister( tableRegister ){
00316 }
00317 
00318 ora::NamedRefMapping::~NamedRefMapping(){
00319 }
00320 
00321 void ora::NamedRefMapping::process( MappingElement& parentElement, 
00322                                     const std::string& attributeName,
00323                                     const std::string& attributeNameForSchema, 
00324                                     const std::string& scopeNameForSchema ){
00325   std::string typeName = m_type.Name(Reflex::SCOPED);
00326   ora::MappingElement& me = parentElement.appendSubElement( ora::MappingElement::namedReferenceMappingElementType(), attributeName, typeName, parentElement.tableName() );
00327 
00328   std::vector< std::string > cols;
00329   std::string inputCol = ora::MappingRules::columnNameForNamedReference( attributeNameForSchema, scopeNameForSchema );
00330   std::string columnName(inputCol);
00331   unsigned int i=0;
00332   while(m_tableRegister.checkColumn(parentElement.tableName(),columnName)){
00333     columnName = ora::MappingRules::newNameForSchemaObject( inputCol, i, ora::MappingRules::MaxColumnNameLength );
00334     i++;
00335   }
00336   m_tableRegister.insertColumn(parentElement.tableName(),columnName);
00337   cols.push_back(columnName);
00338 
00339   me.setColumnNames( cols );
00340   
00341 }
00342 
00343 ora::ArrayMapping::ArrayMapping( const Reflex::Type& attributeType, TableRegister& tableRegister ):
00344   m_type(attributeType), m_tableRegister( tableRegister ){
00345 }
00346 
00347 ora::ArrayMapping::~ArrayMapping(){
00348 }
00349 
00350 void ora::ArrayMapping::process( MappingElement& parentElement,
00351                                  const std::string& attributeName,
00352                                  const std::string& attributeNameForSchema,
00353                                  const std::string& scopeNameForSchema ){
00354   std::string tableName = parentElement.tableName();
00355   std::string initialTable(tableName);
00356 
00357   std::string arrayTable(initialTable);
00358   unsigned int i=0;
00359   while(m_tableRegister.checkTable(arrayTable)){
00360     arrayTable = ora::MappingRules::newNameForArraySchemaObject( initialTable, i, ora::MappingRules::MaxTableNameLength );
00361     i++;
00362   }
00363   m_tableRegister.insertTable(arrayTable);
00364 
00365   std::string className = m_type.Name(Reflex::SCOPED);
00366 
00367   std::string elementType = ora::MappingElement::arrayMappingElementType();
00368   if(ora::ClassUtils::isTypePVector(m_type) || ora::ClassUtils::isTypeQueryableVector(m_type)){
00369     elementType = ora::MappingElement::OraArrayMappingElementType();
00370   }
00371   ora::MappingElement& me = parentElement.appendSubElement( elementType,attributeName,className,arrayTable );
00372   const std::vector<std::string>& parentColumns = parentElement.columnNames();
00373   if( parentColumns.empty()){
00374     throwException( "No column name found in the parent mapping element.","ArrayMapping::process");
00375   }
00376   
00377   std::vector<std::string> columns;
00378   // always comes the oid first
00379   columns.push_back( ora::MappingRules::columnNameForId() );
00380   std::vector<std::string>::const_iterator iColumn = parentColumns.begin();
00381   // then copy the columns except the id...
00382   iColumn++;
00383   for ( ;iColumn != parentColumns.end(); iColumn++ ) {
00384     columns.push_back( ora::MappingRules::columnNameForId() + "_" + *iColumn );
00385   }
00386   // and finally add the position!
00387   columns.push_back( ora::MappingRules::columnNameForPosition() );
00388   
00389   me.setColumnNames( columns );
00390   m_tableRegister.insertColumns(arrayTable, columns );
00391 
00392   std::string arrayScopeNameForSchema = scopeNameForSchema;
00393   if( !arrayScopeNameForSchema.empty() ) arrayScopeNameForSchema +="_";
00394   arrayScopeNameForSchema += attributeNameForSchema;
00395 
00396   
00397   bool singleItemContainer =  ora::ClassUtils::isTypeNonAssociativeContainer(m_type);
00398   bool associativeContainer =  ora::ClassUtils::isTypeAssociativeContainer(m_type);
00399 
00400   Reflex::Type contentType;
00401   Reflex::Type keyType;
00402   
00403   if( singleItemContainer ){
00404     contentType = ClassUtils::containerValueType(m_type);
00405   }
00406   else if ( associativeContainer ) { // This is an associative container type
00407     contentType = ClassUtils::containerDataType( m_type );
00408     keyType = ClassUtils::containerKeyType( m_type );
00409     if( !keyType || !ClassUtils::resolvedType(keyType) ){
00410       throwException( "Cannot not resolve the type of the key item of container \""+m_type.Name(Reflex::SCOPED)+"\".",
00411                       "ArrayMapping::process");
00412     }
00413   }
00414   else {
00415     // Not supported container
00416       throwException( "Container type=\""+m_type.Name(Reflex::SCOPED)+"\".is not supported.",
00417                       "ArrayMapping::process");    
00418   }
00419 
00420   if( !contentType || !ClassUtils::resolvedType(contentType) ){
00421       throwException( "Cannot not resolve the type of the content item of container \""+m_type.Name(Reflex::SCOPED)+"\".",
00422                       "ArrayMapping::process");
00423   }
00424   RelationalMappingFactory mappingFactory( m_tableRegister );
00425   if ( keyType ) {
00426     std::string keyTypeName = keyType.Name();
00427     std::string keyTypeNameForSchema = MappingRules::variableNameForContainerKey();
00428     std::auto_ptr<IRelationalMapping> keyProcessor( mappingFactory.newProcessor( keyType ) );
00429     keyProcessor->process( me, keyTypeName, keyTypeNameForSchema, arrayScopeNameForSchema  );
00430   }
00431   std::string contentTypeName = contentType.Name();
00432   std::string contentTypeNameForSchema = MappingRules::variableNameForContainerValue();
00433   std::auto_ptr<IRelationalMapping> contentProcessor( mappingFactory.newProcessor( contentType ) );
00434   contentProcessor->process( me, contentTypeName, contentTypeNameForSchema, arrayScopeNameForSchema );
00435 }
00436 
00437 ora::CArrayMapping::CArrayMapping( const Reflex::Type& attributeType, TableRegister& tableRegister ):
00438   m_type(attributeType), m_tableRegister( tableRegister ){
00439 }
00440 
00441 ora::CArrayMapping::~CArrayMapping(){
00442 }
00443 
00444 void ora::CArrayMapping::process( MappingElement& parentElement,
00445                                   const std::string& attributeName,
00446                                   const std::string& attributeNameForSchema,
00447                                   const std::string& scopeNameForSchema ){
00448   Reflex::Type arrayElementType = m_type.ToType();
00449   if( !arrayElementType || !ClassUtils::resolvedType( arrayElementType ) ){
00450     throwException("Cannot resolve the type of the content of the array \""+m_type.Name(Reflex::SCOPED)+"\".",
00451                    "CArrayMapping::process");
00452   }
00453 
00454   if(!m_tableRegister.checkTable(parentElement.tableName())){
00455     throwException("Table \""+parentElement.tableName()+"\" has not been allocated.",
00456                    "CArrayMapping::process");
00457   }
00458   std::string className = m_type.Name(Reflex::SCOPED);
00459   RelationalMappingFactory mappingFactory( m_tableRegister );
00460 
00461   std::string arrayScopeNameForSchema = scopeNameForSchema;
00462   if( !arrayScopeNameForSchema.empty() ) arrayScopeNameForSchema +="_";
00463   arrayScopeNameForSchema += attributeNameForSchema;
00464 
00465   std::pair<bool,size_t> arraySizeInColumns = RelationalMapping::sizeInColumnsForCArray( m_type );
00466   if( !arraySizeInColumns.first && arraySizeInColumns.second < MappingRules::MaxColumnsForInlineCArray ) {
00467     size_t columnsInTable = m_tableRegister.numberOfColumns(parentElement.tableName()) + arraySizeInColumns.second;
00468     if( columnsInTable < MappingRules::MaxColumnsPerTable ){
00469       // Inline C-Array
00470       std::string mappingElementType = ora::MappingElement::inlineCArrayMappingElementType();
00471       ora::MappingElement& me = parentElement.appendSubElement( mappingElementType, attributeName, className, parentElement.tableName() );
00472       me.setColumnNames( parentElement.columnNames() );
00473       std::auto_ptr<IRelationalMapping> processor( mappingFactory.newProcessor( arrayElementType ) );
00474       for(size_t i=0;i<m_type.ArrayLength();i++){
00475         processor->process( me, MappingRules::variableNameForArrayIndex(attributeName,i), 
00476                             MappingRules::variableNameForArrayColumn(i), arrayScopeNameForSchema );
00477       }
00478       return;
00479     }
00480   }
00482   std::string tableName = parentElement.tableName();
00483   std::string initialTable(tableName);
00484 
00485   std::string arrayTable(initialTable);
00486   unsigned int i=0;
00487   while(m_tableRegister.checkTable(arrayTable)){
00488     arrayTable = ora::MappingRules::newNameForArraySchemaObject( initialTable, i, ora::MappingRules::MaxTableNameLength );
00489     i++;
00490   }
00491   m_tableRegister.insertTable(arrayTable);
00492   ora::MappingElement& me = parentElement.appendSubElement( ora::MappingElement::CArrayMappingElementType(),
00493                                                             attributeName, className, arrayTable );
00494   const std::vector<std::string>& parentColumns = parentElement.columnNames();
00495   if( parentColumns.empty()){
00496     throwException( "No column name found in the parent mapping element.","CArrayMapping::process");
00497   }
00498   std::vector<std::string> columns;
00499   // always comes the oid first
00500   columns.push_back( ora::MappingRules::columnNameForId() );
00501   std::vector<std::string>::const_iterator iColumn = parentColumns.begin();
00502   // then copy the columns except the id...
00503   iColumn++;
00504   for ( ;iColumn != parentColumns.end(); ++iColumn ) {
00505     columns.push_back( ora::MappingRules::columnNameForId() + "_" + *iColumn );
00506   }
00507   // and finally add the position!
00508   columns.push_back( ora::MappingRules::columnNameForPosition() );
00509   me.setColumnNames( columns );
00510   m_tableRegister.insertColumns(arrayTable, columns );
00511 
00512   std::string contentTypeName = arrayElementType.Name();
00513   std::string variableNameForSchema = MappingRules::variableNameForArrayColumn( m_type  );
00514   std::auto_ptr<IRelationalMapping> processor( mappingFactory.newProcessor( arrayElementType ) );
00515   processor->process( me, contentTypeName, variableNameForSchema, arrayScopeNameForSchema );
00516 }
00517 
00518 ora::ObjectMapping::ObjectMapping( const Reflex::Type& attributeType, TableRegister& tableRegister ):
00519   m_type(attributeType), m_tableRegister( tableRegister ){
00520 }
00521 
00522 ora::ObjectMapping::~ObjectMapping(){
00523 }
00524 
00525 namespace ora {
00526 
00527   bool isLoosePersistencyOnWriting( const Reflex::Member& dataMember ){
00528     std::string persistencyType("");
00529     Reflex::PropertyList memberProps = dataMember.Properties();
00530     if( memberProps.HasProperty(ora::MappingRules::persistencyPropertyNameInDictionary())){
00531        persistencyType = memberProps.PropertyAsString(ora::MappingRules::persistencyPropertyNameInDictionary());
00532     }
00533     return ora::MappingRules::isLooseOnWriting( persistencyType );
00534   }
00535   
00536   void processBaseClasses( MappingElement& mappingElement,
00537                            const Reflex::Type& objType,
00538                            const std::string& scopeNameForSchema,
00539                            TableRegister& tableRegister ){
00540     std::string className = objType.Name(Reflex::SCOPED);
00541     for ( size_t i=0; i< objType.BaseSize(); i++){
00542       Reflex::Base base = objType.BaseAt(i);
00543       Reflex::Type baseType = ClassUtils::resolvedType( base.ToType() );
00544       if(!baseType){
00545         throwException( "Class for base \""+base.Name()+"\" is not in the dictionary.","ObjectMapping::process");
00546       }
00547 
00548       // TO BE FIXED:: here there is still to fix the right scopeName to pass 
00549       processBaseClasses( mappingElement, baseType, scopeNameForSchema, tableRegister );
00550       for ( size_t j=0; j< baseType.DataMemberSize(); j++){
00551         Reflex::Member baseMember = baseType.DataMemberAt(j);
00552         // Skip the transient and the static ones
00553         if ( baseMember.IsTransient() || baseMember.IsStatic() || isLoosePersistencyOnWriting( baseMember ) ) continue;
00554         // Retrieve the data member type
00555         Reflex::Type type = ClassUtils::resolvedType( baseMember.TypeOf() );
00556         Reflex::Type declaringType = ClassUtils::resolvedType( baseMember.DeclaringType());
00557         std::string scope = declaringType.Name(Reflex::SCOPED);
00558         // Retrieve the field name
00559         std::string objectMemberName = ora::MappingRules::scopedVariableName( baseMember.Name(), scope );
00560         std::string objectMemberNameForSchema = ora::MappingRules::scopedVariableForSchemaObjects( baseMember.Name(), scope );
00561 
00562         std::string mappingType("");
00563         Reflex::PropertyList memberProps = baseMember.Properties();
00564         if( memberProps.HasProperty(ora::MappingRules::mappingPropertyNameInDictionary())){
00565           mappingType = memberProps.PropertyAsString(ora::MappingRules::mappingPropertyNameInDictionary());
00566         }
00567         bool blobStreaming = ora::MappingRules::isMappedToBlob( mappingType );
00568         
00569         RelationalMappingFactory mappingFactory( tableRegister );
00570         std::auto_ptr<IRelationalMapping> processor( mappingFactory.newProcessor( type, blobStreaming ) );
00571         processor->process( mappingElement, objectMemberName, objectMemberNameForSchema, scopeNameForSchema );
00572       }
00573     }
00574   }
00575 }
00576 
00577 void ora::ObjectMapping::process( MappingElement& parentElement,
00578                                   const std::string& attributeName,
00579                                   const std::string& attributeNameForSchema,
00580                                   const std::string& scopeNameForSchema ){
00581   std::string className = m_type.Name(Reflex::SCOPED);
00582   std::string elementType = ora::MappingElement::objectMappingElementType();
00583   ora::MappingElement& me = parentElement.appendSubElement( elementType, attributeName, className, parentElement.tableName() );
00584   me.setColumnNames( parentElement.columnNames() );
00585 
00586   // resolve possible typedef chains
00587   Reflex::Type objectType = ClassUtils::resolvedType(m_type);
00588   // process base class data members
00589   processBaseClasses( me, m_type, scopeNameForSchema, m_tableRegister );
00590   RelationalMappingFactory mappingFactory( m_tableRegister );
00591   std::string scope = attributeName;
00592   std::string objectScopeNameForSchema = scopeNameForSchema;
00593   if( !objectScopeNameForSchema.empty() ) objectScopeNameForSchema +="_";
00594   objectScopeNameForSchema += attributeNameForSchema;
00595 
00596   // loop over the data members 
00597   for ( size_t i=0; i< objectType.DataMemberSize(); i++){
00598 
00599     Reflex::Member objectMember = m_type.DataMemberAt(i);
00600     // Skip the transient and the static ones
00601     if ( objectMember.IsTransient() || objectMember.IsStatic() || isLoosePersistencyOnWriting( objectMember )) continue;
00602 
00603     // Retrieve the field type
00604     Reflex::Type type = ClassUtils::resolvedType( objectMember.TypeOf() );
00605     // Check for the existence of the dictionary information
00606     if ( !type ){
00607       throwException( "Type for data member \""+objectMember.Name()+"\" of class \""+className+
00608                       "\" has not been found in the dictionary.",
00609                       "ObjectMapping::process");
00610     }
00611     
00612     // check if the member is from a class in the inheritance tree
00613     Reflex::Type declaringType = ClassUtils::resolvedType( objectMember.DeclaringType());
00614     if( declaringType != objectType ){
00615       continue;
00616     }
00617     // Retrieve the field name
00618     std::string objectMemberName = objectMember.Name();
00619     std::string objectNameForSchema = objectMember.Name();
00620     
00621     std::string mappingType("");
00622     Reflex::PropertyList memberProps = objectMember.Properties();
00623     if( memberProps.HasProperty(ora::MappingRules::mappingPropertyNameInDictionary())){
00624       mappingType = memberProps.PropertyAsString(ora::MappingRules::mappingPropertyNameInDictionary());
00625     }
00626     bool blobStreaming = ora::MappingRules::isMappedToBlob( mappingType );
00627 
00628     std::auto_ptr<IRelationalMapping> processor( mappingFactory.newProcessor( type, blobStreaming ) );
00629     processor->process( me, objectMemberName, objectNameForSchema, objectScopeNameForSchema  );
00630   }
00631   
00632 }
00633 
00634 ora::EmptyMapping::EmptyMapping(){
00635 }
00636 
00637 ora::EmptyMapping::~EmptyMapping(){
00638 }
00639 
00640 void ora::EmptyMapping::process( MappingElement&,
00641                                  const std::string&,
00642                                  const std::string&,
00643                                  const std::string& ){
00644 }