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