/* * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "ref_uri_util.h" #include #include #include #include #include #include #include META_BEGIN_NAMESPACE() static IObjectInstance::ConstPtr FindParentObject(const IObjectInstance::ConstPtr& obj) { auto containee = interface_cast(obj); return containee ? interface_pointer_cast(containee->GetParent()) : nullptr; } static IObjectInstance::ConstPtr FindRootObject(IObjectInstance::ConstPtr obj) { auto prev = obj; while ((obj = FindParentObject(obj))) { prev = obj; } return prev; } static IObjectInstance::ConstPtr FindChildObject(const IObjectInstance::ConstPtr& obj, BASE_NS::string_view name) { auto cont = interface_cast(obj); return cont ? interface_pointer_cast(cont->FindByName(name)) : nullptr; } static IObject::Ptr ResolvePropertySegment( BASE_NS::string_view propName, const IObjectInstance::Ptr& base, const RefUri& ref) { // get the property and see if it contains object to continue the resolve IMetadata* meta = interface_cast(base); if (!meta) { return nullptr; } auto prop = meta->GetPropertyByName(propName); if (prop) { if (ref.GetAbsoluteInterpretation() && ref.IsEmpty()) { return interface_pointer_cast(prop); } if (auto obj = GetPointer(prop)) { return obj->Resolve(ref); } } return nullptr; } static IObject::Ptr ResolveSegment(const IObjectInstance::Ptr& base, RefUri ref) { auto node = ref.TakeFirstNode(); if (node.type == RefUri::Node::OBJECT) { IObjectInstance::ConstPtr obj = (node.name == "..") ? FindParentObject(base) : FindChildObject(base, node.name); return obj ? obj->Resolve(ref) : nullptr; } if (node.type == RefUri::Node::SPECIAL) { if (node.name != "@Context") { return nullptr; } // ask the object to resolve the special segment auto obj = base->Resolve(RefUri::ContextUri()); return obj ? obj->Resolve(ref) : nullptr; } return ResolvePropertySegment(node.name, base, ref); } IObject::Ptr DefaultResolveObject(const IObjectInstance::Ptr& base, const RefUri& uri) { if (!CheckValidResolve(base, uri)) { return nullptr; } RefUri ref { uri.RelativeUri() }; if (ref.IsEmpty()) { return base; } if (ref.StartsFromRoot()) { ref.SetStartsFromRoot(false); auto obj = FindRootObject(base); return obj ? obj->Resolve(BASE_NS::move(ref)) : nullptr; } return ResolveSegment(base, BASE_NS::move(ref)); } META_END_NAMESPACE()