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 #include "importer.h"
16
17 #include <meta/api/util.h>
18 #include <meta/interface/intf_object_context.h>
19 #include <meta/interface/serialization/intf_serializable.h>
20
21 #include "ser_nodes.h"
22
23 META_BEGIN_NAMESPACE()
24 namespace Serialization {
25
IsBuiltinAny(const ObjectId & oid)26 static bool IsBuiltinAny(const ObjectId& oid)
27 {
28 static constexpr BASE_NS::Uid uid = MakeUidImpl(0, BUILTIN_ANY_TAG);
29 return oid.ToUid().data[1] == uid.data[1];
30 }
31
IsBuiltinArrayAny(const ObjectId & oid)32 static bool IsBuiltinArrayAny(const ObjectId& oid)
33 {
34 static constexpr BASE_NS::Uid uid = MakeUidImpl(0, BUILTIN_ARRAY_ANY_TAG);
35 return oid.ToUid().data[1] == uid.data[1];
36 }
37
ConvertInstanceId(const InstanceId & id) const38 InstanceId Importer::ConvertInstanceId(const InstanceId& id) const
39 {
40 auto it = mapInstanceIds_.find(id);
41 return it != mapInstanceIds_.end() ? it->second : id;
42 }
43
IsRegisteredObjectType(const ObjectId & oid) const44 bool Importer::IsRegisteredObjectType(const ObjectId& oid) const
45 {
46 return registry_.GetObjectFactory(oid) != nullptr;
47 }
48
Import(const ISerNode::ConstPtr & tree)49 IObject::Ptr Importer::Import(const ISerNode::ConstPtr& tree)
50 {
51 IObject::Ptr object;
52 if (auto root = interface_cast<IRootNode>(tree)) {
53 importVersion_ = root->GetSerializerVersion();
54 object = ImportObject(root->GetObject());
55 if (object) {
56 // resolve deferred ref uris
57 for (auto&& d : deferred_) {
58 if (auto obj = interface_pointer_cast<CORE_NS::IInterface>(ImportRef(d.uri))) {
59 d.target->SetValue(obj);
60 } else {
61 CORE_LOG_W("Failed to resolve deferred ref uri");
62 }
63 }
64 // execute finalizes
65 for (auto&& f : finalizes_) {
66 if (!f->Finalize(*this)) {
67 CORE_LOG_W("Failed to finalize imported object");
68 }
69 }
70 }
71 } else {
72 CORE_LOG_W("Invalid serialisation tree, expected root node");
73 }
74 return object;
75 }
76
GetReferencedObject(const InstanceId & uid) const77 IObject::Ptr Importer::GetReferencedObject(const InstanceId& uid) const
78 {
79 // first check for globals
80 if (auto obj = globalData_.GetGlobalObject(uid)) {
81 return obj;
82 }
83 // then see the object registry.
84 return registry_.GetObjectInstanceByInstanceId(ConvertInstanceId(uid));
85 }
86
ImportRef(const RefUri & ref)87 IObject::Ptr Importer::ImportRef(const RefUri& ref)
88 {
89 if (ref.BaseObjectUid() == BASE_NS::Uid {}) {
90 // for now we only support anchored references, relative references requires to know the current object
91 CORE_LOG_W("Missing base object for ref uri [%s]", ref.ToString().c_str());
92 return nullptr;
93 }
94 if (auto obj = interface_pointer_cast<IObjectInstance>(GetReferencedObject(ref.BaseObjectUid()))) {
95 auto uri = ref.RelativeUri();
96 // interpret all uris as absolute, pointing to the exact thing they say
97 uri.SetAbsoluteInterpretation(true);
98 if (auto ret = obj->Resolve(uri)) {
99 return ret;
100 }
101 }
102 CORE_LOG_W("Failed to find object for ref uri [%s]", ref.ToString().c_str());
103 return nullptr;
104 }
105
ImportObject(const IObjectNode::ConstPtr & node,IObject::Ptr object)106 IObject::Ptr Importer::ImportObject(const IObjectNode::ConstPtr& node, IObject::Ptr object)
107 {
108 IObject::Ptr result;
109 if (object) {
110 if (auto instance = interface_cast<IObjectInstance>(object)) {
111 if (auto iid = node->GetInstanceId(); iid.IsValid()) {
112 CORE_LOG_D("importing object [%s] -> [%s]", iid.ToString().c_str(),
113 instance->GetInstanceId().ToString().c_str());
114 mapInstanceIds_[iid] = instance->GetInstanceId();
115 }
116 }
117 if (auto ser = interface_cast<ISerializable>(object)) {
118 ImportContext context(*this, object, interface_pointer_cast<IMapNode>(node->GetMembers()));
119 if (ser->Import(context)) {
120 result = object;
121 } else {
122 CORE_LOG_W("Failed to import object [type=%s]", node->GetObjectId().ToString().c_str());
123 }
124 } else if (AutoImportObject(node->GetMembers(), object)) {
125 result = object;
126 }
127 }
128 if (auto fin = interface_pointer_cast<IImportFinalize>(result)) {
129 finalizes_.push_back(fin);
130 }
131 return result;
132 }
133
ImportObject(const ISerNode::ConstPtr & n)134 IObject::Ptr Importer::ImportObject(const ISerNode::ConstPtr& n)
135 {
136 IObject::Ptr result;
137 if (auto node = interface_cast<IRefUriNode>(n)) {
138 result = ImportRef(node->GetValue());
139 }
140 if (auto node = interface_pointer_cast<IObjectNode>(n)) {
141 if (!node->GetObjectId().IsValid()) {
142 return nullptr;
143 }
144 IObject::Ptr object;
145 if (IsRegisteredObjectType(node->GetObjectId())) {
146 object = registry_.Create(node->GetObjectId());
147 } else {
148 // check if it is property?
149 auto name = node->GetObjectName();
150 if (!name.empty()) {
151 object =
152 interface_pointer_cast<IObject>(registry_.GetPropertyRegister().Create(node->GetObjectId(), name));
153 }
154 }
155 if (object) {
156 result = ImportObject(node, object);
157 } else {
158 CORE_LOG_W("Failed to create requested object type [%s]", node->GetObjectId().ToString().c_str());
159 }
160 }
161 return result;
162 }
163
AutoImportObject(const ISerNode::ConstPtr & node,IObject::Ptr object)164 ReturnError Importer::AutoImportObject(const ISerNode::ConstPtr& node, IObject::Ptr object)
165 {
166 if (auto members = interface_cast<IMapNode>(node)) {
167 return AutoImportObject(*members, object);
168 }
169 return GenericError::SUCCESS;
170 }
171
AutoImportObject(const IMapNode & members,IObject::Ptr object)172 ReturnError Importer::AutoImportObject(const IMapNode& members, IObject::Ptr object)
173 {
174 if (auto flags = interface_cast<IObjectFlags>(object)) {
175 if (auto fn = members.FindNode("__flags")) {
176 ImportIObjectFlags(fn, *flags);
177 }
178 }
179 if (auto meta = interface_cast<IMetadata>(object)) {
180 ImportIMetadata(members, object, *meta);
181 }
182 if (auto attach = interface_cast<IAttach>(object)) {
183 if (auto fn = members.FindNode("__attachments")) {
184 ImportIAttach(fn, object, *attach);
185 }
186 }
187 if (auto cont = interface_cast<IContainer>(object)) {
188 if (auto fn = members.FindNode("__children")) {
189 ImportIContainer(fn, *cont);
190 }
191 }
192 return GenericError::SUCCESS;
193 }
194
ImportIObjectFlags(const ISerNode::ConstPtr & node,IObjectFlags & flags)195 ReturnError Importer::ImportIObjectFlags(const ISerNode::ConstPtr& node, IObjectFlags& flags)
196 {
197 Any<uint64_t> any;
198 if (ImportValue(node, any)) {
199 uint64_t v {};
200 if (any.GetValue(v)) {
201 flags.SetObjectFlags(v);
202 return GenericError::SUCCESS;
203 }
204 }
205 return GenericError::FAIL;
206 }
207
ImportIMetadata(const IMapNode & members,const IObject::Ptr & owner,IMetadata & data)208 ReturnError Importer::ImportIMetadata(const IMapNode& members, const IObject::Ptr& owner, IMetadata& data)
209 {
210 if (auto fn = members.FindNode("__properties")) {
211 if (auto cont = data.GetPropertyContainer()) {
212 if (auto array = interface_cast<IArrayNode>(fn)) {
213 for (auto&& m : array->GetMembers()) {
214 IObject::Ptr mobj;
215 if (auto onode = interface_pointer_cast<IObjectNode>(m)) {
216 mobj = interface_pointer_cast<IObject>(data.GetPropertyByName(onode->GetObjectName()));
217 if (mobj) {
218 mobj = ImportObject(onode, mobj);
219 }
220 }
221 if (!mobj) {
222 mobj = ImportObject(m);
223 if (auto p = interface_pointer_cast<IProperty>(mobj)) {
224 data.AddProperty(p);
225 }
226 }
227 }
228 }
229 }
230 }
231 return GenericError::SUCCESS;
232 }
233
ImportIAttach(const ISerNode::ConstPtr & node,const IObject::Ptr & owner,IAttach & cont)234 ReturnError Importer::ImportIAttach(const ISerNode::ConstPtr& node, const IObject::Ptr& owner, IAttach& cont)
235 {
236 if (auto array = interface_cast<IArrayNode>(node)) {
237 auto attachments = cont.GetAttachmentContainer();
238 for (auto&& m : array->GetMembers()) {
239 if (auto att = ImportObject(m)) {
240 if (attachments) {
241 cont.Detach(attachments->FindByName<IAttachment>(att->GetName()));
242 }
243 if (auto attachment = interface_pointer_cast<IAttachment>(att)) {
244 auto context = attachment->DataContext()->GetValue().lock();
245 if (!context) {
246 context = owner;
247 }
248 // Re-attach
249 cont.Attach(attachment, context);
250 }
251 }
252 }
253 }
254 return GenericError::SUCCESS;
255 }
256
ImportIContainer(const ISerNode::ConstPtr & node,IContainer & cont)257 ReturnError Importer::ImportIContainer(const ISerNode::ConstPtr& node, IContainer& cont)
258 {
259 if (auto array = interface_cast<IArrayNode>(node)) {
260 cont.RemoveAll();
261 for (auto&& m : array->GetMembers()) {
262 if (auto object = ImportObject(m)) {
263 cont.Insert(-1, object);
264 }
265 }
266 }
267 return GenericError::SUCCESS;
268 }
269
270 template<typename... Builtins>
ImportSingleBuiltinValue(TypeList<Builtins...>,const ISerNode::ConstPtr & n,IAny & value)271 static ReturnError ImportSingleBuiltinValue(TypeList<Builtins...>, const ISerNode::ConstPtr& n, IAny& value)
272 {
273 AnyReturnValue res = AnyReturn::FAIL;
274 [[maybe_unused]] bool r =
275 ((Builtins::ID == value.GetTypeId() ? (res = Builtins::ExtractValue(n, value), true) : false) || ...);
276 return res ? GenericError::SUCCESS : GenericError::FAIL;
277 }
278
ImportArray(const ISerNode::ConstPtr & n,IArrayAny & array)279 ReturnError Importer::ImportArray(const ISerNode::ConstPtr& n, IArrayAny& array)
280 {
281 if (auto node = interface_cast<IArrayNode>(n)) {
282 array.RemoveAll();
283 for (auto&& m : node->GetMembers()) {
284 if (auto any = array.Clone(AnyCloneOptions { CloneValueType::DEFAULT_VALUE, TypeIdRole::ITEM })) {
285 if (!ImportValue(m, *any) || !array.InsertAnyAt(-1, *any)) {
286 return GenericError::FAIL;
287 }
288 } else {
289 return GenericError::FAIL;
290 }
291 }
292 return GenericError::SUCCESS;
293 }
294 return GenericError::FAIL;
295 }
296
ImportBuiltinValue(const ISerNode::ConstPtr & n,IAny & entity)297 ReturnError Importer::ImportBuiltinValue(const ISerNode::ConstPtr& n, IAny& entity)
298 {
299 if (auto arr = interface_cast<IArrayAny>(&entity)) {
300 return ImportArray(n, *arr);
301 }
302 if (entity.GetTypeId() == UidFromType<float>()) {
303 // handle as double
304 Any<double> d;
305 auto ret = ImportSingleBuiltinValue(SupportedBuiltins {}, n, d);
306 if (ret) {
307 entity.SetValue(static_cast<float>(d.InternalGetValue()));
308 }
309 return ret;
310 }
311 return ImportSingleBuiltinValue(SupportedBuiltins {}, n, entity);
312 }
313
ImportPointer(const ISerNode::ConstPtr & n,IAny & entity)314 ReturnError Importer::ImportPointer(const ISerNode::ConstPtr& n, IAny& entity)
315 {
316 if (auto nil = interface_cast<INilNode>(n)) {
317 entity.SetValue(SharedPtrIInterface {});
318 return GenericError::SUCCESS;
319 }
320 if (auto intf = GetPointer(entity)) {
321 if (auto node = interface_pointer_cast<IObjectNode>(n)) {
322 if (auto object = interface_pointer_cast<IObject>(intf)) {
323 if (ImportObject(node, object)) {
324 return GenericError::SUCCESS;
325 }
326 } else if (auto any = interface_pointer_cast<IAny>(intf)) {
327 return ImportAny(node, any);
328 }
329 }
330 } else {
331 if (auto node = interface_pointer_cast<IObjectNode>(n);
332 (node && IsRegisteredObjectType(node->GetObjectId())) || interface_cast<IBuiltinValueNode<RefUri>>(n)) {
333 if (auto obj = ImportObject(n)) {
334 if (entity.SetValue(interface_pointer_cast<CORE_NS::IInterface>(obj))) {
335 return GenericError::SUCCESS;
336 }
337 }
338 } else if (auto any = ImportAny(n)) {
339 if (entity.SetValue(interface_pointer_cast<CORE_NS::IInterface>(any))) {
340 return GenericError::SUCCESS;
341 }
342 }
343 }
344 return GenericError::FAIL;
345 }
346
ImportValue(const ISerNode::ConstPtr & n,IAny & entity)347 ReturnError Importer::ImportValue(const ISerNode::ConstPtr& n, IAny& entity)
348 {
349 if (auto imp = globalData_.GetValueSerializer(entity.GetTypeId())) {
350 if (auto any = imp->Import(*this, n)) {
351 if (entity.CopyFrom(*any)) {
352 return GenericError::SUCCESS;
353 }
354 } else {
355 CORE_LOG_W("Value import registered for type [%s] but it failed", entity.GetTypeId().ToString().c_str());
356 }
357 }
358 if (ImportBuiltinValue(n, entity)) {
359 return GenericError::SUCCESS;
360 }
361 if (IsGetCompatibleWith<SharedPtrConstIInterface>(entity)) {
362 return ImportPointer(n, entity);
363 }
364 CORE_LOG_F("Failed to import type [%s]", entity.GetTypeId().ToString().c_str());
365 return GenericError::FAIL;
366 }
367
ImportWeakPtrInAny(const ISerNode::ConstPtr & node,const IAny::Ptr & any)368 ReturnError Importer::ImportWeakPtrInAny(const ISerNode::ConstPtr& node, const IAny::Ptr& any)
369 {
370 if (auto nil = interface_cast<INilNode>(node)) {
371 any->SetValue(SharedPtrIInterface {});
372 return GenericError::SUCCESS;
373 }
374 if (auto n = interface_cast<IRefUriNode>(node)) {
375 // defer resolving the ref uri, might point to object that has not been imported yet.
376 deferred_.push_back(DeferredUriResolve { any, n->GetValue() });
377 return GenericError::SUCCESS;
378 }
379 CORE_LOG_F("Cannot import something else than ref uri to weak ptr");
380 return GenericError::FAIL;
381 }
382
ImportAny(const IObjectNode::ConstPtr & node,const IAny::Ptr & any)383 ReturnError Importer::ImportAny(const IObjectNode::ConstPtr& node, const IAny::Ptr& any)
384 {
385 if (auto ser = interface_cast<ISerializable>(any)) {
386 ImportContext context(
387 *this, interface_pointer_cast<IObject>(any), interface_pointer_cast<IMapNode>(node->GetMembers()));
388 if (ser->Import(context)) {
389 return GenericError::SUCCESS;
390 }
391 CORE_LOG_W("Failed to import object [type=%s]", node->GetObjectId().ToString().c_str());
392 } else {
393 if (auto members = interface_cast<IMapNode>(node->GetMembers())) {
394 if (auto value = members->FindNode("value")) {
395 if (IsGetCompatibleWith<WeakPtrConstIInterface>(*any)) {
396 if (ImportWeakPtrInAny(value, any)) {
397 return GenericError::SUCCESS;
398 }
399 } else if (ImportValue(value, *any)) {
400 return GenericError::SUCCESS;
401 }
402 }
403 }
404 }
405 CORE_LOG_F("Failed to import any [%s]", any->GetClassId().ToString().c_str());
406 return GenericError::FAIL;
407 }
408
ImportAny(const ISerNode::ConstPtr & n)409 IAny::Ptr Importer::ImportAny(const ISerNode::ConstPtr& n)
410 {
411 IAny::Ptr any;
412 if (auto node = interface_pointer_cast<IObjectNode>(n)) {
413 if (!node->GetObjectId().IsValid()) {
414 return nullptr;
415 }
416 any = registry_.GetPropertyRegister().ConstructAny(node->GetObjectId());
417 if (any) {
418 if (!ImportAny(node, any)) {
419 any.reset();
420 }
421 } else {
422 CORE_LOG_F("No such any-type registered [%s, classname=%s]", node->GetObjectId().ToString().c_str(),
423 node->GetObjectClassName().c_str());
424 }
425 }
426 return any;
427 }
428
ResolveRefUri(const RefUri & uri)429 IObject::Ptr Importer::ResolveRefUri(const RefUri& uri)
430 {
431 return ImportRef(uri);
432 }
433
ImportFromNode(const ISerNode::ConstPtr & node,IAny & entity)434 ReturnError Importer::ImportFromNode(const ISerNode::ConstPtr& node, IAny& entity)
435 {
436 return ImportValue(node, entity);
437 }
438
HasMember(BASE_NS::string_view name) const439 bool ImportContext::HasMember(BASE_NS::string_view name) const
440 {
441 return node_ && node_->FindNode(name);
442 }
443
Import(BASE_NS::string_view name,IAny & entity)444 ReturnError ImportContext::Import(BASE_NS::string_view name, IAny& entity)
445 {
446 if (node_) {
447 if (auto n = node_->FindNode(name)) {
448 return importer_.ImportValue(n, entity);
449 }
450 }
451 CORE_LOG_W("Failed to import member with name '%s'", BASE_NS::string(name).c_str());
452 return GenericError::FAIL;
453 }
454
ImportAny(BASE_NS::string_view name,IAny::Ptr & any)455 ReturnError ImportContext::ImportAny(BASE_NS::string_view name, IAny::Ptr& any)
456 {
457 if (node_) {
458 if (auto n = node_->FindNode(name)) {
459 any = importer_.ImportAny(n);
460 return GenericError::SUCCESS;
461 }
462 }
463 CORE_LOG_W("Failed to import member with name '%s'", BASE_NS::string(name).c_str());
464 return GenericError::FAIL;
465 }
466
ImportWeakPtr(BASE_NS::string_view name,IObject::WeakPtr & ptr)467 ReturnError ImportContext::ImportWeakPtr(BASE_NS::string_view name, IObject::WeakPtr& ptr)
468 {
469 if (node_) {
470 if (auto n = node_->FindNode(name)) {
471 if (auto node = interface_cast<IRefUriNode>(n)) {
472 ptr = importer_.ImportRef(node->GetValue());
473 return GenericError::SUCCESS;
474 }
475 CORE_LOG_W("Failed to import weak ptr from non ref uri node");
476 }
477 }
478 CORE_LOG_W("Failed to import member with name '%s'", BASE_NS::string(name).c_str());
479 return GenericError::FAIL;
480 }
481
AutoImport()482 ReturnError ImportContext::AutoImport()
483 {
484 if (!object_) {
485 CORE_LOG_W("Failed to auto import, imported type is not IObject");
486 return GenericError::FAIL;
487 }
488 if (node_) {
489 return importer_.AutoImportObject(*node_, object_);
490 }
491 CORE_LOG_W("Failed to auto import, invalid node");
492 return GenericError::FAIL;
493 }
494
ResolveRefUri(const RefUri & uri)495 IObject::Ptr ImportContext::ResolveRefUri(const RefUri& uri)
496 {
497 return importer_.ImportRef(uri);
498 }
499
ImportFromNode(const ISerNode::ConstPtr & node,IAny & entity)500 ReturnError ImportContext::ImportFromNode(const ISerNode::ConstPtr& node, IAny& entity)
501 {
502 return importer_.ImportFromNode(node, entity);
503 }
504
505 } // namespace Serialization
506 META_END_NAMESPACE()
507