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_DETAIL_PROPERTY_H
17 #define META_INTERFACE_DETAIL_PROPERTY_H
18
19 #include <base/containers/type_traits.h>
20
21 #include <meta/interface/detail/any.h>
22 #include <meta/interface/intf_lockable.h>
23 #include <meta/interface/intf_object_registry.h>
24 #include <meta/interface/intf_value.h>
25 #include <meta/interface/property/intf_property.h>
26 #include <meta/interface/property/intf_property_internal.h>
27 #include <meta/interface/property/intf_property_register.h>
28 #include <meta/interface/property/intf_stack_property.h>
29
META_BEGIN_NAMESPACE()30 META_BEGIN_NAMESPACE()
31
32 class ConstTypelessPropertyInterface {
33 public:
34 using PropertyType = const IProperty*;
35
36 explicit ConstTypelessPropertyInterface(PropertyType p) : p_(p) {}
37
38 BASE_NS::string GetName() const
39 {
40 return p_->GetName();
41 }
42 IObject::WeakPtr GetOwner() const
43 {
44 return p_->GetOwner();
45 }
46
47 const IAny& GetValueAny() const
48 {
49 return p_->GetValue();
50 }
51
52 const IAny& GetDefaultValueAny() const
53 {
54 IAny::ConstPtr ret;
55 if (auto i = interface_cast<IStackProperty>(p_)) {
56 return i->GetDefaultValue();
57 }
58 return META_NS::GetObjectRegistry().GetPropertyRegister().InvalidAny();
59 }
60
61 bool IsDefaultValue() const
62 {
63 return p_->IsDefaultValue();
64 }
65 bool IsValueSet() const
66 {
67 return !p_->IsDefaultValue();
68 }
69
70 TypeId GetTypeId() const
71 {
72 return p_->GetTypeId();
73 }
74
75 bool IsCompatible(const TypeId& id) const
76 {
77 return p_->IsCompatible(id);
78 }
79
80 auto OnChanged() const
81 {
82 return p_->OnChanged();
83 }
84
85 void NotifyChange() const
86 {
87 p_->NotifyChange();
88 }
89
90 PropertyType GetProperty() const
91 {
92 return p_;
93 }
94
95 const IStackProperty* GetStackProperty() const
96 {
97 return interface_cast<IStackProperty>(p_);
98 }
99
100 template<typename Interface>
101 BASE_NS::vector<typename Interface::Ptr> GetModifiers() const
102 {
103 BASE_NS::vector<typename Interface::Ptr> res;
104 if (auto i = interface_cast<IStackProperty>(p_)) {
105 const TypeId view[] = { Interface::UID };
106 for (auto& v : i->GetModifiers(view, true)) {
107 res.push_back(interface_pointer_cast<Interface>(v));
108 }
109 }
110 return res;
111 }
112
113 IFunction::ConstPtr GetBind() const
114 {
115 if (auto i = interface_cast<IStackProperty>(p_)) {
116 const TypeId binds[] = { IBind::UID };
117 auto vec = i->GetValues(binds, false);
118 if (!vec.empty()) {
119 if (auto bind = interface_cast<IBind>(vec.back())) {
120 return bind->GetTarget();
121 }
122 }
123 }
124 return nullptr;
125 }
126
127 protected:
128 PropertyType p_;
129 };
130
131 class TypelessPropertyInterface : public ConstTypelessPropertyInterface {
132 public:
133 using PropertyType = IProperty*;
134
TypelessPropertyInterface(PropertyType p)135 TypelessPropertyInterface(PropertyType p) : ConstTypelessPropertyInterface(p), p_(p) {}
136
SetValueAny(const IAny & any)137 AnyReturnValue SetValueAny(const IAny& any)
138 {
139 return p_->SetValue(any);
140 }
141
SetDefaultValueAny(const IAny & value)142 AnyReturnValue SetDefaultValueAny(const IAny& value)
143 {
144 if (auto i = interface_cast<IStackProperty>(p_)) {
145 return i->SetDefaultValue(value);
146 }
147 return AnyReturn::FAIL;
148 }
149
150 template<typename Intf>
PushValue(const BASE_NS::shared_ptr<Intf> & value)151 ReturnError PushValue(const BASE_NS::shared_ptr<Intf>& value)
152 {
153 if (auto i = interface_cast<IStackProperty>(p_)) {
154 if (auto v = interface_pointer_cast<IValue>(value)) {
155 return i->PushValue(v);
156 }
157 }
158 return GenericError::FAIL;
159 }
160
PopValue()161 ReturnError PopValue()
162 {
163 if (auto i = interface_cast<IStackProperty>(p_)) {
164 return i->PopValue();
165 }
166 return GenericError::FAIL;
167 }
168
AddModifier(const IModifier::Ptr & mod)169 ReturnError AddModifier(const IModifier::Ptr& mod)
170 {
171 if (auto i = interface_cast<IStackProperty>(p_)) {
172 return i->AddModifier(mod);
173 }
174 return GenericError::FAIL;
175 }
176
177 bool SetBind(const IFunction::ConstPtr& func, const BASE_NS::array_view<const INotifyOnChange::ConstPtr>& deps = {})
178 {
179 if (auto i = interface_cast<IStackProperty>(p_)) {
180 auto b = CreateBind(*i);
181 if (!b->SetTarget(func, deps.empty(), p_)) {
182 return false;
183 }
184 for (auto& d : deps) {
185 b->AddDependency(d);
186 }
187 return i->PushValue(interface_pointer_cast<IValue>(b));
188 }
189 return false;
190 }
191
192 bool SetBind(const IProperty::ConstPtr& prop, const BASE_NS::array_view<const INotifyOnChange::ConstPtr>& deps = {})
193 {
194 if (auto i = interface_cast<IStackProperty>(p_)) {
195 auto b = CreateBind(*i);
196 if (!b->SetTarget(prop, deps.empty(), p_)) {
197 return false;
198 }
199 for (auto& d : deps) {
200 b->AddDependency(d);
201 }
202 return i->PushValue(interface_pointer_cast<IValue>(b));
203 }
204 return false;
205 }
206
ResetBind()207 void ResetBind()
208 {
209 if (auto i = interface_cast<IStackProperty>(p_)) {
210 const TypeId binds[] = { IBind::UID };
211 auto vec = i->GetValues(binds, false);
212 if (!vec.empty()) {
213 i->RemoveValue(vec.back());
214 NotifyChange();
215 }
216 }
217 }
218
ResetValue()219 void ResetValue()
220 {
221 p_->ResetValue();
222 }
223
Reset()224 void Reset()
225 {
226 ResetValue();
227 }
228
GetProperty()229 PropertyType GetProperty()
230 {
231 return p_;
232 }
233
GetStackProperty()234 IStackProperty* GetStackProperty()
235 {
236 return interface_cast<IStackProperty>(p_);
237 }
238
239 protected:
CreateBind(IStackProperty & prop)240 IBind::Ptr CreateBind(IStackProperty& prop)
241 {
242 if (interface_cast<IBind>(prop.TopValue())) {
243 prop.PopValue();
244 }
245 return META_NS::GetObjectRegistry().GetPropertyRegister().CreateBind();
246 }
247
248 protected:
249 PropertyType p_;
250 };
251
252 template<typename Type>
253 using PropertyBaseType =
254 BASE_NS::conditional_t<BASE_NS::is_const_v<Type>, ConstTypelessPropertyInterface, TypelessPropertyInterface>;
255
256 template<typename Type>
257 class PropertyInterface : public PropertyBaseType<Type> {
258 using Super = PropertyBaseType<Type>;
259 using Super::p_;
260
261 public:
262 using ValueType = BASE_NS::remove_const_t<Type>;
263 using PropertyType = typename Super::PropertyType;
264
PropertyInterface(PropertyType p)265 explicit PropertyInterface(PropertyType p) : Super(p) {}
266
GetDefaultValue()267 ValueType GetDefaultValue() const
268 {
269 ValueType v {};
270 this->GetDefaultValueAny().GetValue(v);
271 return v;
272 }
273
SetDefaultValue(ValueType value,bool resetToDefault)274 AnyReturnValue SetDefaultValue(ValueType value, bool resetToDefault)
275 {
276 auto ret = this->SetDefaultValueAny(Any<ValueType>(value));
277 if (resetToDefault && ret) {
278 this->ResetValue();
279 }
280 return ret;
281 }
282
SetDefaultValue(ValueType value)283 AnyReturnValue SetDefaultValue(ValueType value)
284 {
285 return SetDefaultValue(BASE_NS::move(value), false);
286 }
287
GetValue()288 ValueType GetValue() const
289 {
290 ValueType v {};
291 this->GetValueAny().GetValue(v);
292 return v;
293 }
294
SetValue(ValueType value)295 AnyReturnValue SetValue(ValueType value)
296 {
297 return this->SetValueAny(Any<ValueType>(value));
298 }
299 };
300
301 template<typename Type>
302 class TypedPropertyLock final : public PropertyInterface<Type> {
303 using PropertyType = typename PropertyInterface<Type>::PropertyType;
304 using IT = PropertyInterface<Type>;
305 using InterfaceType = BASE_NS::conditional_t<BASE_NS::is_const_v<Type>, const IT*, IT*>;
306
META_NO_COPY_MOVE(TypedPropertyLock)307 META_NO_COPY_MOVE(TypedPropertyLock)
308
309 public:
310 explicit TypedPropertyLock(PropertyType p) : PropertyInterface<Type>(p)
311 {
312 if (auto i = interface_cast<ILockable>(p)) {
313 i->Lock();
314 }
315 }
~TypedPropertyLock()316 ~TypedPropertyLock()
317 {
318 if (auto i = interface_cast<ILockable>(this->GetProperty())) {
319 i->Unlock();
320 }
321 }
322
323 InterfaceType operator->() const
324 {
325 return const_cast<TypedPropertyLock*>(this);
326 }
327 };
328
329 template<typename Property>
330 class PropertyLock final : public PropertyBaseType<Property> {
331 using InterfaceType = PropertyBaseType<Property>*;
332
META_NO_COPY_MOVE(PropertyLock)333 META_NO_COPY_MOVE(PropertyLock)
334
335 public:
336 explicit PropertyLock(BASE_NS::shared_ptr<Property> p) : PropertyBaseType<Property>(p.get())
337 {
338 if (auto i = interface_cast<ILockable>(p)) {
339 i->Lock();
340 }
341 }
~PropertyLock()342 ~PropertyLock()
343 {
344 if (auto i = interface_cast<ILockable>(this->GetProperty())) {
345 i->Unlock();
346 }
347 }
348
349 InterfaceType operator->() const
350 {
351 return const_cast<PropertyLock*>(this);
352 }
353 };
354
355 META_END_NAMESPACE()
356
357 #endif
358