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 "metav1_compat.h"
16
17 #include <meta/ext/serialization/common_value_serializers.h>
18
19 META_BEGIN_NAMESPACE()
20 namespace Serialization {
21
22 constexpr Version NEW_VERSION(2, 0);
23
24 using BasicMetaTypes = TypeList<float, double, bool, uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t,
25 int64_t, BASE_NS::Uid, BASE_NS::string, BASE_NS::string_view, BASE_NS::Math::Vec2, BASE_NS::Math::UVec2,
26 BASE_NS::Math::IVec2, BASE_NS::Math::Vec3, BASE_NS::Math::UVec3, BASE_NS::Math::IVec3, BASE_NS::Math::Vec4,
27 BASE_NS::Math::UVec4, BASE_NS::Math::IVec4, BASE_NS::Math::Quat, BASE_NS::Math::Mat3X3, BASE_NS::Math::Mat4X4>;
28
IsV1Property(ObjectId oid)29 static bool IsV1Property(ObjectId oid)
30 {
31 static const BASE_NS::Uid propertyUid("00000000-0000-0000-5072-6f7065727479");
32 return oid.ToUid().data[1] == propertyUid.data[1];
33 }
34
35 template<typename... Types>
CheckBasicMetaTypes(ObjectId oid,ObjectId & out,TypeList<Types...>)36 static bool CheckBasicMetaTypes(ObjectId oid, ObjectId& out, TypeList<Types...>)
37 {
38 return (false || ... ||
39 (UidFromType<Types[]>().data[0] == oid.ToUid().data[0] ? (out = UidFromType<Types>(), true) : false));
40 }
41
IsV1BasicArray(ObjectId oid,ObjectId & out)42 static bool IsV1BasicArray(ObjectId oid, ObjectId& out)
43 {
44 return CheckBasicMetaTypes(oid, out, BasicMetaTypes {});
45 }
46
IsV1Any(ObjectId oid)47 static bool IsV1Any(ObjectId oid)
48 {
49 static const BASE_NS::Uid anyUid("00000000-0000-0000-5479-706564416e79");
50 return oid.ToUid().data[1] == anyUid.data[1];
51 }
52
MakeAny(ObjectId oid)53 static ObjectId MakeAny(ObjectId oid)
54 {
55 BASE_NS::Uid uid("00000000-0000-0000-4275-696c74416e79");
56 uid.data[0] = oid.ToUid().data[0];
57 return uid;
58 }
59
MakeArrayAny(ObjectId oid)60 static ObjectId MakeArrayAny(ObjectId oid)
61 {
62 BASE_NS::Uid uid("00000000-0000-0000-4172-726179416e79");
63 uid.data[0] = oid.ToUid().data[0];
64 return uid;
65 }
66
67 class NodeVisitor : public IntroduceInterfaces<ISerNodeVisitor> {
68 public:
VisitNode(ISerNode::Ptr node)69 static ISerNode::Ptr VisitNode(ISerNode::Ptr node)
70 {
71 if (!node) {
72 return nullptr;
73 }
74 NodeVisitor v;
75 node->Apply(v);
76 return v.node;
77 }
78
Visit(const IRootNode & n)79 void Visit(const IRootNode& n) override
80 {
81 node.reset(new RootNode(VisitNode(n.GetObject()), {}));
82 }
Visit(const IObjectNode & n)83 void Visit(const IObjectNode& n) override
84 {
85 node.reset(new ObjectNode(
86 n.GetObjectClassName(), n.GetObjectName(), n.GetObjectId(), n.GetInstanceId(), VisitNode(n.GetMembers())));
87 }
Visit(const IArrayNode & n)88 void Visit(const IArrayNode& n) override
89 {
90 BASE_NS::vector<ISerNode::Ptr> arr;
91 for (auto&& m : n.GetMembers()) {
92 if (auto n = VisitNode(m)) {
93 arr.push_back(n);
94 }
95 }
96 node.reset(new ArrayNode(BASE_NS::move(arr)));
97 }
RewriteValueToAny(ObjectId property,ISerNode::Ptr node)98 ISerNode::Ptr RewriteValueToAny(ObjectId property, ISerNode::Ptr node)
99 {
100 if (auto n = interface_cast<IObjectNode>(node)) {
101 if (IsV1Any(n->GetObjectId())) {
102 return ISerNode::Ptr(new ObjectNode("Any", n->GetObjectName(), MakeAny(n->GetObjectId()),
103 n->GetInstanceId(), VisitNode(n->GetMembers())));
104 }
105 }
106 BASE_NS::vector<NamedNode> m;
107 if (auto n = VisitNode(node)) {
108 m.push_back(NamedNode { "value", n });
109 }
110 ObjectId any = MakeAny(property);
111 ObjectId uid;
112 if (IsV1BasicArray(property, uid)) {
113 any = MakeArrayAny(uid);
114 }
115 return ISerNode::Ptr(new ObjectNode("Any", "", any, {}, CreateShared<MapNode>(m)));
116 }
117
RewritePropertyFlags(ISerNode::Ptr n)118 ISerNode::Ptr RewritePropertyFlags(ISerNode::Ptr n)
119 {
120 uint64_t value {};
121 uint64_t converted { uint64_t(ObjectFlagBits::SERIALIZE) };
122 if (ExtractNumber(n, value)) {
123 if (value & 8) {
124 converted |= 8;
125 }
126 if (value & 128) {
127 converted |= 16;
128 }
129 if (converted != uint64_t(ObjectFlagBits::SERIALIZE)) {
130 return ISerNode::Ptr(new UIntNode(converted));
131 }
132 }
133 return nullptr;
134 }
135
ConstructBind(ISerNode::Ptr n)136 ISerNode::Ptr ConstructBind(ISerNode::Ptr n)
137 {
138 BASE_NS::shared_ptr<IMapNode> fmap(new MapNode);
139 fmap->AddNode("source", n);
140
141 BASE_NS::shared_ptr<IObjectNode> fobj(
142 new ObjectNode("PropertyFunction", "", ClassId::PropertyFunction, {}, BASE_NS::move(fmap)));
143
144 BASE_NS::shared_ptr<IMapNode> map(new MapNode);
145 map->AddNode("function", fobj);
146
147 return BASE_NS::shared_ptr<ISerNode>(new ObjectNode("Bind", "", ClassId::Bind, {}, BASE_NS::move(map)));
148 }
149
RewriteBind(ISerNode::Ptr n)150 ISerNode::Ptr RewriteBind(ISerNode::Ptr n)
151 {
152 if (auto obj = interface_cast<IObjectNode>(n)) {
153 if (auto map = interface_cast<IMapNode>(obj->GetMembers())) {
154 if (auto node = map->FindNode("Property")) {
155 return ConstructBind(node);
156 }
157 }
158 }
159 return nullptr;
160 }
161
RewriteProperty(BASE_NS::string name,const IObjectNode & n)162 ISerNode::Ptr RewriteProperty(BASE_NS::string name, const IObjectNode& n)
163 {
164 ISerNode::Ptr value;
165 ISerNode::Ptr bind;
166 bool hasDefaultValue = false;
167 auto mapNode = CreateShared<MapNode>();
168
169 if (auto m = interface_cast<IMapNode>(n.GetMembers())) {
170 for (auto&& node : m->GetMembers()) {
171 auto nn = node.node;
172 if (node.name == "bind") {
173 bind = RewriteBind(nn);
174 } else {
175 if (node.name == "flags") {
176 node.name = "__flags";
177 nn = RewritePropertyFlags(nn);
178 } else if (node.name == "defaultValue") {
179 hasDefaultValue = true;
180 nn = RewriteValueToAny(n.GetObjectId(), nn);
181 } else if (node.name == "value" || node.name == "valueObject") {
182 node.name = "values";
183 value = RewriteValueToAny(n.GetObjectId(), nn);
184 nn = ISerNode::Ptr(new ArrayNode({ value }));
185 } else {
186 nn = VisitNode(nn);
187 }
188 if (nn) {
189 mapNode->AddNode(node.name, nn);
190 }
191 }
192 }
193 if (!value) {
194 mapNode->AddNode("values", ISerNode::Ptr(new ArrayNode(BASE_NS::vector<ISerNode::Ptr> {})));
195 if (!hasDefaultValue) {
196 CORE_LOG_E("Invalid json file, property doesn't have value or defaultValue");
197 }
198 } else if (!hasDefaultValue) {
199 mapNode->AddNode("defaultValue", value);
200 }
201 if (bind) {
202 if (auto v = mapNode->FindNode("values")) {
203 if (auto arr = interface_cast<IArrayNode>(v)) {
204 arr->AddNode(bind);
205 }
206 }
207 }
208 mapNode->AddNode("modifiers", ISerNode::Ptr(new ArrayNode(BASE_NS::vector<ISerNode::Ptr> {})));
209 }
210 return ISerNode::Ptr(new ObjectNode("Property", name, ClassId::StackProperty, n.GetInstanceId(), mapNode));
211 }
RewriteObject(BASE_NS::string name,IObjectNode & n)212 ISerNode::Ptr RewriteObject(BASE_NS::string name, IObjectNode& n)
213 {
214 if (IsV1Property(n.GetObjectId())) {
215 return RewriteProperty(name, n);
216 }
217 return ISerNode::Ptr(new ObjectNode(
218 n.GetObjectClassName(), n.GetObjectName(), n.GetObjectId(), n.GetInstanceId(), VisitNode(n.GetMembers())));
219 }
RewritePropertyMap(const NamedNode & node,BASE_NS::vector<ISerNode::Ptr> & properties)220 void RewritePropertyMap(const NamedNode& node, BASE_NS::vector<ISerNode::Ptr>& properties)
221 {
222 auto n = VisitNode(node.node);
223 if (auto map = interface_cast<IMapNode>(n)) {
224 if (auto m = map->FindNode("__attachments")) {
225 if (auto arr = interface_cast<IArrayNode>(m)) {
226 for (auto&& an : arr->GetMembers()) {
227 // the rewrite was already done by the above VisitNode call
228 properties.push_back(an);
229 }
230 }
231 }
232 }
233 }
AddProperties(BASE_NS::vector<ISerNode::Ptr> properties,IMapNode & map)234 void AddProperties(BASE_NS::vector<ISerNode::Ptr> properties, IMapNode& map)
235 {
236 if (auto p = interface_cast<IArrayNode>(map.FindNode("__attachments"))) {
237 for (auto&& n : properties) {
238 p->AddNode(n);
239 }
240 } else {
241 map.AddNode("__attachments", IArrayNode::Ptr(new ArrayNode(properties)));
242 }
243 }
Visit(const IMapNode & n)244 void Visit(const IMapNode& n) override
245 {
246 BASE_NS::vector<NamedNode> map;
247 BASE_NS::vector<ISerNode::Ptr> properties;
248 for (auto&& m : n.GetMembers()) {
249 ISerNode::Ptr p;
250 if (auto obj = interface_cast<IObjectNode>(m.node)) {
251 p = RewriteObject(m.name, *obj);
252 if (IsV1Property(obj->GetObjectId())) {
253 properties.push_back(p);
254 p = nullptr;
255 }
256 } else if (m.name == "__properties") {
257 RewritePropertyMap(m, properties);
258 p = nullptr;
259 } else {
260 p = VisitNode(m.node);
261 }
262 if (p) {
263 map.push_back(NamedNode { m.name, p });
264 }
265 }
266 auto mapNode = IMapNode::Ptr(new MapNode(BASE_NS::move(map)));
267 if (!properties.empty()) {
268 AddProperties(properties, *mapNode);
269 }
270 node = mapNode;
271 }
Visit(const INilNode & n)272 void Visit(const INilNode& n) override
273 {
274 node.reset(new NilNode);
275 }
Visit(const IBoolNode & n)276 void Visit(const IBoolNode& n) override
277 {
278 node.reset(new BoolNode(n.GetValue()));
279 }
Visit(const IDoubleNode & n)280 void Visit(const IDoubleNode& n) override
281 {
282 node.reset(new DoubleNode(n.GetValue()));
283 }
Visit(const IIntNode & n)284 void Visit(const IIntNode& n) override
285 {
286 node.reset(new IntNode(n.GetValue()));
287 }
Visit(const IUIntNode & n)288 void Visit(const IUIntNode& n) override
289 {
290 node.reset(new UIntNode(n.GetValue()));
291 }
Visit(const IStringNode & n)292 void Visit(const IStringNode& n) override
293 {
294 node.reset(new StringNode(n.GetValue()));
295 }
Visit(const IRefUriNode & n)296 void Visit(const IRefUriNode& n) override
297 {
298 node.reset(new RefNode(n.GetValue()));
299 }
Visit(const ISerNode &)300 void Visit(const ISerNode&) override
301 {
302 CORE_LOG_E("Unknown node type");
303 }
304
305 ISerNode::Ptr node;
306 };
307
Process(ISerNode::Ptr tree)308 ISerNode::Ptr MetaMigrateV1::Process(ISerNode::Ptr tree)
309 {
310 NodeVisitor v;
311 tree->Apply(v);
312 return v.node;
313 }
314
315 } // namespace Serialization
316 META_END_NAMESPACE()
317