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