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