|
- #pragma once
-
- #include <cppcore/misc/indent.h>
-
- #include "tables.h"
- #include "schema.h"
-
- namespace cpphibernate {
- namespace schema {
-
- namespace __impl
- {
-
- /* schema_t */
-
- template<typename T_name, typename T_tables>
- constexpr schema_t<T_name, T_tables>
- ::schema_t(
- name_type&& p_name,
- tables_type&& p_tables)
- : name (std::forward<name_type> (p_name))
- , tables(std::forward<tables_type>(p_tables))
- { }
-
- template<typename T_name, typename T_tables>
- void schema_t<T_name, T_tables>
- ::print(std::ostream& os) const
- {
- using namespace ::cppcore;
-
- size_t index = 0;
- os << indent << '{'
- << incindent
- << indent << "\"name\": \"" << name << "\","
- << indent << "\"tables\": "
- << indent << '['
- << incindent;
- hana::for_each(tables, [&](auto& table){
- if (index++ > 0) os << ",";
- table.print(os);
- });
- os << decindent
- << indent << ']'
- << decindent
- << indent << '}';
- }
-
- /* schema_builder */
-
- template<typename X, typename>
- struct schema_builder
- {
- template<typename... T_args>
- static constexpr decltype(auto) apply(T_args&&...)
- { static_assert(sizeof...(T_args) == -1, "Invalid parameters for make_schema(...)!"); }
- };
-
- template<typename T_name, typename T_tables>
- struct schema_builder<
- mp::list<T_name, T_tables>,
- mp::enable_if_t<
- is_tables_v<mp::decay_t<T_tables>>>>
- {
- using name_type = T_name;
- using tables_type = T_tables;
- using schema_type = schema_t<name_type, tables_type>;
-
- static constexpr decltype(auto) apply(
- name_type&& name,
- tables_type&& tables)
- {
- return schema_type(
- std::forward<name_type> (name),
- std::forward<tables_type>(tables));
- }
- };
-
- /* get_base_type_builder */
-
- template<typename X, typename>
- struct get_base_type_builder
- {
- template<typename... T_args>
- static constexpr decltype(auto) apply(T_args&&...)
- { static_assert(sizeof...(T_args) == -1, "Invalid parameters for get_base_type(...)!"); }
- };
-
- template<typename T_schema, typename T_wrapped_dataset>
- struct get_base_type_builder<
- mp::list<T_schema, T_wrapped_dataset>,
- mp::enable_if_t<is_schema_v<mp::decay_t<T_schema>>>>
- {
-
- /* is_base_of */
-
- static constexpr decltype(auto) is_base_of = hana::integral(hana::metafunction<mp::is_base_of>);
-
- /* do_fold */
-
- struct do_fold_impl
- {
- template<typename T_type_1, typename T_type_2>
- constexpr decltype(auto) operator()(T_type_1&& type_1, T_type_2&& type_2) const
- {
- auto check = hana::or_(is_base_of(type_1, type_2), is_base_of(type_2, type_1));
- static_assert(decltype(check)::value, "A dataset must not have more than one base class!");
- return hana::if_(is_base_of(type_1, type_2), type_2, type_1);
- }
- };
-
- static constexpr decltype(auto) do_fold = do_fold_impl { };
-
- /* get_base_types */
-
- template<typename T_datasets, typename T_dataset>
- static constexpr decltype(auto) get_base_types(T_datasets datasets, T_dataset dataset)
- {
- return hana::filter(
- datasets,
- [&](auto type){
- return hana::and_(
- is_base_of(type, dataset),
- hana::not_equal(type, dataset));
- });
- }
-
- /* apply */
-
- static constexpr decltype(auto) apply(
- const T_schema& schema,
- const T_wrapped_dataset& wrapped_dataset)
- {
- decltype(auto) wrapped_datasets = hana::transform(
- schema.tables,
- schema::get_wrapped_dataset);
- decltype(auto) base_types = get_base_types(wrapped_datasets, wrapped_dataset);
- return hana::eval_if(
- hana::size(base_types) <= hana::size_c<0>,
- [&](auto _){ return hana::type_c<void>; },
- [&](auto _){ return hana::fold(_(base_types), do_fold); });
- }
- };
-
- /* get_derived_types_builder */
-
- template<typename X, typename>
- struct get_derived_types_builder
- {
- template<typename... T_args>
- static constexpr decltype(auto) apply(T_args&&...)
- { static_assert(sizeof...(T_args) == -1, "Invalid parameters for get_derived_types(...)!"); }
- };
-
- template<typename T_schema, typename T_dataset>
- struct get_derived_types_builder<
- mp::list<T_schema, T_dataset>,
- mp::enable_if_t<
- schema::is_schema_v<mp::decay_t<T_schema>>
- && mp::is_same_v<hana::type_tag, hana::tag_of_t<T_dataset>>
- >>
- {
- struct has_base_impl
- {
- template<typename T_type>
- constexpr decltype(auto) operator()(T_type&&) const
- {
- return decltype(hana::equal(
- get_base_type(
- std::declval<T_schema>(),
- std::declval<T_type>()),
- std::declval<T_dataset>())) { };
- }
- };
-
- static constexpr decltype(auto) has_base = has_base_impl { };
-
- static constexpr decltype(auto) apply(T_schema&& schema, T_dataset&& dataset)
- {
- constexpr decltype(auto) dataset_types =
- decltype(hana::transform(schema.tables, schema::get_wrapped_dataset)) { };
- constexpr decltype(auto) derived_types =
- decltype(hana::filter(dataset_types, has_base)) { };
- return derived_types;
- }
- };
-
- /* get_all_derived_types_builder */
-
- template<typename X, typename>
- struct get_all_derived_types_builder
- {
- template<typename... T_args>
- static constexpr decltype(auto) apply(T_args&&...)
- { static_assert(sizeof...(T_args) == -1, "Invalid parameters for get_all_derived_types(...)!"); }
- };
-
- template<typename T_schema, typename T_dataset>
- struct get_all_derived_types_builder<
- mp::list<T_schema, T_dataset>,
- mp::enable_if_t<
- schema::is_schema_v<mp::decay_t<T_schema>>
- && mp::is_same_v<hana::type_tag, hana::tag_of_t<T_dataset>>
- >>
- {
- struct is_derived_impl
- {
- using dataset_type = decay_unwrap_t<T_dataset>;
-
- template<typename T_type>
- constexpr decltype(auto) operator()(T_type&&) const
- {
- return hana::bool_c<
- std::is_base_of_v<dataset_type, decay_unwrap_t<T_type>>>;
- }
- };
-
- static constexpr decltype(auto) is_derived = is_derived_impl { };
-
- static constexpr decltype(auto) apply(T_schema&& schema, T_dataset&& dataset)
- {
- constexpr decltype(auto) dataset_types =
- decltype(hana::transform(schema.tables, schema::get_wrapped_dataset)) { };
- constexpr decltype(auto) derived_types =
- decltype(hana::filter(dataset_types, is_derived)) { };
- return derived_types;
- }
- };
-
- }
-
- /* is_schema */
-
- template<typename T>
- struct is_schema
- : public mp::is_base_of<__impl::tag_schema, T>
- { };
-
- } }
|