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
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
00035 Reflex::Type typ = ClassUtils::resolvedType( topLevelClassType );
00036 bool isOraPolyPointer = ora::ClassUtils::isTypeUniqueReference(typ);
00037 bool isPrimitive = ora::ClassUtils::isTypePrimitive( typ );
00038
00039
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
00058 typ.UpdateMembers();
00059
00060 for ( size_t i=0; i< typ.DataMemberSize(); i++){
00061 Reflex::Member objMember = typ.DataMemberAt(i);
00062
00063
00064 if ( objMember.IsTransient() ) continue;
00065
00066
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
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 {
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
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
00379 columns.push_back( ora::MappingRules::columnNameForId() );
00380 std::vector<std::string>::const_iterator iColumn = parentColumns.begin();
00381
00382 iColumn++;
00383 for ( ;iColumn != parentColumns.end(); iColumn++ ) {
00384 columns.push_back( ora::MappingRules::columnNameForId() + "_" + *iColumn );
00385 }
00386
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 ) {
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
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
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
00500 columns.push_back( ora::MappingRules::columnNameForId() );
00501 std::vector<std::string>::const_iterator iColumn = parentColumns.begin();
00502
00503 iColumn++;
00504 for ( ;iColumn != parentColumns.end(); ++iColumn ) {
00505 columns.push_back( ora::MappingRules::columnNameForId() + "_" + *iColumn );
00506 }
00507
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
00549 processBaseClasses( mappingElement, baseType, scopeNameForSchema, tableRegister );
00550 for ( size_t j=0; j< baseType.DataMemberSize(); j++){
00551 Reflex::Member baseMember = baseType.DataMemberAt(j);
00552
00553 if ( baseMember.IsTransient() || baseMember.IsStatic() || isLoosePersistencyOnWriting( baseMember ) ) continue;
00554
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
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
00587 Reflex::Type objectType = ClassUtils::resolvedType(m_type);
00588
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
00597 for ( size_t i=0; i< objectType.DataMemberSize(); i++){
00598
00599 Reflex::Member objectMember = m_type.DataMemberAt(i);
00600
00601 if ( objectMember.IsTransient() || objectMember.IsStatic() || isLoosePersistencyOnWriting( objectMember )) continue;
00602
00603
00604 Reflex::Type type = ClassUtils::resolvedType( objectMember.TypeOf() );
00605
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
00613 Reflex::Type declaringType = ClassUtils::resolvedType( objectMember.DeclaringType());
00614 if( declaringType != objectType ){
00615 continue;
00616 }
00617
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 }