001: /**
002: * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
003: *
004: * Permission is hereby granted, free of charge, to any person obtaining a copy
005: * of this software and associated documentation files (the "Software"), to deal
006: * in the Software without restriction, including without limitation the rights
007: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
008: * copies of the Software, and to permit persons to whom the Software is
009: * furnished to do so, subject to the following conditions:
010: *
011: * The above copyright notice and this permission notice shall be included in
012: * all copies or substantial portions of the Software.
013: *
014: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
015: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
016: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
017: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
018: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
019: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
020: * SOFTWARE.
021: */package com.liferay.util.xml;
022:
023: import com.liferay.util.xml.descriptor.XMLDescriptor;
024:
025: import java.util.ArrayList;
026: import java.util.Collection;
027: import java.util.Iterator;
028: import java.util.List;
029: import java.util.Vector;
030:
031: import org.dom4j.Document;
032: import org.dom4j.Element;
033:
034: /**
035: * <a href="XMLMerger.java.html"><b><i>View Source</i></b></a>
036: *
037: * @author Brian Wing Shun Chan
038: * @author Alan Zimmerman
039: * @author Jorge Ferrer
040: *
041: */
042: public class XMLMerger {
043:
044: public XMLMerger(XMLDescriptor descriptor) {
045: _descriptor = descriptor;
046: }
047:
048: public XMLElementComparator getElementComparator() {
049: return new XMLElementComparator(_descriptor);
050: }
051:
052: public Document merge(Document masterDoc, Document slaveDoc) {
053: Document mergedDoc = (Document) masterDoc.clone();
054:
055: Element root1 = mergedDoc.getRootElement();
056: Element root2 = slaveDoc.getRootElement();
057:
058: List children = root2.elements();
059:
060: for (int i = 0; i < children.size(); i++) {
061: Element el2 = (Element) children.get(i);
062:
063: Element el2Clone = (Element) el2.clone();
064:
065: el2Clone.detach();
066:
067: root1.add(el2Clone);
068: }
069:
070: organizeXML(mergedDoc);
071:
072: return mergedDoc;
073: }
074:
075: public void organizeXML(Document doc) {
076: Element root = doc.getRootElement();
077:
078: _orderChildren(root, _descriptor.getRootChildrenOrder());
079: _mergeDuplicateElements(root, getElementComparator());
080: }
081:
082: private void _addChildren(Element first, Collection childrenToJoin) {
083: Collection clones = new Vector();
084:
085: Iterator itr = childrenToJoin.iterator();
086:
087: while (itr.hasNext()) {
088: clones.add(((Element) itr.next()).clone());
089: }
090:
091: first.elements().addAll(clones);
092: }
093:
094: private boolean _containsObjectEqualTo(Element example, List list,
095: ElementComparator comparator) {
096:
097: Iterator itr = list.iterator();
098:
099: 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(Element example, List list,
111: 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(Element el,
127: 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 = _findObjectEqualTo(child,
141: originals, comparator);
142:
143: Collection childrenToJoin = child.elements();
144:
145: _addChildren(first, childrenToJoin);
146: }
147:
148: duplicates.add(child);
149: } else {
150: originals.add(child);
151: }
152: }
153:
154: for (int i = 0; i < duplicates.size(); i++) {
155: Element duplicate = (Element) duplicates.get(i);
156:
157: duplicate.detach();
158: }
159:
160: Iterator itr = originals.iterator();
161:
162: while (itr.hasNext()) {
163: Element child = (Element) itr.next();
164:
165: _mergeDuplicateElements(child, comparator);
166: }
167: }
168: }
169:
170: private void _orderChildren(Element parent,
171: String[] orderedChildrenNames) {
172:
173: if (orderedChildrenNames == null) {
174: return;
175: }
176:
177: List elements = new ArrayList();
178:
179: for (int i = 0; i < orderedChildrenNames.length; i++) {
180: elements.addAll(parent.elements(orderedChildrenNames[i]));
181: }
182:
183: for (int i = 0; i < elements.size(); i++) {
184: Element el = (Element) elements.get(i);
185: el.detach();
186: parent.add(el);
187: }
188: }
189:
190: private XMLDescriptor _descriptor;
191:
192: }
|