001
014
015 package com.liferay.util.xml;
016
017 import com.liferay.util.xml.descriptor.XMLDescriptor;
018
019 import java.util.ArrayList;
020 import java.util.Collection;
021 import java.util.Iterator;
022 import java.util.List;
023 import java.util.Vector;
024
025 import org.dom4j.Document;
026 import org.dom4j.Element;
027
028
033 public class XMLMerger {
034
035 public XMLMerger(XMLDescriptor descriptor) {
036 _descriptor = descriptor;
037 }
038
039 public XMLElementComparator getElementComparator() {
040 return new XMLElementComparator(_descriptor);
041 }
042
043 public Document merge(Document masterDoc, Document slaveDoc) {
044 Document mergedDoc = (Document)masterDoc.clone();
045
046 Element root1 = mergedDoc.getRootElement();
047 Element root2 = slaveDoc.getRootElement();
048
049 List<Element> children = root2.elements();
050
051 for (Element el2 : children) {
052 Element el2Clone = (Element)el2.clone();
053
054 el2Clone.detach();
055
056 root1.add(el2Clone);
057 }
058
059 organizeXML(mergedDoc);
060
061 return mergedDoc;
062 }
063
064 public void organizeXML(Document doc) {
065 Element root = doc.getRootElement();
066
067 _orderChildren(root, _descriptor.getRootChildrenOrder());
068 _mergeDuplicateElements(root, getElementComparator());
069 }
070
071 private void _addChildren(
072 Element first, Collection<Element> childrenToJoin) {
073
074 Collection<Element> clones = new Vector<Element>();
075
076 Iterator<Element> itr = childrenToJoin.iterator();
077
078 while (itr.hasNext()) {
079 clones.add((Element)itr.next().clone());
080 }
081
082 first.elements().addAll(clones);
083
084 _orderChildren(first, _descriptor.getChildrenOrder(first));
085 }
086
087 private boolean _containsObjectEqualTo(
088 Element example, List<Element> list, ElementComparator comparator) {
089
090 Iterator<Element> itr = list.iterator();
091
092 while (itr.hasNext()) {
093 Element candidate = itr.next();
094
095 if (comparator.compare(example, candidate) == 0) {
096 return true;
097 }
098 }
099
100 return false;
101 }
102
103 private Element _findObjectEqualTo(
104 Element example, List<Element> list, ElementComparator comparator) {
105
106 Iterator<Element> itr = list.iterator();
107
108 while (itr.hasNext()) {
109 Element candidate = itr.next();
110
111 if (comparator.compare(example, candidate) == 0) {
112 return candidate;
113 }
114 }
115
116 return example;
117 }
118
119 private void _mergeDuplicateElements(
120 Element el, ElementComparator comparator) {
121
122 if (el.elements().size() > 0) {
123 List<Element> children = el.elements();
124
125 List<Element> originals = new ArrayList<Element>();
126 List<Element> duplicates = new ArrayList<Element>();
127
128 for (int i = 0; i < children.size(); i++) {
129 Element child = children.get(i);
130
131 if (_containsObjectEqualTo(child, originals, comparator)) {
132 if (_descriptor.canJoinChildren(child)) {
133 Element first =
134 _findObjectEqualTo(child, originals, comparator);
135
136 Collection<Element> childrenToJoin = child.elements();
137
138 _addChildren(first, childrenToJoin);
139 }
140
141 duplicates.add(child);
142 }
143 else {
144 originals.add(child);
145 }
146 }
147
148 for (Element duplicate : duplicates) {
149 duplicate.detach();
150 }
151
152 Iterator<Element> itr = originals.iterator();
153
154 while (itr.hasNext()) {
155 Element child = itr.next();
156
157 _mergeDuplicateElements(child, comparator);
158 }
159 }
160 }
161
162 private void _orderChildren(
163 Element parent, String[] orderedChildrenNames) {
164
165 if (orderedChildrenNames == null) {
166 return;
167 }
168
169 List<Element> elements = new ArrayList<Element>();
170
171 for (int i = 0; i < orderedChildrenNames.length; i++) {
172 elements.addAll(parent.elements(orderedChildrenNames[i]));
173 }
174
175 for (Element el : elements) {
176 el.detach();
177
178 parent.add(el);
179 }
180 }
181
182 private XMLDescriptor _descriptor;
183
184 }