1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef META_INTERFACE_PROPERTY_CONSTRUCT_PROPERTY_H
17 #define META_INTERFACE_PROPERTY_CONSTRUCT_PROPERTY_H
18 
19 #include <meta/interface/intf_any.h>
20 #include <meta/interface/intf_object_flags.h>
21 #include <meta/interface/intf_object_registry.h>
22 #include <meta/interface/property/property.h>
23 
24 META_BEGIN_NAMESPACE()
25 
26 struct ValuePtrBase {};
27 
28 template<typename Type, const META_NS::ClassInfo& ClassInfo>
29 struct ValuePtrInstance : ValuePtrBase {
30     static constexpr ObjectId ID = ClassInfo.Id();
31     using TypePtr = typename Type::Ptr;
32     static_assert(IsInterfacePtr_v<TypePtr>, "Invalid type for ValuePtr");
33 };
34 
35 template<typename Type>
36 struct ValuePtrImpl {
37     template<const META_NS::ClassInfo& ClassInfo>
38     using Instance = ValuePtrInstance<Type, ClassInfo>;
39 };
40 template<typename Type, const META_NS::ClassInfo& ClassInfo>
41 using ValuePtr = ValuePtrInstance<Type, ClassInfo>;
42 
43 template<typename T>
44 struct PropertyType {
45     using Type = T;
46 };
47 template<typename T, const META_NS::ClassInfo& ClassInfo>
48 struct PropertyType<ValuePtr<T, ClassInfo>> {
49     using Type = typename ValuePtr<T, ClassInfo>::TypePtr;
50 };
51 template<typename T>
52 using PropertyType_v = typename PropertyType<T>::Type; // NOLINT(readability-identifier-naming)
53 
54 template<typename T>
55 Property<T> ConstructProperty(IObjectRegistry& obr, BASE_NS::string_view name, const T& value = {},
56     ObjectFlagBitsValue flags = ObjectFlagBits::SERIALIZE)
57 {
58     Property<T> p(NOCHECK, obr.GetPropertyRegister().Create(ClassId::StackProperty, name));
59     if (auto i = interface_cast<IPropertyInternalAny>(p.GetProperty())) {
60         i->SetInternalAny(IAny::Ptr(new Any<T>));
61     }
62     auto access = p.GetUnlockedAccess();
63     access.SetDefaultValue(value);
64     if (auto f = interface_cast<IObjectFlags>(p.GetProperty())) {
65         f->SetObjectFlags(flags);
66     }
67     return p;
68 }
69 
70 template<typename T, typename = BASE_NS::enable_if_t<!BASE_NS::is_convertible_v<T*, ValuePtrBase*>>>
71 Property<T> ConstructProperty(
72     BASE_NS::string_view name, const T& value = {}, ObjectFlagBitsValue flags = ObjectFlagBits::SERIALIZE)
73 {
74     return ConstructProperty(GetObjectRegistry(), name, value, flags);
75 }
76 
77 template<typename T, typename Param = typename T::TypePtr>
78 Property<typename T::TypePtr> ConstructProperty(
79     BASE_NS::string_view name, const Param& value = {}, ObjectFlagBitsValue flags = ObjectFlagBits::SERIALIZE)
80 {
81     auto& obr = GetObjectRegistry();
82     Property<typename T::TypePtr> p(NOCHECK, obr.GetPropertyRegister().Create(ClassId::StackProperty, name));
83     if (auto i = interface_cast<IPropertyInternalAny>(p.GetProperty())) {
84         auto obj = obr.Create<IAny>(T::ID);
85         if (!obj) {
86             CORE_LOG_E("invalid class id for ValuePtr");
87             return nullptr;
88         }
89         i->SetInternalAny(obj);
90     }
91     auto access = p.GetUnlockedAccess();
92     access.SetDefaultValueAny(Any<Param>(value));
93     if (auto f = interface_cast<IObjectFlags>(p.GetProperty())) {
94         f->SetObjectFlags(flags);
95     }
96     return p;
97 }
98 
99 inline IProperty::Ptr ConstructPropertyAny(
100     BASE_NS::string_view name, const IAny& value, ObjectFlagBitsValue flags = ObjectFlagBits::SERIALIZE)
101 {
102     auto p = GetObjectRegistry().GetPropertyRegister().Create(ClassId::StackProperty, name);
103     if (auto i = interface_cast<IPropertyInternalAny>(p)) {
104         i->SetInternalAny(value.Clone(true));
105     }
106     if (auto f = interface_cast<IObjectFlags>(p)) {
107         f->SetObjectFlags(flags);
108     }
109     return p;
110 }
111 
112 META_END_NAMESPACE()
113 
114 #endif
115