• 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.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