summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2017-07-08 14:07:24 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2017-07-10 16:03:41 +0100
commit71975cdae467e0789ffe6c65ecbb575ea9fcc804 (patch)
tree1e505af276ca3819b02729e6ef26230e26434e28
parentRefactor setup/shutdown of logger into neater functions (diff)
downloadicetray-71975cdae467e0789ffe6c65ecbb575ea9fcc804.tar.bz2
icetray-71975cdae467e0789ffe6c65ecbb575ea9fcc804.tar.xz
icetray-71975cdae467e0789ffe6c65ecbb575ea9fcc804.zip
Add basic components for populating options classes from Ice::Properties
-rw-r--r--icetray/icetray/Jamfile.jam3
-rw-r--r--icetray/icetray/icetrayService.cpp1
-rw-r--r--icetray/icetray/icetrayService.h2
-rw-r--r--icetray/icetray/options.cpp60
-rw-r--r--icetray/icetray/options.h62
-rw-r--r--icetray/unittests/Jamfile.jam6
-rw-r--r--icetray/unittests/testIceTrayOptions.cpp59
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();
+}
+