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