propertysystem.hh
Go to the documentation of this file.
1 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 // vi: set et ts=4 sw=4 sts=4:
3 /*
4  This file is part of the Open Porous Media project (OPM).
5 
6  OPM is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 2 of the License, or
9  (at your option) any later version.
10 
11  OPM is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with OPM. If not, see <http://www.gnu.org/licenses/>.
18 
19  Consult the COPYING file in the top-level source directory of this
20  module for the precise wording of the license and the list of
21  copyright holders.
22 */
42 #ifndef EWOMS_PROPERTIES_HH
43 #define EWOMS_PROPERTIES_HH
44 
45 #include <dune/common/classname.hh>
46 #include <opm/common/ErrorMacros.hpp>
47 #include <opm/common/Exceptions.hpp>
48 #include <opm/common/Unused.hpp>
49 
50 #include <type_traits> // required for 'is_base_of<A, B>'
51 
52 #include <map>
53 #include <set>
54 #include <list>
55 #include <string>
56 #include <iostream>
57 #include <sstream>
58 #include <cstring>
59 #include <tuple>
60 
62 
63 namespace Ewoms {
64 namespace Properties {
65 
66 #define EWOMS_GET_HEAD_(Arg1, ...) Arg1
67 
68 #if !defined NO_PROPERTY_INTROSPECTION
69 
71 #define PROP_INFO_(EffTypeTagName, PropKind, PropTagName, ...) \
72  template <> \
73  struct PropertyInfo<TTAG(EffTypeTagName), PTAG(PropTagName)> \
74  { \
75  static int init() { \
76  PropertyRegistryKey key( \
77  /*effTypeTagName=*/ Dune::className<TTAG(EffTypeTagName)>(), \
78  /*kind=*/PropKind, \
79  /*name=*/propertyName(), \
80  /*value=*/#__VA_ARGS__, \
81  /*file=*/__FILE__, \
82  /*line=*/__LINE__); \
83  PropertyRegistry::addKey(key); \
84  return 0; \
85  } \
86  static std::string propertyName() { return #PropTagName; } \
87  }; \
88  namespace fooPropInfo_ ## EffTypeTagName { \
89  static const int foo_ ## PropTagName OPM_UNUSED = \
90  PropertyInfo<TTAG(EffTypeTagName), PTAG(PropTagName)>::init(); \
91  }
92 
93 
95 #define TTAG_INFO_(TagName, ...) \
96  template <> \
97  struct TypeTagInfo<TTAG(TagName)> \
98  { \
99  static int init() { \
100  TypeTagRegistry::addAllChildren<TTAG(TagName), __VA_ARGS__>(); \
101  return 0; \
102  } \
103  }; \
104  static const int fooTypeTagInfo_ ## TagName OPM_UNUSED = \
105  TypeTagInfo<TagName>::init();
106 
108 #define SPLICE_INFO_(SpliceName, ...) \
109  template <> \
110  struct SpliceInfo<TTAG(SpliceName)> \
111  { \
112  static int init() { \
113  TypeTagRegistry::addAllSplices<TTAG(SpliceName), __VA_ARGS__>(); \
114  return 0; \
115  } \
116  }; \
117  static const int fooSpliceInfo_ ## SpliceName OPM_UNUSED = \
118  SpliceInfo<TTAG(SpliceName)>::init();
119 
120 #else
121 #define PROP_INFO_(EffTypeTagName, PropKind, PropTagName, ...)
123 #define TTAG_INFO_(EffTypeTagName, ...)
124 #define SPLICE_INFO_(EffTypeTagName, ...)
125 #endif
126 
127 // some macros for simplification
128 
130 
138 #define TTAG(TypeTagName) Ewoms::Properties::TTag::TypeTagName
139 
147 #define PTAG(PropTagName) Ewoms::Properties::PTag::PropTagName
148 
169 #define NEW_TYPE_TAG(...) \
170  namespace TTag { \
171  struct EWOMS_GET_HEAD_(__VA_ARGS__, dontcare) \
172  : public TypeTag<__VA_ARGS__> \
173  { }; \
174  TTAG_INFO_(__VA_ARGS__, void) \
175  } \
176  extern int semicolonHack_
177 
213 #define SET_SPLICES(TypeTagName, ...) \
214  namespace PTag { \
215  template<> \
216  struct Splices<TTAG(TypeTagName)> \
217  { \
218  typedef RevertedTuple<__VA_ARGS__>::type tuple; \
219  }; \
220  SPLICE_INFO_(TypeTagName, __VA_ARGS__) \
221  } \
222  extern int semicolonHack_
223 
230 #define INHERITS_FROM(...) __VA_ARGS__
231 
247 #define NEW_PROP_TAG(PTagName) \
248  namespace PTag { \
249  struct PTagName; } extern int semicolonHack_
250 
252 #define SET_PROP_(EffTypeTagName, PropKind, PropTagName, ...) \
253  template <class TypeTag> \
254  struct Property<TypeTag, \
255  TTAG(EffTypeTagName), \
256  PTAG(PropTagName)>; \
257  PROP_INFO_(EffTypeTagName, \
258  /*kind=*/PropKind, \
259  PropTagName, \
260  /*value=*/__VA_ARGS__) \
261  template <class TypeTag> \
262  struct Property<TypeTag, \
263  TTAG(EffTypeTagName), \
264  PTAG(PropTagName) >
265 
297 #define SET_PROP(EffTypeTagName, PropTagName) \
298  template <class TypeTag> \
299  struct Property<TypeTag, \
300  TTAG(EffTypeTagName), \
301  PTAG(PropTagName)>; \
302  PROP_INFO_(EffTypeTagName, \
303  /*kind=*/"opaque", \
304  PropTagName, \
305  /*value=*/"<opaque>") \
306  template <class TypeTag> \
307  struct Property<TypeTag, \
308  TTAG(EffTypeTagName), \
309  PTAG(PropTagName) >
310 
325 #define UNSET_PROP(EffTypeTagName, PropTagName) \
326  template <> \
327  struct PropertyUnset<TTAG(EffTypeTagName), \
328  PTAG(PropTagName) >; \
329  PROP_INFO_(EffTypeTagName, \
330  /*kind=*/"withdraw", \
331  PropTagName, \
332  /*value=*/<none>) \
333  template <> \
334  struct PropertyUnset<TTAG(EffTypeTagName), \
335  PTAG(PropTagName) > \
336  : public PropertyExplicitlyUnset \
337  {}
338 
345 #define SET_INT_PROP(EffTypeTagName, PropTagName, /*Value*/...) \
346  SET_PROP_(EffTypeTagName, \
347  /*kind=*/"int ", \
348  PropTagName, \
349  /*value=*/__VA_ARGS__) \
350  { \
351  typedef int type; \
352  static const int value = __VA_ARGS__; \
353  }
354 
361 #define SET_BOOL_PROP(EffTypeTagName, PropTagName, /*Value*/...) \
362  SET_PROP_(EffTypeTagName, \
363  /*kind=*/"bool ", \
364  PropTagName, \
365  /*value=*/__VA_ARGS__) \
366  { \
367  typedef bool type; \
368  static const bool value = __VA_ARGS__; \
369  }
370 
377 #define SET_TYPE_PROP(EffTypeTagName, PropTagName, /*Value*/...) \
378  SET_PROP_(EffTypeTagName, \
379  /*kind=*/"type ", \
380  PropTagName, \
381  /*value=*/__VA_ARGS__) \
382  { \
383  typedef __VA_ARGS__ type; \
384  }
385 
394 #define SET_SCALAR_PROP(EffTypeTagName, PropTagName, ...) \
395  SET_PROP_(EffTypeTagName, \
396  /*kind=*/"scalar", \
397  PropTagName, \
398  /*value=*/__VA_ARGS__) \
399  { \
400  typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; \
401  public: \
402  typedef Scalar type; \
403  static const Scalar value; \
404  }; \
405  template <class TypeTag> \
406  const typename Property<TypeTag, TTAG(EffTypeTagName), PTAG(PropTagName)>::type \
407  Property<TypeTag, TTAG(EffTypeTagName), PTAG(PropTagName)>::value(__VA_ARGS__)
408 
416 #define SET_STRING_PROP(EffTypeTagName, PropTagName, ...) \
417  SET_PROP_(EffTypeTagName, \
418  /*kind=*/"string", \
419  PropTagName, \
420  /*value=*/__VA_ARGS__) \
421  { \
422  public: \
423  typedef std::string type; \
424  static const std::string value; \
425  }; \
426  template <class TypeTag> \
427  const typename Property<TypeTag, TTAG(EffTypeTagName), PTAG(PropTagName)>::type \
428  Property<TypeTag, TTAG(EffTypeTagName), PTAG(PropTagName)>::value(__VA_ARGS__)
429 
436 #define SET_TAG_PROP(EffTypeTagName, PropTagName, ValueTypeTagName) \
437  SET_PROP_(EffTypeTagName, \
438  /*kind=*/"tag ", \
439  PropTagName, \
440  /*value=*/TTAG(ValueTypeTagName)) \
441  { \
442  typedef TTAG(ValueTypeTagName) type; \
443  }
444 
445 
454 #define GET_PROP(TypeTag, PropTagName) \
455  ::Ewoms::Properties::GetProperty<TypeTag, PTAG(PropTagName)>::p
456 #define GET_PROP_(TypeTag, PropTag) \
458  ::Ewoms::Properties::GetProperty<TypeTag, PropTag>::p
459 
469 #define GET_PROP_VALUE(TypeTag, PropTagName) \
470  ::Ewoms::Properties::GetProperty<TypeTag, PTAG(PropTagName)>::p::value
471 #define GET_PROP_VALUE_(TypeTag, PropTag) \
473  ::Ewoms::Properties::GetProperty<TypeTag, PropTag>::p::value
474 
486 #define GET_PROP_TYPE(TypeTag, PropTagName) \
487  ::Ewoms::Properties::GetProperty<TypeTag, PTAG(PropTagName)>::p::type
488 #define GET_PROP_TYPE_(TypeTag, PropTag) \
490  ::Ewoms::Properties::GetProperty<TypeTag, PropTag>::p::type
491 
493 #if !defined NO_PROPERTY_INTROSPECTION
494 
511 #define PROP_DIAGNOSTIC(TypeTag, PropTagName) \
512  ::Ewoms::Properties::getDiagnostic<TypeTag>(#PropTagName)
513 
514 #else
515 #define PROP_DIAGNOSTIC(TypeTag, PropTagName) "Property introspection disabled by macro NO_PROPERTY_INTROSPECTION."
516 #endif
517 
519 // some serious template kung fu. Don't look at it too closely, it
520 // might damage your brain!
522 
524 
525 namespace PTag {}
526 namespace TTag {}
527 
528 #if !defined NO_PROPERTY_INTROSPECTION
529 
530 namespace TTag
531 {
532 template <class EffTypeTag>
533 struct TypeTagInfo
534 {};
535 }
536 
537 namespace PTag
538 {
539 template <class EffTypeTagName>
540 struct SpliceInfo
541 {};
542 }
543 
544 template <class EffTypeTagName, class PropTagName>
545 struct PropertyInfo
546 {};
547 
548 class PropertyRegistryKey
549 {
550 public:
551  PropertyRegistryKey()
552  {}
553 
554  PropertyRegistryKey(const std::string& effTypeTagName,
555  const std::string& propertyKind,
556  const std::string& propertyName,
557  const std::string& propertyValue,
558  const std::string& fileDefined,
559  int lineDefined)
560  : effTypeTagName_(effTypeTagName)
561  , propertyKind_(propertyKind)
562  , propertyName_(propertyName)
563  , propertyValue_(propertyValue)
564  , fileDefined_(fileDefined)
565  , lineDefined_(lineDefined)
566  { }
567 
568  // copy constructor
569  PropertyRegistryKey(const PropertyRegistryKey&) = default;
570  PropertyRegistryKey& operator=(const PropertyRegistryKey&) = default;
571 
572  const std::string& effTypeTagName() const
573  { return effTypeTagName_; }
574  const std::string& propertyKind() const
575  { return propertyKind_; }
576  const std::string& propertyName() const
577  { return propertyName_; }
578  const std::string& propertyValue() const
579  { return propertyValue_; }
580  const std::string& fileDefined() const
581  { return fileDefined_; }
582  int lineDefined() const
583  { return lineDefined_; }
584 
585 private:
586  std::string effTypeTagName_;
587  std::string propertyKind_;
588  std::string propertyName_;
589  std::string propertyValue_;
590  std::string fileDefined_;
591  int lineDefined_;
592 };
593 
594 
595 template <class TypeTag, class PropertyTag>
596 struct GetProperty;
597 
598 class TypeTagRegistry
599 {
600 public:
601  struct SpliceRegistryEntry {
602  SpliceRegistryEntry(const std::string& name)
603  { name_ = name; }
604 
605  std::string propertyName() const
606  { return name_; }
607 
608  private:
609  std::string name_;
610  };
611 
612  typedef std::list<std::unique_ptr<SpliceRegistryEntry> > SpliceList;
613  typedef std::map<std::string, SpliceList> SpliceListMap;
614 
615  typedef std::list<std::string> ChildrenList;
616  typedef std::map<std::string, ChildrenList> ChildrenListMap;
617 
618  // this method adds the children of a type tag to the registry if the registry does
619  // not yet contain an entry for that type tag
620  template <class TypeTag, typename ... Children>
621  static void addAllChildren()
622  {
623  std::string typeTagName = Dune::className<TypeTag>();
624 
625  if (children_().find(typeTagName) == children_().end())
626  addChildren<TypeTag, Children...>();
627  }
628 
629 
630  // end of recursion. the last argument is not a child, but 'void'
631  // which is required for the macro magic...
632  template <class TypeTag, class DummyChild>
633  static void addChildren()
634  {}
635 
636  // the last argument is not a child, but 'void' which is required
637  // for the macro magic...
638  template <class TypeTag, class Child1, class Child2, typename ... RemainingChildren>
639  static void addChildren()
640  {
641  std::string typeTagName = Dune::className<TypeTag>();
642 
643  children_()[typeTagName].emplace_front(Dune::className<Child1>());
644 
645  addChildren<TypeTag, Child2, RemainingChildren...>();
646  }
647 
648  // this method adds the splices of a type tag to the registry if the registry does
649  // not yet contain an entry for that type tag
650  template <class TypeTag, typename ... Splices>
651  static void addAllSplices()
652  {
653  std::string typeTagName = Dune::className<TypeTag>();
654 
655  if (splices_().find(typeTagName) == splices_().end())
656  addSplices<TypeTag, Splices...>();
657  }
658 
659 
660  // end of recursion. the last argument is not a child, but 'void'
661  // which is required for the macro magic...
662  template <class TypeTag>
663  static void addSplices()
664  { }
665 
666  // the last argument is not a child, but 'void' which is required
667  // for the macro magic...
668  template <class TypeTag, class Splice1, typename ... RemainingSplices>
669  static void addSplices()
670  {
671  const std::string& typeTagName = Dune::className<TypeTag>();
672  const std::string& propName =
673  PropertyInfo<typename GetProperty<TypeTag, Splice1>::template GetEffectiveTypeTag_<TypeTag>::type, Splice1>::propertyName();
674 
675  splices_()[typeTagName].emplace_front(new SpliceRegistryEntry(propName));
676 
677  addSplices<TypeTag, RemainingSplices...>();
678  }
679 
680  static const SpliceList& splices(const std::string& typeTagName)
681  { return splices_()[typeTagName]; }
682 
683  static const ChildrenList& children(const std::string& typeTagName)
684  { return children_()[typeTagName]; }
685 
686 private:
687  static SpliceListMap& splices_()
688  {
689  static SpliceListMap data;
690  return data;
691  }
692  static ChildrenListMap& children_()
693  {
694  static ChildrenListMap data;
695  return data;
696  }
697 };
698 
699 class PropertyRegistry
700 {
701  typedef Ewoms::Properties::TypeTagRegistry TypeTagRegistry;
702 
703 public:
704  typedef std::map<std::string, PropertyRegistryKey> KeyList;
705  typedef std::map<std::string, KeyList> KeyListMap;
706 
707  static void addKey(const PropertyRegistryKey& key)
708  {
709  keys_()[key.effTypeTagName()][key.propertyName()] = key;
710  }
711 
712  static const std::string& getSpliceTypeTagName(const std::string& typeTagName,
713  const std::string& propertyName)
714  {
715  const auto& keyIt = keys_().find(typeTagName);
716  const auto& keyEndIt = keys_().end();
717  if (keyIt == keyEndIt)
718  OPM_THROW(std::runtime_error,
719  "Unknown type tag key '" << typeTagName << "'");
720 
721  // check whether the propery is directly defined for the type tag currently
722  // checked, ...
723  const auto& propIt = keyIt->second.find(propertyName);
724  const auto& propEndIt = keyIt->second.end();
725  if (propIt != propEndIt)
726  return propIt->second.propertyValue();
727 
728  // ..., if not, check all splices, ...
729  typedef typename TypeTagRegistry::SpliceList SpliceList;
730  const SpliceList& splices = TypeTagRegistry::splices(typeTagName);
731  SpliceList::const_iterator spliceIt = splices.begin();
732  for (; spliceIt != splices.end(); ++spliceIt) {
733  const auto& spliceTypeTagName =
734  PropertyRegistry::getSpliceTypeTagName(typeTagName,
735  (*spliceIt)->propertyName());
736 
737  if (spliceTypeTagName == "")
738  continue;
739 
740  const auto& tmp = getSpliceTypeTagName(spliceTypeTagName, propertyName);
741  if (tmp != "")
742  return tmp;
743  }
744 
745  // .. if still not, check all normal children.
746  typedef TypeTagRegistry::ChildrenList ChildrenList;
747  const ChildrenList& children = TypeTagRegistry::children(typeTagName);
748  ChildrenList::const_iterator ttagIt = children.begin();
749  for (; ttagIt != children.end(); ++ttagIt) {
750  const auto& tmp = getSpliceTypeTagName(*ttagIt, propertyName);
751  if (tmp != "")
752  return tmp;
753  }
754 
755  // if the property was not defined on a given type tag, return
756  // the empty string.
757  static std::string tmp("");
758  return tmp;
759  }
760 
761  static const PropertyRegistryKey& getKey(const std::string& effTypeTagName,
762  const std::string& propertyName)
763  { return keys_()[effTypeTagName][propertyName]; }
764 
765  static const KeyList& getKeys(const std::string& effTypeTagName)
766  { return keys_()[effTypeTagName]; }
767 
768 private:
769  static KeyListMap& keys_()
770  {
771  static KeyListMap data;
772  return data;
773  }
774 };
775 
776 #endif // !defined NO_PROPERTY_INTROSPECTION
777 
778 struct PropertyUndefined { };
779 class PropertyExplicitlyUnset {};
780 
781 template <class RealTypeTag,
782  class EffectiveTypeTag,
783  class PropertyTag>
784 struct Property : public PropertyUndefined
785 {};
786 
787 template <class EffectiveTypeTag,
788  class PropertyTag>
789 struct PropertyUnset : public PropertyUndefined
790 {};
791 
792 template <class Tree, class PropertyTag>
793 struct propertyExplicitlyUnset
794 {
795  const static bool value =
796  std::is_base_of<PropertyExplicitlyUnset,
797  PropertyUnset<typename Tree::SelfType,
798  PropertyTag>
799  >::value;
800 };
801 
802 template <class Tree, class PropertyTag>
803 class propertyExplicitlyUnsetOnTree
804 {
805  static const bool explicitlyUnset = propertyExplicitlyUnset<Tree, PropertyTag>::value;
806 
807  template <class ChildTuple>
808  struct unsetOnAllChildren
809  { static const bool value = true; };
810 
811  template <class Child, class ... RemainingChildren>
812  struct unsetOnAllChildren<std::tuple<Child, RemainingChildren...> >
813  { static const bool value =
814  propertyExplicitlyUnsetOnTree<Child, PropertyTag>::value
815  && unsetOnAllChildren<std::tuple<RemainingChildren...> >::value; };
816 
817 public:
818  static const bool value =
819  (explicitlyUnset || (!Tree::isLeaf && unsetOnAllChildren<typename Tree::ChildrenTuple>::value));
820 };
821 
822 template <class PropertyTag>
823 struct propertyExplicitlyUnsetOnTree<void, PropertyTag>
824 {
825  const static bool value = std::true_type::value;
826 };
827 
828 template <class RealTypeTag, class Tree, class PropertyTag>
829 struct propertyDefinedOnSelf
830 {
831  const static bool value =
832  ! std::is_base_of<PropertyUndefined,
833  Property<RealTypeTag,
834  typename Tree::SelfType,
835  PropertyTag> >::value;
836 };
837 
838 // template class to revert the order or a std::tuple's arguments. This is required to
839 // make the properties of children defined on the right overwrite the properties of the
840 // children on the left. See https://sydius.me/2011/07/reverse-tuple-in-c/
841 template<typename... Args>
842 class RevertedTuple
843 {
844 private:
845  template<unsigned int N, typename... All>
846  struct RevertedTupleOuter
847  {
848  template<typename Head, typename... Tail>
849  struct RevertedTupleInner: RevertedTupleOuter<N-1, Head, All...>::template RevertedTupleInner<Tail...> { };
850  };
851 
852  template<typename... All>
853  struct RevertedTupleOuter<0, All...>
854  {
855  template<typename... Tail>
856  struct RevertedTupleInner {
857  typedef std::tuple<All...> type;
858  };
859  };
860 
861 public:
862  typedef typename RevertedTupleOuter<sizeof...(Args)>::template RevertedTupleInner<Args...>::type type;
863 };
864 
865 template <class SelfT,
866  typename ... Children>
867 class TypeTag
868 {
869 public:
870  typedef SelfT SelfType;
871 
872  typedef typename RevertedTuple<Children...>::type ChildrenTuple;
873  static const bool isLeaf = std::is_same<ChildrenTuple, std::tuple<> >::value;
874 };
875 
876 namespace PTag {
877 // this class needs to be located in the PTag namespace for reasons
878 // you don't really want to know...
879 template <class TypeTag>
880 struct Splices
881 {
882  typedef typename std::tuple<> tuple;
883 };
884 } // namespace PTag
885 
886 template <class TypeTag, class PropertyTag>
887 struct GetProperty
888 {
889  // find the type tag for which the property is defined
890  template <class CurTree, bool directlyDefined =
891  propertyDefinedOnSelf<TypeTag,
892  CurTree,
893  PropertyTag>::value>
894  struct GetEffectiveTypeTag_
895  { typedef typename CurTree::SelfType type; };
896 
897  template <class ...Elements>
898  struct SearchTypeTagList_;
899 
900  template <class EffectiveTypeTag, class ...Elements>
901  struct SearchTypeTagList_FirstThenRemaining_;
902 
903  template <class ...SpliceList>
904  struct SearchSpliceList_;
905 
906  template <class EffectiveTypeTag, class ...Splices>
907  struct SearchSpliceList_FirstThenRemaining_;
908 
909  // find the first type tag in a tuple for which the property is
910  // defined
911  template <class TypeTagTuple>
912  struct SearchTypeTagTuple_
913  { typedef void type; };
914 
915  template <class ...TypeTagList>
916  struct SearchTypeTagTuple_<std::tuple<TypeTagList...> >
917  { typedef typename SearchTypeTagList_<TypeTagList...>::type type; };
918 
919  template <class ...Elements>
920  struct SearchTypeTagList_
921  { typedef void type; };
922 
923  template <class FirstElement, class ...RemainingElements>
924  struct SearchTypeTagList_<FirstElement, RemainingElements...>
925  {
926  typedef typename SearchTypeTagList_FirstThenRemaining_<
927  typename GetEffectiveTypeTag_<FirstElement>::type,
928  RemainingElements...>::type type;
929  };
930 
931  template <class EffectiveTypeTag, class ...Elements>
932  struct SearchTypeTagList_FirstThenRemaining_
933  { typedef EffectiveTypeTag type; };
934 
935  template <class ...RemainingElements>
936  struct SearchTypeTagList_FirstThenRemaining_<void, RemainingElements...>
937  { typedef typename SearchTypeTagList_<RemainingElements...>::type type; };
938 
939  // find the first type tag in a tuple of splices for which the
940  // property is defined
941  template <class SpliceTuple>
942  struct SearchSpliceTuple_
943  { typedef void type; };
944 
945  template <class ...SpliceList>
946  struct SearchSpliceTuple_<std::tuple<SpliceList...> >
947  { typedef typename SearchSpliceList_<SpliceList...>::type type; };
948 
949  template <class ...SpliceList>
950  struct SearchSpliceList_
951  { typedef void type; };
952 
953  template <class FirstSplice, class ...RemainingSplices>
954  struct SearchSpliceList_<FirstSplice, RemainingSplices...>
955  {
956  typedef typename SearchSpliceList_FirstThenRemaining_<
957  typename GetEffectiveTypeTag_<typename GetProperty<TypeTag, FirstSplice>::p::type>::type,
958  RemainingSplices...>::type type;
959  };
960 
961  template <class EffectiveTypeTag, class ...Splices>
962  struct SearchSpliceList_FirstThenRemaining_
963  { typedef EffectiveTypeTag type; };
964 
965  template <class ...RemainingSplices>
966  struct SearchSpliceList_FirstThenRemaining_<void, RemainingSplices...>
967  { typedef typename SearchSpliceList_<RemainingSplices...>::type type; };
968 
969  // find the splice or the child type tag for which the property is defined
970  template <class CurTree,
971  class SpliceTypeTag = typename SearchSpliceTuple_< typename PTag::Splices<CurTree>::tuple >::type >
972  struct SearchSplicesThenChildren_
973  { typedef SpliceTypeTag type; };
974 
975  template <class CurTree>
976  struct SearchSplicesThenChildren_<CurTree, void>
977  { typedef typename SearchTypeTagTuple_<typename CurTree::ChildrenTuple>::type type; };
978 
979  template <class CurTree>
980  struct GetEffectiveTypeTag_<CurTree, /*directlyDefined = */false>
981  { typedef typename SearchSplicesThenChildren_<CurTree>::type type; };
982 
983 public:
984  typedef Property<TypeTag, typename GetEffectiveTypeTag_<TypeTag>::type, PropertyTag> p;
985 };
986 
987 #if !defined NO_PROPERTY_INTROSPECTION
988 inline int myReplaceAll_(std::string& s,
989  const std::string& pattern,
990  const std::string& replacement);
991 inline int myReplaceAll_(std::string& s,
992  const std::string& pattern,
993  const std::string& replacement)
994 {
995  size_t pos;
996  int i = 0;
997  while ( (pos = s.find(pattern)) != s.npos) {
998  s.replace(pos, pattern.size(), replacement);
999  ++i;
1000  };
1001  return i;
1002 }
1003 
1004 inline std::string canonicalTypeTagNameToName_(const std::string& canonicalName);
1005 inline std::string canonicalTypeTagNameToName_(const std::string& canonicalName)
1006 {
1007  std::string result(canonicalName);
1008  myReplaceAll_(result, "Ewoms::Properties::TTag::", "TTAG(");
1009  myReplaceAll_(result, "::", "");
1010  result += ")";
1011  return result;
1012 }
1013 
1014 inline bool getDiagnostic_(const std::string& typeTagName,
1015  const std::string& propTagName,
1016  std::string& result,
1017  const std::string indent)
1018 {
1019  const PropertyRegistryKey *key = 0;
1020 
1021  const typename PropertyRegistry::KeyList& keys =
1022  PropertyRegistry::getKeys(typeTagName);
1023  typename PropertyRegistry::KeyList::const_iterator it = keys.begin();
1024  for (; it != keys.end(); ++it) {
1025  if (it->second.propertyName() == propTagName) {
1026  key = &it->second;
1027  break;
1028  };
1029  }
1030 
1031  if (key) {
1032  std::ostringstream oss;
1033  oss << indent
1034  << key->propertyKind() << " "
1035  << key->propertyName() << " defined on '"
1036  << canonicalTypeTagNameToName_(key->effTypeTagName()) << "' at "
1037  << key->fileDefined() << ":" << key->lineDefined() << "\n";
1038  result = oss.str();
1039  return true;
1040  }
1041 
1042  // print properties defined on children
1043  typedef typename TypeTagRegistry::ChildrenList ChildrenList;
1044  const ChildrenList& children = TypeTagRegistry::children(typeTagName);
1045  ChildrenList::const_iterator ttagIt = children.begin();
1046  std::string newIndent = indent + " ";
1047  for (; ttagIt != children.end(); ++ttagIt) {
1048  if (getDiagnostic_(*ttagIt, propTagName, result, newIndent)) {
1049  result.insert(0, indent + "Inherited from " + canonicalTypeTagNameToName_(typeTagName) + "\n");
1050  return true;
1051  }
1052  }
1053 
1054  return false;
1055 }
1056 
1057 template <class TypeTag>
1058 const std::string getDiagnostic(std::string propTagName)
1059 {
1060  std::string result;
1061 
1062  std::string TypeTagName(Dune::className<TypeTag>());
1063 
1064  propTagName.replace(0, strlen("PTag("), "");
1065  auto n = propTagName.length();
1066  propTagName.replace(n - 1, 1, "");
1067  //TypeTagName.replace(0, strlen("Ewoms::Properties::TTag::"), "");
1068 
1069  return result;
1070 }
1071 
1072 inline void print_(const std::string& rootTypeTagName,
1073  const std::string& curTypeTagName,
1074  const std::string& splicePropName,
1075  std::ostream& os,
1076  const std::string indent,
1077  std::set<std::string>& printedProperties)
1078 {
1079  if (indent == "") {
1080  os << indent << "###########\n";
1081  os << indent << "# Properties\n";
1082  os << indent << "###########\n";
1083  os << indent << "Properties for " << canonicalTypeTagNameToName_(curTypeTagName) << ":";
1084  }
1085  else if (splicePropName != "")
1086  os << indent << "Inherited from splice " << splicePropName << " (set to " << canonicalTypeTagNameToName_(curTypeTagName) << "):";
1087  else
1088  os << indent << "Inherited from " << canonicalTypeTagNameToName_(curTypeTagName) << ":";
1089  const typename PropertyRegistry::KeyList& keys =
1090  PropertyRegistry::getKeys(curTypeTagName);
1091  typename PropertyRegistry::KeyList::const_iterator it = keys.begin();
1092  bool somethingPrinted = false;
1093  for (; it != keys.end(); ++it) {
1094  const PropertyRegistryKey& key = it->second;
1095  if (printedProperties.count(key.propertyName()) > 0)
1096  continue; // property already printed
1097  if (!somethingPrinted) {
1098  os << "\n";
1099  somethingPrinted = true;
1100  }
1101  os << indent << " "
1102  << key.propertyKind() << " " << key.propertyName();
1103  if (key.propertyKind() != "opaque") {
1104  std::string s(key.propertyValue());
1105  myReplaceAll_(s, "typename ", "");
1106  if (myReplaceAll_(s, "::Ewoms::Properties::TTag::", "TTAG("))
1107  s += ')';
1108  myReplaceAll_(s, "::Ewoms::Properties::PTag::", "");
1109  myReplaceAll_(s, "::Ewoms::Properties::GetProperty<", "GET_PROP(");
1110  myReplaceAll_(s, ">::p::", ")::");
1111  myReplaceAll_(s, "GET_PROP(TypeTag, Scalar)::type", "Scalar");
1112 
1113  os << " = '" << s << "'";
1114  }
1115  os << " defined at " << key.fileDefined()
1116  << ":" << key.lineDefined()
1117  << "\n";
1118  printedProperties.insert(key.propertyName());
1119  };
1120  if (!somethingPrinted)
1121  os << " (none)\n";
1122  // print properties defined on splices or children
1123  std::string newIndent = indent + " ";
1124 
1125  // first, iterate over the splices, ...
1126  typedef TypeTagRegistry::SpliceList SpliceList;
1127  const SpliceList& splices = TypeTagRegistry::splices(curTypeTagName);
1128  SpliceList::const_iterator spliceIt = splices.begin();
1129  for (; spliceIt != splices.end(); ++ spliceIt) {
1130  const auto& spliceTypeTagName = PropertyRegistry::getSpliceTypeTagName(rootTypeTagName,
1131  (*spliceIt)->propertyName());
1132  print_(rootTypeTagName, spliceTypeTagName, (*spliceIt)->propertyName(), os, newIndent, printedProperties);
1133  }
1134 
1135  // ... then, over the children
1136  typedef typename TypeTagRegistry::ChildrenList ChildrenList;
1137  const ChildrenList& children = TypeTagRegistry::children(curTypeTagName);
1138  ChildrenList::const_iterator ttagIt = children.begin();
1139  for (; ttagIt != children.end(); ++ttagIt) {
1140  print_(rootTypeTagName, *ttagIt, /*splicePropName=*/"", os, newIndent, printedProperties);
1141  }
1142 }
1143 
1144 template <class TypeTag>
1145 void printValues(std::ostream& os = std::cout)
1146 {
1147  std::set<std::string> printedProps;
1148  print_(Dune::className<TypeTag>(), Dune::className<TypeTag>(), /*splicePropertyName=*/"", os, /*indent=*/"", printedProps);
1149 }
1150 #else // !defined NO_PROPERTY_INTROSPECTION
1151 template <class TypeTag>
1152 void printValues(std::ostream& os = std::cout)
1153 {
1154  os <<
1155  "The eWoms property system was compiled with the macro\n"
1156  "NO_PROPERTY_INTROSPECTION defined.\n"
1157  "No diagnostic messages this time, sorry.\n";
1158 }
1159 
1160 template <class TypeTag>
1161 const std::string getDiagnostic(std::string propTagName)
1162 {
1163  std::string result;
1164  result =
1165  "The eWoms property system was compiled with the macro\n"
1166  "NO_PROPERTY_INTROSPECTION defined.\n"
1167  "No diagnostic messages this time, sorry.\n";
1168  return result;
1169 }
1170 
1171 #endif // !defined NO_PROPERTY_INTROSPECTION
1172 
1174 
1175 } // namespace Properties
1176 } // namespace Ewoms
1177 
1178 #endif
Definition: baseauxiliarymodule.hh:37
void printValues(std::ostream &os=std::cout)
Print values of the run-time parameters.
Definition: parametersystem.hh:547