Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef OPENMS_CONCEPT_UNIQUEIDINDEXER_H
00036 #define OPENMS_CONCEPT_UNIQUEIDINDEXER_H
00037
00038 #include <OpenMS/CONCEPT/UniqueIdInterface.h>
00039 #include <OpenMS/CONCEPT/LogStream.h>
00040
00041 #ifdef _MSC_VER // disable some BOOST warnings that distract from ours
00042 # pragma warning( push ) // save warning state
00043 # pragma warning( disable : 4396 )
00044 #endif
00045
00046 #include <boost/unordered_map.hpp>
00047
00048 #ifdef _MSC_VER
00049 # pragma warning( pop ) // restore old warning state
00050 #endif
00051
00052
00053 namespace OpenMS
00054 {
00055
00062 template <typename RandomAccessContainer>
00063 class UniqueIdIndexer
00064 {
00065 public:
00066
00067 typedef boost::unordered_map<UInt64, Size> UniqueIdMap;
00068
00084 Size
00085 uniqueIdToIndex(UInt64 unique_id) const
00086 {
00087 Size index;
00088 try
00089 {
00090 index = uniqueid_to_index_.at(unique_id);
00091 if (getBase_().at(index).getUniqueId() != unique_id)
00092 {
00093 throw std::out_of_range("unique_id_to_index_");
00094 }
00095 }
00096 catch (std::out_of_range &)
00097 {
00098 try
00099 {
00100 this->updateUniqueIdToIndex();
00101 index = uniqueid_to_index_.at(unique_id);
00102 }
00103 catch (std::out_of_range &)
00104 {
00105 index = -1;
00106 }
00107 }
00108 return index;
00109 }
00110
00115 void
00116 updateUniqueIdToIndex() const
00117 {
00118 Size num_valid_unique_id = 0;
00119
00120 for (Size index = 0; index < getBase_().size(); ++index)
00121 {
00122 UInt64 unique_id = getBase_()[index].getUniqueId();
00123 if (UniqueIdInterface::isValid(unique_id))
00124 {
00125 uniqueid_to_index_[unique_id] = index;
00126 ++num_valid_unique_id;
00127 }
00128 }
00129
00130 uniqueid_to_index_.erase(UniqueIdInterface::INVALID);
00131 for (UniqueIdMap::iterator iter = uniqueid_to_index_.begin(); iter != uniqueid_to_index_.end(); )
00132 {
00133 if (iter->second >= getBase_().size() || getBase_()[iter->second].getUniqueId() != iter->first)
00134 {
00135 iter = uniqueid_to_index_.erase(iter);
00136 }
00137 else
00138 {
00139 ++iter;
00140 }
00141 }
00142 if (uniqueid_to_index_.size() != num_valid_unique_id)
00143 {
00144 std::stringstream ss;
00145 ss << "Duplicate valid unique ids detected! RandomAccessContainer has size()==" << getBase_().size();
00146 ss << ", num_valid_unique_id==" << num_valid_unique_id;
00147 ss << ", uniqueid_to_index_.size()==" << uniqueid_to_index_.size();
00148 throw Exception::Postcondition(__FILE__, __LINE__, __PRETTY_FUNCTION__, ss.str());
00149 }
00150 return;
00151 }
00152
00166 Size
00167 resolveUniqueIdConflicts()
00168 {
00169 Size invalid_uids(0);
00170 uniqueid_to_index_.clear();
00171
00172 for (Size index = 0; index < getBase_().size(); ++index)
00173 {
00174 UInt64 unique_id = getBase_()[index].getUniqueId();
00175 if (!UniqueIdInterface::isValid(unique_id))
00176 {
00177 getBase_()[index].ensureUniqueId();
00178 unique_id = getBase_()[index].getUniqueId();
00179 }
00180
00181
00182 while (uniqueid_to_index_.find(unique_id) != uniqueid_to_index_.end())
00183 {
00184 getBase_()[index].setUniqueId();
00185 unique_id = getBase_()[index].getUniqueId();
00186 ++invalid_uids;
00187 }
00188
00189 uniqueid_to_index_[unique_id] = index;
00190
00191 }
00192
00193 return invalid_uids;
00194 }
00195
00200 void
00201 swap(UniqueIdIndexer & rhs)
00202 {
00203 std::swap(uniqueid_to_index_, rhs.uniqueid_to_index_);
00204 return;
00205 }
00206
00207 protected:
00208
00213 const RandomAccessContainer &
00214 getBase_() const
00215 {
00216 return *static_cast<const RandomAccessContainer *>(this);
00217 }
00218
00223 RandomAccessContainer &
00224 getBase_()
00225 {
00226 return *static_cast<RandomAccessContainer *>(this);
00227 }
00228
00233 mutable UniqueIdMap uniqueid_to_index_;
00234
00235 };
00236
00237 }
00238
00239 #endif // OPENMS_CONCEPT_UNIQUEIDINDEXER_H