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.List;
022
023 import org.dom4j.Document;
024 import org.dom4j.Element;
025
026
031 public class XMLMerger {
032
033 public XMLMerger(XMLDescriptor descriptor) {
034 _descriptor = descriptor;
035 }
036
037 public XMLElementComparator getElementComparator() {
038 return new XMLElementComparator(_descriptor);
039 }
040
041 public Document merge(Document masterDocument, Document slaveDocument) {
042 Document mergedDocument = (Document)masterDocument.clone();
043
044 Element mergedRootElement = mergedDocument.getRootElement();
045 Element slaveRootElement = slaveDocument.getRootElement();
046
047 for (Element slaveElement :
048 (List<Element>)slaveRootElement.elements()) {
049
050 Element clonedSlaveElement = (Element)slaveElement.clone();
051
052 clonedSlaveElement.detach();
053
054 mergedRootElement.add(clonedSlaveElement);
055 }
056
057 organizeXML(mergedDocument);
058
059 return mergedDocument;
060 }
061
062 public void organizeXML(Document document) {
063 Element rootElement = document.getRootElement();
064
065 _orderChildren(rootElement, _descriptor.getRootChildrenOrder());
066 _mergeDuplicateElements(rootElement, getElementComparator());
067 }
068
069 private void _addChildren(
070 Element firstElement, Collection<Element> childElements) {
071
072 List<Element> elements = firstElement.elements();
073
074 for (Element childElement : childElements) {
075 elements.add((Element)childElement.clone());
076 }
077
078 _orderChildren(
079 firstElement, _descriptor.getChildrenOrder(firstElement));
080 }
081
082 private boolean _containsObjectEqualTo(
083 Element element, List<Element> elements,
084 ElementComparator elementComparator) {
085
086 for (Element curElement : elements) {
087 if (elementComparator.compare(element, curElement) == 0) {
088 return true;
089 }
090 }
091
092 return false;
093 }
094
095 private Element _findObjectEqualTo(
096 Element element, List<Element> elements,
097 ElementComparator elementComparator) {
098
099 for (Element curElement : elements) {
100 if (elementComparator.compare(element, curElement) == 0) {
101 return curElement;
102 }
103 }
104
105 return element;
106 }
107
108 private void _mergeDuplicateElements(
109 Element element, ElementComparator elementComparator) {
110
111 List<Element> childElements = element.elements();
112
113 if (childElements.isEmpty()) {
114 return;
115 }
116
117 List<Element> originalElements = new ArrayList<Element>();
118 List<Element> duplicateElements = new ArrayList<Element>();
119
120 for (int i = 0; i < childElements.size(); i++) {
121 Element childElement = childElements.get(i);
122
123 if (_containsObjectEqualTo(
124 childElement, originalElements, elementComparator)) {
125
126 if (_descriptor.canJoinChildren(childElement)) {
127 Element firstElement = _findObjectEqualTo(
128 childElement, originalElements, elementComparator);
129
130 _addChildren(firstElement, childElement.elements());
131 }
132
133 duplicateElements.add(childElement);
134 }
135 else {
136 originalElements.add(childElement);
137 }
138
139 _orderChildren(
140 childElement, _descriptor.getChildrenOrder(childElement));
141 }
142
143 for (Element duplicateElement : duplicateElements) {
144 duplicateElement.detach();
145 }
146
147 for (Element childElement : originalElements) {
148 _mergeDuplicateElements(childElement, elementComparator);
149 }
150 }
151
152 private void _orderChildren(
153 Element parentElement, String[] orderedChildrenNames) {
154
155 if (orderedChildrenNames == null) {
156 return;
157 }
158
159 List<Element> elements = new ArrayList<Element>();
160
161 for (int i = 0; i < orderedChildrenNames.length; i++) {
162 elements.addAll(parentElement.elements(orderedChildrenNames[i]));
163 }
164
165 for (Element element : elements) {
166 element.detach();
167
168 parentElement.add(element);
169 }
170 }
171
172 private XMLDescriptor _descriptor;
173
174 }