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 std::string
00070 ora::MappingDatabase::newMappingVersionForContainer( const std::string& containerName ){
00071 if(!m_isLoaded){
00072 m_schema.mappingSchema().getVersionList( m_versions );
00073 m_isLoaded = true;
00074 }
00075
00076 std::string newMappingVersion = "";
00077 for ( int iteration = 0;; ++iteration ) {
00078 newMappingVersion = MappingRules::newMappingVersionForContainer( containerName, iteration );
00079 bool found = false;
00080 for ( std::set<std::string>::reverse_iterator iVersion = m_versions.rbegin();
00081 iVersion != m_versions.rend(); ++iVersion ) {
00082 if ( *iVersion == newMappingVersion ) {
00083 found = true;
00084 break;
00085 }
00086 }
00087 if ( ! found ){
00088 m_versions.insert( newMappingVersion );
00089 break;
00090 }
00091
00092 }
00093 return newMappingVersion;
00094 }
00095
00096 std::string
00097 ora::MappingDatabase::newMappingVersionForDependentClass( const std::string& containerName, const std::string& className ){
00098 if(!m_isLoaded){
00099 m_schema.mappingSchema().getVersionList( m_versions );
00100 m_isLoaded = true;
00101 }
00102
00103 std::string newMappingVersion = "";
00104 for ( int iteration = 0;; ++iteration ) {
00105 newMappingVersion = MappingRules::newMappingVersionForDependentClass( containerName, className, iteration );
00106 bool found = false;
00107 for ( std::set<std::string>::reverse_iterator iVersion = m_versions.rbegin();
00108 iVersion != m_versions.rend(); ++iVersion ) {
00109 if ( *iVersion == newMappingVersion ) {
00110 found = true;
00111 break;
00112 }
00113 }
00114 if ( ! found ){
00115 m_versions.insert( newMappingVersion );
00116 break;
00117 }
00118
00119 }
00120 return newMappingVersion;
00121 }
00122
00123 bool ora::MappingDatabase::getMappingByVersion( const std::string& version, MappingTree& destination ){
00124 bool ret = false;
00125 MappingRawData mapData;
00126 if(m_schema.mappingSchema().getMapping( version, mapData )){
00127 ret = true;
00128 MappingRawElement topLevelElement;
00129 bool topLevelFound = false;
00130 bool dependency = false;
00131 std::map<std::string, std::vector<MappingRawElement> > innerElements;
00132 for( std::map< int, MappingRawElement>::iterator iElem = mapData.elements.begin();
00133 iElem != mapData.elements.end(); iElem++ ){
00134
00135 if( iElem->second.scopeName == MappingRawElement::emptyScope() ){
00136 if( iElem->second.elementType == MappingElement::classMappingElementType() ||
00137 iElem->second.elementType == MappingElement::dependencyMappingElementType() ){
00138 if( topLevelFound ){
00139 throwException("Mapping inconsistent.More then one top level element found.",
00140 "MappingDatabase::getMappingByVersion");
00141 }
00142 topLevelElement = iElem->second;
00143 if( topLevelElement.elementType == MappingElement::dependencyMappingElementType() ) dependency = true;
00144 topLevelFound = true;
00145 }
00146 } else {
00147 std::map<std::string, std::vector<MappingRawElement> >::iterator iN = innerElements.find( iElem->second.scopeName );
00148 if(iN==innerElements.end()){
00149 innerElements.insert( std::make_pair( iElem->second.scopeName, std::vector<MappingRawElement>(1,iElem->second) ) );
00150 } else {
00151 iN->second.push_back( iElem->second );
00152 }
00153 }
00154 }
00155 if( !topLevelFound ){
00156 throwException( "Could not find top element for mapping version \""+version+"\".",
00157 "MappingDatabase::getMappingByVersion" );
00158 }
00159 MappingElement& topElement = destination.setTopElement( topLevelElement.variableName,
00160 topLevelElement.tableName,
00161 dependency );
00162 topElement.setColumnNames( topLevelElement.columns);
00163 buildElement( topElement, topLevelElement.variableName, innerElements );
00164 destination.setVersion( version );
00165 }
00166 return ret;
00167 }
00168
00169 void ora::MappingDatabase::removeMapping( const std::string& version ){
00170 m_schema.mappingSchema().removeMapping( version );
00171 }
00172
00173 bool
00174 ora::MappingDatabase::getMappingForContainer( const Reflex::Type& containerClass,
00175 int containerId,
00176 MappingTree& destination ){
00177
00178 bool ret = false;
00179
00180 std::string className = containerClass.Name(Reflex::SCOPED);
00181 std::string classVersion = versionOfClass( containerClass );
00182 std::string classId = MappingRules::classId( className, classVersion );
00183
00184 std::string version("");
00185 bool found = m_schema.mappingSchema().selectMappingVersion( classId, containerId, version );
00186
00187 if( found ){
00188 ret = getMappingByVersion( version, destination );
00189 if( !ret ){
00190 throwException("Mapping version \""+version+"\" not found.",
00191 "MappingDatabase::getMappingForContainer");
00192 }
00193 if( destination.className() != className ){
00194 throwException("Mapping inconsistency detected for version=\""+version+"\"",
00195 "MappingDatabase::getMappingForContainer");
00196 }
00197 }
00198 return ret;
00199 }
00200
00201 bool ora::MappingDatabase::getBaseMappingForContainer( const std::string& className,
00202 int containerId,
00203 MappingTree& destination ){
00204 bool ret = false;
00205 std::string classId = MappingRules::baseIdForClass( className );
00206 std::string mappingVersion("");
00207 bool found = m_schema.mappingSchema().selectMappingVersion( classId, containerId, mappingVersion );
00208
00209 if( found ){
00210 ret = getMappingByVersion( mappingVersion, destination );
00211 if( !ret ){
00212 throwException("Mapping version \""+mappingVersion+"\" not found.",
00213 "MappingDatabase::getBaseMappingForContainer");
00214 }
00215 if( destination.className() != className ){
00216 throwException("Mapping inconsistency detected for version=\""+mappingVersion+"\"",
00217 "MappingDatabase::getBaseMappingForContainer");
00218 }
00219 }
00220 return ret;
00221 }
00222
00223 bool ora::MappingDatabase::getDependentMappingsForContainer( int containerId,
00224 std::vector<MappingElement>& destination ){
00225 bool ret = false;
00226 std::set<std::string> versions;
00227 if( m_schema.mappingSchema().getMappingVersionListForContainer( containerId, versions, true ) ){
00228 ret = true;
00229 for( std::set<std::string>::iterator iM = versions.begin();
00230 iM != versions.end(); ++iM ){
00231 MappingTree mapping;
00232 if( ! getMappingByVersion( *iM, mapping )){
00233 throwException("Mapping version \""+*iM+"\" not found.",
00234 "MappingDatabase::getDependentMappingsForContainer");
00235
00236 }
00237 destination.push_back( mapping.topElement() );
00238 }
00239 }
00240 return ret;
00241 }
00242
00243 bool ora::MappingDatabase::getClassVersionListForMappingVersion( const std::string& mappingVersion,
00244 std::set<std::string>& destination ){
00245 return m_schema.mappingSchema().getClassVersionListForMappingVersion( mappingVersion, destination );
00246 }
00247
00248 void ora::MappingDatabase::insertClassVersion( const std::string& className,
00249 const std::string& classVersion,
00250 int dependencyIndex,
00251 int containerId,
00252 const std::string& mappingVersion,
00253 bool asBase ){
00254 std::string classId = MappingRules::classId( className, classVersion );
00255 m_schema.mappingSchema().insertClassVersion( className, classVersion, classId, dependencyIndex, containerId, mappingVersion );
00256 if( asBase ){
00257 m_schema.mappingSchema().insertClassVersion( className, MappingRules::baseClassVersion(), MappingRules::baseIdForClass( className ), dependencyIndex, containerId, mappingVersion );
00258 }
00259 }
00260
00261 bool ora::MappingDatabase::getClassVersionListForContainer( int containerId,
00262 std::map<std::string,std::string>& versionMap ){
00263
00264 return m_schema.mappingSchema().getClassVersionListForContainer( containerId, versionMap );
00265 }
00266
00267 void ora::MappingDatabase::insertClassVersion( const Reflex::Type& dictionaryEntry,
00268 int depIndex,
00269 int containerId,
00270 const std::string& mappingVersion,
00271 bool asBase ){
00272 std::string className = dictionaryEntry.Name( Reflex::SCOPED );
00273 std::string classVersion = versionOfClass( dictionaryEntry );
00274 insertClassVersion( className, classVersion, depIndex, containerId, mappingVersion, asBase );
00275 }
00276
00277 void ora::MappingDatabase::setMappingVersionForClass( const Reflex::Type& dictionaryEntry,
00278 int containerId,
00279 const std::string& mappingVersion,
00280 bool dependency ){
00281 std::string className = dictionaryEntry.Name( Reflex::SCOPED );
00282 std::string classVersion = versionOfClass( dictionaryEntry );
00283 std::string classId = MappingRules::classId( className, classVersion );
00284 std::string mv("");
00285 bool found = m_schema.mappingSchema().selectMappingVersion( classId, containerId, mv );
00286 if( !found ){
00287 int depIndex = 0;
00288 if( dependency ) depIndex = 1;
00289 m_schema.mappingSchema().insertClassVersion( className, classVersion, classId, depIndex, containerId, mappingVersion );
00290 } else {
00291 m_schema.mappingSchema().setMappingVersion( classId, containerId, mappingVersion );
00292 }
00293 }
00294
00295 void ora::MappingDatabase::storeMapping( const MappingTree& mapping ){
00296 MappingRawData rowMapping( mapping.version() );
00297 unfoldElement( mapping.topElement(), rowMapping );
00298 m_mappingSequence.sinchronize();
00299 m_schema.mappingSchema().storeMapping( rowMapping );
00300 }
00301
00302 bool ora::MappingDatabase::getMappingVersionsForContainer( int containerId, std::set<std::string>& versionList ){
00303 return m_schema.mappingSchema().getMappingVersionListForContainer( containerId, versionList );
00304 }
00305
00306 const std::set<std::string>& ora::MappingDatabase::versions(){
00307 if(!m_isLoaded){
00308 m_schema.mappingSchema().getVersionList( m_versions );
00309 m_isLoaded = true;
00310 }
00311 return m_versions;
00312 }
00313
00314 bool ora::MappingDatabase::getDependentClassesForContainer( int containerId,
00315 std::set<std::string>& list ){
00316 return m_schema.mappingSchema().getDependentClassesInContainerMapping( containerId, list );
00317 }
00318
00319 void ora::MappingDatabase::clear(){
00320 m_versions.clear();
00321 m_isLoaded = false;
00322 }
00323