1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 package org.openoffice.xmerge.converter.xml.sxc; 25 26 import org.w3c.dom.Node; 27 import org.w3c.dom.Element; 28 import org.w3c.dom.NodeList; 29 30 import org.openoffice.xmerge.Document; 31 import org.openoffice.xmerge.DocumentMerger; 32 import org.openoffice.xmerge.MergeException; 33 import org.openoffice.xmerge.ConverterCapabilities; 34 import org.openoffice.xmerge.converter.xml.OfficeConstants; 35 import org.openoffice.xmerge.merger.DiffAlgorithm; 36 import org.openoffice.xmerge.merger.Difference; 37 import org.openoffice.xmerge.merger.Iterator; 38 import org.openoffice.xmerge.merger.NodeMergeAlgorithm; 39 import org.openoffice.xmerge.merger.diff.IteratorRowCompare; 40 import org.openoffice.xmerge.merger.diff.RowIterator; 41 import org.openoffice.xmerge.merger.merge.SheetMerge; 42 import org.openoffice.xmerge.merger.merge.PositionBaseRowMerge; 43 import org.openoffice.xmerge.merger.MergeAlgorithm; 44 import org.openoffice.xmerge.util.XmlUtil; 45 import org.openoffice.xmerge.util.Debug; 46 47 48 /** 49 * Generic small device implementation of <code>DocumentMerger</code> for 50 * the {@link 51 * org.openoffice.xmerge.converter.xml.sxc.SxcPluginFactory 52 * SxcPluginFactory}. Used with SXC <code>Document</code> objects. 53 */ 54 public class DocumentMergerImpl implements DocumentMerger { 55 56 private ConverterCapabilities cc_; 57 private org.openoffice.xmerge.Document orig = null; 58 59 /** 60 * Constructor 61 * 62 * @param doc The original "Office" <code>Document</code> 63 * to merge. 64 * @param cc The <code>ConverterCapabilities</code>. 65 */ DocumentMergerImpl(org.openoffice.xmerge.Document doc, ConverterCapabilities cc)66 public DocumentMergerImpl(org.openoffice.xmerge.Document doc, ConverterCapabilities cc) { 67 cc_ = cc; 68 this.orig = doc; 69 } 70 merge(Document modifiedDoc)71 public void merge(Document modifiedDoc) throws MergeException { 72 73 SxcDocument sdoc1 = (SxcDocument)orig; 74 SxcDocument sdoc2 = (SxcDocument)modifiedDoc; 75 76 org.w3c.dom.Document doc1 = sdoc1.getContentDOM(); 77 org.w3c.dom.Document doc2 = sdoc2.getContentDOM(); 78 79 Element elem1 = doc1.getDocumentElement(); 80 Element elem2 = doc2.getDocumentElement(); 81 82 // get table name 83 NodeList workSheetList1 = 84 elem1.getElementsByTagName(OfficeConstants.TAG_TABLE); 85 NodeList workSheetList2 = 86 elem2.getElementsByTagName(OfficeConstants.TAG_TABLE); 87 88 int numOfWorkSheet = workSheetList1.getLength(); 89 90 for (int i=0; i < numOfWorkSheet; i++) { 91 Node workSheet = workSheetList1.item(i); 92 93 // try to match the workSheet 94 Node matchingWorkSheet = matchWorkSheet(workSheet, workSheetList2); 95 96 if (matchingWorkSheet != null) { 97 98 // need to put it into a row Iterator 99 // use a straight comparsion algorithm then do a merge on it 100 Iterator i1 = new RowIterator(cc_, workSheet); 101 Iterator i2 = new RowIterator(cc_, matchingWorkSheet); 102 103 // find out the diff 104 DiffAlgorithm diffAlgo = new IteratorRowCompare(); 105 106 // find out the paragrah level diffs 107 Difference[] diffResult = diffAlgo.computeDiffs(i1, i2); 108 109 if (Debug.isFlagSet(Debug.INFO)) { 110 Debug.log(Debug.INFO, "Diff Result: "); 111 112 for (int j = 0; j < diffResult.length; j++) { 113 Debug.log(Debug.INFO, diffResult[j].debug()); 114 } 115 } 116 117 // merge back the result 118 NodeMergeAlgorithm rowMerger = new PositionBaseRowMerge(cc_); 119 MergeAlgorithm merger = new SheetMerge(cc_, rowMerger); 120 121 Iterator result = null; 122 123 merger.applyDifference(i1, i2, diffResult); 124 } 125 } 126 127 numOfWorkSheet = workSheetList2.getLength(); 128 129 // for those workSheet from target don't have a matching one 130 // in the original workSheet list, we add it 131 132 // find out the office body node first 133 NodeList officeBodyList = 134 elem1.getElementsByTagName(OfficeConstants.TAG_OFFICE_BODY); 135 136 Node officeBody = officeBodyList.item(0); 137 138 // for each WorkSheets, try to see whether we have it or not 139 for (int j=0; j < numOfWorkSheet; j++) { 140 Node workSheet= workSheetList2.item(j); 141 142 // try to match the workSheet 143 // 144 Node matchingWorkSheet = matchWorkSheet(workSheet, workSheetList1); 145 146 // add the new WorkSheet to the original document iff match not 147 // found 148 // 149 if (matchingWorkSheet == null) { 150 Node cloneNode = XmlUtil.deepClone(officeBody, workSheet); 151 officeBody.appendChild(cloneNode); 152 } 153 } 154 } 155 156 /** 157 * Try to find a WorkSheet from the modified WorkSheetList that 158 * has a matching table name from the original WorkSheet. 159 * 160 * @param orgSheet The original WorkSheet. 161 * @param modSheetList The modified WorkSheet. 162 * 163 * @return The Node in modSheetList that matches the orgSheet. 164 */ matchWorkSheet(Node orgSheet, NodeList modSheetList)165 private Node matchWorkSheet(Node orgSheet, NodeList modSheetList) { 166 167 Node matchSheet = null; 168 169 String orgTableName = ((Element)orgSheet).getAttribute( 170 OfficeConstants.ATTRIBUTE_TABLE_NAME); 171 172 if (orgTableName == null) 173 return null; 174 175 int numOfWorkSheet = modSheetList.getLength(); 176 177 String modTableName; 178 179 for (int i=0; i < numOfWorkSheet; i++) { 180 modTableName = ((Element)modSheetList.item(i)).getAttribute( 181 OfficeConstants.ATTRIBUTE_TABLE_NAME); 182 if (modTableName == null) 183 continue; 184 185 if (orgTableName.equals(modTableName)) { 186 matchSheet = modSheetList.item(i); 187 break; 188 } 189 } 190 191 return matchSheet; 192 } 193 } 194 195