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