1
14
15 package com.liferay.util.xml;
16
17 import com.liferay.util.xml.descriptor.XMLDescriptor;
18
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.Vector;
24
25 import org.dom4j.Document;
26 import org.dom4j.Element;
27
28
35 public class XMLMerger {
36
37 public XMLMerger(XMLDescriptor descriptor) {
38 _descriptor = descriptor;
39 }
40
41 public XMLElementComparator getElementComparator() {
42 return new XMLElementComparator(_descriptor);
43 }
44
45 public Document merge(Document masterDoc, Document slaveDoc) {
46 Document mergedDoc = (Document)masterDoc.clone();
47
48 Element root1 = mergedDoc.getRootElement();
49 Element root2 = slaveDoc.getRootElement();
50
51 List<Element> children = root2.elements();
52
53 for (Element el2 : children) {
54 Element el2Clone = (Element)el2.clone();
55
56 el2Clone.detach();
57
58 root1.add(el2Clone);
59 }
60
61 organizeXML(mergedDoc);
62
63 return mergedDoc;
64 }
65
66 public void organizeXML(Document doc) {
67 Element root = doc.getRootElement();
68
69 _orderChildren(root, _descriptor.getRootChildrenOrder());
70 _mergeDuplicateElements(root, getElementComparator());
71 }
72
73 private void _addChildren(
74 Element first, Collection<Element> childrenToJoin) {
75
76 Collection<Element> clones = new Vector<Element>();
77
78 Iterator<Element> itr = childrenToJoin.iterator();
79
80 while (itr.hasNext()) {
81 clones.add((Element)itr.next().clone());
82 }
83
84 first.elements().addAll(clones);
85
86 _orderChildren(first, _descriptor.getChildrenOrder(first));
87 }
88
89 private boolean _containsObjectEqualTo(
90 Element example, List<Element> list, ElementComparator comparator) {
91
92 Iterator<Element> itr = list.iterator();
93
94 while (itr.hasNext()) {
95 Element candidate = itr.next();
96
97 if (comparator.compare(example, candidate) == 0) {
98 return true;
99 }
100 }
101
102 return false;
103 }
104
105 private Element _findObjectEqualTo(
106 Element example, List<Element> list, ElementComparator comparator) {
107
108 Iterator<Element> itr = list.iterator();
109
110 while (itr.hasNext()) {
111 Element candidate = itr.next();
112
113 if (comparator.compare(example, candidate) == 0) {
114 return candidate;
115 }
116 }
117
118 return example;
119 }
120
121 private void _mergeDuplicateElements(
122 Element el, ElementComparator comparator) {
123
124 if (el.elements().size() > 0) {
125 List<Element> children = el.elements();
126
127 List<Element> originals = new ArrayList<Element>();
128 List<Element> duplicates = new ArrayList<Element>();
129
130 for (int i = 0; i < children.size(); i++) {
131 Element child = children.get(i);
132
133 if (_containsObjectEqualTo(child, originals, comparator)) {
134 if (_descriptor.canJoinChildren(child)) {
135 Element first =
136 _findObjectEqualTo(child, originals, comparator);
137
138 Collection<Element> childrenToJoin = child.elements();
139
140 _addChildren(first, childrenToJoin);
141 }
142
143 duplicates.add(child);
144 }
145 else {
146 originals.add(child);
147 }
148 }
149
150 for (Element duplicate : duplicates) {
151 duplicate.detach();
152 }
153
154 Iterator<Element> itr = originals.iterator();
155
156 while (itr.hasNext()) {
157 Element child = itr.next();
158
159 _mergeDuplicateElements(child, comparator);
160 }
161 }
162 }
163
164 private void _orderChildren(
165 Element parent, String[] orderedChildrenNames) {
166
167 if (orderedChildrenNames == null) {
168 return;
169 }
170
171 List<Element> elements = new ArrayList<Element>();
172
173 for (int i = 0; i < orderedChildrenNames.length; i++) {
174 elements.addAll(parent.elements(orderedChildrenNames[i]));
175 }
176
177 for (Element el : elements) {
178 el.detach();
179
180 parent.add(el);
181 }
182 }
183
184 private XMLDescriptor _descriptor;
185
186 }