diff --git a/Modules/Core/include/mitkUIDGenerator.h b/Modules/Core/include/mitkUIDGenerator.h index c87ffebd7e..8deb9525c5 100644 --- a/Modules/Core/include/mitkUIDGenerator.h +++ b/Modules/Core/include/mitkUIDGenerator.h @@ -1,54 +1,53 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITK_UID_GENERATOR_INDCLUDED_FASAWE #define MITK_UID_GENERATOR_INDCLUDED_FASAWE #include -#include +#include +#include #include namespace mitk { /*! \brief Generated unique IDs - Creates (somehow most of the time) unique IDs from a given prefix, - the current date/time and a random part. + Creates unique IDs from a given prefix, the current date/time and a random part. Be aware that, a length of one or + two might not be sufficient. The prefix is given to the constructor, together with the desired - length of the random part (minimum 5 digits). + length of the random part. - The current implementation uses the time in seconds in combination with an a random part. This - should assure a unique ID on a very high probability. Still, there is a very small chance to get - identical random numbers. A feature request for improved UID generation is handled in BUG 14333. + The current implementation uses the time in seconds in combination with an a random part. */ class MITKCORE_EXPORT UIDGenerator { public: UIDGenerator(const char *prefix = "UID_", unsigned int lengthOfRandomPart = 8); /** @return Returns a unique ID as string. You will get another unique ID each time you call GetUID. */ std::string GetUID(); private: std::string m_Prefix; unsigned int m_LengthOfRandomPart; - itk::Statistics::MersenneTwisterRandomVariateGenerator::Pointer m_RandomGenerator; + std::uniform_int_distribution m_Distribution; }; -} +} // namespace mitk #endif diff --git a/Modules/Core/src/Algorithms/mitkUIDGenerator.cpp b/Modules/Core/src/Algorithms/mitkUIDGenerator.cpp index 0f2c8553c1..509a2a2eaf 100644 --- a/Modules/Core/src/Algorithms/mitkUIDGenerator.cpp +++ b/Modules/Core/src/Algorithms/mitkUIDGenerator.cpp @@ -1,84 +1,59 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include -#include -#include -#include +#include #include -#include mitk::UIDGenerator::UIDGenerator(const char *prefix, unsigned int lengthOfRandomPart) : m_Prefix(prefix), m_LengthOfRandomPart(lengthOfRandomPart), - m_RandomGenerator(itk::Statistics::MersenneTwisterRandomVariateGenerator::New()) + m_Distribution(std::uniform_int_distribution(0, std::numeric_limits::max())) { - if (lengthOfRandomPart < 5) - { - MITK_ERROR << "To few digits requested (" << lengthOfRandomPart << " digits)"; - throw std::invalid_argument("To few digits requested"); - } - - m_RandomGenerator->Initialize(); } std::string mitk::UIDGenerator::GetUID() { std::ostringstream s; s << m_Prefix; - time_t tt = time(nullptr); - tm *t = gmtime(&tt); - - if (t) - { - s << t->tm_year + 1900; - - if (t->tm_mon < 9) - s << "0"; // add a 0 for months 1 to 9 - s << t->tm_mon + 1; + auto time = std::time(nullptr); + auto tm = std::localtime(&time); - if (t->tm_mday < 10) - s << "0"; // add a 0 for days 1 to 9 - s << t->tm_mday; + s << std::put_time(tm, "%Y%m%d%H%M%S"); - if (t->tm_hour < 10) - s << "0"; // add a 0 for hours 1 to 9 - s << t->tm_hour; + std::ostringstream rs; - if (t->tm_min < 10) - s << "0"; // add a 0 for minutes 1 to 9 - s << t->tm_min; + static std::random_device rd; // Will be used to obtain a seed for the random number engine + static std::mt19937 generator(rd()); // Standard mersenne_twister_engine seeded with rd() - if (t->tm_sec < 10) - s << "0"; // add a 0 for seconds 1 to 9 - s << t->tm_sec; - - std::ostringstream rs; - rs << (long int)(pow(10.0, double(m_LengthOfRandomPart)) / double(RAND_MAX) * - double(m_RandomGenerator->GetUniformVariate(0, RAND_MAX))); + while (rs.str().length() < m_LengthOfRandomPart) + { + rs << m_Distribution(generator); + } - for (size_t i = rs.str().length(); i < m_LengthOfRandomPart; ++i) // add zeros for non available digits - { - s << "0"; - } + auto randomString = rs.str(); - s << rs.str(); + if (randomString.length() > m_LengthOfRandomPart) + { + randomString = randomString.substr(randomString.length() - m_LengthOfRandomPart); } + s << randomString; + return s.str(); } diff --git a/Modules/Core/test/mitkUIDGeneratorTest.cpp b/Modules/Core/test/mitkUIDGeneratorTest.cpp index 9000834607..20508c0dea 100644 --- a/Modules/Core/test/mitkUIDGeneratorTest.cpp +++ b/Modules/Core/test/mitkUIDGeneratorTest.cpp @@ -1,85 +1,63 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkUIDGenerator.h" #include +#include #include -void newGeneratorInstancesHeapTest() +class mitkUIDGeneratorTestSuite : public mitk::TestFixture { - auto uidGen1 = new mitk::UIDGenerator("UID_", 8); - mitk::UIDGenerator *uidGen2 = uidGen1; - std::string uid1_1, uid2_1; + CPPUNIT_TEST_SUITE(mitkUIDGeneratorTestSuite); + MITK_TEST(UIDGeneratorInstanceRenewalSucceed); + MITK_TEST(UIDGeneratorMultipleInstancesSucceed); - uid1_1 = uidGen1->GetUID(); + CPPUNIT_TEST_SUITE_END(); - uidGen1 = new mitk::UIDGenerator("UID_", 8); + unsigned short m_UidLengthStart = 5; + unsigned short m_UidLengthEnd = 20; - uid2_1 = uidGen1->GetUID(); - delete uidGen1; - delete uidGen2; + void UIDGeneratorInstanceRenewalSucceed() + { + for (auto k = m_UidLengthStart; k < m_UidLengthEnd; ++k) + { + mitk::UIDGenerator uidGen1("UID_", k); + auto uid1_1 = uidGen1.GetUID(); - MITK_TEST_CONDITION(uid1_1 != uid2_1, "Different UIDs are not allowed to be equal"); -} + uidGen1 = mitk::UIDGenerator("UID_", k); + auto uid2_1 = uidGen1.GetUID(); -void multipleUIDsFromSameGeneratorTest(int /*UIDlength*/) -{ - auto uidGen = new mitk::UIDGenerator("UID_", 8); - std::string uid1, uid2; - uid1 = uidGen->GetUID(); - uid2 = uidGen->GetUID(); - delete uidGen; - MITK_TEST_CONDITION(uid1 != uid2, - "Testing two UIDs from the same generator. Different UIDs are not allowed to be equal"); -} - -void newGeneratorInstancesTest() -{ - mitk::UIDGenerator uidGen1("UID_", 8); - std::string uid1_1, uid2_1; - - uid1_1 = uidGen1.GetUID(); - - uidGen1 = mitk::UIDGenerator("UID_", 8); + CPPUNIT_ASSERT_MESSAGE("Different UIDs are not allowed to be equal", uid1_1 != uid2_1); + } + } - uid2_1 = uidGen1.GetUID(); + void UIDGeneratorMultipleInstancesSucceed() + { + for (auto k = m_UidLengthStart; k < m_UidLengthEnd; ++k) + { + mitk::UIDGenerator uidGen1("UID_", k); + mitk::UIDGenerator uidGen2("UID_", k); - MITK_TEST_CONDITION(uid1_1 != uid2_1, "Different UIDs are not allowed to be equal"); -} + auto uid1_1 = uidGen1.GetUID(); + auto uid2_1 = uidGen2.GetUID(); -void severalGeneratorInstancesTest() -{ - mitk::UIDGenerator uidGen1("UID_", 8); - mitk::UIDGenerator uidGen2("UID_", 8); - std::string uid1_1, uid2_1; - - uid1_1 = uidGen1.GetUID(); - uid2_1 = uidGen2.GetUID(); + CPPUNIT_ASSERT_MESSAGE("Different UIDs are not allowed to be equal", uid1_1 != uid2_1); + } + } +}; - MITK_TEST_CONDITION(uid1_1 != uid2_1, "Different UIDs are not allowed to be equal"); -} - -int mitkUIDGeneratorTest(int /*argc*/, char * /*argv*/ []) -{ - MITK_TEST_BEGIN("mitkUIDGeneratorTest"); - severalGeneratorInstancesTest(); - newGeneratorInstancesTest(); - newGeneratorInstancesHeapTest(); - multipleUIDsFromSameGeneratorTest(8); - multipleUIDsFromSameGeneratorTest(16); - MITK_TEST_END(); -} +MITK_TEST_SUITE_REGISTRATION(mitkUIDGenerator)