diff options
-rw-r--r-- | icetray/icetray/Jamfile.jam | 3 | ||||
-rw-r--r-- | icetray/icetray/icetrayService.cpp | 1 | ||||
-rw-r--r-- | icetray/icetray/icetrayService.h | 2 | ||||
-rw-r--r-- | icetray/icetray/options.cpp | 60 | ||||
-rw-r--r-- | icetray/icetray/options.h | 62 | ||||
-rw-r--r-- | icetray/unittests/Jamfile.jam | 6 | ||||
-rw-r--r-- | icetray/unittests/testIceTrayOptions.cpp | 59 |
7 files changed, 193 insertions, 0 deletions
diff --git a/icetray/icetray/Jamfile.jam b/icetray/icetray/Jamfile.jam index 7944202..6398f6a 100644 --- a/icetray/icetray/Jamfile.jam +++ b/icetray/icetray/Jamfile.jam @@ -1,5 +1,7 @@ import package ; +lib boost_program_options ; + lib icetray : [ glob-tree *.cpp *.ice : bin ] : @@ -14,6 +16,7 @@ lib icetray : <library>..//boost_system <library>..//boost_thread <library>../..//glibmm + <library>boost_program_options <allow-ice>yes <slicer>yes : : diff --git a/icetray/icetray/icetrayService.cpp b/icetray/icetray/icetrayService.cpp index 79d50bd..d785632 100644 --- a/icetray/icetray/icetrayService.cpp +++ b/icetray/icetray/icetrayService.cpp @@ -30,6 +30,7 @@ namespace IceTray { { adp = ic->createObjectAdapter(name); configureLoggers(adp, ic->getProperties()); + optionsCollation.apply(ic->getProperties()); addObjects(name, ic, args, adp); adp->activate(); } diff --git a/icetray/icetray/icetrayService.h b/icetray/icetray/icetrayService.h index 23fee17..63ccd7e 100644 --- a/icetray/icetray/icetrayService.h +++ b/icetray/icetray/icetrayService.h @@ -6,6 +6,7 @@ #include <visibility.h> #include "database.h" #include "logger.h" +#include "options.h" namespace IceTray { class DLL_PUBLIC Service : public IceBox::Service, public AdHoc::AbstractPluginImplementation { @@ -31,6 +32,7 @@ namespace IceTray { Ice::ObjectAdapterPtr adp; static Service * current; std::set<Logging::LogWriterPrx> logWriters; + OptionsCollation optionsCollation; }; typedef IceInternal::Handle<Service> ServicePtr; diff --git a/icetray/icetray/options.cpp b/icetray/icetray/options.cpp new file mode 100644 index 0000000..6a0b5bf --- /dev/null +++ b/icetray/icetray/options.cpp @@ -0,0 +1,60 @@ +#include "options.h" +#include <factory.impl.h> + +INSTANTIATEVOIDFACTORY(IceTray::Options); +INSTANTIATEPLUGINOF(IceTray::Options); + +namespace po = boost::program_options; + +namespace IceTray { + Options::Options(const std::string & name) : + optionsName(name) + { + } + + OptionsDescPtr + Options::getOptions() + { + auto opts = OptionsDescPtr(new boost::program_options::options_description(optionsName)); + options(opts->add_options()); + return opts; + } + + OptionsCollation::OptionsCollation() + { + auto defManager = AdHoc::PluginManager::getDefault(); + for (auto f : defManager->getAll<OptionsFactory>()) { + auto o = f->implementation()->create(); + defManager->add<Options>(o, typeid(*o).name(), __FILE__, __LINE__); + all.add(*o->getOptions()); + } + } + + OptionsCollation::~OptionsCollation() + { + auto defManager = AdHoc::PluginManager::getDefault(); + for (auto o : defManager->getAll<Options>()) { + defManager->remove<Options>(o->name); + } + } + + void + OptionsCollation::apply(Ice::PropertiesPtr p) + { + po::parsed_options result(&all); + + for (const auto & optDesc : all.options()) { + po::option opt; + opt.value = p->getPropertyAsList(optDesc->long_name()); + if (opt.value.empty()) continue; + opt.string_key = optDesc->long_name(); + opt.unregistered = false; + result.options.push_back(opt); + } + + po::variables_map vm; + po::store(result, vm); + po::notify(vm); + } +} + diff --git a/icetray/icetray/options.h b/icetray/icetray/options.h new file mode 100644 index 0000000..00911d3 --- /dev/null +++ b/icetray/icetray/options.h @@ -0,0 +1,62 @@ +#ifndef ICETRAY_OPTIONS_H +#define ICETRAY_OPTIONS_H + +#include <factory.h> +#include <visibility.h> +#include <boost/program_options.hpp> +#include <Ice/Properties.h> + +namespace IceTray { + typedef boost::shared_ptr<boost::program_options::options_description> OptionsDescPtr; + class DLL_PUBLIC Options : public AdHoc::AbstractPluginImplementation { + public: + Options(const std::string & name); + + + private: + friend class OptionsCollation; + virtual void options(boost::program_options::options_description_easy_init && optDesc) = 0; + OptionsDescPtr getOptions(); + const std::string optionsName; + }; + typedef AdHoc::Factory<Options> OptionsFactory; + typedef AdHoc::PluginOf<Options> OptionsPlugin; + + template <typename T> + class DLL_PUBLIC OptionsResolver { + public: + OptionsResolver() : + opts(dynamic_cast<T&>(*AdHoc::PluginManager::getDefault()->get<Options>(typeid(T).name())->implementation())) + { + } + + const T * operator->() const { return &opts; } + + private: + const T & opts; + }; + + class DLL_PUBLIC OptionsCollation { + public: + OptionsCollation(); + ~OptionsCollation(); + + void apply(Ice::PropertiesPtr p); + + private: + boost::program_options::options_description all; + }; +} +#define ICETRAY_OPTIONS_FUNC \ + options(boost::program_options::options_description_easy_init && optDesc) +#define ICETRAY_OPTIONS_BODY(OptsDef) \ + { optDesc OptsDef ; } +#define ICETRAY_OPTIONS_DECLARE \ + void ICETRAY_OPTIONS_FUNC; +#define ICETRAY_OPTIONS_INLINE(OptsDef) \ + void ICETRAY_OPTIONS_FUNC ICETRAY_OPTIONS_BODY(OptsDef) +#define ICETRAY_OPTIONS(Class, OptsDef) \ + void Class::ICETRAY_OPTIONS_FUNC ICETRAY_OPTIONS_BODY(OptsDef) + +#endif + diff --git a/icetray/unittests/Jamfile.jam b/icetray/unittests/Jamfile.jam index 7b25761..2b44a74 100644 --- a/icetray/unittests/Jamfile.jam +++ b/icetray/unittests/Jamfile.jam @@ -89,5 +89,11 @@ run <library>testCommon ; +run + testIceTrayOptions.cpp + : : : + <library>testCommon + ; + IMPORT $(__name__) : icetray.c++.sql : : icetray.c++.sql ; diff --git a/icetray/unittests/testIceTrayOptions.cpp b/icetray/unittests/testIceTrayOptions.cpp new file mode 100644 index 0000000..2c56537 --- /dev/null +++ b/icetray/unittests/testIceTrayOptions.cpp @@ -0,0 +1,59 @@ +#define BOOST_TEST_MODULE TestIceTrayLogger +#include <boost/test/unit_test.hpp> + +#include <options.h> +#include <Ice/Communicator.h> +#include <Ice/ObjectAdapter.h> +#include <Ice/Initialize.h> +#include "icetrayService.h" + +class TestOptions : public IceTray::Options { + public: + TestOptions() : IceTray::Options("Test options") + { + } + + ICETRAY_OPTIONS_INLINE( + ("testInt", boost::program_options::value(&testInt), "testInt") + ("testString", boost::program_options::value(&testString)->default_value("some string"), "testString") + ("vec", boost::program_options::value(&testVec), "vector") + ); + + int testInt; + std::string testString; + std::vector<int> testVec; +}; +FACTORY(TestOptions, IceTray::OptionsFactory); + +class TestService : public IceTray::Service { + public: + void addObjects(const std::string &, const Ice::CommunicatorPtr &, const Ice::StringSeq &, const Ice::ObjectAdapterPtr &) + { + } +}; + +BOOST_AUTO_TEST_CASE( testOptions ) +{ + auto ic = Ice::initialize(); + auto p = ic->getProperties(); + p->setProperty("test.Endpoints", "default"); + p->setProperty("testInt", "3"); + p->setProperty("vec", "1,2,4,8"); + BOOST_REQUIRE_EQUAL(4, p->getPropertyAsList("vec").size()); + + TestService ts; + ts.start("", ic, {}); + + IceTray::OptionsResolver<TestOptions> myOpts; + BOOST_REQUIRE_EQUAL(3, myOpts->testInt); + BOOST_REQUIRE_EQUAL("some string", myOpts->testString); + BOOST_REQUIRE_EQUAL(4, myOpts->testVec.size()); + BOOST_REQUIRE_EQUAL(1, myOpts->testVec[0]); + BOOST_REQUIRE_EQUAL(2, myOpts->testVec[1]); + BOOST_REQUIRE_EQUAL(4, myOpts->testVec[2]); + BOOST_REQUIRE_EQUAL(8, myOpts->testVec[3]); + + ts.stop(); + ic->destroy(); +} + |