00001 #include "CondCore/ORA/interface/Exception.h"
00002 #include "MappingDatabase.h"
00003 #include "IDatabaseSchema.h"
00004 #include "MappingTree.h"
00005 #include "MappingRules.h"
00006
00007 #include <sstream>
00008
00009 #include "Reflex/Type.h"
00010
00011 std::string
00012 ora::MappingDatabase::versionOfClass( const Reflex::Type& dictionary ){
00013 std::string className = dictionary.Name(Reflex::SCOPED);
00014 Reflex::PropertyList classProps = dictionary.Properties();
00015 std::string classVersion = MappingRules::defaultClassVersion(className);
00016 if(classProps.HasProperty(MappingRules::classVersionPropertyNameInDictionary())){
00017 classVersion = classProps.PropertyAsString(MappingRules::classVersionPropertyNameInDictionary());
00018 }
00019 return classVersion;
00020 }
00021
00022 void ora::MappingDatabase::buildElement( MappingElement& parentElement,
00023 const std::string& scopeName,
00024 std::map<std::string, std::vector<MappingRawElement> >& innerElements ){
00025 std::map<std::string,std::vector<MappingRawElement> >::iterator iScope = innerElements.find(scopeName);
00026 if(iScope != innerElements.end()){
00027 for( std::vector<MappingRawElement>::const_iterator iM = iScope->second.begin();
00028 iM != iScope->second.end(); ++iM ){
00029 MappingElement& element = parentElement.appendSubElement( iM->elementType,
00030 iM->variableName,
00031 iM->variableType,
00032 iM->tableName );
00033 element.setColumnNames(iM->columns);
00034 std::string nextScope(scopeName);
00035 nextScope.append("::").append(iM->variableName);
00036 buildElement( element, nextScope, innerElements );
00037 }
00038 }
00039 innerElements.erase(scopeName);
00040 }
00041
00042 void ora::MappingDatabase::unfoldElement( const MappingElement& element, MappingRawData& destination ){
00043 int newElemId = m_mappingSequence.getNextId();
00044 MappingRawElement& elem = destination.addElement( newElemId );
00045 elem.elementType = MappingElement::elementTypeAsString( element.elementType() );
00046 elem.scopeName = element.scopeName();
00047 if(elem.scopeName.empty()) elem.scopeName = MappingRawElement::emptyScope();
00048 elem.variableName = element.variableName();
00049 elem.variableType = element.variableType();
00050 elem.tableName = element.tableName();
00051 elem.columns = element.columnNames();
00052 for ( MappingElement::const_iterator iSubEl = element.begin();
00053 iSubEl != element.end(); ++iSubEl) {
00054 unfoldElement( iSubEl->second, destination );
00055 }
00056 }
00057
00058 ora::MappingDatabase::MappingDatabase( ora::IDatabaseSchema& schema ):
00059 m_schema( schema ),
00060 m_mappingSequence( MappingRules::sequenceNameForMapping(), schema ),
00061 m_versions(),
00062 m_isLoaded( false ){
00063 }
00064
00065
00066 ora::MappingDatabase::~MappingDatabase(){
00067 }
00068
00069 void ora::MappingDatabase::setUp(){
00070 m_mappingSequence.create();
00071 }
00072
00073 std::string
00074 ora::MappingDatabase::newMappingVersionForContainer( const std::string& containerName ){
00075 if(!m_isLoaded){
00076 m_schema.mappingSchema().getVersionList( m_versions );
00077 m_isLoaded = true;
00078 }
00079
00080 std::string newMappingVersion = "";
00081 for ( int iteration = 0;; ++iteration ) {
00082 newMappingVersion = MappingRules::newMappingVersionForContainer( containerName, iteration );
00083 bool found = false;
00084 for ( std::set<std::string>::reverse_iterator iVersion = m_versions.rbegin();
00085 iVersion != m_versions.rend(); ++iVersion ) {
00086 if ( *iVersion == newMappingVersion ) {
00087 found = true;
00088 break;
00089 }
00090 }
00091 if ( ! found ){
00092 m_versions.insert( newMappingVersion );
00093 break;
00094 }
00095
00096 }
00097 return newMappingVersion;
00098 }
00099
00100 std::string
00101 ora::MappingDatabase::newMappingVersionForDependentClass( const std::string& containerName, const std::string& className ){
00102 if(!m_isLoaded){
00103 m_schema.mappingSchema().getVersionList( m_versions );
00104 m_isLoaded = true;
00105 }
00106
00107 std::string newMappingVersion = "";
00108 for ( int iteration = 0;; ++iteration ) {
00109 newMappingVersion = MappingRules::newMappingVersionForDependentClass( containerName, className, iteration );
00110 bool found = false;
00111 for ( std::set<std::string>::reverse_iterator iVersion = m_versions.rbegin();
00112 iVersion != m_versions.rend(); ++iVersion ) {
00113 if ( *iVersion == newMappingVersion ) {
00114 found = true;
00115 break;
00116 }
00117 }
00118 if ( ! found ){
00119 m_versions.insert( newMappingVersion );
00120 break;
00121 }
00122
00123 }
00124 return newMappingVersion;
00125 }
00126
00127 bool ora::MappingDatabase::getMappingByVersion( const std::string& version, MappingTree& destination ){
00128 bool ret = false;
00129 MappingRawData mapData;
00130 if(m_schema.mappingSchema().getMapping( version, mapData )){
00131 ret = true;
00132 MappingRawElement topLevelElement;
00133 bool topLevelFound = false;
00134 bool dependency = false;
00135 std::map<std::string, std::vector<MappingRawElement> > innerElements;
00136 for( std::map< int, MappingRawElement>::iterator iElem = mapData.elements.begin();
00137 iElem != mapData.elements.end(); iElem++ ){
00138
00139 if( iElem->second.scopeName == MappingRawElement::emptyScope() ){
00140 if( iElem->second.elementType == MappingElement::classMappingElementType() ||
00141 iElem->second.elementType == MappingElement::dependencyMappingElementType() ){
00142 if( topLevelFound ){
00143 throwException("Mapping inconsistent.More then one top level element found.",
00144 "MappingDatabase::getMappingByVersion");
00145 }
00146 topLevelElement = iElem->second;
00147 if( topLevelElement.elementType == MappingElement::dependencyMappingElementType() ) dependency = true;
00148 topLevelFound = true;
00149 }
00150 } else {
00151 std::map<std::string, std::vector<MappingRawElement> >::iterator iN = innerElements.find( iElem->second.scopeName );
00152 if(iN==innerElements.end()){
00153 innerElements.insert( std::make_pair( iElem->second.scopeName, std::vector<MappingRawElement>(1,iElem->second) ) );
00154 } else {
00155 iN->second.push_back( iElem->second );
00156 }
00157 }
00158 }
00159 if( !topLevelFound ){
00160 throwException( "Could not find top element for mapping version \""+version+"\".",
00161 "MappingDatabase::getMappingByVersion" );
00162 }
00163 MappingElement& topElement = destination.setTopElement( topLevelElement.variableName,
00164 topLevelElement.tableName,
00165 dependency );
00166 topElement.setColumnNames( topLevelElement.columns);
00167 buildElement( topElement, topLevelElement.variableName, innerElements );
00168 destination.setVersion( version );
00169 }
00170 return ret;
00171 }
00172
00173 void ora::MappingDatabase::removeMapping( const std::string& version ){
00174 m_schema.mappingSchema().removeMapping( version );
00175 }
00176
00177 bool
00178 ora::MappingDatabase::getMappingForContainer( const Reflex::Type& containerClass,
00179 int containerId,
00180 MappingTree& destination ){
00181
00182 bool ret = false;
00183
00184 std::string className = containerClass.Name(Reflex::SCOPED);
00185 std::string classVersion = versionOfClass( containerClass );
00186 std::string classId = MappingRules::classId( className, classVersion );
00187
00188 std::string version("");
00189 bool found = m_schema.mappingSchema().selectMappingVersion( classId, containerId, version );
00190
00191 if( found ){
00192 ret = getMappingByVersion( version, destination );
00193 if( !ret ){
00194 throwException("Mapping version \""+version+"\" not found.",
00195 "MappingDatabase::getMappingForContainer");
00196 }
00197 if( destination.className() != className ){
00198 throwException("Mapping inconsistency detected for version=\""+version+"\"",
00199 "MappingDatabase::getMappingForContainer");
00200 }
00201 }
00202 return ret;
00203 }
00204
00205 bool ora::MappingDatabase::getBaseMappingForContainer( const std::string& className,
00206 int containerId,
00207 MappingTree& destination ){
00208 bool ret = false;
00209 std::string classId = MappingRules::baseIdForClass( className );
00210 std::string mappingVersion("");
00211 bool found = m_schema.mappingSchema().selectMappingVersion( classId, containerId, mappingVersion );
00212
00213 if( found ){
00214 ret = getMappingByVersion( mappingVersion, destination );
00215 if( !ret ){
00216 throwException("Mapping version \""+mappingVersion+"\" not found.",
00217 "MappingDatabase::getBaseMappingForContainer");
00218 }
00219 if( destination.className() != className ){
00220 throwException("Mapping inconsistency detected for version=\""+mappingVersion+"\"",
00221 "MappingDatabase::getBaseMappingForContainer");
00222 }
00223 }
00224 return ret;
00225 }
00226
00227 bool ora::MappingDatabase::getDependentMappingsForContainer( int containerId,
00228 std::vector<MappingElement>& destination ){
00229 bool ret = false;
00230 std::set<std::string> versions;
00231 if( m_schema.mappingSchema().getMappingVersionListForContainer( containerId, versions, true ) ){
00232 ret = true;
00233 for( std::set<std::string>::iterator iM = versions.begin();
00234 iM != versions.end(); ++iM ){
00235 MappingTree mapping;
00236 if( ! getMappingByVersion( *iM, mapping )){
00237 throwException("Mapping version \""+*iM+"\" not found.",
00238 "MappingDatabase::getDependentMappingsForContainer");
00239
00240 }
00241 destination.push_back( mapping.topElement() );
00242 }
00243 }
00244 return ret;
00245 }
00246
00247 bool ora::MappingDatabase::getClassVersionListForMappingVersion( const std::string& mappingVersion,
00248 std::set<std::string>& destination ){
00249 return m_schema.mappingSchema().getClassVersionListForMappingVersion( mappingVersion, destination );
00250 }
00251
00252 void ora::MappingDatabase::insertClassVersion( const std::string& className,
00253 const std::string& classVersion,
00254 int dependencyIndex,
00255 int containerId,
00256 const std::string& mappingVersion,
00257 bool asBase ){
00258 std::string classId = MappingRules::classId( className, classVersion );
00259 m_schema.mappingSchema().insertClassVersion( className, classVersion, classId, dependencyIndex, containerId, mappingVersion );
00260 if( asBase ){
00261 m_schema.mappingSchema().insertClassVersion( className, MappingRules::baseClassVersion(), MappingRules::baseIdForClass( className ), dependencyIndex, containerId, mappingVersion );
00262 }
00263 }
00264
00265 bool ora::MappingDatabase::getClassVersionListForContainer( int containerId,
00266 std::map<std::string,std::string>& versionMap ){
00267
00268 return m_schema.mappingSchema().getClassVersionListForContainer( containerId, versionMap );
00269 }
00270
00271 void ora::MappingDatabase::insertClassVersion( const Reflex::Type& dictionaryEntry,
00272 int depIndex,
00273 int containerId,
00274 const std::string& mappingVersion,
00275 bool asBase ){
00276 std::string className = dictionaryEntry.Name( Reflex::SCOPED );
00277 std::string classVersion = versionOfClass( dictionaryEntry );
00278 insertClassVersion( className, classVersion, depIndex, containerId, mappingVersion, asBase );
00279 }
00280
00281 void ora::MappingDatabase::setMappingVersionForClass( const Reflex::Type& dictionaryEntry,
00282 int containerId,
00283 const std::string& mappingVersion,
00284 bool dependency ){
00285 std::string className = dictionaryEntry.Name( Reflex::SCOPED );
00286 std::string classVersion = versionOfClass( dictionaryEntry );
00287 std::string classId = MappingRules::classId( className, classVersion );
00288 std::string mv("");
00289 bool found = m_schema.mappingSchema().selectMappingVersion( classId, containerId, mv );
00290 if( !found ){
00291 int depIndex = 0;
00292 if( dependency ) depIndex = 1;
00293 m_schema.mappingSchema().insertClassVersion( className, classVersion, classId, depIndex, containerId, mappingVersion );
00294 } else {
00295 m_schema.mappingSchema().setMappingVersion( classId, containerId, mappingVersion );
00296 }
00297 }
00298
00299 void ora::MappingDatabase::storeMapping( const MappingTree& mapping ){
00300 MappingRawData rowMapping( mapping.version() );
00301 unfoldElement( mapping.topElement(), rowMapping );
00302 m_mappingSequence.sinchronize();
00303 m_schema.mappingSchema().storeMapping( rowMapping );
00304 }
00305
00306 bool ora::MappingDatabase::getMappingVersionsForContainer( int containerId, std::set<std::string>& versionList ){
00307 return m_schema.mappingSchema().getMappingVersionListForContainer( containerId, versionList );
00308 }
00309
00310 const std::set<std::string>& ora::MappingDatabase::versions(){
00311 if(!m_isLoaded){
00312 m_schema.mappingSchema().getVersionList( m_versions );
00313 m_isLoaded = true;
00314 }
00315 return m_versions;
00316 }
00317
00318 bool ora::MappingDatabase::getDependentClassesForContainer( int containerId,
00319 std::set<std::string>& list ){
00320 return m_schema.mappingSchema().getDependentClassesInContainerMapping( containerId, list );
00321 }
00322
00323 void ora::MappingDatabase::clear(){
00324 m_versions.clear();
00325 m_isLoaded = false;
00326 }
00327