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(Element first, Collection childrenToJoin) {
83 Collection clones = new Vector();
84
85 Iterator itr = childrenToJoin.iterator();
86
87 while (itr.hasNext()) {
88 clones.add(((Element)itr.next()).clone());
89 }
90
91 first.elements().addAll(clones);
92 }
93
94 private boolean _containsObjectEqualTo(
95 Element example, List list, ElementComparator comparator) {
96
97 Iterator itr = list.iterator();
98
99 while (itr.hasNext()) {
100 Element candidate = (Element)itr.next();
101
102 if (comparator.compare(example, candidate) == 0) {
103 return true;
104 }
105 }
106
107 return false;
108 }
109
110 private Element _findObjectEqualTo(
111 Element example, List list, ElementComparator comparator) {
112
113 Iterator itr = list.iterator();
114
115 while (itr.hasNext()) {
116 Element candidate = (Element)itr.next();
117
118 if (comparator.compare(example, candidate) == 0) {
119 return candidate;
120 }
121 }
122
123 return example;
124 }
125
126 private void _mergeDuplicateElements(
127 Element el, ElementComparator comparator) {
128
129 if (el.elements().size() > 0) {
130 List children = el.elements();
131
132 List originals = new ArrayList();
133 List duplicates = new ArrayList();
134
135 for (int i = 0; i < children.size(); i++) {
136 Element child = (Element)children.get(i);
137
138 if (_containsObjectEqualTo(child, originals, comparator)) {
139 if (_descriptor.canJoinChildren(child)) {
140 Element first =
141 _findObjectEqualTo(child, originals, comparator);
142
143 Collection childrenToJoin = child.elements();
144
145 _addChildren(first, childrenToJoin);
146 }
147
148 duplicates.add(child);
149 }
150 else {
151 originals.add(child);
152 }
153 }
154
155 for (int i = 0; i < duplicates.size(); i++) {
156 Element duplicate = (Element)duplicates.get(i);
157
158 duplicate.detach();
159 }
160
161 Iterator itr = originals.iterator();
162
163 while (itr.hasNext()) {
164 Element child = (Element)itr.next();
165
166 _mergeDuplicateElements(child, comparator);
167 }
168 }
169 }
170
171 private void _orderChildren(
172 Element parent, String[] orderedChildrenNames) {
173
174 if (orderedChildrenNames == null) {
175 return;
176 }
177
178 List elements = new ArrayList();
179
180 for (int i = 0; i < orderedChildrenNames.length; i++) {
181 elements.addAll(parent.elements(orderedChildrenNames[i]));
182 }
183
184 for (int i = 0; i < elements.size(); i++) {
185 Element el = (Element)elements.get(i);
186 el.detach();
187 parent.add(el);
188 }
189 }
190
191 private XMLDescriptor _descriptor;
192
193 }