19#ifndef CPPREALM_SCHEMA_HPP
20#define CPPREALM_SCHEMA_HPP
22#include <cpprealm/link.hpp>
23#include <cpprealm/internal/bridge/lnklst.hpp>
24#include <cpprealm/internal/bridge/object_schema.hpp>
25#include <cpprealm/internal/bridge/realm.hpp>
26#include <cpprealm/internal/bridge/table.hpp>
27#include <cpprealm/internal/type_info.hpp>
34 enum class ObjectType {
43 template <
typename Result,
typename Class>
46 using class_type = Class;
47 using member_type = Result;
54 template<
typename... Ts>
55 constexpr auto make_subpack_tuple(Ts&&... xs)
57 return std::tuple<Ts...>(std::forward<Ts>(xs)...);
69 template <auto Ptr,
bool IsPrimaryKey = false>
76 static constexpr auto ptr = Ptr;
78 internal::bridge::property::type type;
79 const char* name =
"";
84 explicit constexpr property(
const char* actual_name)
93 if constexpr (std::is_pointer_v<typename Result::value_type>) {
94 property.set_object_link(
managed<std::remove_pointer_t<typename Result::value_type>,
void>::schema.name);
97 if constexpr (std::is_pointer_v<typename Result::value_type>) {
98 property.set_object_link(
managed<std::remove_pointer_t<typename Result::value_type>,
void>::schema.name);
103 property.set_object_link(
managed<std::remove_pointer_t<typename Result::mapped_type::value_type>,
void>::schema.name);
104 property.set_type(type | internal::bridge::property::type::Nullable);
106 }
else if constexpr (std::is_pointer_v<typename Result::mapped_type>) {
107 property.set_object_link(
managed<std::remove_pointer_t<typename Result::mapped_type>,
void>::schema.name);
108 property.set_type(type | internal::bridge::property::type::Nullable);
110 }
else if constexpr (std::is_pointer_v<Result>) {
111 property.set_object_link(
managed<
typename std::remove_pointer_t<Result>,
void>::schema.name);
112 property.set_type(type | internal::bridge::property::type::Nullable);
121 template <
typename T,
typename ... Types>
126 template <
template<
typename...>
typename Variant,
typename... VariantTypes,
typename NextType,
typename... RemainingTypes>
129 std::disjunction< std::is_same<NextType, VariantTypes> ... >::value
130 , unique_variant<Variant<VariantTypes...>, RemainingTypes...>
131 , unique_variant<Variant<VariantTypes..., NextType>, RemainingTypes...>
135 template <
typename Class,
typename ...Properties>
138 const char *names[
sizeof...(Properties)] = {};
139 const char *primary_key_name =
"";
141 static constexpr std::tuple<Properties...> properties{};
145 constexpr auto do_apply_name(
const std::tuple<Properties...> &tup) {
146 if constexpr (N + 1 ==
sizeof...(Properties)) {
147 names[N] = std::get<N>(tup).name;
148 if (std::get<N>(tup).is_primary_key) {
149 primary_key_name = std::get<N>(tup).name;
153 names[N] = std::get<N>(tup).name;
154 if (std::get<N>(tup).is_primary_key) {
155 primary_key_name = std::get<N>(tup).name;
157 return do_apply_name<N + 1>(tup);
161 constexpr auto apply_name(
const std::tuple<Properties...> &tup) {
162 return do_apply_name<0>(tup);
165 std::tuple<Properties...> ps;
167 explicit constexpr schema(
const char *name_, Properties &&... props)
170 auto tup = std::make_tuple(props...);
173 explicit constexpr schema(
const char *name_, std::tuple<Properties...>&& props)
178 explicit constexpr schema(
const char *name_, ObjectType object_type, std::tuple<Properties...>&& props)
180 , ps(props), m_object_type(object_type) {
183 template<
size_t N,
typename P>
185 if constexpr (P::is_primary_key) {
188 if constexpr (N + 1 ==
sizeof...(Properties)) {
200 using PrimaryKeyProperty =
decltype(
primary_key());
201 static constexpr bool HasPrimaryKeyProperty = !std::is_void_v<PrimaryKeyProperty>;
203 bool is_embedded()
const {
204 return m_object_type == ObjectType::Embedded;
212 if (!p.name().empty()) {
216 std::apply([&](
const auto&... p) {
217 (add_property(p), ...);
220 if constexpr (HasPrimaryKeyProperty) {
221 schema.set_primary_key(primary_key_name);
223 if (m_object_type == ObjectType::Embedded) {
224 schema.set_object_type(internal::bridge::object_schema::object_type::Embedded);
226 if (m_object_type == ObjectType::Asymmetric) {
227 schema.set_object_type(internal::bridge::object_schema::object_type::TopLevelAsymmetric);
232 template<
size_t N,
typename P>
233 constexpr auto set(Class &
object, P &
property)
const {
234 if constexpr (N + 1 ==
sizeof...(Properties)) {
235 property.set(
object, names[N]);
238 property.set(
object, names[N]);
239 return set<N + 1>(
object, std::get<N + 1>(properties));
243 template<
size_t N,
typename P>
245 property_value_for_name(std::string_view property_name,
const managed<Class, void> &cls, P &
property,
bool excluding_collections =
true)
const {
246 bool is_array = realm::internal::bridge::property_has_flag(
property.type, realm::internal::bridge::property::type::Array);
247 bool is_dictionary = realm::internal::bridge::property_has_flag(
property.type, realm::internal::bridge::property::type::Dictionary);
248 bool is_set = realm::internal::bridge::property_has_flag(
property.type, realm::internal::bridge::property::type::Set);
249 bool is_collection = is_array || is_dictionary || is_set;
250 if (excluding_collections && is_collection) {
251 return variant_t{std::monostate()};
254 if constexpr (N + 1 ==
sizeof...(Properties)) {
255 if (property_name == std::string_view(names[N])) {
257 if constexpr (std::is_pointer_v<typename P::Result>) {
260 return (cls.*ptr).detach();
265 if (property_name == std::string_view(names[N])) {
267 if constexpr (std::is_pointer_v<typename P::Result>) {
270 return (cls.*ptr).detach();
273 return property_value_for_name<N + 1>(property_name, cls, std::get<N + 1>(properties), excluding_collections);
276 constexpr auto property_value_for_name(std::string_view property_name,
const managed<Class, void> &cls,
bool excluding_collections =
true)
const {
277 return property_value_for_name<0>(property_name, cls, std::get<0>(properties), excluding_collections);
280 template<
size_t N,
typename T,
typename P>
281 constexpr const char*
282 name_for_property(T ptr, P &
property)
const {
283 if constexpr (N + 1 ==
sizeof...(Properties)) {
284 if constexpr (std::is_same_v<
decltype(ptr), std::remove_const_t<
decltype(
property.ptr)>>) {
286 return property.name;
291 if constexpr (std::is_same_v<
decltype(ptr), std::remove_const_t<
decltype(
property.ptr)>>) {
293 return property.name;
296 return name_for_property<N + 1>(ptr, std::get<N + 1>(ps));
300 constexpr const char* name_for_property()
const {
301 return name_for_property<0>(ptr, std::get<0>(ps));
303 template <
typename T>
304 constexpr const char* name_for_property(T ptr)
const {
305 return name_for_property<0>(ptr, std::get<0>(ps));
308 ObjectType m_object_type = ObjectType::None;
311 template <auto Ptr,
bool IsPrimaryKey = false>
312 static constexpr auto property(
const char* name)
317 template <
typename ...T>
318 static constexpr auto schema(
const char * name,
320 auto tup = internal::make_subpack_tuple(props...);
321 auto i = std::get<0>(tup);
322 using Cls =
typename decltype(i)::Class;
323 return schemagen::schema<Cls, T...>(name, std::move(props)...);
326 template <
typename ...T>
327 static constexpr auto schema(
const char * name,
328 std::tuple<T...>&& props) {
329 auto i = std::get<0>(props);
330 using Cls =
typename decltype(i)::Class;
331 return schemagen::schema<Cls, T...>(name, std::move(props));
334 template <
typename ...T>
335 static constexpr auto schema(
const char * name,
336 ObjectType object_type,
337 std::tuple<T...>&& props) {
338 auto i = std::get<0>(props);
339 using Cls =
typename decltype(i)::Class;
340 return schemagen::schema<Cls, T...>(name, object_type, std::move(props));
Definition: object_schema.hpp:33
Definition: property.hpp:33
Definition: type_info.hpp:161
Definition: type_info.hpp:145
Definition: type_info.hpp:70
Definition: type_info.hpp:45
Definition: type_info.hpp:297
Definition: type_info.hpp:62
Definition: type_info.hpp:54
Definition: managed_primary_key.hpp:30
Definition: schema.hpp:70
Definition: schema.hpp:136
Definition: schema.hpp:122