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_internal.h>
26 #include <meta/interface/property/intf_property_register.h>
27 #include <meta/interface/property/intf_stack_property.h>
28
META_BEGIN_NAMESPACE()29 META_BEGIN_NAMESPACE()
30
31 class ConstTypelessPropertyInterface {
32 public:
33 using PropertyType = const IProperty*;
34
35 explicit ConstTypelessPropertyInterface(PropertyType p) : p_(p) {}
36
37 BASE_NS::string GetName() const
38 {
39 return p_->GetName();
40 }
41 IOwner::WeakPtr GetOwner() const
42 {
43 return p_->GetOwner();
44 }
45
46 const IAny& GetValueAny() const
47 {
48 assert(p_);
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
161 template<typename Intf>
RemoveValue(const BASE_NS::shared_ptr<Intf> & value)162 ReturnError RemoveValue(const BASE_NS::shared_ptr<Intf>& value)
163 {
164 if (auto i = interface_cast<IStackProperty>(p_)) {
165 if (auto v = interface_pointer_cast<IValue>(value)) {
166 return i->RemoveValue(v);
167 }
168 }
169 return GenericError::FAIL;
170 }
171
PopValue()172 ReturnError PopValue()
173 {
174 if (auto i = interface_cast<IStackProperty>(p_)) {
175 return i->PopValue();
176 }
177 return GenericError::FAIL;
178 }
179
AddModifier(const IModifier::Ptr & mod)180 ReturnError AddModifier(const IModifier::Ptr& mod)
181 {
182 if (auto i = interface_cast<IStackProperty>(p_)) {
183 return i->AddModifier(mod);
184 }
185 return GenericError::FAIL;
186 }
187
188 bool SetBind(const IFunction::ConstPtr& func, const BASE_NS::array_view<const INotifyOnChange::ConstPtr>& deps = {})
189 {
190 if (auto i = interface_cast<IStackProperty>(p_)) {
191 auto b = CreateBind(*i);
192 if (!b->SetTarget(func, deps.empty(), p_)) {
193 return false;
194 }
195 for (auto& d : deps) {
196 b->AddDependency(d);
197 }
198 return i->PushValue(interface_pointer_cast<IValue>(b));
199 }
200 return false;
201 }
202
203 bool SetBind(const IProperty::ConstPtr& prop, const BASE_NS::array_view<const INotifyOnChange::ConstPtr>& deps = {})
204 {
205 if (auto i = interface_cast<IStackProperty>(p_)) {
206 auto b = CreateBind(*i);
207 if (!b->SetTarget(prop, deps.empty(), p_)) {
208 return false;
209 }
210 for (auto& d : deps) {
211 b->AddDependency(d);
212 }
213 return i->PushValue(interface_pointer_cast<IValue>(b));
214 }
215 return false;
216 }
217
ResetBind()218 void ResetBind()
219 {
220 if (auto i = interface_cast<IStackProperty>(p_)) {
221 const TypeId binds[] = { IBind::UID };
222 auto vec = i->GetValues(binds, false);
223 if (!vec.empty()) {
224 i->RemoveValue(vec.back());
225 NotifyChange();
226 }
227 }
228 }
229
ResetValue()230 void ResetValue()
231 {
232 p_->ResetValue();
233 }
234
Reset()235 void Reset()
236 {
237 ResetValue();
238 }
239
240 using ConstTypelessPropertyInterface::GetProperty;
GetProperty()241 PropertyType GetProperty()
242 {
243 return p_;
244 }
245
246 using ConstTypelessPropertyInterface::GetStackProperty;
GetStackProperty()247 IStackProperty* GetStackProperty()
248 {
249 return interface_cast<IStackProperty>(p_);
250 }
251
252 protected:
CreateBind(IStackProperty & prop)253 IBind::Ptr CreateBind(IStackProperty& prop)
254 {
255 if (interface_cast<IBind>(prop.TopValue())) {
256 prop.PopValue();
257 }
258 return META_NS::GetObjectRegistry().GetPropertyRegister().CreateBind();
259 }
260
261 protected:
262 PropertyType p_;
263 };
264
265 template<typename Type>
266 using PropertyBaseType =
267 BASE_NS::conditional_t<BASE_NS::is_const_v<Type>, ConstTypelessPropertyInterface, TypelessPropertyInterface>;
268
269 template<typename Type>
270 class PropertyInterface : public PropertyBaseType<Type> {
271 using Super = PropertyBaseType<Type>;
272 using Super::p_;
273
274 public:
275 using ValueType = BASE_NS::remove_const_t<Type>;
276 using PropertyType = typename Super::PropertyType;
277
PropertyInterface(PropertyType p)278 explicit PropertyInterface(PropertyType p) : Super(p) {}
279
GetDefaultValue()280 ValueType GetDefaultValue() const
281 {
282 ValueType v {};
283 this->GetDefaultValueAny().GetValue(v);
284 return v;
285 }
286
SetDefaultValue(ValueType value,bool resetToDefault)287 AnyReturnValue SetDefaultValue(ValueType value, bool resetToDefault)
288 {
289 auto ret = this->SetDefaultValueAny(Any<ValueType>(value));
290 if (resetToDefault && ret) {
291 this->ResetValue();
292 }
293 return ret;
294 }
295
SetDefaultValue(ValueType value)296 AnyReturnValue SetDefaultValue(ValueType value)
297 {
298 return SetDefaultValue(BASE_NS::move(value), false);
299 }
300
GetValue()301 ValueType GetValue() const
302 {
303 ValueType v {};
304 this->GetValueAny().GetValue(v);
305 return v;
306 }
307
SetValue(ValueType value)308 AnyReturnValue SetValue(ValueType value)
309 {
310 return this->SetValueAny(Any<ValueType>(value));
311 }
312 };
313
314 template<typename Type>
315 class TypedPropertyLock final : public PropertyInterface<Type> {
316 using PropertyType = typename PropertyInterface<Type>::PropertyType;
317 using IT = PropertyInterface<Type>;
318 using InterfaceType = BASE_NS::conditional_t<BASE_NS::is_const_v<Type>, const IT*, IT*>;
319
META_NO_COPY_MOVE(TypedPropertyLock)320 META_NO_COPY_MOVE(TypedPropertyLock)
321
322 bool CanConstructFrom(PropertyType p) const
323 {
324 return p && p->IsCompatible(META_NS::GetTypeId<BASE_NS::remove_const_t<Type>>());
325 }
326
327 public:
TypedPropertyLock(NoCheckT,PropertyType p)328 TypedPropertyLock(NoCheckT, PropertyType p) : PropertyInterface<Type>(p)
329 {
330 if (auto i = interface_cast<ILockable>(this->GetProperty())) {
331 i->Lock();
332 }
333 }
TypedPropertyLock(PropertyType p)334 explicit TypedPropertyLock(PropertyType p) : TypedPropertyLock(NOCHECK, CanConstructFrom(p) ? p : nullptr) {}
TypedPropertyLock(const IProperty::Ptr & p)335 explicit TypedPropertyLock(const IProperty::Ptr& p) : TypedPropertyLock(p.get()) {}
TypedPropertyLock(const IProperty::ConstPtr & p)336 explicit TypedPropertyLock(const IProperty::ConstPtr& p) : TypedPropertyLock(p.get()) {}
~TypedPropertyLock()337 ~TypedPropertyLock()
338 {
339 if (auto i = interface_cast<ILockable>(this->GetProperty())) {
340 i->Unlock();
341 }
342 }
343
344 InterfaceType operator->() const
345 {
346 return const_cast<TypedPropertyLock*>(this);
347 }
348
IsValid()349 bool IsValid() const
350 {
351 return this->GetProperty() != nullptr;
352 }
353
354 explicit operator bool() const
355 {
356 return IsValid();
357 }
358 };
359
360 template<typename Property>
361 class PropertyLock final : public PropertyBaseType<Property> {
362 using InterfaceType = PropertyBaseType<Property>*;
363
META_NO_COPY_MOVE(PropertyLock)364 META_NO_COPY_MOVE(PropertyLock)
365
366 public:
367 explicit PropertyLock(Property* p) : PropertyBaseType<Property>(p)
368 {
369 if (auto i = interface_cast<ILockable>(this->GetProperty())) {
370 i->Lock();
371 }
372 }
PropertyLock(BASE_NS::shared_ptr<Property> p)373 explicit PropertyLock(BASE_NS::shared_ptr<Property> p) : PropertyLock(p.get()) {}
~PropertyLock()374 ~PropertyLock()
375 {
376 if (auto i = interface_cast<ILockable>(this->GetProperty())) {
377 i->Unlock();
378 }
379 }
380
381 InterfaceType operator->() const
382 {
383 return const_cast<PropertyLock*>(this);
384 }
385
IsValid()386 bool IsValid() const
387 {
388 return this->GetProperty() != nullptr;
389 }
390
391 explicit operator bool() const
392 {
393 return IsValid();
394 }
395 };
396
397 META_END_NAMESPACE()
398
399 #endif
400