You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

239 lines
8.3 KiB

  1. #pragma once
  2. #include <cppcore/misc/indent.h>
  3. #include "tables.h"
  4. #include "schema.h"
  5. namespace cpphibernate {
  6. namespace schema {
  7. namespace __impl
  8. {
  9. /* schema_t */
  10. template<typename T_name, typename T_tables>
  11. constexpr schema_t<T_name, T_tables>
  12. ::schema_t(
  13. name_type&& p_name,
  14. tables_type&& p_tables)
  15. : name (std::forward<name_type> (p_name))
  16. , tables(std::forward<tables_type>(p_tables))
  17. { }
  18. template<typename T_name, typename T_tables>
  19. void schema_t<T_name, T_tables>
  20. ::print(std::ostream& os) const
  21. {
  22. using namespace ::cppcore;
  23. size_t index = 0;
  24. os << indent << '{'
  25. << incindent
  26. << indent << "\"name\": \"" << name << "\","
  27. << indent << "\"tables\": "
  28. << indent << '['
  29. << incindent;
  30. hana::for_each(tables, [&](auto& table){
  31. if (index++ > 0) os << ",";
  32. table.print(os);
  33. });
  34. os << decindent
  35. << indent << ']'
  36. << decindent
  37. << indent << '}';
  38. }
  39. /* schema_builder */
  40. template<typename X, typename>
  41. struct schema_builder
  42. {
  43. template<typename... T_args>
  44. static constexpr decltype(auto) apply(T_args&&...)
  45. { static_assert(sizeof...(T_args) == -1, "Invalid parameters for make_schema(...)!"); }
  46. };
  47. template<typename T_name, typename T_tables>
  48. struct schema_builder<
  49. mp::list<T_name, T_tables>,
  50. mp::enable_if_t<
  51. is_tables_v<mp::decay_t<T_tables>>>>
  52. {
  53. using name_type = T_name;
  54. using tables_type = T_tables;
  55. using schema_type = schema_t<name_type, tables_type>;
  56. static constexpr decltype(auto) apply(
  57. name_type&& name,
  58. tables_type&& tables)
  59. {
  60. return schema_type(
  61. std::forward<name_type> (name),
  62. std::forward<tables_type>(tables));
  63. }
  64. };
  65. /* get_base_type_builder */
  66. template<typename X, typename>
  67. struct get_base_type_builder
  68. {
  69. template<typename... T_args>
  70. static constexpr decltype(auto) apply(T_args&&...)
  71. { static_assert(sizeof...(T_args) == -1, "Invalid parameters for get_base_type(...)!"); }
  72. };
  73. template<typename T_schema, typename T_wrapped_dataset>
  74. struct get_base_type_builder<
  75. mp::list<T_schema, T_wrapped_dataset>,
  76. mp::enable_if_t<is_schema_v<mp::decay_t<T_schema>>>>
  77. {
  78. /* is_base_of */
  79. static constexpr decltype(auto) is_base_of = hana::integral(hana::metafunction<mp::is_base_of>);
  80. /* do_fold */
  81. struct do_fold_impl
  82. {
  83. template<typename T_type_1, typename T_type_2>
  84. constexpr decltype(auto) operator()(T_type_1&& type_1, T_type_2&& type_2) const
  85. {
  86. auto check = hana::or_(is_base_of(type_1, type_2), is_base_of(type_2, type_1));
  87. static_assert(decltype(check)::value, "A dataset must not have more than one base class!");
  88. return hana::if_(is_base_of(type_1, type_2), type_2, type_1);
  89. }
  90. };
  91. static constexpr decltype(auto) do_fold = do_fold_impl { };
  92. /* get_base_types */
  93. template<typename T_datasets, typename T_dataset>
  94. static constexpr decltype(auto) get_base_types(T_datasets datasets, T_dataset dataset)
  95. {
  96. return hana::filter(
  97. datasets,
  98. [&](auto type){
  99. return hana::and_(
  100. is_base_of(type, dataset),
  101. hana::not_equal(type, dataset));
  102. });
  103. }
  104. /* apply */
  105. static constexpr decltype(auto) apply(
  106. const T_schema& schema,
  107. const T_wrapped_dataset& wrapped_dataset)
  108. {
  109. decltype(auto) wrapped_datasets = hana::transform(
  110. schema.tables,
  111. schema::get_wrapped_dataset);
  112. decltype(auto) base_types = get_base_types(wrapped_datasets, wrapped_dataset);
  113. return hana::eval_if(
  114. hana::size(base_types) <= hana::size_c<0>,
  115. [&](auto _){ return hana::type_c<void>; },
  116. [&](auto _){ return hana::fold(_(base_types), do_fold); });
  117. }
  118. };
  119. /* get_derived_types_builder */
  120. template<typename X, typename>
  121. struct get_derived_types_builder
  122. {
  123. template<typename... T_args>
  124. static constexpr decltype(auto) apply(T_args&&...)
  125. { static_assert(sizeof...(T_args) == -1, "Invalid parameters for get_derived_types(...)!"); }
  126. };
  127. template<typename T_schema, typename T_dataset>
  128. struct get_derived_types_builder<
  129. mp::list<T_schema, T_dataset>,
  130. mp::enable_if_t<
  131. schema::is_schema_v<mp::decay_t<T_schema>>
  132. && mp::is_same_v<hana::type_tag, hana::tag_of_t<T_dataset>>
  133. >>
  134. {
  135. struct has_base_impl
  136. {
  137. template<typename T_type>
  138. constexpr decltype(auto) operator()(T_type&&) const
  139. {
  140. return decltype(hana::equal(
  141. get_base_type(
  142. std::declval<T_schema>(),
  143. std::declval<T_type>()),
  144. std::declval<T_dataset>())) { };
  145. }
  146. };
  147. static constexpr decltype(auto) has_base = has_base_impl { };
  148. static constexpr decltype(auto) apply(T_schema&& schema, T_dataset&& dataset)
  149. {
  150. constexpr decltype(auto) dataset_types =
  151. decltype(hana::transform(schema.tables, schema::get_wrapped_dataset)) { };
  152. constexpr decltype(auto) derived_types =
  153. decltype(hana::filter(dataset_types, has_base)) { };
  154. return derived_types;
  155. }
  156. };
  157. /* get_all_derived_types_builder */
  158. template<typename X, typename>
  159. struct get_all_derived_types_builder
  160. {
  161. template<typename... T_args>
  162. static constexpr decltype(auto) apply(T_args&&...)
  163. { static_assert(sizeof...(T_args) == -1, "Invalid parameters for get_all_derived_types(...)!"); }
  164. };
  165. template<typename T_schema, typename T_dataset>
  166. struct get_all_derived_types_builder<
  167. mp::list<T_schema, T_dataset>,
  168. mp::enable_if_t<
  169. schema::is_schema_v<mp::decay_t<T_schema>>
  170. && mp::is_same_v<hana::type_tag, hana::tag_of_t<T_dataset>>
  171. >>
  172. {
  173. struct is_derived_impl
  174. {
  175. using dataset_type = decay_unwrap_t<T_dataset>;
  176. template<typename T_type>
  177. constexpr decltype(auto) operator()(T_type&&) const
  178. {
  179. return hana::bool_c<
  180. std::is_base_of_v<dataset_type, decay_unwrap_t<T_type>>>;
  181. }
  182. };
  183. static constexpr decltype(auto) is_derived = is_derived_impl { };
  184. static constexpr decltype(auto) apply(T_schema&& schema, T_dataset&& dataset)
  185. {
  186. constexpr decltype(auto) dataset_types =
  187. decltype(hana::transform(schema.tables, schema::get_wrapped_dataset)) { };
  188. constexpr decltype(auto) derived_types =
  189. decltype(hana::filter(dataset_types, is_derived)) { };
  190. return derived_types;
  191. }
  192. };
  193. }
  194. /* is_schema */
  195. template<typename T>
  196. struct is_schema
  197. : public mp::is_base_of<__impl::tag_schema, T>
  198. { };
  199. } }