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