diff options
Diffstat (limited to 'xmerge/source/xmerge/java/org/openoffice/xmerge/merger/merge/PositionBaseRowMerge.java')
-rw-r--r-- | xmerge/source/xmerge/java/org/openoffice/xmerge/merger/merge/PositionBaseRowMerge.java | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/xmerge/source/xmerge/java/org/openoffice/xmerge/merger/merge/PositionBaseRowMerge.java b/xmerge/source/xmerge/java/org/openoffice/xmerge/merger/merge/PositionBaseRowMerge.java new file mode 100644 index 000000000000..4d912d1c8a56 --- /dev/null +++ b/xmerge/source/xmerge/java/org/openoffice/xmerge/merger/merge/PositionBaseRowMerge.java @@ -0,0 +1,260 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package org.openoffice.xmerge.merger.merge; + +import org.w3c.dom.Node; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.w3c.dom.NamedNodeMap; + +import org.openoffice.xmerge.ConverterCapabilities; +import org.openoffice.xmerge.merger.Iterator; +import org.openoffice.xmerge.merger.NodeMergeAlgorithm; +import org.openoffice.xmerge.merger.diff.CellNodeIterator; +import org.openoffice.xmerge.converter.xml.OfficeConstants; +import org.openoffice.xmerge.util.XmlUtil; + + +/** + * This is an implementation of the <code>NodeMergeAlgorithm</code> + * interface. It is used to merge two rows using a positional + * comparison base method. + */ +public final class PositionBaseRowMerge implements NodeMergeAlgorithm { + + /** The capabilities of this converter. */ + private ConverterCapabilities cc_; + + + /** + * Constructor. + * + * @param cc The <code>ConverterCapabilities</code>. + */ + public PositionBaseRowMerge(ConverterCapabilities cc) { + cc_ = cc; + } + + + public void merge(Node orgRow, Node modRow) { + + Iterator orgCells = new CellNodeIterator(cc_, orgRow); + Iterator modCells = new CellNodeIterator(cc_, modRow); + + mergeCellSequences(orgCells, modCells); + } + + + // used to compare the cell 1 by 1 + private void mergeCellSequences(Iterator orgSeq, Iterator modSeq) { + + boolean needMerge = true; + Element orgCell, modCell; + + Object orgSeqObject = orgSeq.start(); + Object modSeqObject = modSeq.start(); + + while (orgSeqObject != null) { + + + needMerge = true; + + if (modSeqObject == null) { + // no corresponding cell in the target, empty out the cell + SheetUtil.emptyCell(cc_, (Node)orgSeqObject); + orgSeqObject = orgSeq.next(); + + } else { + + // compare the cell directly + if (!orgSeq.equivalent(orgSeqObject, modSeqObject)) { + + orgCell = (Element)orgSeqObject; + modCell = (Element)modSeqObject; + + // check whether the original cell with multiple column + // if so, need to split one out for merge + String orgColRepeated = orgCell.getAttribute( + OfficeConstants.ATTRIBUTE_TABLE_NUM_COLUMNS_REPEATED); + String modColRepeated = modCell.getAttribute( + OfficeConstants.ATTRIBUTE_TABLE_NUM_COLUMNS_REPEATED); + + int orgColNum = 1; + int modColNum = 1; + + if (orgColRepeated.length() > 0) { + orgColNum = + Integer.valueOf(orgColRepeated).intValue(); + } + if (modColRepeated.length() > 0) { + modColNum = + Integer.valueOf(modColRepeated).intValue(); + } + + // try to find out the common number of repeated cols + if (orgColNum == modColNum) { + orgSeqObject = orgSeq.next(); + modSeqObject = modSeq.next(); + + // cut the original cell into 2 half, first half + // have the repeated attribute = modify cell attr + } else if (orgColNum > modColNum) { + Element orgSplitCell = splitColRepeatedCell( + orgCell, modColNum, + orgColNum - modColNum); + // it may equal after the split! + if (orgSeq.equivalent(orgSplitCell, modCell)) { + needMerge = false; + } + orgCell = orgSplitCell; + modSeqObject = modSeq.next(); + + // cut the modified cell into 2 half, first half + // have the repeated attribute = original cell attr + } else { + Element modSplitCell = splitColRepeatedCell( + modCell, orgColNum, + modColNum - orgColNum); + // it may equal after the split! + if (modSeq.equivalent(orgCell, modSplitCell)) { + needMerge = false; + } + modCell = modSplitCell; + orgSeqObject = orgSeq.next(); + } + + if (needMerge) { + mergeCells(orgCell, modCell); + } + + } else { + // cells are equivalent, move on to next one. + orgSeqObject = orgSeq.next(); + modSeqObject = modSeq.next(); + } // end if-else + } // end if-else + } // end while loop + + // get the one of the original cell, so that the cloned node + // can base it to find the document node + orgCell = (Element)orgSeq.start(); + + // add any extra cells to the original cell sequence. + for (; modSeqObject != null; modSeqObject = modSeq.next()) { + Node clonedNode = XmlUtil.deepClone(orgCell, (Node)modSeqObject); + Node parent = orgCell.getParentNode(); + parent.appendChild(clonedNode); + } + } + + + private Element splitColRepeatedCell(Element orgCell, + int splitNum, int orgNum) { + // NOTE: should we really want to do deep clone? + // in most the case, it is an empty cell, but the + // specification didn't forbid any node to use multiple + // column attributes. i.e. the node can contain text + // nodes or other things under it. + Element splitCell = (Element)(orgCell.cloneNode(true)); + + if (splitNum > 1) { + splitCell.setAttribute( + OfficeConstants.ATTRIBUTE_TABLE_NUM_COLUMNS_REPEATED, + String.valueOf(splitNum)); + } else if (splitNum == 1) { + splitCell.removeAttribute( + OfficeConstants.ATTRIBUTE_TABLE_NUM_COLUMNS_REPEATED); + } + if (orgNum > 1) { + orgCell.setAttribute( + OfficeConstants.ATTRIBUTE_TABLE_NUM_COLUMNS_REPEATED, + String.valueOf(orgNum)); + } else if (orgNum == 1) { + orgCell.removeAttribute( + OfficeConstants.ATTRIBUTE_TABLE_NUM_COLUMNS_REPEATED); + } + + Node parentNode = orgCell.getParentNode(); + parentNode.insertBefore(splitCell, orgCell); + + return splitCell; + } + + + private void mergeCells(Element orgCell, Element modCell) { + + // remove all the supported attributes and possible text child for + // string cells + SheetUtil.emptyCell(cc_, orgCell); + + // copy all the supported attributes and possible text child from + // the modified cell + NamedNodeMap attrNodes = modCell.getAttributes(); + + if (attrNodes != null) { + + // copy the first text:p node. As it's not necessary only string + // type cell can have a text:p section. + NodeList paraNodes = + modCell.getElementsByTagName(OfficeConstants.TAG_PARAGRAPH); + + Node firstParaNode = paraNodes.item(0); + + // try to clone the node + if (firstParaNode != null) { + + Node clonedNode = XmlUtil.deepClone(orgCell, firstParaNode); + + // insert as the first child of the original cell + Node firstChild = orgCell.getFirstChild(); + if (firstChild != null) { + orgCell.insertBefore(clonedNode, firstChild); + } else { + orgCell.appendChild(clonedNode); + } + } + + // check all the attributes and copy those we supported in + // converter + // NOTE: for attribute list, refer to section 4.7.2 in specification + int len = attrNodes.getLength(); + + for (int i = 0; i < len; i++) { + Node attr = attrNodes.item(i); + + // copy the supported attrs + if (cc_.canConvertAttribute(OfficeConstants.TAG_TABLE_CELL, + attr.getNodeName())) { + orgCell.setAttribute(attr.getNodeName(), + attr.getNodeValue()); + } + } + } + } +} + |