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(); +} +  | 
