#pragma once #include #include "tables.h" #include "schema.h" namespace cpphibernate { namespace schema { namespace __impl { /* schema_t */ template constexpr schema_t ::schema_t( name_type&& p_name, tables_type&& p_tables) : name (std::forward (p_name)) , tables(std::forward(p_tables)) { } template void schema_t ::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 struct schema_builder { template static constexpr decltype(auto) apply(T_args&&...) { static_assert(sizeof...(T_args) == -1, "Invalid parameters for make_schema(...)!"); } }; template struct schema_builder< mp::list, mp::enable_if_t< is_tables_v>>> { using name_type = T_name; using tables_type = T_tables; using schema_type = schema_t; static constexpr decltype(auto) apply( name_type&& name, tables_type&& tables) { return schema_type( std::forward (name), std::forward(tables)); } }; /* get_base_type_builder */ template struct get_base_type_builder { template static constexpr decltype(auto) apply(T_args&&...) { static_assert(sizeof...(T_args) == -1, "Invalid parameters for get_base_type(...)!"); } }; template struct get_base_type_builder< mp::list, mp::enable_if_t>>> { /* is_base_of */ static constexpr decltype(auto) is_base_of = hana::integral(hana::metafunction); /* do_fold */ struct do_fold_impl { template 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 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; }, [&](auto _){ return hana::fold(_(base_types), do_fold); }); } }; /* get_derived_types_builder */ template struct get_derived_types_builder { template static constexpr decltype(auto) apply(T_args&&...) { static_assert(sizeof...(T_args) == -1, "Invalid parameters for get_derived_types(...)!"); } }; template struct get_derived_types_builder< mp::list, mp::enable_if_t< schema::is_schema_v> && mp::is_same_v> >> { struct has_base_impl { template constexpr decltype(auto) operator()(T_type&&) const { return decltype(hana::equal( get_base_type( std::declval(), std::declval()), std::declval())) { }; } }; 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 struct get_all_derived_types_builder { template static constexpr decltype(auto) apply(T_args&&...) { static_assert(sizeof...(T_args) == -1, "Invalid parameters for get_all_derived_types(...)!"); } }; template struct get_all_derived_types_builder< mp::list, mp::enable_if_t< schema::is_schema_v> && mp::is_same_v> >> { struct is_derived_impl { using dataset_type = decay_unwrap_t; template constexpr decltype(auto) operator()(T_type&&) const { return hana::bool_c< std::is_base_of_v>>; } }; 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 struct is_schema : public mp::is_base_of<__impl::tag_schema, T> { }; } }