• 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 "exporter.h"
17 
18 #include <meta/api/util.h>
19 #include <meta/interface/intf_attach.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 
ShouldSerialize(const IObject::ConstPtr & object) const28 bool Exporter::ShouldSerialize(const IObject::ConstPtr& object) const
29 {
30     return IsFlagSet(object, ObjectFlagBits::SERIALIZE);
31 }
ShouldSerialize(const IAny & any) const32 bool Exporter::ShouldSerialize(const IAny& any) const
33 {
34     SharedPtrConstIInterface p;
35     if (any.GetValue(p)) {
36         if (auto flags = interface_cast<IObjectFlags>(p)) {
37             return flags->GetObjectFlags().IsSet(ObjectFlagBits::SERIALIZE);
38         }
39     }
40     return true;
41 }
42 
SetInstanceIdMapping(BASE_NS::unordered_map<InstanceId,InstanceId> map)43 void Exporter::SetInstanceIdMapping(BASE_NS::unordered_map<InstanceId, InstanceId> map)
44 {
45     mapInstanceIds_ = BASE_NS::move(map);
46 }
SetResourceManager(CORE_NS::IResourceManager::Ptr p)47 void Exporter::SetResourceManager(CORE_NS::IResourceManager::Ptr p)
48 {
49     resources_ = BASE_NS::move(p);
50 }
SetUserContext(IObject::Ptr p)51 void Exporter::SetUserContext(IObject::Ptr p)
52 {
53     userContext_ = BASE_NS::move(p);
54 }
SetMetadata(SerMetadata m)55 void Exporter::SetMetadata(SerMetadata m)
56 {
57     metadata_ = BASE_NS::move(m);
58 }
59 
ConvertInstanceId(const InstanceId & id) const60 InstanceId Exporter::ConvertInstanceId(const InstanceId& id) const
61 {
62     auto it = mapInstanceIds_.find(id);
63     return it != mapInstanceIds_.end() ? it->second : id;
64 }
65 
MarkExported(const IObject::ConstPtr & object)66 bool Exporter::MarkExported(const IObject::ConstPtr& object)
67 {
68     bool res = false;
69     if (auto i = interface_cast<IObjectInstance>(object)) {
70         auto id = i->GetInstanceId();
71         auto it = exported_.find(id);
72         res = it != exported_.end();
73         if (!res) {
74             exported_[id] = object;
75         }
76     }
77     return res;
78 }
79 
HasBeenExported(const InstanceId & id) const80 bool Exporter::HasBeenExported(const InstanceId& id) const
81 {
82     return exported_.find(id) != exported_.end();
83 }
84 
Export(const IObject::ConstPtr & object)85 ISerNode::Ptr Exporter::Export(const IObject::ConstPtr& object)
86 {
87     BASE_NS::shared_ptr<RootNode> res;
88     if (object) {
89         ISerNode::Ptr node;
90         auto r = ExportObject(object, node);
91         if (r) {
92             // resolve deferred weak ptr exports
93             for (auto&& d : deferred_) {
94                 if (!ResolveDeferredWeakPtr(d)) {
95                     CORE_LOG_E("Failed to resolve deferred weak ptr export");
96                 }
97             }
98             res.reset(new RootNode { BASE_NS::move(node), metadata_ });
99         }
100     }
101     return res;
102 }
103 
CreateObjectNode(const IObject::ConstPtr & object,BASE_NS::shared_ptr<MapNode> node)104 ISerNode::Ptr Exporter::CreateObjectNode(const IObject::ConstPtr& object, BASE_NS::shared_ptr<MapNode> node)
105 {
106     ISerNode::Ptr res;
107     InstanceId iid;
108     BASE_NS::string name = object->GetName();
109     if (auto i = interface_cast<IObjectInstance>(object)) {
110         iid = ConvertInstanceId(i->GetInstanceId());
111     }
112     if (name == iid.ToString()) {
113         name = "";
114     }
115     return ISerNode::Ptr(new ObjectNode(
116         BASE_NS::string(object->GetClassName()), BASE_NS::move(name), object->GetClassId(), iid, BASE_NS::move(node)));
117 }
118 
CreateObjectRefNode(const RefUri & ref)119 ISerNode::Ptr Exporter::CreateObjectRefNode(const RefUri& ref)
120 {
121     RefUri uri(ref);
122     uri.SetBaseObjectUid(ConvertInstanceId(uri.BaseObjectUid()).ToUid());
123     return ISerNode::Ptr(new RefNode { uri });
124 }
125 
CreateObjectRefNode(const IObject::ConstPtr & object)126 ISerNode::Ptr Exporter::CreateObjectRefNode(const IObject::ConstPtr& object)
127 {
128     ISerNode::Ptr res;
129     if (auto i = interface_cast<IObjectInstance>(object)) {
130         RefUri ref(i->GetInstanceId().ToUid());
131         res = CreateObjectRefNode(ref);
132     }
133     return res;
134 }
135 
ExportObject(const IObject::ConstPtr & object,ISerNode::Ptr & res)136 ReturnError Exporter::ExportObject(const IObject::ConstPtr& object, ISerNode::Ptr& res)
137 {
138     ReturnError err = GenericError::SUCCESS;
139     if (ShouldSerialize(object)) {
140         if (MarkExported(object)) {
141             res = CreateObjectRefNode(object);
142         } else if (auto ser = interface_cast<ISerializable>(object)) {
143             ExportContext context(*this, object);
144             err = ser->Export(context);
145             if (err) {
146                 res = context.GetSubstitution();
147                 if (!res) {
148                     res = CreateObjectNode(object, context.ExtractNode());
149                 }
150             }
151         } else {
152             res = AutoExportObject(object);
153         }
154     }
155     return err;
156 }
157 
AutoExportObject(const IObject::ConstPtr & object)158 ISerNode::Ptr Exporter::AutoExportObject(const IObject::ConstPtr& object)
159 {
160     BASE_NS::vector<NamedNode> members;
161     AutoExportObjectMembers(object, members);
162     return CreateObjectNode(object, BASE_NS::shared_ptr<MapNode>(new MapNode(members)));
163 }
164 
AutoExportObjectMembers(const IObject::ConstPtr & object,BASE_NS::vector<NamedNode> & members)165 ReturnError Exporter::AutoExportObjectMembers(const IObject::ConstPtr& object, BASE_NS::vector<NamedNode>& members)
166 {
167     if (auto flags = interface_cast<IObjectFlags>(object)) {
168         if (flags->GetObjectDefaultFlags() != flags->GetObjectFlags()) {
169             ISerNode::Ptr node;
170             auto res = ExportValue(Any<uint64_t>(flags->GetObjectFlags().GetValue()), node);
171             if (res && node) {
172                 members.push_back(NamedNode { "__flags", node });
173             }
174         }
175     }
176     if (auto attach = interface_cast<IAttach>(object)) {
177         if (IsFlagSet(object, ObjectFlagBits::SERIALIZE_ATTACHMENTS)) {
178             if (auto cont = attach->GetAttachmentContainer()) {
179                 if (auto node = ExportIContainer(*cont)) {
180                     members.push_back(NamedNode { "__attachments", node });
181                 }
182             }
183         }
184     }
185     if (auto cont = interface_cast<IContainer>(object)) {
186         if (IsFlagSet(object, ObjectFlagBits::SERIALIZE_HIERARCHY)) {
187             if (auto node = ExportIContainer(*cont)) {
188                 members.push_back(NamedNode { "__children", node });
189             }
190         }
191     }
192     return GenericError::SUCCESS;
193 }
194 
ExportIContainer(const IContainer & cont)195 ISerNode::Ptr Exporter::ExportIContainer(const IContainer& cont)
196 {
197     BASE_NS::vector<ISerNode::Ptr> elements;
198     for (size_t i = 0; i != cont.GetSize(); ++i) {
199         ISerNode::Ptr node;
200         if (ExportObject(cont.GetAt(i), node) && node) {
201             elements.push_back(BASE_NS::move(node));
202         }
203     }
204     return ISerNode::Ptr(new ArrayNode(BASE_NS::move(elements)));
205 }
206 
207 template<typename... Builtins>
ExportSingleBuiltinValue(TypeList<Builtins...>,const IAny & value)208 static ISerNode::Ptr ExportSingleBuiltinValue(TypeList<Builtins...>, const IAny& value)
209 {
210     ISerNode::Ptr res;
211     [[maybe_unused]] bool r =
212         ((META_NS::IsCompatible(value, Builtins::ID) ? (res = Builtins::CreateNode(value), true) : false) || ...);
213     return res;
214 }
215 
ExportArray(const IArrayAny & array)216 ISerNode::Ptr Exporter::ExportArray(const IArrayAny& array)
217 {
218     ISerNode::Ptr res;
219     auto any = array.Clone(AnyCloneOptions { CloneValueType::DEFAULT_VALUE, TypeIdRole::ITEM });
220     if (any) {
221         BASE_NS::vector<ISerNode::Ptr> elements;
222         for (size_t i = 0; i != array.GetSize(); ++i) {
223             if (!array.GetAnyAt(i, *any)) {
224                 return nullptr;
225             }
226             ISerNode::Ptr node;
227             if (ExportValue(*any, node) && node) {
228                 elements.push_back(BASE_NS::move(node));
229             }
230         }
231         res.reset(new ArrayNode(BASE_NS::move(elements)));
232     }
233     return res;
234 }
235 
ExportBuiltinValue(const IAny & value)236 ISerNode::Ptr Exporter::ExportBuiltinValue(const IAny& value)
237 {
238     ISerNode::Ptr res;
239     if (auto arr = interface_cast<IArrayAny>(&value)) {
240         res = ExportArray(*arr);
241     } else {
242         if (value.GetTypeId() == UidFromType<float>()) {
243             // handle as double
244             res = ExportSingleBuiltinValue(SupportedBuiltins {}, Any<double>(GetValue<float>(value)));
245         } else {
246             res = ExportSingleBuiltinValue(SupportedBuiltins {}, value);
247         }
248     }
249     return res;
250 }
251 
ExportPointer(const IAny & entity,ISerNode::Ptr & res)252 ReturnError Exporter::ExportPointer(const IAny& entity, ISerNode::Ptr& res)
253 {
254     // first see if it is a weak pointer
255     BASE_NS::weak_ptr<const CORE_NS::IInterface> weak;
256     bool isWeak = entity.GetValue(weak);
257     if (isWeak) {
258         if (auto obj = interface_pointer_cast<IObject>(weak)) {
259             return ExportWeakPtr(obj, res);
260         }
261     }
262 
263     BASE_NS::shared_ptr<const CORE_NS::IInterface> intf;
264     if (entity.GetValue(intf)) {
265         // see if it is null pointer
266         if (!intf) {
267             res = ISerNode::Ptr(new NilNode);
268             return GenericError::SUCCESS;
269         }
270         // finally handle normal pointer case
271         if (!isWeak) {
272             if (auto obj = interface_pointer_cast<IObject>(intf)) {
273                 return ExportObject(obj, res);
274             }
275             if (auto any = interface_pointer_cast<IAny>(intf)) {
276                 return ExportAny(any, res);
277             }
278         }
279     }
280     return GenericError::FAIL;
281 }
282 
ExportValue(const IAny & entity,ISerNode::Ptr & res)283 ReturnError Exporter::ExportValue(const IAny& entity, ISerNode::Ptr& res)
284 {
285     if (!ShouldSerialize(entity)) {
286         return GenericError::SUCCESS;
287     }
288     if (auto exp = globalData_.GetValueSerializer(entity.GetTypeId())) {
289         res = exp->Export(*this, entity);
290         if (res) {
291             return GenericError::SUCCESS;
292         }
293         CORE_LOG_W("Value export registered for type [%s, %s] but it failed", entity.GetTypeIdString().c_str(),
294             entity.GetTypeId().ToString().c_str());
295     }
296     res = ExportBuiltinValue(entity);
297     if (!res) {
298         ExportPointer(entity, res);
299     }
300     if (!res) {
301         CORE_LOG_F(
302             "Failed to export type [%s, %s]", entity.GetTypeIdString().c_str(), entity.GetTypeId().ToString().c_str());
303         return GenericError::FAIL;
304     }
305     return GenericError::SUCCESS;
306 }
307 
ExportAny(const IAny::ConstPtr & any,ISerNode::Ptr & res)308 ReturnError Exporter::ExportAny(const IAny::ConstPtr& any, ISerNode::Ptr& res)
309 {
310     ReturnError err = GenericError::SUCCESS;
311     if (any && !registry_.GetPropertyRegister().IsAnyRegistered(any->GetClassId())) {
312         CORE_LOG_W("Exporting any that is not registered [class id=%s, type=%s, type id=%s]",
313             any->GetClassId().ToString().c_str(), any->GetTypeIdString().c_str(), any->GetTypeId().ToString().c_str());
314     }
315     if (!any) {
316         res = ISerNode::Ptr(new NilNode);
317     } else if (auto ser = interface_cast<ISerializable>(any)) {
318         ExportContext context(*this, interface_pointer_cast<IObject>(any));
319         err = ser->Export(context);
320         if (err) {
321             res = context.GetSubstitution();
322             if (!res) {
323                 res = ISerNode::Ptr(
324                     new ObjectNode(BASE_NS::string("Any"), {}, any->GetClassId(), {}, context.ExtractNode()));
325             }
326         }
327     } else {
328         ISerNode::Ptr node;
329         err = ExportValue(*any, node);
330         if (err && node) {
331             auto members = CreateShared<MapNode>(BASE_NS::vector<NamedNode> { NamedNode { "value", node } });
332             res = ISerNode::Ptr(
333                 new ObjectNode(BASE_NS::string("Any"), {}, any->GetClassId(), {}, BASE_NS::move(members)));
334         }
335     }
336     return err;
337 }
338 
ResolveUriSegment(const IObject::ConstPtr & ptr,RefUri & uri) const339 IObject::Ptr Exporter::ResolveUriSegment(const IObject::ConstPtr& ptr, RefUri& uri) const
340 {
341     if (auto instance = interface_cast<IObjectInstance>(ptr)) {
342         if (auto context = interface_cast<IObjectContext>(ptr)) {
343             uri.PushObjectContextSegment();
344         } else {
345             uri.PushObjectSegment(instance->GetName());
346         }
347         return ptr->Resolve(RefUri::ParentUri());
348     }
349     if (auto property = interface_cast<IProperty>(ptr)) {
350         uri.PushPropertySegment(property->GetName());
351         auto owner = interface_pointer_cast<IObject>(property->GetOwner());
352         if (!owner) {
353             CORE_LOG_E("No Owner for property '%s' when exporting weak ptr", property->GetName().c_str());
354         }
355         return owner;
356     }
357     return nullptr;
358 }
359 
ResolveDeferredWeakPtr(const DeferredWeakPtrResolve & d)360 ReturnError Exporter::ResolveDeferredWeakPtr(const DeferredWeakPtrResolve& d)
361 {
362     if (auto p = d.ptr.lock()) {
363         auto original = p;
364         RefUri uri;
365         while (p) {
366             if (auto obj = interface_cast<IObjectInstance>(p)) {
367                 auto iid = ConvertInstanceId(obj->GetInstanceId());
368                 if (HasBeenExported(iid) || globalData_.GetGlobalObject(obj->GetInstanceId())) {
369                     uri.SetBaseObjectUid(iid.ToUid());
370                     d.node->SetValue(uri);
371                     return GenericError::SUCCESS;
372                 }
373             }
374             p = ResolveUriSegment(p, uri);
375         }
376         CORE_LOG_E("Could not find suitable anchor object when exporting weak ptr [%s, %s, %s]",
377             BASE_NS::string(original->GetClassName()).c_str(), original->GetName().c_str(),
378             original->GetClassId().ToString().c_str());
379     } else {
380         CORE_LOG_E("Weak ptr is null when doing deferred resolve");
381     }
382     return GenericError::FAIL;
383 }
384 
ExportWeakPtr(const IObject::ConstWeakPtr & ptr,ISerNode::Ptr & res)385 ReturnError Exporter::ExportWeakPtr(const IObject::ConstWeakPtr& ptr, ISerNode::Ptr& res)
386 {
387     if (auto p = ptr.lock()) {
388         auto node = CreateShared<RefNode>(RefUri {});
389         res = ISerNode::Ptr(node);
390         deferred_.push_back(DeferredWeakPtrResolve { node, ptr });
391     } else {
392         res = ISerNode::Ptr(new NilNode);
393     }
394     return GenericError::SUCCESS;
395 }
396 
ExportToNode(const IAny & entity,ISerNode::Ptr & res)397 ReturnError Exporter::ExportToNode(const IAny& entity, ISerNode::Ptr& res)
398 {
399     return ExportValue(entity, res);
400 }
401 
Export(BASE_NS::string_view name,const IAny & entity)402 ReturnError ExportContext::Export(BASE_NS::string_view name, const IAny& entity)
403 {
404     ISerNode::Ptr node;
405     auto res = exporter_.ExportValue(entity, node);
406     if (res && node) {
407         elements_.push_back(NamedNode { BASE_NS::string(name), BASE_NS::move(node) });
408     }
409     if (!res) {
410         CORE_LOG_W("Failed to export member with name '%s'", BASE_NS::string(name).c_str());
411     }
412     return res;
413 }
414 
ExportAny(BASE_NS::string_view name,const IAny::Ptr & any)415 ReturnError ExportContext::ExportAny(BASE_NS::string_view name, const IAny::Ptr& any)
416 {
417     ISerNode::Ptr node;
418     auto res = exporter_.ExportAny(any, node);
419     if (res && node) {
420         elements_.push_back(NamedNode { BASE_NS::string(name), BASE_NS::move(node) });
421     }
422     if (!res) {
423         CORE_LOG_W("Failed to export member with name '%s'", BASE_NS::string(name).c_str());
424     }
425     return res;
426 }
427 
ExportWeakPtr(BASE_NS::string_view name,const IObject::ConstWeakPtr & ptr)428 ReturnError ExportContext::ExportWeakPtr(BASE_NS::string_view name, const IObject::ConstWeakPtr& ptr)
429 {
430     ISerNode::Ptr node;
431     auto res = exporter_.ExportWeakPtr(ptr, node);
432     if (res && node) {
433         elements_.push_back(NamedNode { BASE_NS::string(name), BASE_NS::move(node) });
434     }
435     if (!res) {
436         CORE_LOG_W("Failed to export member with name '%s'", BASE_NS::string(name).c_str());
437     }
438     return res;
439 }
440 
AutoExport()441 ReturnError ExportContext::AutoExport()
442 {
443     if (object_) {
444         BASE_NS::vector<NamedNode> vec;
445         auto res = exporter_.AutoExportObjectMembers(object_, vec);
446         if (res) {
447             elements_.insert(elements_.end(), vec.begin(), vec.end());
448         }
449         return res;
450     }
451     CORE_LOG_W("Failed to auto export, exported type is not IObject");
452     return GenericError::FAIL;
453 }
454 
ExtractNode()455 BASE_NS::shared_ptr<MapNode> ExportContext::ExtractNode()
456 {
457     return BASE_NS::shared_ptr<MapNode>(new MapNode { BASE_NS::move(elements_) });
458 }
459 
ExportToNode(const IAny & entity,ISerNode::Ptr & res)460 ReturnError ExportContext::ExportToNode(const IAny& entity, ISerNode::Ptr& res)
461 {
462     return exporter_.ExportToNode(entity, res);
463 }
464 
Context() const465 CORE_NS::IInterface* ExportContext::Context() const
466 {
467     return exporter_.GetInterface(CORE_NS::IInterface::UID);
468 }
UserContext() const469 META_NS::IObject::Ptr ExportContext::UserContext() const
470 {
471     return exporter_.GetUserContext();
472 }
SubstituteThis(ISerNode::Ptr n)473 ReturnError ExportContext::SubstituteThis(ISerNode::Ptr n)
474 {
475     ReturnError res = GenericError::FAIL;
476     if (n) {
477         substNode_ = BASE_NS::move(n);
478         // do instance mapping
479         if (auto node = interface_cast<IObjectNode>(substNode_)) {
480             InstanceId iid;
481             if (auto i = interface_cast<IObjectInstance>(object_)) {
482                 iid = exporter_.ConvertInstanceId(i->GetInstanceId());
483             }
484             node->SetInstanceId(iid);
485         }
486         res = GenericError::SUCCESS;
487     }
488     return res;
489 }
GetMetadata() const490 SerMetadata ExportContext::GetMetadata() const
491 {
492     return exporter_.GetMetadata();
493 }
494 
495 } // namespace Serialization
496 META_END_NAMESPACE()
497