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