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