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 std::string& className,
00179 const std::string& classVersion,
00180 int containerId,
00181 MappingTree& destination ){
00182 bool ret = false;
00183
00184 std::string classId = MappingRules::classId( className, classVersion );
00185
00186 std::string version("");
00187 bool found = m_schema.mappingSchema().selectMappingVersion( classId, containerId, version );
00188
00189 if( found ){
00190 ret = getMappingByVersion( version, destination );
00191 if( !ret ){
00192 throwException("Mapping version \""+version+"\" not found.",
00193 "MappingDatabase::getMappingForContainer");
00194 }
00195 if( destination.className() != className ){
00196 throwException("Mapping inconsistency detected for version=\""+version+"\"",
00197 "MappingDatabase::getMappingForContainer");
00198 }
00199 }
00200 return ret;
00201 }
00202
00203 bool ora::MappingDatabase::getBaseMappingForContainer( const std::string& className,
00204 int containerId,
00205 MappingTree& destination ){
00206 bool ret = false;
00207 std::string classId = MappingRules::baseIdForClass( className );
00208 std::string mappingVersion("");
00209 bool found = m_schema.mappingSchema().selectMappingVersion( classId, containerId, mappingVersion );
00210
00211 if( found ){
00212 ret = getMappingByVersion( mappingVersion, destination );
00213 if( !ret ){
00214 throwException("Mapping version \""+mappingVersion+"\" not found.",
00215 "MappingDatabase::getBaseMappingForContainer");
00216 }
00217 if( destination.className() != className ){
00218 throwException("Mapping inconsistency detected for version=\""+mappingVersion+"\"",
00219 "MappingDatabase::getBaseMappingForContainer");
00220 }
00221 }
00222 return ret;
00223 }
00224
00225 bool ora::MappingDatabase::getDependentMappingsForContainer( int containerId,
00226 std::vector<MappingElement>& destination ){
00227 bool ret = false;
00228 std::set<std::string> versions;
00229 if( m_schema.mappingSchema().getMappingVersionListForContainer( containerId, versions, true ) ){
00230 ret = true;
00231 for( std::set<std::string>::iterator iM = versions.begin();
00232 iM != versions.end(); ++iM ){
00233 MappingTree mapping;
00234 if( ! getMappingByVersion( *iM, mapping )){
00235 throwException("Mapping version \""+*iM+"\" not found.",
00236 "MappingDatabase::getDependentMappingsForContainer");
00237
00238 }
00239 destination.push_back( mapping.topElement() );
00240 }
00241 }
00242 return ret;
00243 }
00244
00245 bool ora::MappingDatabase::getClassVersionListForMappingVersion( const std::string& mappingVersion,
00246 std::set<std::string>& destination ){
00247 return m_schema.mappingSchema().getClassVersionListForMappingVersion( mappingVersion, destination );
00248 }
00249
00250 void ora::MappingDatabase::insertClassVersion( const std::string& className,
00251 const std::string& classVersion,
00252 int dependencyIndex,
00253 int containerId,
00254 const std::string& mappingVersion,
00255 bool asBase ){
00256 std::string classId = MappingRules::classId( className, classVersion );
00257 m_schema.mappingSchema().insertClassVersion( className, classVersion, classId, dependencyIndex, containerId, mappingVersion );
00258 if( asBase ){
00259 m_schema.mappingSchema().insertClassVersion( className, MappingRules::baseClassVersion(), MappingRules::baseIdForClass( className ), dependencyIndex, containerId, mappingVersion );
00260 }
00261 }
00262
00263 bool ora::MappingDatabase::getClassVersionListForContainer( int containerId,
00264 std::map<std::string,std::string>& versionMap ){
00265
00266 return m_schema.mappingSchema().getClassVersionListForContainer( containerId, versionMap );
00267 }
00268
00269 void ora::MappingDatabase::insertClassVersion( const Reflex::Type& dictionaryEntry,
00270 int depIndex,
00271 int containerId,
00272 const std::string& mappingVersion,
00273 bool asBase ){
00274 std::string className = dictionaryEntry.Name( Reflex::SCOPED );
00275 std::string classVersion = versionOfClass( dictionaryEntry );
00276 insertClassVersion( className, classVersion, depIndex, containerId, mappingVersion, asBase );
00277 }
00278
00279 void ora::MappingDatabase::setMappingVersionForClass( const Reflex::Type& dictionaryEntry,
00280 int containerId,
00281 const std::string& mappingVersion,
00282 bool dependency ){
00283 std::string className = dictionaryEntry.Name( Reflex::SCOPED );
00284 std::string classVersion = versionOfClass( dictionaryEntry );
00285 std::string classId = MappingRules::classId( className, classVersion );
00286 std::string mv("");
00287 bool found = m_schema.mappingSchema().selectMappingVersion( classId, containerId, mv );
00288 if( !found ){
00289 int depIndex = 0;
00290 if( dependency ) depIndex = 1;
00291 m_schema.mappingSchema().insertClassVersion( className, classVersion, classId, depIndex, containerId, mappingVersion );
00292 } else {
00293 m_schema.mappingSchema().setMappingVersion( classId, containerId, mappingVersion );
00294 }
00295 }
00296
00297 void ora::MappingDatabase::storeMapping( const MappingTree& mapping ){
00298 MappingRawData rowMapping( mapping.version() );
00299 unfoldElement( mapping.topElement(), rowMapping );
00300 m_mappingSequence.sinchronize();
00301 m_schema.mappingSchema().storeMapping( rowMapping );
00302 }
00303
00304 bool ora::MappingDatabase::getMappingVersionsForContainer( int containerId, std::set<std::string>& versionList ){
00305 return m_schema.mappingSchema().getMappingVersionListForContainer( containerId, versionList );
00306 }
00307
00308 const std::set<std::string>& ora::MappingDatabase::versions(){
00309 if(!m_isLoaded){
00310 m_schema.mappingSchema().getVersionList( m_versions );
00311 m_isLoaded = true;
00312 }
00313 return m_versions;
00314 }
00315
00316 bool ora::MappingDatabase::getDependentClassesForContainer( int containerId,
00317 std::set<std::string>& list ){
00318 return m_schema.mappingSchema().getDependentClassesInContainerMapping( containerId, list );
00319 }
00320
00321 void ora::MappingDatabase::clear(){
00322 m_versions.clear();
00323 m_isLoaded = false;
00324 }
00325