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 assert(p_);
50 return p_->GetValue();
51 }
52
53 const IAny& GetDefaultValueAny() const
54 {
55 IAny::ConstPtr ret;
56 if (auto i = interface_cast<IStackProperty>(p_)) {
57 return i->GetDefaultValue();
58 }
59 return META_NS::GetObjectRegistry().GetPropertyRegister().InvalidAny();
60 }
61
62 bool IsDefaultValue() const
63 {
64 return p_->IsDefaultValue();
65 }
66 bool IsValueSet() const
67 {
68 return !p_->IsDefaultValue();
69 }
70
71 TypeId GetTypeId() const
72 {
73 return p_->GetTypeId();
74 }
75
76 bool IsCompatible(const TypeId& id) const
77 {
78 return p_->IsCompatible(id);
79 }
80
81 auto OnChanged() const
82 {
83 return p_->OnChanged();
84 }
85
86 void NotifyChange() const
87 {
88 p_->NotifyChange();
89 }
90
91 PropertyType GetProperty() const
92 {
93 return p_;
94 }
95
96 const IStackProperty* GetStackProperty() const
97 {
98 return interface_cast<IStackProperty>(p_);
99 }
100
101 template<typename Interface>
102 BASE_NS::vector<typename Interface::Ptr> GetModifiers() const
103 {
104 BASE_NS::vector<typename Interface::Ptr> res;
105 if (auto i = interface_cast<IStackProperty>(p_)) {
106 const TypeId view[] = { Interface::UID };
107 for (auto& v : i->GetModifiers(view, true)) {
108 res.push_back(interface_pointer_cast<Interface>(v));
109 }
110 }
111 return res;
112 }
113
114 IFunction::ConstPtr GetBind() const
115 {
116 if (auto i = interface_cast<IStackProperty>(p_)) {
117 const TypeId binds[] = { IBind::UID };
118 auto vec = i->GetValues(binds, false);
119 if (!vec.empty()) {
120 if (auto bind = interface_cast<IBind>(vec.back())) {
121 return bind->GetTarget();
122 }
123 }
124 }
125 return nullptr;
126 }
127
128 protected:
129 PropertyType p_;
130 };
131
132 class TypelessPropertyInterface : public ConstTypelessPropertyInterface {
133 public:
134 using PropertyType = IProperty*;
135
TypelessPropertyInterface(PropertyType p)136 TypelessPropertyInterface(PropertyType p) : ConstTypelessPropertyInterface(p), p_(p) {}
137
SetValueAny(const IAny & any)138 AnyReturnValue SetValueAny(const IAny& any)
139 {
140 return p_->SetValue(any);
141 }
142
SetDefaultValueAny(const IAny & value)143 AnyReturnValue SetDefaultValueAny(const IAny& value)
144 {
145 if (auto i = interface_cast<IStackProperty>(p_)) {
146 return i->SetDefaultValue(value);
147 }
148 return AnyReturn::FAIL;
149 }
150
151 template<typename Intf>
PushValue(const BASE_NS::shared_ptr<Intf> & value)152 ReturnError PushValue(const BASE_NS::shared_ptr<Intf>& value)
153 {
154 if (auto i = interface_cast<IStackProperty>(p_)) {
155 if (auto v = interface_pointer_cast<IValue>(value)) {
156 return i->PushValue(v);
157 }
158 }
159 return GenericError::FAIL;
160 }
161
162 template<typename Intf>
RemoveValue(const BASE_NS::shared_ptr<Intf> & value)163 ReturnError RemoveValue(const BASE_NS::shared_ptr<Intf>& value)
164 {
165 if (auto i = interface_cast<IStackProperty>(p_)) {
166 if (auto v = interface_pointer_cast<IValue>(value)) {
167 return i->RemoveValue(v);
168 }
169 }
170 return GenericError::FAIL;
171 }
172
PopValue()173 ReturnError PopValue()
174 {
175 if (auto i = interface_cast<IStackProperty>(p_)) {
176 return i->PopValue();
177 }
178 return GenericError::FAIL;
179 }
180
AddModifier(const IModifier::Ptr & mod)181 ReturnError AddModifier(const IModifier::Ptr& mod)
182 {
183 if (auto i = interface_cast<IStackProperty>(p_)) {
184 return i->AddModifier(mod);
185 }
186 return GenericError::FAIL;
187 }
188
189 bool SetBind(const IFunction::ConstPtr& func, const BASE_NS::array_view<const INotifyOnChange::ConstPtr>& deps = {})
190 {
191 if (auto i = interface_cast<IStackProperty>(p_)) {
192 auto b = CreateBind(*i);
193 if (!b->SetTarget(func, deps.empty(), p_)) {
194 return false;
195 }
196 for (auto& d : deps) {
197 b->AddDependency(d);
198 }
199 return i->PushValue(interface_pointer_cast<IValue>(b));
200 }
201 return false;
202 }
203
204 bool SetBind(const IProperty::ConstPtr& prop, const BASE_NS::array_view<const INotifyOnChange::ConstPtr>& deps = {})
205 {
206 if (auto i = interface_cast<IStackProperty>(p_)) {
207 auto b = CreateBind(*i);
208 if (!b->SetTarget(prop, deps.empty(), p_)) {
209 return false;
210 }
211 for (auto& d : deps) {
212 b->AddDependency(d);
213 }
214 return i->PushValue(interface_pointer_cast<IValue>(b));
215 }
216 return false;
217 }
218
ResetBind()219 void ResetBind()
220 {
221 if (auto i = interface_cast<IStackProperty>(p_)) {
222 const TypeId binds[] = { IBind::UID };
223 auto vec = i->GetValues(binds, false);
224 if (!vec.empty()) {
225 i->RemoveValue(vec.back());
226 NotifyChange();
227 }
228 }
229 }
230
ResetValue()231 void ResetValue()
232 {
233 p_->ResetValue();
234 }
235
Reset()236 void Reset()
237 {
238 ResetValue();
239 }
240
241 using ConstTypelessPropertyInterface::GetProperty;
GetProperty()242 PropertyType GetProperty()
243 {
244 return p_;
245 }
246
247 using ConstTypelessPropertyInterface::GetStackProperty;
GetStackProperty()248 IStackProperty* GetStackProperty()
249 {
250 return interface_cast<IStackProperty>(p_);
251 }
252
253 protected:
CreateBind(IStackProperty & prop)254 IBind::Ptr CreateBind(IStackProperty& prop)
255 {
256 if (interface_cast<IBind>(prop.TopValue())) {
257 prop.PopValue();
258 }
259 return META_NS::GetObjectRegistry().GetPropertyRegister().CreateBind();
260 }
261
262 protected:
263 PropertyType p_;
264 };
265
266 template<typename Type>
267 using PropertyBaseType =
268 BASE_NS::conditional_t<BASE_NS::is_const_v<Type>, ConstTypelessPropertyInterface, TypelessPropertyInterface>;
269
270 template<typename Type>
271 class PropertyInterface : public PropertyBaseType<Type> {
272 using Super = PropertyBaseType<Type>;
273 using Super::p_;
274
275 public:
276 using ValueType = BASE_NS::remove_const_t<Type>;
277 using PropertyType = typename Super::PropertyType;
278
PropertyInterface(PropertyType p)279 explicit PropertyInterface(PropertyType p) : Super(p) {}
280
GetDefaultValue()281 ValueType GetDefaultValue() const
282 {
283 ValueType v {};
284 this->GetDefaultValueAny().GetValue(v);
285 return v;
286 }
287
SetDefaultValue(ValueType value,bool resetToDefault)288 AnyReturnValue SetDefaultValue(ValueType value, bool resetToDefault)
289 {
290 auto ret = this->SetDefaultValueAny(Any<ValueType>(value));
291 if (resetToDefault && ret) {
292 this->ResetValue();
293 }
294 return ret;
295 }
296
SetDefaultValue(ValueType value)297 AnyReturnValue SetDefaultValue(ValueType value)
298 {
299 return SetDefaultValue(BASE_NS::move(value), false);
300 }
301
GetValue()302 ValueType GetValue() const
303 {
304 ValueType v {};
305 this->GetValueAny().GetValue(v);
306 return v;
307 }
308
SetValue(ValueType value)309 AnyReturnValue SetValue(ValueType value)
310 {
311 return this->SetValueAny(Any<ValueType>(value));
312 }
313 };
314
315 template<typename Type>
316 class TypedPropertyLock final : public PropertyInterface<Type> {
317 using PropertyType = typename PropertyInterface<Type>::PropertyType;
318 using IT = PropertyInterface<Type>;
319 using InterfaceType = BASE_NS::conditional_t<BASE_NS::is_const_v<Type>, const IT*, IT*>;
320
META_NO_COPY_MOVE(TypedPropertyLock)321 META_NO_COPY_MOVE(TypedPropertyLock)
322
323 bool CanConstructFrom(PropertyType p) const
324 {
325 return p && p->IsCompatible(META_NS::GetTypeId<BASE_NS::remove_const_t<Type>>());
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 }
IsValid()348 bool IsValid() const
349 {
350 return this->GetProperty() != nullptr;
351 }
352 explicit operator bool() const
353 {
354 return IsValid();
355 }
356 };
357
358 template<typename Property>
359 class PropertyLock final : public PropertyBaseType<Property> {
360 using InterfaceType = PropertyBaseType<Property>*;
361
META_NO_COPY_MOVE(PropertyLock)362 META_NO_COPY_MOVE(PropertyLock)
363
364 public:
365 explicit PropertyLock(Property* p) : PropertyBaseType<Property>(p)
366 {
367 if (auto i = interface_cast<ILockable>(this->GetProperty())) {
368 i->Lock();
369 }
370 }
PropertyLock(BASE_NS::shared_ptr<Property> p)371 explicit PropertyLock(BASE_NS::shared_ptr<Property> p) : PropertyLock(p.get()) {}
~PropertyLock()372 ~PropertyLock()
373 {
374 if (auto i = interface_cast<ILockable>(this->GetProperty())) {
375 i->Unlock();
376 }
377 }
378
379 InterfaceType operator->() const
380 {
381 return const_cast<PropertyLock*>(this);
382 }
IsValid()383 bool IsValid() const
384 {
385 return this->GetProperty() != nullptr;
386 }
387 explicit operator bool() const
388 {
389 return IsValid();
390 }
391 };
392
393 META_END_NAMESPACE()
394
395 #endif
396