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 "ref_uri_util.h" 178bf80f4bSopenharmony_ci 188bf80f4bSopenharmony_ci#include <meta/api/util.h> 198bf80f4bSopenharmony_ci#include <meta/base/ref_uri.h> 208bf80f4bSopenharmony_ci#include <meta/ext/resolve_helper.h> 218bf80f4bSopenharmony_ci#include <meta/interface/intf_containable.h> 228bf80f4bSopenharmony_ci#include <meta/interface/intf_container.h> 238bf80f4bSopenharmony_ci#include <meta/interface/intf_metadata.h> 248bf80f4bSopenharmony_ci#include <meta/interface/property/intf_property.h> 258bf80f4bSopenharmony_ci 268bf80f4bSopenharmony_ciMETA_BEGIN_NAMESPACE() 278bf80f4bSopenharmony_ci 288bf80f4bSopenharmony_cistatic IObjectInstance::ConstPtr FindParentObject(const IObjectInstance::ConstPtr& obj) 298bf80f4bSopenharmony_ci{ 308bf80f4bSopenharmony_ci auto containee = interface_cast<IContainable>(obj); 318bf80f4bSopenharmony_ci return containee ? interface_pointer_cast<IObjectInstance>(containee->GetParent()) : nullptr; 328bf80f4bSopenharmony_ci} 338bf80f4bSopenharmony_ci 348bf80f4bSopenharmony_cistatic IObjectInstance::ConstPtr FindRootObject(IObjectInstance::ConstPtr obj) 358bf80f4bSopenharmony_ci{ 368bf80f4bSopenharmony_ci auto prev = obj; 378bf80f4bSopenharmony_ci while ((obj = FindParentObject(obj))) { 388bf80f4bSopenharmony_ci prev = obj; 398bf80f4bSopenharmony_ci } 408bf80f4bSopenharmony_ci return prev; 418bf80f4bSopenharmony_ci} 428bf80f4bSopenharmony_ci 438bf80f4bSopenharmony_cistatic IObjectInstance::ConstPtr FindChildObject(const IObjectInstance::ConstPtr& obj, BASE_NS::string_view name) 448bf80f4bSopenharmony_ci{ 458bf80f4bSopenharmony_ci auto cont = interface_cast<IContainer>(obj); 468bf80f4bSopenharmony_ci return cont ? interface_pointer_cast<IObjectInstance>(cont->FindByName(name)) : nullptr; 478bf80f4bSopenharmony_ci} 488bf80f4bSopenharmony_ci 498bf80f4bSopenharmony_cistatic IObject::Ptr ResolvePropertySegment( 508bf80f4bSopenharmony_ci BASE_NS::string_view propName, const IObjectInstance::Ptr& base, const RefUri& ref) 518bf80f4bSopenharmony_ci{ 528bf80f4bSopenharmony_ci // get the property and see if it contains object to continue the resolve 538bf80f4bSopenharmony_ci IMetadata* meta = interface_cast<IMetadata>(base); 548bf80f4bSopenharmony_ci if (!meta) { 558bf80f4bSopenharmony_ci return nullptr; 568bf80f4bSopenharmony_ci } 578bf80f4bSopenharmony_ci 588bf80f4bSopenharmony_ci auto prop = meta->GetPropertyByName(propName); 598bf80f4bSopenharmony_ci if (prop) { 608bf80f4bSopenharmony_ci if (ref.GetAbsoluteInterpretation() && ref.IsEmpty()) { 618bf80f4bSopenharmony_ci return interface_pointer_cast<IObject>(prop); 628bf80f4bSopenharmony_ci } 638bf80f4bSopenharmony_ci if (auto obj = GetPointer<IObjectInstance>(prop)) { 648bf80f4bSopenharmony_ci return obj->Resolve(ref); 658bf80f4bSopenharmony_ci } 668bf80f4bSopenharmony_ci } 678bf80f4bSopenharmony_ci return nullptr; 688bf80f4bSopenharmony_ci} 698bf80f4bSopenharmony_ci 708bf80f4bSopenharmony_cistatic IObject::Ptr ResolveSegment(const IObjectInstance::Ptr& base, RefUri ref) 718bf80f4bSopenharmony_ci{ 728bf80f4bSopenharmony_ci auto node = ref.TakeFirstNode(); 738bf80f4bSopenharmony_ci if (node.type == RefUri::Node::OBJECT) { 748bf80f4bSopenharmony_ci IObjectInstance::ConstPtr obj = (node.name == "..") ? FindParentObject(base) : FindChildObject(base, node.name); 758bf80f4bSopenharmony_ci return obj ? obj->Resolve(ref) : nullptr; 768bf80f4bSopenharmony_ci } 778bf80f4bSopenharmony_ci 788bf80f4bSopenharmony_ci if (node.type == RefUri::Node::SPECIAL) { 798bf80f4bSopenharmony_ci if (node.name != "@Context") { 808bf80f4bSopenharmony_ci return nullptr; 818bf80f4bSopenharmony_ci } 828bf80f4bSopenharmony_ci // ask the object to resolve the special segment 838bf80f4bSopenharmony_ci auto obj = base->Resolve<IObjectInstance>(RefUri::ContextUri()); 848bf80f4bSopenharmony_ci return obj ? obj->Resolve(ref) : nullptr; 858bf80f4bSopenharmony_ci } 868bf80f4bSopenharmony_ci 878bf80f4bSopenharmony_ci return ResolvePropertySegment(node.name, base, ref); 888bf80f4bSopenharmony_ci} 898bf80f4bSopenharmony_ci 908bf80f4bSopenharmony_ciIObject::Ptr DefaultResolveObject(const IObjectInstance::Ptr& base, const RefUri& uri) 918bf80f4bSopenharmony_ci{ 928bf80f4bSopenharmony_ci if (!CheckValidResolve(base, uri)) { 938bf80f4bSopenharmony_ci return nullptr; 948bf80f4bSopenharmony_ci } 958bf80f4bSopenharmony_ci 968bf80f4bSopenharmony_ci RefUri ref { uri.RelativeUri() }; 978bf80f4bSopenharmony_ci if (ref.IsEmpty()) { 988bf80f4bSopenharmony_ci return base; 998bf80f4bSopenharmony_ci } 1008bf80f4bSopenharmony_ci 1018bf80f4bSopenharmony_ci if (ref.StartsFromRoot()) { 1028bf80f4bSopenharmony_ci ref.SetStartsFromRoot(false); 1038bf80f4bSopenharmony_ci auto obj = FindRootObject(base); 1048bf80f4bSopenharmony_ci return obj ? obj->Resolve(BASE_NS::move(ref)) : nullptr; 1058bf80f4bSopenharmony_ci } 1068bf80f4bSopenharmony_ci 1078bf80f4bSopenharmony_ci return ResolveSegment(base, BASE_NS::move(ref)); 1088bf80f4bSopenharmony_ci} 1098bf80f4bSopenharmony_ci 1108bf80f4bSopenharmony_ciMETA_END_NAMESPACE() 111