• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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