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