diff --git a/Util/Makefile b/Util/Makefile index e7f66a687..469be5846 100644 --- a/Util/Makefile +++ b/Util/Makefile @@ -8,7 +8,7 @@ include $(POCO_BASE)/build/rules/global objects = AbstractConfiguration Application ConfigurationMapper \ ConfigurationView HelpFormatter IniFileConfiguration LayeredConfiguration \ - LoggingConfigurator LoggingSubsystem MapConfiguration \ + LocalConfigurationView LoggingConfigurator LoggingSubsystem MapConfiguration \ Option OptionException OptionProcessor OptionSet \ PropertyFileConfiguration Subsystem SystemConfiguration \ FilesystemConfiguration ServerApplication \ diff --git a/Util/Util_vs140.vcxproj b/Util/Util_vs140.vcxproj index 007a952f2..841c429fb 100644 --- a/Util/Util_vs140.vcxproj +++ b/Util/Util_vs140.vcxproj @@ -551,6 +551,7 @@ + @@ -605,6 +606,9 @@ true + + true + true diff --git a/Util/Util_vs140.vcxproj.filters b/Util/Util_vs140.vcxproj.filters index 6a0eead48..f980cb726 100644 --- a/Util/Util_vs140.vcxproj.filters +++ b/Util/Util_vs140.vcxproj.filters @@ -90,6 +90,9 @@ Configuration\Header Files + + Configuration\Header Files + Configuration\Header Files @@ -188,6 +191,9 @@ Configuration\Source Files + + Configuration\Source Files + Configuration\Source Files diff --git a/Util/Util_vs150.vcxproj b/Util/Util_vs150.vcxproj index 5254a494f..0b395ac35 100644 --- a/Util/Util_vs150.vcxproj +++ b/Util/Util_vs150.vcxproj @@ -551,6 +551,7 @@ + @@ -605,6 +606,9 @@ true + + true + true diff --git a/Util/Util_vs150.vcxproj.filters b/Util/Util_vs150.vcxproj.filters index ffe987df4..0ee6e3a3a 100644 --- a/Util/Util_vs150.vcxproj.filters +++ b/Util/Util_vs150.vcxproj.filters @@ -90,6 +90,9 @@ Configuration\Header Files + + Configuration\Header Files + Configuration\Header Files @@ -188,6 +191,9 @@ Configuration\Source Files + + Configuration\Source Files + Configuration\Source Files diff --git a/Util/Util_vs160.vcxproj b/Util/Util_vs160.vcxproj index a9cb1e14d..8df3c5599 100644 --- a/Util/Util_vs160.vcxproj +++ b/Util/Util_vs160.vcxproj @@ -551,6 +551,7 @@ + @@ -605,6 +606,9 @@ true + + true + true diff --git a/Util/Util_vs160.vcxproj.filters b/Util/Util_vs160.vcxproj.filters index 1ab41dcf8..30e637553 100644 --- a/Util/Util_vs160.vcxproj.filters +++ b/Util/Util_vs160.vcxproj.filters @@ -90,6 +90,9 @@ Configuration\Header Files + + Configuration\Header Files + Configuration\Header Files @@ -188,6 +191,9 @@ Configuration\Source Files + + Configuration\Source Files + Configuration\Source Files diff --git a/Util/Util_vs170.vcxproj b/Util/Util_vs170.vcxproj index 279eb8648..02b1894ca 100644 --- a/Util/Util_vs170.vcxproj +++ b/Util/Util_vs170.vcxproj @@ -551,6 +551,7 @@ + @@ -605,6 +606,9 @@ true + + true + true diff --git a/Util/Util_vs170.vcxproj.filters b/Util/Util_vs170.vcxproj.filters index f5e6c274c..a4d7b4d68 100644 --- a/Util/Util_vs170.vcxproj.filters +++ b/Util/Util_vs170.vcxproj.filters @@ -90,6 +90,9 @@ Configuration\Header Files + + Configuration\Header Files + Configuration\Header Files @@ -188,6 +191,9 @@ Configuration\Source Files + + Configuration\Source Files + Configuration\Source Files diff --git a/Util/Util_vs90.vcproj b/Util/Util_vs90.vcproj index 82bef7fa0..bf81a867d 100644 --- a/Util/Util_vs90.vcproj +++ b/Util/Util_vs90.vcproj @@ -571,6 +571,9 @@ RelativePath=".\include\Poco\Util\LayeredConfiguration.h" > + @@ -623,6 +626,9 @@ RelativePath=".\src\LayeredConfiguration.cpp" > + diff --git a/Util/include/Poco/Util/AbstractConfiguration.h b/Util/include/Poco/Util/AbstractConfiguration.h index 30fabc12b..3276056ee 100644 --- a/Util/include/Poco/Util/AbstractConfiguration.h +++ b/Util/include/Poco/Util/AbstractConfiguration.h @@ -300,6 +300,12 @@ public: Ptr createView(const std::string& prefix); /// Creates a view (see ConfigurationView) into the configuration. + + const Ptr createLocalView(const std::string& prefix) const; + /// Creates a non-mutable view (see LocalConfigurationView) into the configuration. + + Ptr createLocalView(const std::string& prefix); + /// Creates a view (see LocalConfigurationView) into the configuration. std::string expand(const std::string& value) const; /// Replaces all occurrences of ${} in value with the @@ -383,6 +389,7 @@ private: friend class LayeredConfiguration; friend class ConfigurationView; + friend class LocalConfigurationView; friend class ConfigurationMapper; }; diff --git a/Util/include/Poco/Util/LocalConfigurationView.h b/Util/include/Poco/Util/LocalConfigurationView.h new file mode 100644 index 000000000..febb309ce --- /dev/null +++ b/Util/include/Poco/Util/LocalConfigurationView.h @@ -0,0 +1,72 @@ +// +// LocalConfigurationView.h +// +// Library: Util +// Package: Configuration +// Module: LocalConfigurationView +// +// Definition of the ConfigurationView class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + +#ifndef Util_LocalConfigurationView_INCLUDED +#define Util_LocalConfigurationView_INCLUDED + +#include "Poco/Util/AbstractConfiguration.h" +#include "Poco/Util/Util.h" + +namespace Poco { + namespace Util { + + class Util_API LocalConfigurationView : public AbstractConfiguration + /// This configuration implements a "view" into a sub-hierarchy + /// of another configuration. + /// + /// For example, given a configuration with the following properties: + /// config.value1 + /// config.value2 + /// config.sub.value1 + /// config.sub.value2 + /// and a LocalConfigurationView with the prefix "config", then + /// the above properties will be available via the view as + /// value1 + /// value2 + /// sub.value1 + /// sub.value2 + /// + /// A LocalConfigurationView is most useful in combination with a + /// LayeredConfiguration. + /// + /// The LocalConfigurationView only searches for the properties in the viewed Space. + { + public: + LocalConfigurationView(const std::string& prefix, AbstractConfiguration::Ptr pConfig); + /// Creates the LocalConfigurationView. The LocalConfigurationView + /// retains (shared) ownership of the passed configuration. + + protected: + bool getRaw(const std::string& key, std::string& value) const; + void setRaw(const std::string& key, const std::string& value); + void enumerate(const std::string& key, Keys& range) const; + void removeRaw(const std::string& key); + + std::string translateKey(const std::string& key) const; + + ~LocalConfigurationView(); + + private: + LocalConfigurationView(const LocalConfigurationView&); + LocalConfigurationView& operator=(const LocalConfigurationView&); + + std::string _prefix; + AbstractConfiguration::Ptr _pConfig; + }; + + } // namespace Util +} // namespace Poco + +#endif // Util_LocalConfigurationView_INCLUDED diff --git a/Util/src/AbstractConfiguration.cpp b/Util/src/AbstractConfiguration.cpp index 559ea65de..285d90249 100644 --- a/Util/src/AbstractConfiguration.cpp +++ b/Util/src/AbstractConfiguration.cpp @@ -14,6 +14,7 @@ #include "Poco/Util/AbstractConfiguration.h" #include "Poco/Util/ConfigurationView.h" +#include "Poco/Util/LocalConfigurationView.h" #include "Poco/Exception.h" #include "Poco/NumberParser.h" #include "Poco/NumberFormatter.h" @@ -348,6 +349,18 @@ AbstractConfiguration::Ptr AbstractConfiguration::createView(const std::string& } +const AbstractConfiguration::Ptr AbstractConfiguration::createLocalView(const std::string& prefix) const +{ + return new LocalConfigurationView(prefix, AbstractConfiguration::Ptr(const_cast(this), true)); +} + + +AbstractConfiguration::Ptr AbstractConfiguration::createLocalView(const std::string& prefix) +{ + return new LocalConfigurationView(prefix, AbstractConfiguration::Ptr(this, true)); +} + + namespace { class AutoCounter diff --git a/Util/src/LocalConfigurationView.cpp b/Util/src/LocalConfigurationView.cpp new file mode 100644 index 000000000..10b414c61 --- /dev/null +++ b/Util/src/LocalConfigurationView.cpp @@ -0,0 +1,55 @@ +// +// LocalConfigurationView.cpp +// +// Library: Util +// Package: Configuration +// Module: LocalConfigurationView +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + +#include "Poco/Util/LocalConfigurationView.h" + +namespace Poco { + namespace Util { + + LocalConfigurationView::LocalConfigurationView(const std::string& prefix, AbstractConfiguration::Ptr pConfig) : _prefix(prefix), + _pConfig(pConfig) { + poco_check_ptr(pConfig); + } + + LocalConfigurationView::~LocalConfigurationView() { + } + + bool LocalConfigurationView::getRaw(const std::string& key, std::string& value) const { + std::string translatedKey = translateKey(key); + return _pConfig->getRaw(translatedKey, value); + } + + void LocalConfigurationView::setRaw(const std::string& key, const std::string& value) { + std::string translatedKey = translateKey(key); + _pConfig->setRaw(translatedKey, value); + } + + void LocalConfigurationView::enumerate(const std::string& key, Keys& range) const { + std::string translatedKey = translateKey(key); + _pConfig->enumerate(translatedKey, range); + } + + void LocalConfigurationView::removeRaw(const std::string& key) { + std::string translatedKey = translateKey(key); + _pConfig->remove(translatedKey); + } + + std::string LocalConfigurationView::translateKey(const std::string& key) const { + std::string result = _prefix; + if (!result.empty() && !key.empty() && key[0] != '[') result += '.'; + result += key; + return result; + } + + } // namespace Util +} // namespace Poco diff --git a/Util/testsuite/Makefile b/Util/testsuite/Makefile index 0df4f107d..233e84cde 100644 --- a/Util/testsuite/Makefile +++ b/Util/testsuite/Makefile @@ -9,7 +9,7 @@ include $(POCO_BASE)/build/rules/global objects = AbstractConfigurationTest ConfigurationTestSuite \ ConfigurationMapperTest ConfigurationViewTest Driver \ HelpFormatterTest IniFileConfigurationTest LayeredConfigurationTest \ - LoggingConfiguratorTest MapConfigurationTest \ + LocalConfigurationView LoggingConfiguratorTest MapConfigurationTest \ OptionProcessorTest OptionSetTest OptionTest \ OptionsTestSuite PropertyFileConfigurationTest \ SystemConfigurationTest UtilTestSuite XMLConfigurationTest \ diff --git a/Util/testsuite/TestSuite_vs140.vcxproj b/Util/testsuite/TestSuite_vs140.vcxproj index 4f20fee3e..3415784aa 100644 --- a/Util/testsuite/TestSuite_vs140.vcxproj +++ b/Util/testsuite/TestSuite_vs140.vcxproj @@ -607,6 +607,7 @@ + @@ -656,6 +657,9 @@ true + + true + true diff --git a/Util/testsuite/TestSuite_vs140.vcxproj.filters b/Util/testsuite/TestSuite_vs140.vcxproj.filters index 63093c75b..b13277f6d 100644 --- a/Util/testsuite/TestSuite_vs140.vcxproj.filters +++ b/Util/testsuite/TestSuite_vs140.vcxproj.filters @@ -90,6 +90,9 @@ Configuration\Header Files + + Configuration\Header Files + Configuration\Header Files @@ -173,6 +176,9 @@ Configuration\Source Files + + Configuration\Source Files + Configuration\Source Files diff --git a/Util/testsuite/TestSuite_vs150.vcxproj b/Util/testsuite/TestSuite_vs150.vcxproj index 227c2d17d..2b0ddcb8b 100644 --- a/Util/testsuite/TestSuite_vs150.vcxproj +++ b/Util/testsuite/TestSuite_vs150.vcxproj @@ -607,6 +607,7 @@ + @@ -656,6 +657,9 @@ true + + true + true diff --git a/Util/testsuite/TestSuite_vs150.vcxproj.filters b/Util/testsuite/TestSuite_vs150.vcxproj.filters index d177951c1..2450e1951 100644 --- a/Util/testsuite/TestSuite_vs150.vcxproj.filters +++ b/Util/testsuite/TestSuite_vs150.vcxproj.filters @@ -90,6 +90,9 @@ Configuration\Header Files + + Configuration\Header Files + Configuration\Header Files @@ -173,6 +176,9 @@ Configuration\Source Files + + Configuration\Source Files + Configuration\Source Files diff --git a/Util/testsuite/TestSuite_vs160.vcxproj b/Util/testsuite/TestSuite_vs160.vcxproj index 6f5fda372..2c7bddd40 100644 --- a/Util/testsuite/TestSuite_vs160.vcxproj +++ b/Util/testsuite/TestSuite_vs160.vcxproj @@ -607,6 +607,7 @@ + @@ -656,6 +657,9 @@ true + + true + true diff --git a/Util/testsuite/TestSuite_vs160.vcxproj.filters b/Util/testsuite/TestSuite_vs160.vcxproj.filters index 396616e62..d9480d4ba 100644 --- a/Util/testsuite/TestSuite_vs160.vcxproj.filters +++ b/Util/testsuite/TestSuite_vs160.vcxproj.filters @@ -90,6 +90,9 @@ Configuration\Header Files + + Configuration\Header Files + Configuration\Header Files @@ -173,6 +176,9 @@ Configuration\Source Files + + Configuration\Source Files + Configuration\Source Files diff --git a/Util/testsuite/TestSuite_vs170.vcxproj b/Util/testsuite/TestSuite_vs170.vcxproj index 2006a634e..9b087deca 100644 --- a/Util/testsuite/TestSuite_vs170.vcxproj +++ b/Util/testsuite/TestSuite_vs170.vcxproj @@ -607,6 +607,7 @@ + @@ -656,6 +657,9 @@ true + + true + true diff --git a/Util/testsuite/TestSuite_vs170.vcxproj.filters b/Util/testsuite/TestSuite_vs170.vcxproj.filters index af08b5781..9782f4318 100644 --- a/Util/testsuite/TestSuite_vs170.vcxproj.filters +++ b/Util/testsuite/TestSuite_vs170.vcxproj.filters @@ -93,6 +93,9 @@ Configuration\Header Files + + Configuration\Header Files + Configuration\Header Files @@ -173,6 +176,9 @@ Configuration\Source Files + + Configuration\Source Files + Configuration\Source Files diff --git a/Util/testsuite/TestSuite_vs90.vcproj b/Util/testsuite/TestSuite_vs90.vcproj index 6db531f29..5e15eca66 100644 --- a/Util/testsuite/TestSuite_vs90.vcproj +++ b/Util/testsuite/TestSuite_vs90.vcproj @@ -491,6 +491,8 @@ RelativePath=".\src\JSONConfigurationTest.h"/> + + addTest(ConfigurationViewTest::suite()); + pSuite->addTest(LocalConfigurationViewTest::suite()); pSuite->addTest(ConfigurationMapperTest::suite()); pSuite->addTest(MapConfigurationTest::suite()); pSuite->addTest(LayeredConfigurationTest::suite()); diff --git a/Util/testsuite/src/LocalConfigurationViewTest.cpp b/Util/testsuite/src/LocalConfigurationViewTest.cpp new file mode 100644 index 000000000..94f2f852a --- /dev/null +++ b/Util/testsuite/src/LocalConfigurationViewTest.cpp @@ -0,0 +1,114 @@ +// +// LocalConfigurationViewTest.cpp +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + +#include "LocalConfigurationViewTest.h" + +#include + +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Poco/AutoPtr.h" +#include "Poco/Exception.h" +#include "Poco/Util/MapConfiguration.h" + +using Poco::AutoPtr; +using Poco::Util::AbstractConfiguration; +using Poco::Util::MapConfiguration; + +LocalConfigurationViewTest::LocalConfigurationViewTest(const std::string& name) : AbstractConfigurationTest(name) { +} + +LocalConfigurationViewTest::~LocalConfigurationViewTest() { +} + +void LocalConfigurationViewTest::testLocalView() { + AbstractConfiguration::Ptr pConf = createConfiguration(); + AbstractConfiguration::Ptr pView = pConf->createLocalView(""); + assertTrue(pView->hasProperty("prop1")); + assertTrue(pView->hasProperty("prop2")); + + AbstractConfiguration::Keys keys; + pView->keys(keys); + assertTrue(keys.size() == 13); + assertTrue(std::find(keys.begin(), keys.end(), "prop1") != keys.end()); + assertTrue(std::find(keys.begin(), keys.end(), "prop2") != keys.end()); + assertTrue(std::find(keys.begin(), keys.end(), "prop3") != keys.end()); + assertTrue(std::find(keys.begin(), keys.end(), "prop4") != keys.end()); + + assertTrue(pView->getString("prop1") == "foo"); + assertTrue(pView->getString("prop3.string1") == "foo"); + + pView->setString("prop6", "foobar"); + assertTrue(pConf->getString("prop6") == "foobar"); + + pView = pConf->createLocalView("prop1"); + pView->keys(keys); + assertTrue(keys.empty()); + assertFalse(pView->hasProperty("prop1")); + + pView->setString("prop11", "foobar"); + assertTrue(pConf->getString("prop1.prop11") == "foobar"); + + pView = pConf->createLocalView("prop3"); + pView->keys(keys); + assertTrue(keys.size() == 2); + assertTrue(std::find(keys.begin(), keys.end(), "string1") != keys.end()); + assertTrue(std::find(keys.begin(), keys.end(), "string2") != keys.end()); + + assertTrue(pView->getString("string1") == "foo"); + assertTrue(pView->getString("string2") == "bar"); + + pView->setString("string3", "foobar"); + assertTrue(pConf->getString("prop3.string3") == "foobar"); + + pView = pConf->createLocalView("prop5"); + pView->keys(keys); + assertTrue(keys.size() == 4); + assertTrue(std::find(keys.begin(), keys.end(), "string1") != keys.end()); + assertTrue(std::find(keys.begin(), keys.end(), "string1") != keys.end()); + assertTrue(std::find(keys.begin(), keys.end(), "sub1") != keys.end()); + assertTrue(std::find(keys.begin(), keys.end(), "sub2") != keys.end()); + + assertTrue(pView->getString("sub1.string1") == "FOO"); + assertTrue(pView->getString("sub2.string2") == "Bar"); + + pView = pConf->createLocalView("prop5.sub1"); + pView->keys(keys); + assertTrue(keys.size() == 2); + assertTrue(std::find(keys.begin(), keys.end(), "string1") != keys.end()); + assertTrue(std::find(keys.begin(), keys.end(), "string2") != keys.end()); + + assertTrue(pView->getString("string1") == "FOO"); + assertTrue(pView->getString("string2") == "BAR"); + + pView->setString("string3", "foobar"); + assertTrue(pConf->getString("prop5.sub1.string3") == "foobar"); + + pView->remove("string3"); + assertTrue(!pConf->hasProperty("prop5.sub1.string3")); +} + +AbstractConfiguration::Ptr LocalConfigurationViewTest::allocConfiguration() const { + return new MapConfiguration; +} + +void LocalConfigurationViewTest::setUp() { +} + +void LocalConfigurationViewTest::tearDown() { +} + +CppUnit::Test* LocalConfigurationViewTest::suite() { + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("LocalConfigurationViewTest"); + + AbstractConfigurationTest_addTests(pSuite, LocalConfigurationViewTest); + CppUnit_addTest(pSuite, LocalConfigurationViewTest, testLocalView); + + return pSuite; +} diff --git a/Util/testsuite/src/LocalConfigurationViewTest.h b/Util/testsuite/src/LocalConfigurationViewTest.h new file mode 100644 index 000000000..34b67756b --- /dev/null +++ b/Util/testsuite/src/LocalConfigurationViewTest.h @@ -0,0 +1,34 @@ +// +// LocalConfigurationViewTest.h +// +// Definition of the ConfigurationViewTest class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + +#ifndef LocalConfigurationViewTest_INCLUDED +#define LocalConfigurationViewTest_INCLUDED + +#include "AbstractConfigurationTest.h" +#include "Poco/Util/Util.h" + +class LocalConfigurationViewTest : public AbstractConfigurationTest { + public: + LocalConfigurationViewTest(const std::string& name); + virtual ~LocalConfigurationViewTest(); + + void testLocalView(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + + private: + virtual Poco::Util::AbstractConfiguration::Ptr allocConfiguration() const; +}; + +#endif // LocalConfigurationViewTest_INCLUDED