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 #define JSON_IMPL
16 #include "json_output.h"
17 
18 #include <base/containers/vector.h>
19 #include <base/util/uid_util.h>
20 #include <core/json/json.h>
21 
22 #include <meta/base/namespace.h>
23 #include <meta/base/plugin.h>
24 #include <meta/base/ref_uri.h>
25 #include <meta/ext/minimal_object.h>
26 
27 META_BEGIN_NAMESPACE()
28 
29 namespace Serialization {
30 
31 constexpr Version CURRENT_JSON_VERSION(2, 0);
32 
33 META_REGISTER_CLASS(Visitor, "2838202a-b362-4715-96ed-59f19334b3ac", ObjectCategoryBits::NO_CATEGORY)
34 
35 struct Visitor : MinimalObject<ClassId::Visitor, ISerNodeVisitor> {
GetValueSerialization::Visitor36     json_value GetValue()
37     {
38         return BASE_NS::move(node_);
39     }
40 
41 private:
VisitSerialization::Visitor42     void Visit(const IRootNode&) override
43     {
44         CORE_LOG_E("Second root node, ignoring...");
45     }
VisitSerialization::Visitor46     void Visit(const INilNode&) override
47     {
48         node_ = json_value::null {};
49     }
VisitSerialization::Visitor50     void Visit(const IObjectNode& n) override
51     {
52         json_value::object object;
53         if (n.GetObjectId().IsValid() && n.GetMembers()) {
54             Visitor v;
55             n.GetMembers()->Apply(v);
56             auto value = v.GetValue();
57             if (value.is_object()) {
58                 object.emplace_back("$classId", json_value::string(n.GetObjectId().ToString()));
59                 if (!n.GetObjectClassName().empty()) {
60                     object.emplace_back("$className", json_value::string(n.GetObjectClassName()));
61                 }
62                 if (!n.GetObjectName().empty() && n.GetObjectName() != n.GetInstanceId().ToString()) {
63                     object.emplace_back("$name", json_value::string(n.GetObjectName()));
64                 }
65                 if (n.GetInstanceId().IsValid()) {
66                     object.emplace_back("$instanceId", json_value::string(n.GetInstanceId().ToString()));
67                 }
68                 json_value::object obj = value.object_;
69                 object.insert(object.end(), obj.begin(), obj.end());
70             }
71         }
72         node_ = BASE_NS::move(object);
73     }
VisitSerialization::Visitor74     void Visit(const IArrayNode& n) override
75     {
76         auto members = n.GetMembers();
77         json_value::array array;
78         array.reserve(members.size());
79         for (auto&& m : members) {
80             Visitor v;
81             m->Apply(v);
82             array.emplace_back(v.GetValue());
83         }
84         node_ = BASE_NS::move(array);
85     }
VisitSerialization::Visitor86     void Visit(const IMapNode& n) override
87     {
88         auto members = n.GetMembers();
89         json_value::object object;
90         for (auto&& m : members) {
91             Visitor v;
92             m.node->Apply(v);
93             object.emplace_back(BASE_NS::move(m.name), v.GetValue());
94         }
95         node_ = BASE_NS::move(object);
96     }
VisitSerialization::Visitor97     void Visit(const IBuiltinValueNode<bool>& n) override
98     {
99         node_ = json_value { n.GetValue() };
100     }
VisitSerialization::Visitor101     void Visit(const IBuiltinValueNode<double>& n) override
102     {
103         node_ = json_value { n.GetValue() };
104     }
VisitSerialization::Visitor105     void Visit(const IBuiltinValueNode<int64_t>& n) override
106     {
107         node_ = json_value { n.GetValue() };
108     }
VisitSerialization::Visitor109     void Visit(const IBuiltinValueNode<uint64_t>& n) override
110     {
111         node_ = json_value { n.GetValue() };
112     }
VisitSerialization::Visitor113     void Visit(const IBuiltinValueNode<BASE_NS::string>& n) override
114     {
115         node_ = json_value { n.GetValue() };
116     }
VisitSerialization::Visitor117     void Visit(const IBuiltinValueNode<RefUri>& n) override
118     {
119         json_value::object object;
120         object.emplace_back("$ref", n.GetValue().ToString());
121         node_ = BASE_NS::move(object);
122     }
VisitSerialization::Visitor123     void Visit(const ISerNode&) override
124     {
125         CORE_LOG_E("Unknown node type");
126     }
127 
128 private:
129     json_value node_;
130 };
131 
MetadataObject(const IRootNode & root)132 json_value MetadataObject(const IRootNode& root)
133 {
134     json_value::object object;
135     object.emplace_back("meta-version", json_value::string(META_VERSION.ToString()));
136     object.emplace_back("version", json_value::string(CURRENT_JSON_VERSION.ToString()));
137     object.emplace_back("exporter-version", json_value::string(root.GetSerializerVersion().ToString()));
138     return object;
139 }
140 
Process(const ISerNode::Ptr & tree)141 BASE_NS::string JsonOutput::Process(const ISerNode::Ptr& tree)
142 {
143     CORE_NS::json::standalone_value res;
144 
145     if (auto root = interface_cast<IRootNode>(tree)) {
146         if (root->GetObject()) {
147             json_value::object object;
148             object.emplace_back("$meta", MetadataObject(*root));
149 
150             Visitor v;
151             root->GetObject()->Apply(v);
152             auto node = v.GetValue();
153             if (node.is_object()) {
154                 object.emplace_back("$root", BASE_NS::move(node));
155                 res = BASE_NS::move(object);
156             } else {
157                 CORE_LOG_E("failed to output root node object");
158             }
159         } else {
160             CORE_LOG_E("root node did not contain object");
161         }
162     }
163     return CORE_NS::json::to_string(res);
164 }
165 
166 } // namespace Serialization
167 
168 META_END_NAMESPACE()
169