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 std::vector<std::string> cols;
00162 cols.push_back( columnName );
00163
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
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
00387 columns.push_back( ora::MappingRules::columnNameForId() );
00388 std::vector<std::string>::const_iterator iColumn = parentColumns.begin();
00389
00390 iColumn++;
00391 for ( ;iColumn != parentColumns.end(); iColumn++ ) {
00392 columns.push_back( ora::MappingRules::columnNameForId() + "_" + *iColumn );
00393 }
00394
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 ) {
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
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
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
00508 columns.push_back( ora::MappingRules::columnNameForId() );
00509 std::vector<std::string>::const_iterator iColumn = parentColumns.begin();
00510
00511 iColumn++;
00512 for ( ;iColumn != parentColumns.end(); ++iColumn ) {
00513 columns.push_back( ora::MappingRules::columnNameForId() + "_" + *iColumn );
00514 }
00515
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
00557 processBaseClasses( mappingElement, baseType, scopeNameForSchema, tableRegister );
00558 for ( size_t j=0; j< baseType.DataMemberSize(); j++){
00559 Reflex::Member baseMember = baseType.DataMemberAt(j);
00560
00561 if ( baseMember.IsTransient() || baseMember.IsStatic() || isLoosePersistencyOnWriting( baseMember ) ) continue;
00562
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
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
00595 Reflex::Type objectType = ClassUtils::resolvedType(m_type);
00596
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
00605 for ( size_t i=0; i< objectType.DataMemberSize(); i++){
00606
00607 Reflex::Member objectMember = m_type.DataMemberAt(i);
00608
00609 if ( objectMember.IsTransient() || objectMember.IsStatic() || isLoosePersistencyOnWriting( objectMember )) continue;
00610
00611
00612 Reflex::Type type = ClassUtils::resolvedType( objectMember.TypeOf() );
00613
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
00621 Reflex::Type declaringType = ClassUtils::resolvedType( objectMember.DeclaringType());
00622 if( declaringType != objectType ){
00623 continue;
00624 }
00625
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 }