From 71975cdae467e0789ffe6c65ecbb575ea9fcc804 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 8 Jul 2017 14:07:24 +0100 Subject: Add basic components for populating options classes from Ice::Properties --- icetray/icetray/Jamfile.jam | 3 ++ icetray/icetray/icetrayService.cpp | 1 + icetray/icetray/icetrayService.h | 2 ++ icetray/icetray/options.cpp | 60 +++++++++++++++++++++++++++++++ icetray/icetray/options.h | 62 ++++++++++++++++++++++++++++++++ icetray/unittests/Jamfile.jam | 6 ++++ icetray/unittests/testIceTrayOptions.cpp | 59 ++++++++++++++++++++++++++++++ 7 files changed, 193 insertions(+) create mode 100644 icetray/icetray/options.cpp create mode 100644 icetray/icetray/options.h create mode 100644 icetray/unittests/testIceTrayOptions.cpp 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 : ..//boost_system ..//boost_thread ../..//glibmm + boost_program_options yes 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 #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 logWriters; + OptionsCollation optionsCollation; }; typedef IceInternal::Handle 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 + +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()) { + auto o = f->implementation()->create(); + defManager->add(o, typeid(*o).name(), __FILE__, __LINE__); + all.add(*o->getOptions()); + } + } + + OptionsCollation::~OptionsCollation() + { + auto defManager = AdHoc::PluginManager::getDefault(); + for (auto o : defManager->getAll()) { + defManager->remove(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 +#include +#include +#include + +namespace IceTray { + typedef boost::shared_ptr 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 OptionsFactory; + typedef AdHoc::PluginOf OptionsPlugin; + + template + class DLL_PUBLIC OptionsResolver { + public: + OptionsResolver() : + opts(dynamic_cast(*AdHoc::PluginManager::getDefault()->get(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 testCommon ; +run + testIceTrayOptions.cpp + : : : + 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 + +#include +#include +#include +#include +#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 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 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(); +} + -- cgit v1.2.3