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
168bf80f4bSopenharmony_ci#include "class_registry.h"
178bf80f4bSopenharmony_ci
188bf80f4bSopenharmony_ci#include <base/util/uid_util.h>
198bf80f4bSopenharmony_ci
208bf80f4bSopenharmony_ci#include "meta/base/interface_utils.h"
218bf80f4bSopenharmony_ci
228bf80f4bSopenharmony_ciMETA_BEGIN_NAMESPACE()
238bf80f4bSopenharmony_ci
248bf80f4bSopenharmony_civoid ClassRegistry::Clear()
258bf80f4bSopenharmony_ci{
268bf80f4bSopenharmony_ci    std::unique_lock lock { mutex_ };
278bf80f4bSopenharmony_ci    objectFactories_.clear();
288bf80f4bSopenharmony_ci}
298bf80f4bSopenharmony_ci
308bf80f4bSopenharmony_cibool ClassRegistry::Unregister(const IObjectFactory::Ptr& fac)
318bf80f4bSopenharmony_ci{
328bf80f4bSopenharmony_ci    if (!fac) {
338bf80f4bSopenharmony_ci        CORE_LOG_E("ClassRegistry: Cannot unregister a null object factory");
348bf80f4bSopenharmony_ci        return false;
358bf80f4bSopenharmony_ci    }
368bf80f4bSopenharmony_ci    size_t erased = 0;
378bf80f4bSopenharmony_ci    {
388bf80f4bSopenharmony_ci        std::unique_lock lock { mutex_ };
398bf80f4bSopenharmony_ci        erased = objectFactories_.erase(fac->GetClassInfo());
408bf80f4bSopenharmony_ci    }
418bf80f4bSopenharmony_ci    if (erased) {
428bf80f4bSopenharmony_ci        onUnregistered_->Invoke({ fac });
438bf80f4bSopenharmony_ci        return true;
448bf80f4bSopenharmony_ci    }
458bf80f4bSopenharmony_ci    return false;
468bf80f4bSopenharmony_ci}
478bf80f4bSopenharmony_ci
488bf80f4bSopenharmony_cibool ClassRegistry::Register(const IObjectFactory::Ptr& fac)
498bf80f4bSopenharmony_ci{
508bf80f4bSopenharmony_ci    if (!fac) {
518bf80f4bSopenharmony_ci        CORE_LOG_E("ClassRegistry: Cannot register a null object factory");
528bf80f4bSopenharmony_ci        return false;
538bf80f4bSopenharmony_ci    }
548bf80f4bSopenharmony_ci    {
558bf80f4bSopenharmony_ci        std::unique_lock lock { mutex_ };
568bf80f4bSopenharmony_ci        auto& info = fac->GetClassInfo();
578bf80f4bSopenharmony_ci        auto& i = objectFactories_[info];
588bf80f4bSopenharmony_ci        if (i) {
598bf80f4bSopenharmony_ci            CORE_LOG_W("ClassRegistry: Cannot register a class that was already registered [name=%s, uid=%s]",
608bf80f4bSopenharmony_ci                info.Name().data(), info.Id().ToString().c_str());
618bf80f4bSopenharmony_ci            return false;
628bf80f4bSopenharmony_ci        }
638bf80f4bSopenharmony_ci        i = fac;
648bf80f4bSopenharmony_ci    }
658bf80f4bSopenharmony_ci    onRegistered_->Invoke({ fac });
668bf80f4bSopenharmony_ci    return true;
678bf80f4bSopenharmony_ci}
688bf80f4bSopenharmony_ci
698bf80f4bSopenharmony_ciIObjectFactory::ConstPtr ClassRegistry::GetObjectFactory(const BASE_NS::Uid& uid) const
708bf80f4bSopenharmony_ci{
718bf80f4bSopenharmony_ci    std::shared_lock lock { mutex_ };
728bf80f4bSopenharmony_ci    auto it = objectFactories_.find(uid);
738bf80f4bSopenharmony_ci    return it != objectFactories_.end() ? it->second : nullptr;
748bf80f4bSopenharmony_ci}
758bf80f4bSopenharmony_ci
768bf80f4bSopenharmony_ciBASE_NS::string ClassRegistry::GetClassName(BASE_NS::Uid uid) const
778bf80f4bSopenharmony_ci{
788bf80f4bSopenharmony_ci    std::shared_lock lock { mutex_ };
798bf80f4bSopenharmony_ci    auto it = objectFactories_.find(uid);
808bf80f4bSopenharmony_ci    return it != objectFactories_.end() ? BASE_NS::string(it->second->GetClassInfo().Name())
818bf80f4bSopenharmony_ci                                        : BASE_NS::string("Unknown class id [") + BASE_NS::to_string(uid) + "]";
828bf80f4bSopenharmony_ci}
838bf80f4bSopenharmony_ci
848bf80f4bSopenharmony_ciBASE_NS::vector<IClassInfo::ConstPtr> ClassRegistry::GetAllTypes(
858bf80f4bSopenharmony_ci    ObjectCategoryBits category, bool strict, bool excludeDeprecated) const
868bf80f4bSopenharmony_ci{
878bf80f4bSopenharmony_ci    std::shared_lock lock { mutex_ };
888bf80f4bSopenharmony_ci    BASE_NS::vector<IClassInfo::ConstPtr> infos;
898bf80f4bSopenharmony_ci    for (auto&& v : objectFactories_) {
908bf80f4bSopenharmony_ci        const auto& factory = v.second;
918bf80f4bSopenharmony_ci        if (excludeDeprecated && (factory->GetClassInfo().category & ObjectCategoryBits::DEPRECATED)) {
928bf80f4bSopenharmony_ci            // Omit DEPRECATED classes if excludeDeprecated flag is true
938bf80f4bSopenharmony_ci            continue;
948bf80f4bSopenharmony_ci        }
958bf80f4bSopenharmony_ci        if (CheckCategoryBits(factory->GetClassInfo().category, category, strict)) {
968bf80f4bSopenharmony_ci            infos.emplace_back(factory);
978bf80f4bSopenharmony_ci        }
988bf80f4bSopenharmony_ci    }
998bf80f4bSopenharmony_ci    return infos;
1008bf80f4bSopenharmony_ci}
1018bf80f4bSopenharmony_ci
1028bf80f4bSopenharmony_ciBASE_NS::vector<IClassInfo::ConstPtr> ClassRegistry::GetAllTypes(
1038bf80f4bSopenharmony_ci    const BASE_NS::vector<BASE_NS::Uid>& interfaceUids, bool strict, bool excludeDeprecated) const
1048bf80f4bSopenharmony_ci{
1058bf80f4bSopenharmony_ci    std::shared_lock lock { mutex_ };
1068bf80f4bSopenharmony_ci    BASE_NS::vector<IClassInfo::ConstPtr> infos;
1078bf80f4bSopenharmony_ci    for (auto&& v : objectFactories_) {
1088bf80f4bSopenharmony_ci        const auto& factory = v.second;
1098bf80f4bSopenharmony_ci        if (factory->GetClassInfo().category & ObjectCategoryBits::INTERNAL) {
1108bf80f4bSopenharmony_ci            // Omit classes with INTERNAL flag from the list
1118bf80f4bSopenharmony_ci            continue;
1128bf80f4bSopenharmony_ci        }
1138bf80f4bSopenharmony_ci        if (excludeDeprecated && (factory->GetClassInfo().category & ObjectCategoryBits::DEPRECATED)) {
1148bf80f4bSopenharmony_ci            // Omit DEPRECATED classes if excludeDeprecated flag is true
1158bf80f4bSopenharmony_ci            continue;
1168bf80f4bSopenharmony_ci        }
1178bf80f4bSopenharmony_ci        if (CheckInterfaces(factory->GetClassInterfaces(), interfaceUids, strict)) {
1188bf80f4bSopenharmony_ci            infos.push_back(factory);
1198bf80f4bSopenharmony_ci        }
1208bf80f4bSopenharmony_ci    }
1218bf80f4bSopenharmony_ci    return infos;
1228bf80f4bSopenharmony_ci}
1238bf80f4bSopenharmony_ci
1248bf80f4bSopenharmony_ciMETA_END_NAMESPACE()
125