1
2
3
4
5
6 #include <cpp2cm/cpp2cm/Merge.hpp>
7 #include <sngxml/xpath/XPathEvaluate.hpp>
8 #include <sngxml/dom/Element.hpp>
9
10 namespace cpp2cm {
11
12 sngxml::dom::Node* AddElement(sngxml::dom::Element* sourceElement, sngxml::dom::Element* parentElement, sngxml::dom::Document* targetDoc, bool deep, const std::u32string& container)
13 {
14 sngxml::dom::Element* originalParent = parentElement;
15 if (parentElement == nullptr)
16 {
17 if (sourceElement->Parent() && sourceElement->Parent()->GetNodeType() == sngxml::dom::NodeType::elementNode)
18 {
19 parentElement = static_cast<sngxml::dom::Element*>(sourceElement->Parent());
20 }
21 }
22 else
23 {
24 if (parentElement->Parent() && parentElement->Parent()->GetNodeType() == sngxml::dom::NodeType::elementNode)
25 {
26 parentElement = static_cast<sngxml::dom::Element*>(parentElement->Parent());
27 }
28 }
29 if (parentElement)
30 {
31 std::u32string parentId = parentElement->GetAttribute(U"id");
32 if (!parentId.empty())
33 {
34 sngxml::dom::Element* targetParentElement = targetDoc->GetElementById(parentId);
35 if (!targetParentElement)
36 {
37 sngxml::dom::Node* newNode = AddElement(parentElement, parentElement, targetDoc, false, container);
38 if (newNode)
39 {
40 if (newNode->GetNodeType() == sngxml::dom::NodeType::elementNode)
41 {
42 targetParentElement = static_cast<sngxml::dom::Element*>(newNode);
43 }
44 }
45 }
46 if (targetParentElement)
47 {
48 if (originalParent && originalParent->Name() == container)
49 {
50 std::unique_ptr<sngxml::xpath::XPathObject> result = sngxml::xpath::Evaluate(container, targetParentElement);
51 if (result)
52 {
53 if (result->Type() == sngxml::xpath::XPathObjectType::nodeSet)
54 {
55 sngxml::xpath::XPathNodeSet* nodeSet = static_cast<sngxml::xpath::XPathNodeSet*>(result.get());
56 int n = nodeSet->Length();
57 if (n == 0)
58 {
59 sngxml::dom::Node* parentNode = targetParentElement->AppendChild(originalParent->CloneNode(false));
60 if (parentNode->GetNodeType() == sngxml::dom::NodeType::elementNode)
61 {
62 targetParentElement = static_cast<sngxml::dom::Element*>(parentNode);
63 }
64 }
65 else if (n == 1)
66 {
67 sngxml::dom::Node* node = (*nodeSet)[0];
68 if (node->GetNodeType() == sngxml::dom::NodeType::elementNode)
69 {
70 targetParentElement = static_cast<sngxml::dom::Element*>(node);
71 }
72 }
73 }
74 }
75 }
76 return targetParentElement->AppendChild(sourceElement->CloneNode(deep));
77 }
78 }
79 else
80 {
81 return AddElement(sourceElement, parentElement, targetDoc, deep, container);
82 }
83 }
84 return nullptr;
85 }
86
87 void RemoveElement(sngxml::dom::Element* element)
88 {
89 if (element->Parent() && element->Parent()->GetNodeType() == sngxml::dom::NodeType::elementNode)
90 {
91 sngxml::dom::Element* parentElement = static_cast<sngxml::dom::Element*>(element->Parent());
92 parentElement->RemoveChild(element);
93 }
94 }
95
96 void MergeConstructors(sngxml::dom::Element* sourceElement, sngxml::dom::Document* targetDoc)
97 {
98 std::vector<sngxml::dom::Element*> elementsToRemove;
99 std::vector<sngxml::dom::Element*> elementsToAdd;
100 std::unique_ptr<sngxml::xpath::XPathObject> result = sngxml::xpath::Evaluate(U"constructors/constructor", sourceElement);
101 if (result)
102 {
103 if (result->Type() == sngxml::xpath::XPathObjectType::nodeSet)
104 {
105 sngxml::xpath::XPathNodeSet* nodeSet = static_cast<sngxml::xpath::XPathNodeSet*>(result.get());
106 int n = nodeSet->Length();
107 for (int i = 0; i < n; ++i)
108 {
109 sngxml::dom::Node* node = (*nodeSet)[i];
110 if (node->GetNodeType() == sngxml::dom::NodeType::elementNode)
111 {
112 sngxml::dom::Element* constructorElement = static_cast<sngxml::dom::Element*>(node);
113 std::u32string constructorId = constructorElement->GetAttribute(U"id");
114 if (!constructorId.empty())
115 {
116 sngxml::dom::Element* targetConstructorElement = targetDoc->GetElementById(constructorId);
117 if (targetConstructorElement)
118 {
119 std::u32string targetAttr = targetConstructorElement->GetAttribute(U"target");
120 if (targetAttr.empty())
121 {
122 elementsToRemove.push_back(targetConstructorElement);
123 elementsToAdd.push_back(constructorElement);
124 }
125 }
126 else
127 {
128 elementsToAdd.push_back(constructorElement);
129 }
130 }
131 }
132 }
133 }
134 }
135 for (sngxml::dom::Element* elementToRemove : elementsToRemove)
136 {
137 RemoveElement(elementToRemove);
138 }
139 for (sngxml::dom::Element* elementToAdd : elementsToAdd)
140 {
141 AddElement(elementToAdd, nullptr, targetDoc, true, U"constructors");
142 }
143 }
144
145 void MergeFunctions(sngxml::dom::Element* sourceElement, sngxml::dom::Document* targetDoc)
146 {
147 std::vector<sngxml::dom::Element*> elementsToRemove;
148 std::vector<sngxml::dom::Element*> elementsToAdd;
149 std::unique_ptr<sngxml::xpath::XPathObject> result = sngxml::xpath::Evaluate(U"functions/function", sourceElement);
150 if (result)
151 {
152 if (result->Type() == sngxml::xpath::XPathObjectType::nodeSet)
153 {
154 sngxml::xpath::XPathNodeSet* nodeSet = static_cast<sngxml::xpath::XPathNodeSet*>(result.get());
155 int n = nodeSet->Length();
156 for (int i = 0; i < n; ++i)
157 {
158 sngxml::dom::Node* node = (*nodeSet)[i];
159 if (node->GetNodeType() == sngxml::dom::NodeType::elementNode)
160 {
161 sngxml::dom::Element* functionElement = static_cast<sngxml::dom::Element*>(node);
162 std::u32string functionId = functionElement->GetAttribute(U"id");
163 if (!functionId.empty())
164 {
165 sngxml::dom::Element* targetFunctionElement = targetDoc->GetElementById(functionId);
166 if (targetFunctionElement)
167 {
168 std::u32string targetAttr = targetFunctionElement->GetAttribute(U"target");
169 if (targetAttr.empty())
170 {
171 elementsToRemove.push_back(targetFunctionElement);
172 elementsToAdd.push_back(functionElement);
173 }
174 }
175 else
176 {
177 elementsToAdd.push_back(functionElement);
178 }
179 }
180 }
181 }
182 }
183 }
184 for (sngxml::dom::Element* elementToRemove : elementsToRemove)
185 {
186 RemoveElement(elementToRemove);
187 }
188 for (sngxml::dom::Element* elementToAdd : elementsToAdd)
189 {
190 AddElement(elementToAdd, nullptr, targetDoc, true, U"functions");
191 }
192 }
193
194 void MergeTypedefs(sngxml::dom::Element* sourceElement, sngxml::dom::Document* targetDoc)
195 {
196 std::vector<sngxml::dom::Element*> elementsToRemove;
197 std::vector<sngxml::dom::Element*> elementsToAdd;
198 std::unique_ptr<sngxml::xpath::XPathObject> result = sngxml::xpath::Evaluate(U"typedefs/typedef", sourceElement);
199 if (result)
200 {
201 if (result->Type() == sngxml::xpath::XPathObjectType::nodeSet)
202 {
203 sngxml::xpath::XPathNodeSet* nodeSet = static_cast<sngxml::xpath::XPathNodeSet*>(result.get());
204 int n = nodeSet->Length();
205 for (int i = 0; i < n; ++i)
206 {
207 sngxml::dom::Node* node = (*nodeSet)[i];
208 if (node->GetNodeType() == sngxml::dom::NodeType::elementNode)
209 {
210 sngxml::dom::Element* typedefElement = static_cast<sngxml::dom::Element*>(node);
211 std::u32string typedefId = typedefElement->GetAttribute(U"id");
212 if (!typedefId.empty())
213 {
214 sngxml::dom::Element* targetTypedefElement = targetDoc->GetElementById(typedefId);
215 if (targetTypedefElement)
216 {
217 std::u32string targetAttr = targetTypedefElement->GetAttribute(U"target");
218 if (targetAttr.empty())
219 {
220 elementsToRemove.push_back(targetTypedefElement);
221 elementsToAdd.push_back(typedefElement);
222 }
223 }
224 else
225 {
226 elementsToAdd.push_back(typedefElement);
227 }
228 }
229 }
230 }
231 }
232 }
233 for (sngxml::dom::Element* elementToRemove : elementsToRemove)
234 {
235 RemoveElement(elementToRemove);
236 }
237 for (sngxml::dom::Element* elementToAdd : elementsToAdd)
238 {
239 AddElement(elementToAdd, nullptr, targetDoc, true, U"typedefs");
240 }
241 }
242
243 void MergeClasses(sngxml::dom::Element* sourceElement, sngxml::dom::Document* targetDoc)
244 {
245 std::vector<sngxml::dom::Element*> elementsToRemove;
246 std::vector<sngxml::dom::Element*> elementsToAdd;
247 std::unique_ptr<sngxml::xpath::XPathObject> result = sngxml::xpath::Evaluate(U"classes/class", sourceElement);
248 if (result)
249 {
250 if (result->Type() == sngxml::xpath::XPathObjectType::nodeSet)
251 {
252 sngxml::xpath::XPathNodeSet* nodeSet = static_cast<sngxml::xpath::XPathNodeSet*>(result.get());
253 int n = nodeSet->Length();
254 for (int i = 0; i < n; ++i)
255 {
256 sngxml::dom::Node* node = (*nodeSet)[i];
257 if (node->GetNodeType() == sngxml::dom::NodeType::elementNode)
258 {
259 sngxml::dom::Element* classElement = static_cast<sngxml::dom::Element*>(node);
260 std::u32string classId = classElement->GetAttribute(U"id");
261 if (!classId.empty())
262 {
263 sngxml::dom::Element* targetClassElement = targetDoc->GetElementById(classId);
264 if (targetClassElement)
265 {
266 std::u32string targetAttr = targetClassElement->GetAttribute(U"target");
267 if (targetAttr.empty())
268 {
269 elementsToRemove.push_back(targetClassElement);
270 elementsToAdd.push_back(classElement);
271 }
272 }
273 else
274 {
275 elementsToAdd.push_back(classElement);
276 }
277 }
278 MergeClasses(classElement, targetDoc);
279 MergeConstructors(classElement, targetDoc);
280 MergeFunctions(classElement, targetDoc);
281 MergeTypedefs(classElement, targetDoc);
282 }
283 }
284 }
285 }
286 for (sngxml::dom::Element* elementToRemove : elementsToRemove)
287 {
288 RemoveElement(elementToRemove);
289 }
290 for (sngxml::dom::Element* elementToAdd : elementsToAdd)
291 {
292 AddElement(elementToAdd, nullptr, targetDoc, true, U"classes");
293 }
294 }
295
296 void MergeTypes(sngxml::dom::Element* sourceElement, sngxml::dom::Document* targetDoc)
297 {
298 std::vector<sngxml::dom::Element*> elementsToRemove;
299 std::vector<sngxml::dom::Element*> elementsToAdd;
300 std::unique_ptr<sngxml::xpath::XPathObject> result = sngxml::xpath::Evaluate(U"types", sourceElement);
301 if (result)
302 {
303 if (result->Type() == sngxml::xpath::XPathObjectType::nodeSet)
304 {
305 sngxml::xpath::XPathNodeSet* nodeSet = static_cast<sngxml::xpath::XPathNodeSet*>(result.get());
306 int n = nodeSet->Length();
307 if (n == 1)
308 {
309 sngxml::dom::Node* node = (*nodeSet)[0];
310 if (node->GetNodeType() == sngxml::dom::NodeType::elementNode)
311 {
312 sngxml::dom::Element* typesElement = static_cast<sngxml::dom::Element*>(node);
313 sngxml::dom::Node* typeNode = typesElement->FirstChild();
314 while (typeNode)
315 {
316 if (typeNode->GetNodeType() == sngxml::dom::NodeType::elementNode)
317 {
318 sngxml::dom::Element* typeElement = static_cast<sngxml::dom::Element*>(typeNode);
319 std::u32string typeId = typeElement->GetAttribute(U"id");
320 if (!typeId.empty())
321 {
322 sngxml::dom::Element* targetTypeElement = targetDoc->GetElementById(typeId);
323 if (targetTypeElement)
324 {
325 std::u32string targetAttr = targetTypeElement->GetAttribute(U"target");
326 if (targetAttr.empty())
327 {
328 elementsToRemove.push_back(targetTypeElement);
329 elementsToAdd.push_back(typeElement);
330 }
331 }
332 else
333 {
334 elementsToAdd.push_back(typeElement);
335 }
336 }
337 }
338 typeNode = typeNode->NextSibling();
339 }
340 }
341 }
342 }
343 }
344 for (sngxml::dom::Element* elementToRemove : elementsToRemove)
345 {
346 RemoveElement(elementToRemove);
347 }
348 std::unique_ptr<sngxml::xpath::XPathObject> targetResult = sngxml::xpath::Evaluate(U"types", targetDoc->DocumentElement());
349 if (targetResult)
350 {
351 if (targetResult->Type() == sngxml::xpath::XPathObjectType::nodeSet)
352 {
353 sngxml::xpath::XPathNodeSet* nodeSet = static_cast<sngxml::xpath::XPathNodeSet*>(targetResult.get());
354 int n = nodeSet->Length();
355 if (n == 1)
356 {
357 sngxml::dom::Node* node = (*nodeSet)[0];
358 if (node->GetNodeType() == sngxml::dom::NodeType::elementNode)
359 {
360 sngxml::dom::Element* typesElement = static_cast<sngxml::dom::Element*>(node);
361 for (sngxml::dom::Element* elementToAdd : elementsToAdd)
362 {
363 typesElement->AppendChild(elementToAdd->CloneNode(true));
364 }
365 }
366 }
367 }
368 }
369 }
370
371 std::std::unique_ptr<sngxml::dom::Document>Merge(sngxml::dom::Document*symbolTableXmlDoc, std::std::unique_ptr<sngxml::dom::Document>&stageSymbolTableXmlDoc)
372 {
373 std::unique_ptr<sngxml::xpath::XPathObject> ns = sngxml::xpath::Evaluate(U"//namespace", symbolTableXmlDoc);
374 if (ns)
375 {
376 if (ns->Type() == sngxml::xpath::XPathObjectType::nodeSet)
377 {
378 sngxml::xpath::XPathNodeSet* nodeSet = static_cast<sngxml::xpath::XPathNodeSet*>(ns.get());
379 int n = nodeSet->Length();
380 for (int i = 0; i < n; ++i)
381 {
382 sngxml::dom::Node* node = (*nodeSet)[i];
383 if (node->GetNodeType() == sngxml::dom::NodeType::elementNode)
384 {
385 sngxml::dom::Element* element = static_cast<sngxml::dom::Element*>(node);
386 MergeClasses(element, stageSymbolTableXmlDoc.get());
387 MergeFunctions(element, stageSymbolTableXmlDoc.get());
388 MergeTypedefs(element, stageSymbolTableXmlDoc.get());
389 }
390 }
391 }
392 }
393 MergeTypes(symbolTableXmlDoc->DocumentElement(), stageSymbolTableXmlDoc.get());
394 std::unique_ptr<sngxml::dom::Document> result;
395 result = std::move(stageSymbolTableXmlDoc);
396 return result;
397 }
398
399 }
400