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