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