• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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