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 "ref_uri_util.h"
17
18 #include <meta/api/util.h>
19 #include <meta/base/ref_uri.h>
20 #include <meta/ext/resolve_helper.h>
21 #include <meta/interface/intf_containable.h>
22 #include <meta/interface/intf_container.h>
23 #include <meta/interface/intf_metadata.h>
24 #include <meta/interface/property/intf_property.h>
25
META_BEGIN_NAMESPACE()26 META_BEGIN_NAMESPACE()
27
28 static IObjectInstance::ConstPtr FindParentObject(const IObjectInstance::ConstPtr& obj)
29 {
30 auto containee = interface_cast<IContainable>(obj);
31 return containee ? interface_pointer_cast<IObjectInstance>(containee->GetParent()) : nullptr;
32 }
33
FindRootObject(IObjectInstance::ConstPtr obj)34 static IObjectInstance::ConstPtr FindRootObject(IObjectInstance::ConstPtr obj)
35 {
36 auto prev = obj;
37 while ((obj = FindParentObject(obj))) {
38 prev = obj;
39 }
40 return prev;
41 }
42
FindChildObject(const IObjectInstance::ConstPtr & obj,BASE_NS::string_view name)43 static IObjectInstance::ConstPtr FindChildObject(const IObjectInstance::ConstPtr& obj, BASE_NS::string_view name)
44 {
45 auto cont = interface_cast<IContainer>(obj);
46 return cont ? interface_pointer_cast<IObjectInstance>(cont->FindByName(name)) : nullptr;
47 }
48
ResolvePropertySegment(BASE_NS::string_view propName,const IObjectInstance::Ptr & base,const RefUri & ref)49 static IObject::Ptr ResolvePropertySegment(
50 BASE_NS::string_view propName, const IObjectInstance::Ptr& base, const RefUri& ref)
51 {
52 // get the property and see if it contains object to continue the resolve
53 IMetadata* meta = interface_cast<IMetadata>(base);
54 if (!meta) {
55 return nullptr;
56 }
57
58 auto prop = meta->GetPropertyByName(propName);
59 if (prop) {
60 if (ref.GetAbsoluteInterpretation() && ref.IsEmpty()) {
61 return interface_pointer_cast<IObject>(prop);
62 }
63 if (auto obj = GetPointer<IObjectInstance>(prop)) {
64 return obj->Resolve(ref);
65 }
66 }
67 return nullptr;
68 }
69
ResolveSegment(const IObjectInstance::Ptr & base,RefUri ref)70 static IObject::Ptr ResolveSegment(const IObjectInstance::Ptr& base, RefUri ref)
71 {
72 auto node = ref.TakeFirstNode();
73 if (node.type == RefUri::Node::OBJECT) {
74 IObjectInstance::ConstPtr obj = (node.name == "..") ? FindParentObject(base) : FindChildObject(base, node.name);
75 return obj ? obj->Resolve(ref) : nullptr;
76 }
77
78 if (node.type == RefUri::Node::SPECIAL) {
79 if (node.name != "@Context") {
80 return nullptr;
81 }
82 // ask the object to resolve the special segment
83 auto obj = base->Resolve<IObjectInstance>(RefUri::ContextUri());
84 return obj ? obj->Resolve(ref) : nullptr;
85 }
86
87 return ResolvePropertySegment(node.name, base, ref);
88 }
89
DefaultResolveObject(const IObjectInstance::Ptr & base,const RefUri & uri)90 IObject::Ptr DefaultResolveObject(const IObjectInstance::Ptr& base, const RefUri& uri)
91 {
92 if (!CheckValidResolve(base, uri)) {
93 return nullptr;
94 }
95
96 RefUri ref { uri.RelativeUri() };
97 if (ref.IsEmpty()) {
98 return base;
99 }
100
101 if (ref.StartsFromRoot()) {
102 ref.SetStartsFromRoot(false);
103 auto obj = FindRootObject(base);
104 return obj ? obj->Resolve(BASE_NS::move(ref)) : nullptr;
105 }
106
107 return ResolveSegment(base, BASE_NS::move(ref));
108 }
109
110 META_END_NAMESPACE()
111