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