LibreOffice Module xmerge (master) 1
IteratorRowCompare.java
Go to the documentation of this file.
1/*
2 * This file is part of the LibreOffice project.
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 *
8 * This file incorporates work covered by the following license notice:
9 *
10 * Licensed to the Apache Software Foundation (ASF) under one or more
11 * contributor license agreements. See the NOTICE file distributed
12 * with this work for additional information regarding copyright
13 * ownership. The ASF licenses this file to you under the Apache
14 * License, Version 2.0 (the "License"); you may not use this file
15 * except in compliance with the License. You may obtain a copy of
16 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
17 */
18
19package org.openoffice.xmerge.merger.diff;
20
21import org.w3c.dom.Node;
22import org.w3c.dom.Element;
23
24import java.util.ArrayList;
29
61public class IteratorRowCompare implements DiffAlgorithm {
62
77 public Difference[] computeDiffs(Iterator orgSeq, Iterator modSeq) {
78
79 ArrayList<Difference> diffVector = new ArrayList<Difference>();
80
81 // i and j are counters to keep track the current position in the
82 // iterator
83 int i = 0;
84 int j = 0;
85 Object orgSeqObject = orgSeq.start();
86 Object modSeqObject = modSeq.start();
87 Element orgRow, modRow;
88 boolean different = false;
89 boolean orgSplited = false;
90 boolean modSplited = false;
91
92 while (orgSeqObject != null) {
93
94 different = true;
95
96 if (modSeqObject == null) {
97 // no more modsequence, all the remaining org sequence objs
98 // should consider as a delete.
99 Difference diff = new Difference(Difference.DELETE, i, j);
100 diffVector.add(diff);
101 orgSeqObject = orgSeq.next();
102
103 } else {
104 if (!orgSeq.equivalent(orgSeqObject, modSeqObject)) {
105
106 orgRow = (Element)orgSeqObject;
107 modRow = (Element)modSeqObject;
108
109 // check whether the original Row with multiple row
110 // if so, need to split one out for merge
111 String orgRowRepeated = orgRow.getAttribute(
113 String modRowRepeated = modRow.getAttribute(
115
116
117 int orgRowNum = 1;
118 int modRowNum = 1;
119
120 if (orgRowRepeated.length() > 0) {
121 orgRowNum = Integer.parseInt(orgRowRepeated);
122 }
123 if (modRowRepeated.length() > 0) {
124 modRowNum = Integer.parseInt(modRowRepeated);
125 }
126
127 // try to find out the common number of repeated Rows
128 if (orgRowNum == modRowNum) {
129 orgSeqObject = orgSeq.next();
130 modSeqObject = modSeq.next();
131
132 // cut the original row into two halves, first half
133 // have the repeated attribute = modify row attr
134 } else if (orgRowNum > modRowNum) {
135 Element orgSplitRow = splitRepeatedRow(
136 orgRow, modRowNum,
137 orgRowNum - modRowNum);
138 // it may equal after the split!
139 if (orgSeq.equivalent(orgSplitRow, modRow)) {
140 different = false;
141 }
142 orgSplited = true;
143 modSeqObject = modSeq.next();
144
145 // cut the modified Row into two halves, first half
146 // have the repeated attribute = original Row attr
147 } else {
148 Element modSplitRow = splitRepeatedRow(
149 modRow, orgRowNum,
150 modRowNum - orgRowNum);
151
152 // check whether rows are equal after the split
153 if (modSeq.equivalent(orgRow, modSplitRow)) {
154 different = false;
155 }
156 modSplited = true;
157 orgSeqObject = orgSeq.next();
158 }
159
160 if (different) {
162 i, j);
163 diffVector.add(diff);
164 }
165
166 } else {
167 // Rows are equivalent, move on to next one.
168 orgSeqObject = orgSeq.next();
169 modSeqObject = modSeq.next();
170 } // end if-else
171 j++;
172 } // end if-else
173 i++;
174 } // end while loop
175
176 // any extra objects in modify sequence should consider as an add
177 // to the original sequence
178 for (; modSeqObject != null; modSeqObject = modSeq.next(), j++) {
179 Difference diff = new Difference(Difference.ADD, i, j);
180 diffVector.add(diff);
181 }
182
183 // need to refresh the iterator if we split the rows
184 if (orgSplited) {
185 orgSeq.refresh();
186 }
187
188 if (modSplited) {
189 modSeq.refresh();
190 }
191
192 // convert the vector to array
193 Difference[] diffArray = new Difference[diffVector.size()];
194 diffVector.toArray(diffArray);
195
196 return diffArray;
197 }
198
199 private Element splitRepeatedRow(Element orgRow, int splitNum, int orgNum) {
200 // NOTE: should we really want to do deep clone?
201 // in most the case, it is an empty Row, but the
202 // specification didn't forbid any node to use multiple
203 // column attributes. i.e. the node can contain text
204 // nodes or other things under it.
205 Element splitRow = (Element)(orgRow.cloneNode(true));
206
207 if (splitNum > 1) {
208 splitRow.setAttribute(
210 String.valueOf(splitNum));
211 } else if (splitNum == 1) {
212 splitRow.removeAttribute(
214 }
215 if (orgNum > 1) {
216 orgRow.setAttribute(
218 String.valueOf(orgNum));
219 } else if (orgNum == 1) {
220 orgRow.removeAttribute(
222 }
223
224 Node parentNode = orgRow.getParentNode();
225 parentNode.insertBefore(splitRow, orgRow);
226
227 return splitRow;
228 }
229}
This is the Difference basic unit.
Definition: Difference.java:27
static final int CHANGE
Change operation.
Definition: Difference.java:36
static final int DELETE
Delete operation.
Definition: Difference.java:33
static final int ADD
Add operation.
Definition: Difference.java:30
A very simple and direct difference algorithm for row Node objects in a spreadsheet.
Difference[] computeDiffs(Iterator orgSeq, Iterator modSeq)
Compute the differences of the given two sequences.
Element splitRepeatedRow(Element orgRow, int splitNum, int orgNum)
This interface contains constants for StarOffice XML tags, attributes (StarCalc cell types,...
String ATTRIBUTE_TABLE_NUM_ROWS_REPEATED
Attribute tag for table:number-rows-repeated of element table:table-row.
This is the difference algorithm interface.
This is an interface used by the DiffAlgorithm and MergeAlgorithm to access a Document.
Definition: Iterator.java:27
void refresh()
A method to force the Iterator to traverse the tree again to refresh the content.
boolean equivalent(Object obj1, Object obj2)
A method to allow the difference algorithm to test whether the obj1 and obj2 in the Iterator are cons...
Object start()
Move to the beginning of the sequence.
Object next()
Move to next element in the sequence.
int i
Document and PluginFactory implementations for XML based formats.
The DiffAlgorithm and MergeAlgorithm are used to provide the merge capabilities of this project.
Provides interfaces for converting between two Document formats, and supports a "merge" interface for...
Definition: Convert.java:19