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