18bf80f4bSopenharmony_ci/*
28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License.
58bf80f4bSopenharmony_ci * You may obtain a copy of the License at
68bf80f4bSopenharmony_ci *
78bf80f4bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88bf80f4bSopenharmony_ci *
98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and
138bf80f4bSopenharmony_ci * limitations under the License.
148bf80f4bSopenharmony_ci */
158bf80f4bSopenharmony_ci#include "bind.h"
168bf80f4bSopenharmony_ci
178bf80f4bSopenharmony_ci#include <meta/ext/serialization/serializer.h>
188bf80f4bSopenharmony_ci
198bf80f4bSopenharmony_ci#include "../any.h"
208bf80f4bSopenharmony_ci#include "dependencies.h"
218bf80f4bSopenharmony_ci
228bf80f4bSopenharmony_ciMETA_BEGIN_NAMESPACE()
238bf80f4bSopenharmony_cinamespace Internal {
248bf80f4bSopenharmony_ci
258bf80f4bSopenharmony_ciBind::~Bind()
268bf80f4bSopenharmony_ci{
278bf80f4bSopenharmony_ci    for (auto it = dependencies_.begin(); it != dependencies_.end(); ++it) {
288bf80f4bSopenharmony_ci        if (auto p = it->lock()) {
298bf80f4bSopenharmony_ci            p->OnChanged()->RemoveHandler(uintptr_t(this));
308bf80f4bSopenharmony_ci        }
318bf80f4bSopenharmony_ci    }
328bf80f4bSopenharmony_ci}
338bf80f4bSopenharmony_ci
348bf80f4bSopenharmony_ciAnyReturnValue Bind::SetValue(const IAny& value)
358bf80f4bSopenharmony_ci{
368bf80f4bSopenharmony_ci    return AnyReturn::NOT_SUPPORTED;
378bf80f4bSopenharmony_ci}
388bf80f4bSopenharmony_ciconst IAny& Bind::GetValue() const
398bf80f4bSopenharmony_ci{
408bf80f4bSopenharmony_ci    if (func_ && context_) {
418bf80f4bSopenharmony_ci        context_->Reset();
428bf80f4bSopenharmony_ci        func_->Invoke(context_);
438bf80f4bSopenharmony_ci        if (context_->Succeeded()) {
448bf80f4bSopenharmony_ci            return *context_->GetResult();
458bf80f4bSopenharmony_ci        }
468bf80f4bSopenharmony_ci    }
478bf80f4bSopenharmony_ci    CORE_LOG_W("GetValue called for invalid bind");
488bf80f4bSopenharmony_ci    return INVALID_ANY;
498bf80f4bSopenharmony_ci}
508bf80f4bSopenharmony_cibool Bind::IsCompatible(const TypeId& id) const
518bf80f4bSopenharmony_ci{
528bf80f4bSopenharmony_ci    return context_ && context_->GetResult() && META_NS::IsCompatible(*context_->GetResult(), id);
538bf80f4bSopenharmony_ci}
548bf80f4bSopenharmony_cibool Bind::SetTarget(const IProperty::ConstPtr& prop, bool getDeps, const IProperty* owner)
558bf80f4bSopenharmony_ci{
568bf80f4bSopenharmony_ci    auto f = GetObjectRegistry().Create<IFunction>(META_NS::ClassId::PropertyFunction);
578bf80f4bSopenharmony_ci    if (auto i = interface_cast<IPropertyFunction>(f)) {
588bf80f4bSopenharmony_ci        i->SetTarget(prop);
598bf80f4bSopenharmony_ci        if (SetTarget(f, getDeps, owner)) {
608bf80f4bSopenharmony_ci            return AddDependency(prop);
618bf80f4bSopenharmony_ci        }
628bf80f4bSopenharmony_ci    }
638bf80f4bSopenharmony_ci    return false;
648bf80f4bSopenharmony_ci}
658bf80f4bSopenharmony_cibool Bind::SetTarget(const IFunction::ConstPtr& func, bool getDeps, const IProperty* owner)
668bf80f4bSopenharmony_ci{
678bf80f4bSopenharmony_ci    // inherit serializability from the function
688bf80f4bSopenharmony_ci    META_NS::SetObjectFlags(static_cast<IObjectFlags*>(this), ObjectFlagBits::SERIALIZE,
698bf80f4bSopenharmony_ci        META_NS::IsFlagSet(func, ObjectFlagBits::SERIALIZE));
708bf80f4bSopenharmony_ci    func_ = func;
718bf80f4bSopenharmony_ci    return func_ && CreateContext(getDeps, owner);
728bf80f4bSopenharmony_ci}
738bf80f4bSopenharmony_ciIFunction::ConstPtr Bind::GetTarget() const
748bf80f4bSopenharmony_ci{
758bf80f4bSopenharmony_ci    return func_;
768bf80f4bSopenharmony_ci}
778bf80f4bSopenharmony_cibool Bind::AddDependency(const INotifyOnChange::ConstPtr& dep)
788bf80f4bSopenharmony_ci{
798bf80f4bSopenharmony_ci    for (auto& d : dependencies_) {
808bf80f4bSopenharmony_ci        if (dep == d.lock()) {
818bf80f4bSopenharmony_ci            return true;
828bf80f4bSopenharmony_ci        }
838bf80f4bSopenharmony_ci    }
848bf80f4bSopenharmony_ci    dep->OnChanged()->AddHandler(event_, uintptr_t(this));
858bf80f4bSopenharmony_ci    dependencies_.push_back(dep);
868bf80f4bSopenharmony_ci    return true;
878bf80f4bSopenharmony_ci}
888bf80f4bSopenharmony_cibool Bind::RemoveDependency(const INotifyOnChange::ConstPtr& dep)
898bf80f4bSopenharmony_ci{
908bf80f4bSopenharmony_ci    for (auto it = dependencies_.begin(); it != dependencies_.end(); ++it) {
918bf80f4bSopenharmony_ci        if (it->lock() == dep) {
928bf80f4bSopenharmony_ci            dep->OnChanged()->RemoveHandler(uintptr_t(this));
938bf80f4bSopenharmony_ci            dependencies_.erase(it);
948bf80f4bSopenharmony_ci            return true;
958bf80f4bSopenharmony_ci        }
968bf80f4bSopenharmony_ci    }
978bf80f4bSopenharmony_ci    return false;
988bf80f4bSopenharmony_ci}
998bf80f4bSopenharmony_ciBASE_NS::vector<INotifyOnChange::ConstPtr> Bind::GetDependencies() const
1008bf80f4bSopenharmony_ci{
1018bf80f4bSopenharmony_ci    BASE_NS::vector<INotifyOnChange::ConstPtr> deps;
1028bf80f4bSopenharmony_ci    for (auto&& v : dependencies_) {
1038bf80f4bSopenharmony_ci        if (auto d = v.lock()) {
1048bf80f4bSopenharmony_ci            deps.push_back(d);
1058bf80f4bSopenharmony_ci        }
1068bf80f4bSopenharmony_ci    }
1078bf80f4bSopenharmony_ci    return deps;
1088bf80f4bSopenharmony_ci}
1098bf80f4bSopenharmony_ciBASE_NS::shared_ptr<IEvent> Bind::EventOnChanged() const
1108bf80f4bSopenharmony_ci{
1118bf80f4bSopenharmony_ci    return event_;
1128bf80f4bSopenharmony_ci}
1138bf80f4bSopenharmony_ciReturnError Bind::Export(IExportContext& c) const
1148bf80f4bSopenharmony_ci{
1158bf80f4bSopenharmony_ci    return Serializer(c) & NamedValue("function", func_);
1168bf80f4bSopenharmony_ci}
1178bf80f4bSopenharmony_ciReturnError Bind::Import(IImportContext& c)
1188bf80f4bSopenharmony_ci{
1198bf80f4bSopenharmony_ci    return Serializer(c) & NamedValue("function", func_);
1208bf80f4bSopenharmony_ci}
1218bf80f4bSopenharmony_ciReturnError Bind::Finalize(IImportFunctions&)
1228bf80f4bSopenharmony_ci{
1238bf80f4bSopenharmony_ci    if (func_) {
1248bf80f4bSopenharmony_ci        if (CreateContext(false, nullptr)) {
1258bf80f4bSopenharmony_ci            if (auto i = interface_cast<IPropertyFunction>(func_)) {
1268bf80f4bSopenharmony_ci                if (auto noti = interface_pointer_cast<INotifyOnChange>(i->GetDestination())) {
1278bf80f4bSopenharmony_ci                    AddDependency(noti);
1288bf80f4bSopenharmony_ci                }
1298bf80f4bSopenharmony_ci            }
1308bf80f4bSopenharmony_ci            return GenericError::SUCCESS;
1318bf80f4bSopenharmony_ci        }
1328bf80f4bSopenharmony_ci    }
1338bf80f4bSopenharmony_ci    return GenericError::FAIL;
1348bf80f4bSopenharmony_ci}
1358bf80f4bSopenharmony_ci
1368bf80f4bSopenharmony_cibool Bind::CreateContext(bool eval, const IProperty* owner)
1378bf80f4bSopenharmony_ci{
1388bf80f4bSopenharmony_ci    context_ = func_->CreateCallContext();
1398bf80f4bSopenharmony_ci    if (context_ && eval) {
1408bf80f4bSopenharmony_ci        BASE_NS::vector<IProperty::ConstPtr> deps;
1418bf80f4bSopenharmony_ci
1428bf80f4bSopenharmony_ci        auto& d = GetDeps();
1438bf80f4bSopenharmony_ci        d.Start();
1448bf80f4bSopenharmony_ci        // Evaluate to collect dependencies
1458bf80f4bSopenharmony_ci        GetValue();
1468bf80f4bSopenharmony_ci        auto state = d.GetImmediateDependencies(deps);
1478bf80f4bSopenharmony_ci        if (state && owner && d.HasDependency(owner)) {
1488bf80f4bSopenharmony_ci            state = GenericError::RECURSIVE_CALL;
1498bf80f4bSopenharmony_ci        }
1508bf80f4bSopenharmony_ci        d.End();
1518bf80f4bSopenharmony_ci        if (!state) {
1528bf80f4bSopenharmony_ci            return false;
1538bf80f4bSopenharmony_ci        }
1548bf80f4bSopenharmony_ci        for (auto&& v : deps) {
1558bf80f4bSopenharmony_ci            if (auto noti = interface_pointer_cast<INotifyOnChange>(v)) {
1568bf80f4bSopenharmony_ci                AddDependency(noti);
1578bf80f4bSopenharmony_ci            }
1588bf80f4bSopenharmony_ci        }
1598bf80f4bSopenharmony_ci    }
1608bf80f4bSopenharmony_ci    return context_ != nullptr;
1618bf80f4bSopenharmony_ci}
1628bf80f4bSopenharmony_ci
1638bf80f4bSopenharmony_civoid Bind::Reset() {}
1648bf80f4bSopenharmony_ci
1658bf80f4bSopenharmony_ci} // namespace Internal
1668bf80f4bSopenharmony_ciMETA_END_NAMESPACE()