• 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 "bind.h"
17 
18 #include <meta/ext/serialization/serializer.h>
19 
20 #include "../any.h"
21 #include "dependencies.h"
22 
23 META_BEGIN_NAMESPACE()
24 namespace Internal {
25 
~Bind()26 Bind::~Bind()
27 {
28     for (auto it = dependencies_.begin(); it != dependencies_.end(); ++it) {
29         if (auto p = it->lock()) {
30             p->OnChanged()->RemoveHandler(uintptr_t(this));
31         }
32     }
33 }
34 
SetValue(const IAny & value)35 AnyReturnValue Bind::SetValue(const IAny& value)
36 {
37     return AnyReturn::NOT_SUPPORTED;
38 }
GetValue() const39 const IAny& Bind::GetValue() const
40 {
41     if (func_ && context_) {
42         context_->Reset();
43         func_->Invoke(context_);
44         if (context_->Succeeded()) {
45             return *context_->GetResult();
46         }
47     }
48     CORE_LOG_W("GetValue called for invalid bind");
49     return INVALID_ANY;
50 }
IsCompatible(const TypeId & id) const51 bool Bind::IsCompatible(const TypeId& id) const
52 {
53     return context_ && context_->GetResult() && META_NS::IsCompatible(*context_->GetResult(), id);
54 }
SetTarget(const IProperty::ConstPtr & prop,bool getDeps,const IProperty * owner)55 bool Bind::SetTarget(const IProperty::ConstPtr& prop, bool getDeps, const IProperty* owner)
56 {
57     auto f = GetObjectRegistry().Create<IFunction>(META_NS::ClassId::PropertyFunction);
58     if (auto i = interface_cast<IPropertyFunction>(f)) {
59         i->SetTarget(prop);
60         if (SetTarget(f, getDeps, owner)) {
61             return AddDependency(prop);
62         }
63     }
64     return false;
65 }
SetTarget(const IFunction::ConstPtr & func,bool getDeps,const IProperty * owner)66 bool Bind::SetTarget(const IFunction::ConstPtr& func, bool getDeps, const IProperty* owner)
67 {
68     // inherit serializability from the function
69     META_NS::SetObjectFlags(static_cast<IObjectFlags*>(this), ObjectFlagBits::SERIALIZE,
70         META_NS::IsFlagSet(func, ObjectFlagBits::SERIALIZE));
71     func_ = func;
72     return func_ && CreateContext(getDeps, owner);
73 }
GetTarget() const74 IFunction::ConstPtr Bind::GetTarget() const
75 {
76     return func_;
77 }
AddDependency(const INotifyOnChange::ConstPtr & dep)78 bool Bind::AddDependency(const INotifyOnChange::ConstPtr& dep)
79 {
80     for (auto& d : dependencies_) {
81         if (dep == d.lock()) {
82             return true;
83         }
84     }
85     dep->OnChanged()->AddHandler(event_, uintptr_t(this));
86     dependencies_.push_back(dep);
87     return true;
88 }
RemoveDependency(const INotifyOnChange::ConstPtr & dep)89 bool Bind::RemoveDependency(const INotifyOnChange::ConstPtr& dep)
90 {
91     for (auto it = dependencies_.begin(); it != dependencies_.end(); ++it) {
92         if (it->lock() == dep) {
93             dep->OnChanged()->RemoveHandler(uintptr_t(this));
94             dependencies_.erase(it);
95             return true;
96         }
97     }
98     return false;
99 }
GetDependencies() const100 BASE_NS::vector<INotifyOnChange::ConstPtr> Bind::GetDependencies() const
101 {
102     BASE_NS::vector<INotifyOnChange::ConstPtr> deps;
103     for (auto&& v : dependencies_) {
104         if (auto d = v.lock()) {
105             deps.push_back(d);
106         }
107     }
108     return deps;
109 }
EventOnChanged(MetadataQuery) const110 BASE_NS::shared_ptr<IEvent> Bind::EventOnChanged(MetadataQuery) const
111 {
112     return event_;
113 }
Export(IExportContext & c) const114 ReturnError Bind::Export(IExportContext& c) const
115 {
116     return Serializer(c) & NamedValue("function", func_);
117 }
Import(IImportContext & c)118 ReturnError Bind::Import(IImportContext& c)
119 {
120     return Serializer(c) & NamedValue("function", func_);
121 }
Finalize(IImportFunctions &)122 ReturnError Bind::Finalize(IImportFunctions&)
123 {
124     if (func_) {
125         if (CreateContext(false, nullptr)) {
126             if (auto i = interface_cast<IPropertyFunction>(func_)) {
127                 if (auto noti = interface_pointer_cast<INotifyOnChange>(i->GetDestination())) {
128                     AddDependency(noti);
129                 }
130             }
131             return GenericError::SUCCESS;
132         }
133     }
134     return GenericError::FAIL;
135 }
136 
CreateContext(bool eval,const IProperty * owner)137 bool Bind::CreateContext(bool eval, const IProperty* owner)
138 {
139     context_ = func_->CreateCallContext();
140     if (context_ && eval) {
141         BASE_NS::vector<IProperty::ConstPtr> deps;
142 
143         auto& d = GetDeps();
144         d.Start();
145         // Evaluate to collect dependencies
146         GetValue();
147         auto state = d.GetImmediateDependencies(deps);
148         if (state && owner && d.HasDependency(owner)) {
149             state = GenericError::RECURSIVE_CALL;
150         }
151         d.End();
152         if (!state) {
153             return false;
154         }
155         for (auto&& v : deps) {
156             if (auto noti = interface_pointer_cast<INotifyOnChange>(v)) {
157                 AddDependency(noti);
158             }
159         }
160     }
161     return context_ != nullptr;
162 }
163 
Reset()164 void Bind::Reset() {}
165 
166 } // namespace Internal
167 META_END_NAMESPACE()