• 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 #include "stack_property.h"
17 
18 #include <meta/api/util.h>
19 #include <meta/base/interface_utils.h>
20 #include <meta/ext/serialization/serializer.h>
21 #include <meta/interface/property/intf_stack_resetable.h>
22 
23 #include "../any.h"
24 #include "dependencies.h"
25 
26 META_BEGIN_NAMESPACE()
27 namespace Internal {
28 
StackProperty(BASE_NS::string name)29 StackProperty::StackProperty(BASE_NS::string name)
30     : Super(BASE_NS::move(name)), onChangedCallback_(MakeCallback<IOnChanged>([this] { InternalOnChanged(); }))
31 {}
32 
~StackProperty()33 StackProperty::~StackProperty()
34 {
35     CleanUp();
36 }
37 
CleanUp()38 void StackProperty::CleanUp()
39 {
40     if (auto i = interface_cast<INotifyOnChange>(defaultValue_)) {
41         i->OnChanged()->RemoveHandler(uintptr_t(this));
42     }
43     for (auto&& m : modifiers_) {
44         if (auto i = interface_cast<INotifyOnChange>(m)) {
45             i->OnChanged()->RemoveHandler(uintptr_t(this));
46         }
47     }
48     modifiers_.clear();
49     for (auto&& v : values_) {
50         if (auto i = interface_cast<INotifyOnChange>(v)) {
51             i->OnChanged()->RemoveHandler(uintptr_t(this));
52         }
53     }
54     values_.clear();
55 }
56 
SetValueInValueStack(const IAny & value)57 AnyReturnValue StackProperty::SetValueInValueStack(const IAny& value)
58 {
59     AnyReturnValue res = AnyReturn::FAIL;
60     // find first value that accepts the new value, all non-accepting values are removed
61     for (int i = int(values_.size()) - 1; i >= 0; --i) {
62         {
63             auto noti = interface_cast<INotifyOnChange>(values_[i]);
64             InterfaceUniqueLock lock { values_[i] };
65             if (noti) {
66                 noti->OnChanged()->EnableHandler(uintptr_t(this), false);
67             }
68             res = values_[i]->SetValue(value);
69             if (res) {
70                 if (noti) {
71                     noti->OnChanged()->EnableHandler(uintptr_t(this), true);
72                 }
73                 break;
74             }
75             if (noti) {
76                 noti->OnChanged()->RemoveHandler(uintptr_t(this), true);
77             }
78         }
79         values_.pop_back();
80     }
81     // if there was no any to set the new value, create one
82     if (!res) {
83         if (auto c = interface_pointer_cast<IValue>(value.Clone(true))) {
84             if (auto i = interface_cast<INotifyOnChange>(c)) {
85                 i->OnChanged()->AddHandler(onChangedCallback_, uintptr_t(this));
86             }
87             values_.push_back(c);
88             res = AnyReturn::SUCCESS;
89         } else {
90             res = AnyReturn::INCOMPATIBLE_TYPE;
91         }
92     }
93     return res;
94 }
95 
SetValueToStack(const IAny::Ptr & internal)96 AnyReturnValue StackProperty::SetValueToStack(const IAny::Ptr& internal)
97 {
98     // first go through modifiers and let them alter the value
99     for (auto it = modifiers_.rbegin(); it != modifiers_.rend(); ++it) {
100         auto m = (*it)->ProcessOnSet(*internal, GetValueFromStack());
101         if (m & EVAL_ERROR) {
102             return AnyReturn::FAIL;
103         }
104         if (m & EVAL_RETURN) {
105             if (m & EVAL_VALUE_CHANGED) {
106                 NotifyChange();
107             }
108             return AnyReturn::SUCCESS;
109         }
110     }
111 
112     auto res = SetValueInValueStack(*internal);
113     if (res != AnyReturn::NOTHING_TO_DO) {
114         // reset cached value so that shared_ptrs et al get destroyed
115         currentValue_->ResetValue();
116         NotifyChange();
117     }
118     return res;
119 }
SetValue(const IAny & value)120 AnyReturnValue StackProperty::SetValue(const IAny& value)
121 {
122     if (evaluating_) {
123         CORE_LOG_E("Recursive property evaluation requested [property name=%s]", GetName().c_str());
124         return AnyReturn::RECURSIVE_CALL;
125     }
126     evaluating_ = true;
127 
128     AnyReturnValue res = AnyReturn::SUCCESS;
129 
130     auto v = GetData();
131     if (!v) {
132         CORE_LOG_D("Initializing internal any with SetValue");
133         res = SetInternalAny(value.Clone(false));
134         if (res) {
135             v = GetData();
136         }
137     }
138     if (res) {
139         CORE_ASSERT(v);
140         res = SetInternalValue(value);
141         if (res) {
142             res = SetValueToStack(v);
143         }
144     }
145 
146     evaluating_ = false;
147     return res;
148 }
GetValueFromStack() const149 const IAny& StackProperty::GetValueFromStack() const
150 {
151     if (requiresEvaluation_) {
152         AnyReturnValue res = AnyReturn::FAIL;
153         if (values_.empty()) {
154             res = currentValue_->CopyFrom(*defaultValue_);
155         } else {
156             auto& v = values_.back();
157             InterfaceSharedLock lock { v };
158             res = currentValue_->CopyFrom(v->GetValue());
159         }
160         if (!res) {
161             CORE_LOG_E("Invalid value in stack, could not copy from [property name=%s]", GetName().c_str());
162             return INVALID_ANY;
163         }
164         for (auto&& m : modifiers_) {
165             auto mres = m->ProcessOnGet(*currentValue_);
166             if (mres & EVAL_RETURN) {
167                 break;
168             }
169         }
170         requiresEvaluation_ = false;
171     }
172     return *currentValue_;
173 }
RawGetValue() const174 const IAny& StackProperty::RawGetValue() const
175 {
176     if (evaluating_) {
177         CORE_LOG_E("Recursive property evaluation requested [property name=%s]", GetName().c_str());
178         return INVALID_ANY;
179     }
180     if (!currentValue_) {
181         CORE_LOG_E("GetValue called for not initialized property [property name=%s]", GetName().c_str());
182         return INVALID_ANY;
183     }
184     evaluating_ = true;
185     const IAny& res = GetValueFromStack();
186     evaluating_ = false;
187     return res;
188 }
189 
GetValue() const190 const IAny& StackProperty::GetValue() const
191 {
192     bool isActive = false;
193     if constexpr (ENABLE_DEPENDENCY_CHECK) {
194         auto& d = GetDeps();
195         if (d.IsActive()) {
196             if (!d.AddDependency(self_.lock())) {
197                 return INVALID_ANY;
198             }
199             // force evaluation since we are checking dependencies
200             requiresEvaluation_ = true;
201             isActive = true;
202             d.Start();
203         }
204     }
205     const IAny& res = RawGetValue();
206     if constexpr (ENABLE_DEPENDENCY_CHECK) {
207         if (isActive) {
208             GetDeps().End();
209         }
210     }
211     return res;
212 }
213 
PushValue(const IValue::Ptr & value)214 ReturnError StackProperty::PushValue(const IValue::Ptr& value)
215 {
216     auto& internal = GetData();
217     if (!internal || !value || !IsValueGetCompatible(*internal, *value)) {
218         CORE_LOG_W("Incompatible value");
219         return GenericError::INCOMPATIBLE_TYPES;
220     }
221     values_.push_back(value);
222     // if it is property, see that there is no circular dependency
223     if (interface_cast<IProperty>(value)) {
224         requiresEvaluation_ = true;
225         if (!RawGetValue().GetTypeId().IsValid()) {
226             values_.pop_back();
227             return GenericError::RECURSIVE_CALL;
228         }
229     }
230     if (auto i = interface_cast<INotifyOnChange>(value)) {
231         i->OnChanged()->AddHandler(onChangedCallback_, uintptr_t(this));
232     }
233     NotifyChange();
234     return GenericError::SUCCESS;
235 }
PopValue()236 ReturnError StackProperty::PopValue()
237 {
238     if (!values_.empty()) {
239         if (auto i = interface_cast<INotifyOnChange>(values_.back())) {
240             i->OnChanged()->RemoveHandler(uintptr_t(this));
241         }
242         values_.pop_back();
243         NotifyChange();
244         return GenericError::SUCCESS;
245     }
246     return GenericError::NOT_FOUND;
247 }
TopValue() const248 IValue::Ptr StackProperty::TopValue() const
249 {
250     return !values_.empty() ? values_.back() : nullptr;
251 }
RemoveValue(const IValue::Ptr & value)252 ReturnError StackProperty::RemoveValue(const IValue::Ptr& value)
253 {
254     size_t index = 0;
255     for (auto m = values_.rbegin(); m != values_.rend(); ++m, ++index) {
256         if (*m == value) {
257             if (auto i = interface_cast<INotifyOnChange>(*m)) {
258                 i->OnChanged()->RemoveHandler(uintptr_t(this));
259             }
260             values_.erase(m.base() - 1);
261             // notify if the top-most value was removed (i.e. pop value)
262             if (index == 0) {
263                 NotifyChange();
264             }
265             return GenericError::SUCCESS;
266         }
267     }
268 
269     return GenericError::NOT_FOUND;
270 }
GetValues(const BASE_NS::array_view<const TypeId> & ids,bool strict) const271 BASE_NS::vector<IValue::Ptr> StackProperty::GetValues(const BASE_NS::array_view<const TypeId>& ids, bool strict) const
272 {
273     BASE_NS::vector<IValue::Ptr> ret;
274     for (auto&& v : values_) {
275         if (CheckInterfaces(interface_pointer_cast<CORE_NS::IInterface>(v), ids, strict)) {
276             ret.push_back(v);
277         }
278     }
279     return ret;
280 }
InsertModifier(IndexType pos,const IModifier::Ptr & mod)281 ReturnError StackProperty::InsertModifier(IndexType pos, const IModifier::Ptr& mod)
282 {
283     auto& internal = GetData();
284     if (!internal || !mod || !IsModifierGetCompatible(*internal, *mod)) {
285         CORE_LOG_W("Incompatible modifier");
286         return GenericError::INCOMPATIBLE_TYPES;
287     }
288     if (auto i = interface_cast<INotifyOnChange>(mod)) {
289         i->OnChanged()->AddHandler(onChangedCallback_, uintptr_t(this));
290     }
291     IndexType i = pos < modifiers_.size() ? pos : modifiers_.size();
292     modifiers_.insert(modifiers_.begin() + i, mod);
293     NotifyChange();
294     return GenericError::SUCCESS;
295 }
RemoveModifier(IndexType pos)296 IModifier::Ptr StackProperty::RemoveModifier(IndexType pos)
297 {
298     IModifier::Ptr p;
299     if (pos < modifiers_.size()) {
300         p = modifiers_[pos];
301         modifiers_.erase(modifiers_.begin() + pos);
302         if (auto i = interface_cast<INotifyOnChange>(p)) {
303             i->OnChanged()->RemoveHandler(uintptr_t(this));
304         }
305         NotifyChange();
306     }
307     return p;
308 }
RemoveModifier(const IModifier::Ptr & mod)309 ReturnError StackProperty::RemoveModifier(const IModifier::Ptr& mod)
310 {
311     for (auto m = modifiers_.begin(); m != modifiers_.end(); ++m) {
312         if (*m == mod) {
313             if (auto i = interface_cast<INotifyOnChange>(*m)) {
314                 i->OnChanged()->RemoveHandler(uintptr_t(this));
315             }
316             modifiers_.erase(m);
317             NotifyChange();
318             return GenericError::SUCCESS;
319         }
320     }
321 
322     return GenericError::NOT_FOUND;
323 }
324 
GetModifiers(const BASE_NS::array_view<const TypeId> & ids,bool strict) const325 BASE_NS::vector<IModifier::Ptr> StackProperty::GetModifiers(
326     const BASE_NS::array_view<const TypeId>& ids, bool strict) const
327 {
328     BASE_NS::vector<IModifier::Ptr> ret;
329     for (auto&& m : modifiers_) {
330         if (CheckInterfaces(interface_pointer_cast<CORE_NS::IInterface>(m), ids, strict)) {
331             ret.push_back(m);
332         }
333     }
334     return ret;
335 }
SetDefaultValue(const IAny & value)336 AnyReturnValue StackProperty::SetDefaultValue(const IAny& value)
337 {
338     CORE_ASSERT_MSG(defaultValue_, "SetInternalAny not called");
339     AnyReturnValue res = defaultValue_->CopyFrom(value);
340     if (res && values_.empty()) {
341         NotifyChange();
342     }
343     return res;
344 }
GetDefaultValue() const345 const IAny& StackProperty::GetDefaultValue() const
346 {
347     CORE_ASSERT_MSG(defaultValue_, "SetInternalAny not called");
348     return *defaultValue_;
349 }
SetInternalAny(IAny::Ptr any)350 AnyReturnValue StackProperty::SetInternalAny(IAny::Ptr any)
351 {
352     auto res = Super::SetInternalAny(any);
353     if (res) {
354         defaultValue_ = any->Clone(true);
355         if (auto i = interface_cast<INotifyOnChange>(defaultValue_)) {
356             i->OnChanged()->AddHandler(onChangedCallback_, uintptr_t(this));
357         }
358         currentValue_ = defaultValue_->Clone(true);
359         requiresEvaluation_ = true;
360         values_.clear();
361         modifiers_.clear();
362     }
363     return res;
364 }
NotifyChange() const365 void StackProperty::NotifyChange() const
366 {
367     requiresEvaluation_ = true;
368     CallOnChanged();
369 }
370 template<typename Vec>
ProcessResetables(Vec & vec)371 bool StackProperty::ProcessResetables(Vec& vec)
372 {
373     for (int i = int(vec.size()) - 1; i >= 0; --i) {
374         ResetResult res = ResetResult::RESET_REMOVE_ME;
375         if (auto rable = interface_cast<IStackResetable>(vec[i])) {
376             res = rable->ProcessOnReset(*defaultValue_);
377         }
378         if (res & RESET_REMOVE_ME) {
379             vec.erase(vec.begin() + i);
380         }
381         if (res & RESET_STOP) {
382             return false;
383         }
384     }
385     return true;
386 }
ResetValue()387 void StackProperty::ResetValue()
388 {
389     if (ProcessResetables(modifiers_)) {
390         ProcessResetables(values_);
391     }
392     // reset the currentValue_ and internal value so we don't accidentally keep any shared_ptrs alive
393     currentValue_ = defaultValue_->Clone(false);
394     SetInternalValue(*currentValue_);
395     NotifyChange();
396 }
RemoveAll()397 void StackProperty::RemoveAll()
398 {
399     values_.clear();
400     modifiers_.clear();
401     // reset the currentValue_ and internal value so we don't accidentally keep any shared_ptrs alive
402     currentValue_ = defaultValue_->Clone(false);
403     SetInternalValue(*currentValue_);
404     NotifyChange();
405 }
Export(IExportContext & c) const406 ReturnError StackProperty::Export(IExportContext& c) const
407 {
408     return Serializer(c) & NamedValue("defaultValue", defaultValue_) & NamedValue("values", values_) &
409            NamedValue("modifiers", modifiers_);
410 }
Import(IImportContext & c)411 ReturnError StackProperty::Import(IImportContext& c)
412 {
413     CleanUp();
414     BASE_NS::vector<SharedPtrIInterface> values;
415     BASE_NS::vector<SharedPtrIInterface> modifiers;
416     Serializer ser(c);
417     ser& NamedValue("defaultValue", defaultValue_) & NamedValue("values", values) & NamedValue("modifiers", modifiers);
418     if (ser) {
419         if (!defaultValue_) {
420             return GenericError::FAIL;
421         }
422         if (auto i = interface_cast<INotifyOnChange>(defaultValue_)) {
423             i->OnChanged()->AddHandler(onChangedCallback_, uintptr_t(this));
424         }
425         if (auto res = Super::SetInternalAny(defaultValue_->Clone(false))) {
426             currentValue_ = defaultValue_->Clone(true);
427             requiresEvaluation_ = true;
428         }
429         for (auto&& i : values) {
430             if (auto v = interface_pointer_cast<IValue>(i)) {
431                 if (auto i = interface_cast<INotifyOnChange>(v)) {
432                     i->OnChanged()->AddHandler(onChangedCallback_, uintptr_t(this));
433                 }
434                 values_.push_back(BASE_NS::move(v));
435             }
436         }
437         for (auto&& i : modifiers) {
438             if (auto v = interface_pointer_cast<IModifier>(i)) {
439                 if (auto i = interface_cast<INotifyOnChange>(v)) {
440                     i->OnChanged()->AddHandler(onChangedCallback_, uintptr_t(this));
441                 }
442                 modifiers_.push_back(BASE_NS::move(v));
443             }
444         }
445     }
446     return ser;
447 }
448 
IsDefaultValue() const449 bool StackProperty::IsDefaultValue() const
450 {
451     return values_.empty();
452 }
453 
454 } // namespace Internal
455 META_END_NAMESPACE()
456