EnvironmentConfiguration.hpp
Go to the documentation of this file.
1 // @formatter:off
2 //
3 // Balau core C++ library
4 //
5 // Copyright (C) 2017 Bora Software (contact@borasoftware.com)
6 //
7 // Licensed under the Boost Software License - Version 1.0 - August 17th, 2003.
8 // See the LICENSE file for the full license text.
9 //
10 
16 
17 #ifndef COM_BORA_SOFTWARE__BALAU_APPLICATION__ENVIRONMENT_CONFIGURATION
18 #define COM_BORA_SOFTWARE__BALAU_APPLICATION__ENVIRONMENT_CONFIGURATION
19 
22 #include <Balau/Application/Impl/EnvironmentConfigurationBuilder.hpp>
25 #include <Balau/Util/Streams.hpp>
26 #include <Balau/Util/Vectors.hpp>
27 
28 // Avoid false positives.
29 #pragma clang diagnostic push
30 #pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection"
31 
32 namespace Balau {
33 
99 
116  public: template <typename ValueT>
117  static void registerValueType(const std::string & typeString) {
118  Impl::registerEnvironmentPropertyValueType<ValueT>(typeString);
119  }
120 
138  public: template <typename BaseT>
139  static void registerUniqueType(const std::string & typeString, const UniquePropertyCloner<BaseT> & cloner) {
140  Impl::registerEnvironmentPropertyUniqueType<BaseT>(typeString, cloner);
141  }
142 
159  public: static void registerUnsignedTypes() {
160  Impl::registerEnvironmentPropertyUnsignedTypes();
161  }
162 
164 
171  public: EnvironmentConfiguration(const std::vector<std::shared_ptr<Resource::Uri>> & inputs,
172  const std::vector<std::shared_ptr<Resource::Uri>> & specs = {})
173  : propertyStringsHierarchy(Impl::EnvironmentConfigurationBuilderUtils::createPropertyStrings(inputs))
174  , typeSpecificationsUris(specs) {}
175 
184  public: EnvironmentConfiguration(const std::vector<Resource::File> & inputs,
185  const std::vector<Resource::File> & specs = {})
187  Util::Vectors::map<std::shared_ptr<Resource::Uri>, Resource::File>(
188  inputs, [] (const auto & file) { return std::shared_ptr<Resource::Uri>(new Resource::File(file)); }
189  )
190  , Util::Vectors::map<std::shared_ptr<Resource::Uri>, Resource::File>(
191  specs, [] (const auto & file) { return std::shared_ptr<Resource::Uri>(new Resource::File(file)); }
192  )
193  ) {}
194 
203  public: template <typename ... UriT>
205  const Resource::Uri & firstTypeSpecifications,
206  const UriT & ... moreTypeSpecifications)
207  : propertyStringsHierarchy(Impl::EnvironmentConfigurationBuilderUtils::createPropertyStrings({ input.clone() }))
208  , typeSpecificationsUris(
210  std::shared_ptr<Resource::Uri>(firstTypeSpecifications.clone())
211  , std::shared_ptr<Resource::Uri>(moreTypeSpecifications.clone()) ...
212  )
213  ) {}
214 
223  public: template <typename ... UriT>
224  EnvironmentConfiguration(const std::shared_ptr<Resource::Uri> & input,
225  const std::shared_ptr<Resource::Uri> & firstTypeSpecifications,
226  const UriT & ... moreTypeSpecifications)
227  : propertyStringsHierarchy(Impl::EnvironmentConfigurationBuilderUtils::createPropertyStrings({ input }))
228  , typeSpecificationsUris(Util::Vectors::pushBack(firstTypeSpecifications, moreTypeSpecifications ...)) {}
229 
236  public: EnvironmentConfiguration(const std::string & input, const std::string & typeSpecifications_)
237  : propertyStringsHierarchy(Impl::EnvironmentConfigurationBuilderUtils::createPropertyStrings({ std::shared_ptr<Resource::Uri>(new Resource::StringUri(input)) }))
238  , typeSpecificationsUris(Util::Vectors::pushBack(std::shared_ptr<Resource::Uri>(new Resource::StringUri(input)))) {}
239 
246  : propertyStringsHierarchy(Impl::EnvironmentConfigurationBuilderUtils::createPropertyStrings({ input.clone() })) {}
247 
253  public: EnvironmentConfiguration(const std::shared_ptr<Resource::Uri> & input)
254  : propertyStringsHierarchy(Impl::EnvironmentConfigurationBuilderUtils::createPropertyStrings({ input })) {}
255 
261  public: EnvironmentConfiguration(const std::string & input)
262  : propertyStringsHierarchy(Impl::EnvironmentConfigurationBuilderUtils::createPropertyStrings({ std::shared_ptr<Resource::Uri>(new Resource::StringUri(input)) })) {}
263 
265 
276  protected: template <typename ... FactoryPtrT>
277  Impl::PropertyBindingBuilderFactoryPtr group(std::string name, FactoryPtrT ... tokens) const {
278  auto factory = Impl::PropertyBindingBuilderFactoryPtr(
279  new Impl::CompositePropertyBindingBuilderFactory(std::move(name))
280  );
281 
282  allBindingBuilderFactories.emplace_back(factory);
283 
284  auto composite = std::static_pointer_cast<Impl::CompositePropertyBindingBuilderFactory>(factory);
285  Impl::EnvironmentConfigurationBuilderUtils::addToComposite(*composite, tokens ...);
286  Impl::EnvironmentConfigurationBuilderUtils::incrementLevel(tokens ...);
287 
288  return factory;
289  }
290 
298  protected: template <typename ValueT = std::string>
299  Impl::PropertyBindingBuilderFactoryPtr value(std::string name) const {
300  auto factory = Impl::PropertyBindingBuilderFactoryPtr(
301  new Impl::ValuePropertyBindingBuilderFactory<ValueT>(std::move(name))
302  );
303 
304  allBindingBuilderFactories.emplace_back(factory);
305  return factory;
306  }
307 
319  protected: template <typename ValueT = std::string>
320  Impl::PropertyBindingBuilderFactoryPtr value(std::string name, ValueT defaultValue) const {
321  auto factory = Impl::PropertyBindingBuilderFactoryPtr(
322  new Impl::ValuePropertyBindingBuilderFactory<ValueT>(std::move(name), defaultValue)
323  );
324 
325  allBindingBuilderFactories.emplace_back(factory);
326  return factory;
327  }
328 
343  protected: template <typename BaseT>
344  Impl::PropertyBindingBuilderFactoryPtr unique(std::string name) const {
345  Impl::PropertyBindingBuilderFactoryPtr factory = Impl::getBindingBuilderFactory(typeid(BaseT), name, "");
346  allBindingBuilderFactories.emplace_back(factory);
347  return factory;
348  }
349 
364  protected: template <typename BaseT>
365  Impl::PropertyBindingBuilderFactoryPtr unique(std::string name, std::unique_ptr<BaseT> && defaultValue) const {
366  Impl::PropertyBindingBuilderFactoryPtr factory = Impl::getBindingBuilderFactory(typeid(BaseT), name, "");
367  auto f = factory->clone(name, defaultValue);
368  allBindingBuilderFactories.emplace_back(f);
369  return f;
370  }
371 
381  protected: template <typename BaseT>
382  Impl::PropertyBindingBuilderFactoryPtr unique(std::string name, const UniquePropertyCloner<BaseT> & cloner) const {
383  auto factory = Impl::PropertyBindingBuilderFactoryPtr(
384  new Impl::UniquePropertyBindingBuilderFactory<BaseT>(std::move(name), cloner)
385  );
386 
387  allBindingBuilderFactories.emplace_back(factory);
388  return factory;
389  }
390 
404  protected: template <typename BaseT>
405  Impl::PropertyBindingBuilderFactoryPtr unique(std::string name,
406  const UniquePropertyCloner<BaseT> & cloner,
407  std::unique_ptr<BaseT> && defaultValue) const {
408  auto factory = Impl::PropertyBindingBuilderFactoryPtr(
409  new Impl::UniquePropertyBindingBuilderFactory<BaseT>(std::move(name), cloner, std::move(defaultValue))
410  );
411 
412  allBindingBuilderFactories.emplace_back(factory);
413  return factory;
414  }
415 
417 
418  //
419  // Empty configure() implementation. Called when a non-derived EnvironmentConfiguration
420  // instance is created by specifying one or more type specification URIs.
421  //
422  public: void configure() const override {}
423 
424  //
425  // The main build method. Run after the configure() method by the base class.
426  // This method delegates the building to a separate builder class.
427  //
428  public: std::vector<std::shared_ptr<Impl::BindingBuilderBase>> build() const override {
429  if (!testing) {
430  std::vector<Impl::PropertyBindingBuilderFactoryPtr> bindingBuilderFactoriesVector;
431 
432  for (auto & factory : allBindingBuilderFactories) {
433  if (factory->level == 0) {
434  bindingBuilderFactoriesVector.push_back(std::move(factory));
435  }
436  }
437 
438  builders = Impl::EnvironmentConfigurationBuilder::build(
439  typeSpecificationsUris, bindingBuilderFactoriesVector, propertyStringsHierarchy
440  );
441  }
442 
443  return builders;
444  }
445 
446  public: std::vector<const InjectorConfiguration *> getExtraConfiguration() const override {
447  return std::vector<const InjectorConfiguration *>(); // Not used.
448  }
449 
450  public: std::list<std::function<void (const Injector& )>> getPostConstructionCalls() const override {
451  return std::list<std::function<void (const Injector& )>>(); // Not used.
452  }
453 
454  public: std::list<std::function<void ()>> getPreDestructionCalls() const override {
455  return std::list<std::function<void ()>>(); // Not used.
456  }
457 
458  public: std::list<std::unique_ptr<StaticSingletonRegistrationBase>> getStaticSingletonPostConstructionCalls() const override {
459  return std::list<std::unique_ptr<StaticSingletonRegistrationBase>>(); // Not used.
460  }
461 
462  private: static std::shared_ptr<Resource::Uri> verifyPropertyFileExists(const Resource::File & propertyFile) {
464 
465  if (!propertyFile.exists()) {
468  , toString("The property file does not exist: ", propertyFile)
469  );
470  }
471 
472  if (!propertyFile.isRegularFile()) {
475  , toString("The property file is not a regular file: ", propertyFile)
476  );
477  }
478 
479  return propertyFile.clone();
480  }
481 
482  friend class Impl::PropertyTypeSpecificationVisitor;
483 
484  //
485  // The property strings trie is built during construction, by passing the input properties file
486  // to the property parser service, then running the visitor to construct the hierarchy.
487  //
488  private: Container::ObjectTrie<Impl::PropertyString> propertyStringsHierarchy;
489 
490  //
491  // The URIs of the type specification sources that will be used
492  // (used during direct usage of the EnvironmentConfiguration class).
493  //
494  private: std::vector<std::shared_ptr<Resource::Uri>> typeSpecificationsUris;
495 
496  //
497  // Temporary data structure used to hold binding builder factories during the
498  // configure() method call. The binding builder factories are kept in an
499  // initially flatted structure (this vector).
500  //
501  // Before executing the main builder logic, the level 0 factories are extracted
502  // into a new vector.
503  //
504  private: mutable std::vector<Impl::PropertyBindingBuilderFactoryPtr> allBindingBuilderFactories;
505 
506  //
507  // The binding builders are constructed in the second part of the build() method call,
508  // by iterating over the property strings hierarchy.
509  //
510  // - If the property is composite, an EnvironmentProperties named binding is created.
511  //
512  // - If the property is simple and a corresponding binding builder factory is found
513  // in the binding builder factory hierarchy, a typed named binding is created.
514  //
515  // - If the property is simple and no corresponding binding builder factory is found
516  // in the binding builder factory hierarchy, a std::string named binding is created.
517  //
518  // During iteration over the property strings hierarchy, the constructed bindings are
519  // placed within the current binding level. The level is either the root (injector)
520  // level or is a descendant EnvironmentProperties instance.
521  //
522  private: mutable std::vector<std::shared_ptr<Impl::BindingBuilderBase>> builders;
523 
524  friend struct Impl::EnvironmentConfigurationBuilderTest;
525 
526  // For testing only.
527  private: static EnvironmentConfiguration testInstance(std::vector<std::shared_ptr<Impl::BindingBuilderBase>> && builders_) {
529  conf.builders = std::move(builders_);
530  return conf;
531  }
532 
533  // For testing only.
534  private: EnvironmentConfiguration() : testing(true) {}
535 
536  // For testing only. Bypasses the normal binding builder creation.
537  private: const bool testing = false;
538 };
539 
540 } // namespace Balau
541 
542 #pragma clang diagnostic pop
543 
544 #endif // COM_BORA_SOFTWARE__BALAU_APPLICATION__ENVIRONMENT_CONFIGURATION
The abstract base class for all Injector configuration classes.
static std::vector< T > pushBack()
Create and populate a vector via emplace back of multiple elements (empty case).
Definition: Vectors.hpp:71
EnvironmentConfiguration(const Resource::Uri &input, const Resource::Uri &firstTypeSpecifications, const UriT &... moreTypeSpecifications)
Create an environment configuration by specifying the source properties file and the property types v...
Definition: EnvironmentConfiguration.hpp:204
EnvironmentConfiguration(const std::vector< Resource::File > &inputs, const std::vector< Resource::File > &specs={})
Create an environment configuration by specifying a vector of files pointing to the source properties...
Definition: EnvironmentConfiguration.hpp:184
#define ThrowBalauException(ExceptionClass,...)
Throw a Balau style exception, with implicit file and line number, and optional stacktrace.
Definition: BalauException.hpp:45
static void registerValueType(const std::string &typeString)
Add a non-polymorphic type custom property binding builder factory to the global property binding bui...
Definition: EnvironmentConfiguration.hpp:117
EnvironmentConfiguration(const std::string &input, const std::string &typeSpecifications_)
Create an environment configuration by specifying a string for the source properties text and the pro...
Definition: EnvironmentConfiguration.hpp:236
An abstract universal resource identifier.
Definition: Uri.hpp:131
Utilities for streams.
Utilities for vectors.
static void registerUniqueType(const std::string &typeString, const UniquePropertyCloner< BaseT > &cloner)
Add a polymorphic type custom property binding builder factory to the global property binding builder...
Definition: EnvironmentConfiguration.hpp:139
Balau::U8String< AllocatorT > toString(const BalauException &e)
Base class toString<AllocatorT> function for Balau exceptions.
Definition: BalauException.hpp:122
EnvironmentConfiguration(const std::string &input)
Create an environment configuration by specifying a string for the source properties text...
Definition: EnvironmentConfiguration.hpp:261
std::unique_ptr< Uri > clone() const override
Clone the concrete Uri.
Definition: File.hpp:217
virtual std::unique_ptr< Uri > clone() const =0
Clone the concrete Uri.
The root Balau namespace.
Definition: ApplicationConfiguration.hpp:23
Environment configurations specify typed and untyped environment injector bindings.
Definition: EnvironmentConfiguration.hpp:97
Impl::PropertyBindingBuilderFactoryPtr unique(std::string name) const
Declare a polymorphic "unique" value property specification in the environment configuration.
Definition: EnvironmentConfiguration.hpp:344
EnvironmentConfiguration(const std::vector< std::shared_ptr< Resource::Uri >> &inputs, const std::vector< std::shared_ptr< Resource::Uri >> &specs={})
Create an environment configuration by specifying a vector of URIs pointing to the source properties ...
Definition: EnvironmentConfiguration.hpp:171
EnvironmentConfiguration(const std::shared_ptr< Resource::Uri > &input, const std::shared_ptr< Resource::Uri > &firstTypeSpecifications, const UriT &... moreTypeSpecifications)
Create an environment configuration by specifying a URI pointing to the source properties text and th...
Definition: EnvironmentConfiguration.hpp:224
Impl::PropertyBindingBuilderFactoryPtr value(std::string name, ValueT defaultValue) const
Declare a non-polymorphic value property specification in the environment configuration, specifying a default value.
Definition: EnvironmentConfiguration.hpp:320
Parser service for property file parsing.
An immediate string pseudo-URI.
bool isRegularFile() const override
Returns true if the file URI points to a regular file.
Definition: File.hpp:495
An immediate string pseudo-URI.
Definition: StringUri.hpp:49
Thrown when there is an issue loading an environment property file.
Definition: InjectorExceptions.hpp:111
A file on the local file system.
Definition: File.hpp:35
Impl::PropertyBindingBuilderFactoryPtr unique(std::string name, const UniquePropertyCloner< BaseT > &cloner, std::unique_ptr< BaseT > &&defaultValue) const
Declare a polymorphic "unique" value property specification in the environment configuration, specifying a default value.
Definition: EnvironmentConfiguration.hpp:405
static std::vector< D > map(const std::vector< S > &input, std::function< D(const S &)> f)
Perform a map operator from one vector to another (transform the input elements to a vector of differ...
Definition: Vectors.hpp:122
void configure() const override
Configure the injector configuration.
Definition: EnvironmentConfiguration.hpp:422
EnvironmentConfiguration(const std::shared_ptr< Resource::Uri > &input)
Create an environment configuration by specifying a URI pointing to the source properties text...
Definition: EnvironmentConfiguration.hpp:253
EnvironmentConfiguration(const Resource::Uri &input)
Create an environment configuration by specifying the source properties file.
Definition: EnvironmentConfiguration.hpp:245
Injector configurations specify injector bindings.
Definition: InjectorConfiguration.hpp:32
Impl::PropertyBindingBuilderFactoryPtr unique(std::string name, std::unique_ptr< BaseT > &&defaultValue) const
Declare a polymorphic "unique" value property specification in the environment configuration, specifying a default value.
Definition: EnvironmentConfiguration.hpp:365
Impl::PropertyBindingBuilderFactoryPtr group(std::string name, FactoryPtrT ... tokens) const
Declare a composite property specification in the environment configuration.
Definition: EnvironmentConfiguration.hpp:277
Impl::PropertyBindingBuilderFactoryPtr value(std::string name) const
Declare a non-polymorphic value property specification in the environment configuration.
Definition: EnvironmentConfiguration.hpp:299
std::function< std::unique_ptr< BaseT >(const std::unique_ptr< const BaseT > &)> UniquePropertyCloner
The clone function type for unique pointer prototypes.
Definition: BindingBuilder.hpp:36
bool exists() const
Returns true if an item exits in the file system for the file URI.
Definition: File.hpp:449
static void registerUnsignedTypes()
Register C++ specific unsigned integer value type property binding builder factories in the global pr...
Definition: EnvironmentConfiguration.hpp:159
Balau::U8String< AllocatorT > toString(LoggingLevel level)
Print the logging level as a UTF-8 string.
Definition: LoggingLevel.hpp:73
An injector binding candidate created via the injector configuration.
Impl::PropertyBindingBuilderFactoryPtr unique(std::string name, const UniquePropertyCloner< BaseT > &cloner) const
Declare a polymorphic "unique" value property specification in the environment configuration.
Definition: EnvironmentConfiguration.hpp:382