You are viewing a plain text version of this content. The canonical link for it is here.
Posted to odf-commits@incubator.apache.org by sv...@apache.org on 2016/10/04 20:38:44 UTC

svn commit: r1763327 [2/3] - in /incubator/odf/trunk/simple/src: main/java/org/odftoolkit/simple/table/Table.java test/java/org/odftoolkit/simple/SpreadsheetIteratorTest.java test/resources/SpreadsheetIteratorTest.ods

Modified: incubator/odf/trunk/simple/src/main/java/org/odftoolkit/simple/table/Table.java
URL: http://svn.apache.org/viewvc/incubator/odf/trunk/simple/src/main/java/org/odftoolkit/simple/table/Table.java?rev=1763327&r1=1763326&r2=1763327&view=diff
==============================================================================
--- incubator/odf/trunk/simple/src/main/java/org/odftoolkit/simple/table/Table.java (original)
+++ incubator/odf/trunk/simple/src/main/java/org/odftoolkit/simple/table/Table.java Tue Oct  4 20:38:44 2016
@@ -1,3490 +1,3492 @@
-/* 
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you under the Apache License, Version 2.0 (the
-"License"); you may not use this file except in compliance
-with the License.  You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing,
-software distributed under the License is distributed on an
-"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, either express or implied.  See the License for the
-specific language governing permissions and limitations
-under the License.
-*/
-
-package org.odftoolkit.simple.table;
-
-import java.text.DecimalFormat;
-import java.text.DecimalFormatSymbols;
-import java.util.ArrayList;
-import java.util.IdentityHashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.StringTokenizer;
-import java.util.Vector;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import org.odftoolkit.odfdom.dom.OdfContentDom;
-import org.odftoolkit.odfdom.dom.OdfDocumentNamespace;
-import org.odftoolkit.odfdom.dom.OdfStylesDom;
-import org.odftoolkit.odfdom.dom.attribute.table.TableAlignAttribute;
-import org.odftoolkit.odfdom.dom.element.OdfStyleBase;
-import org.odftoolkit.odfdom.dom.element.office.OfficeAnnotationElement;
-import org.odftoolkit.odfdom.dom.element.style.StylePageLayoutPropertiesElement;
-import org.odftoolkit.odfdom.dom.element.style.StyleTableCellPropertiesElement;
-import org.odftoolkit.odfdom.dom.element.style.StyleTableColumnPropertiesElement;
-import org.odftoolkit.odfdom.dom.element.style.StyleTablePropertiesElement;
-import org.odftoolkit.odfdom.dom.element.table.TableCoveredTableCellElement;
-import org.odftoolkit.odfdom.dom.element.table.TableNamedExpressionsElement;
-import org.odftoolkit.odfdom.dom.element.table.TableNamedRangeElement;
-import org.odftoolkit.odfdom.dom.element.table.TableTableCellElement;
-import org.odftoolkit.odfdom.dom.element.table.TableTableCellElementBase;
-import org.odftoolkit.odfdom.dom.element.table.TableTableColumnElement;
-import org.odftoolkit.odfdom.dom.element.table.TableTableColumnsElement;
-import org.odftoolkit.odfdom.dom.element.table.TableTableElement;
-import org.odftoolkit.odfdom.dom.element.table.TableTableHeaderColumnsElement;
-import org.odftoolkit.odfdom.dom.element.table.TableTableHeaderRowsElement;
-import org.odftoolkit.odfdom.dom.element.table.TableTableRowElement;
-import org.odftoolkit.odfdom.dom.element.table.TableTableRowGroupElement;
-import org.odftoolkit.odfdom.dom.element.table.TableTableRowsElement;
-import org.odftoolkit.odfdom.dom.element.text.TextHElement;
-import org.odftoolkit.odfdom.dom.element.text.TextListElement;
-import org.odftoolkit.odfdom.dom.element.text.TextPElement;
-import org.odftoolkit.odfdom.dom.style.OdfStyleFamily;
-import org.odftoolkit.odfdom.dom.style.props.OdfTableProperties;
-import org.odftoolkit.odfdom.incubator.doc.office.OdfOfficeAutomaticStyles;
-import org.odftoolkit.odfdom.incubator.doc.style.OdfStyle;
-import org.odftoolkit.odfdom.incubator.doc.style.OdfStylePageLayout;
-import org.odftoolkit.odfdom.pkg.OdfElement;
-import org.odftoolkit.odfdom.pkg.OdfFileDom;
-import org.odftoolkit.odfdom.pkg.OdfName;
-import org.odftoolkit.odfdom.pkg.OdfXMLFactory;
-import org.odftoolkit.odfdom.type.Length;
-import org.odftoolkit.odfdom.type.PositiveLength;
-import org.odftoolkit.odfdom.type.Length.Unit;
-import org.odftoolkit.simple.Component;
-import org.odftoolkit.simple.Document;
-import org.odftoolkit.simple.SpreadsheetDocument;
-import org.odftoolkit.simple.TextDocument;
-import org.odftoolkit.simple.style.DefaultStyleHandler;
-import org.odftoolkit.simple.text.Paragraph;
-import org.w3c.dom.DOMException;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-/**
- * Table represents the table feature in ODF spreadsheet and text documents.
- * <p>
- * Table provides methods to get/add/delete/modify table column/row/cell.
- * 
- */
-public class Table extends Component {
-
-	private final TableTableElement mTableElement;
-	protected Document mDocument;
-	protected boolean mIsSpreadsheet;
-	protected boolean mIsCellStyleInheritance = true;
-	protected boolean mIsDescribedBySingleElement = true;
-	private static final int DEFAULT_ROW_COUNT = 2;
-	private static final int DEFAULT_COLUMN_COUNT = 5;
-	private static final double DEFAULT_TABLE_WIDTH = 6.692; // 6
-	private static final int DEFAULT_REL_TABLE_WIDTH = 65535;
-	private static final String DEFAULT_TABLE_ALIGN = "margins";
-	private static final DecimalFormat IN_FORMAT = new DecimalFormat("##0.0000");
-	// TODO: should save seperately for different dom tree
-	IdentityHashMap<TableTableCellElementBase, Vector<Cell>> mCellRepository = new IdentityHashMap<TableTableCellElementBase, Vector<Cell>>();
-	IdentityHashMap<TableTableRowElement, Vector<Row>> mRowRepository = new IdentityHashMap<TableTableRowElement, Vector<Row>>();
-	IdentityHashMap<TableTableColumnElement, Vector<Column>> mColumnRepository = new IdentityHashMap<TableTableColumnElement, Vector<Column>>();
-	private DefaultStyleHandler mStyleHandler;
-	static {
-		IN_FORMAT.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.US));
-	}
-
-	/**
-	 * This is a tool class which supplies all of the table creation detail.
-	 * <p>
-	 * The end user isn't allowed to create it directly, otherwise an
-	 * <code>IllegalStateException</code> will be thrown.
-	 * 
-	 *@since 0.3.5
-	 */
-	public static class TableBuilder {
-
-		private final TableContainer ownerContainer;
-
-		private final IdentityHashMap<TableTableElement, Table> mTableRepository = new IdentityHashMap<TableTableElement, Table>();
-
-		/**
-		 * TableBuilder constructor. This constructor should only be use in
-		 * owner {@link org.odftoolkit.simple.table.TableContainer
-		 * TableContainer} constructor. The end user isn't allowed to call it
-		 * directly, otherwise an <code>IllegalStateException</code> will be
-		 * thrown.
-		 * 
-		 * @param container
-		 *            the owner <code>TableContainer</code>.
-		 * @throws IllegalStateException
-		 *             if new TableBuilder out of owner Document constructor,
-		 *             this exception will be thrown.
-		 */
-		public TableBuilder(TableContainer container) {
-			if (container.getTableBuilder() == null) {
-				ownerContainer = container;
-			} else {
-				throw new IllegalStateException("TableBuilder only can be created in table containter constructor.");
-			}
-		}
-
-		/**
-		 * Get a table feature instance by an instance of
-		 * <code>TableTableElement</code>.
-		 * 
-		 * @param odfElement
-		 *            an instance of <code>TableTableElement</code>
-		 * @return an instance of <code>Table</code> that can represent
-		 *         <code>odfElement</code>
-		 */
-		public synchronized Table getTableInstance(TableTableElement odfElement) {
-			if (mTableRepository.containsKey(odfElement)) {
-				return mTableRepository.get(odfElement);
-			} else {
-				Table newTable = new Table(ownerContainer, odfElement);
-				mTableRepository.put(odfElement, newTable);
-				return newTable;
-			}
-		}
-
-		/**
-		 * Construct the <code>Table</code> feature. The default column count is
-		 * 5. The default row count is 2.
-		 * <p>
-		 * The table will be inserted at the end of the table container. An
-		 * unique table name will be given, you may set a custom table name
-		 * using the <code>setTableName</code> method.
-		 * <p>
-		 * If the container is a text document, cell borders will be created by
-		 * default.
-		 * 
-		 * @return the created <code>Table</code> feature instance
-		 */
-		public Table newTable() {
-			return newTable(DEFAULT_ROW_COUNT, DEFAULT_COLUMN_COUNT, 0, 0);
-		}
-
-		/**
-		 * Construct the <code>Table</code> feature with a specified row number,
-		 * column number, header row number, header column number.
-		 * <p>
-		 * The table will be inserted at the end of the container. An unique
-		 * table name will be given, you may set a custom table name using the
-		 * <code>setTableName</code> method.
-		 * <p>
-		 * If the container is a text document, cell borders will be created by
-		 * default.
-		 * 
-		 * @param numRows
-		 *            the row number
-		 * @param numCols
-		 *            the column number
-		 * @param headerRowNumber
-		 *            the header row number
-		 * @param headerColumnNumber
-		 *            the header column number
-		 * @return a new instance of <code>Table</code>
-		 * */
-		public Table newTable(int numRows, int numCols, int headerRowNumber, int headerColumnNumber) {
-			try {
-				TableTableElement newTEle = createTable(ownerContainer, numRows, numCols, headerRowNumber,
-						headerColumnNumber);
-				ownerContainer.getTableContainerElement().appendChild(newTEle);
-				return getTableInstance(newTEle);
-			} catch (DOMException e) {
-				Logger.getLogger(Table.class.getName()).log(Level.SEVERE, e.getMessage(), e);
-			} catch (Exception e) {
-				Logger.getLogger(Table.class.getName()).log(Level.SEVERE, e.getMessage(), e);
-			}
-			return null;
-		}
-		
-		/**
-		 * Construct the <code>Table</code> feature with a specified row number,
-		 * column number, header row number, header column number, left margin
-		 * space and right margin space.
-		 * <p>
-		 * The table will be inserted at the end of the container. An unique
-		 * table name will be given, you may set a custom table name using the
-		 * <code>setTableName</code> method.
-		 * <p>
-		 * If the container is a text document, cell borders will be created by
-		 * default.
-		 * 
-		 * @param numRows
-		 *            the row number
-		 * @param numCols
-		 *            the column number
-		 * @param headerRowNumber
-		 *            the header row number
-		 * @param headerColumnNumber
-		 *            the header column number
-		 * @param marginLeft
-		 *            the left table margin in centimeter(cm), between the left
-		 *            margin of table container and the table
-		 * @param marginRight
-		 *            the right table margin in centimeter(cm), between the
-		 *            right margin of table container and the table
-		 * 
-		 * @return a new instance of <code>Table</code>
-		 * 
-		 * @since 0.5.5
-		 * */
-		public Table newTable(int numRows, int numCols, int headerRowNumber, int headerColumnNumber, double marginLeft,
-				double marginRight) {
-			try {
-				TableTableElement newTEle = createTable(ownerContainer, numRows, numCols, headerRowNumber,
-						headerColumnNumber, marginLeft, marginRight);
-				ownerContainer.getTableContainerElement().appendChild(newTEle);
-				return getTableInstance(newTEle);
-			} catch (Exception e) {
-				Logger.getLogger(Table.class.getName()).log(Level.SEVERE, e.getMessage(), e);
-			}
-			return null;
-		}
-
-		/**
-		 * Construct the <code>Table</code> feature with a specified row number
-		 * and column number.
-		 * <p>
-		 * The table will be inserted at the end of the container. An unique
-		 * table name will be given, you may set a custom table name using the
-		 * <code>setTableName</code> method.
-		 * <p>
-		 * If the container is a text document, cell borders will be created by
-		 * default.
-		 * 
-		 * @param numRows
-		 *            the row number
-		 * @param numCols
-		 *            the column number
-		 * @return a new instance of <code>Table</code>
-		 */
-		public Table newTable(int numRows, int numCols) {
-			return newTable(numRows, numCols, 0, 0);
-		}
-
-		/**
-		 * Construct the Table feature with a specified 2 dimension array as the
-		 * data of this table. The value type of each cell is float.
-		 * <p>
-		 * The table will be inserted at the end of the container. An unique
-		 * table name will be given, you may set a custom table name using the
-		 * <code>setTableName</code> method.
-		 * <p>
-		 * If the container is a text document, cell borders will be created by
-		 * default.
-		 * 
-		 * @param rowLabel
-		 *            set as the header row, it can be null if no header row
-		 *            needed
-		 * @param columnLabel
-		 *            set as the header column, it can be null if no header
-		 *            column needed
-		 * @param data
-		 *            the two dimension array of double as the data of this
-		 *            table
-		 * @return a new instance of <code>Table</code>
-		 */
-		public Table newTable(String[] rowLabel, String[] columnLabel, double[][] data) {
-			int rowNumber = DEFAULT_ROW_COUNT;
-			int columnNumber = DEFAULT_COLUMN_COUNT;
-			if (data != null) {
-				rowNumber = data.length;
-				columnNumber = data[0].length;
-			}
-			int rowHeaders = 0, columnHeaders = 0;
-
-			if (rowLabel != null) {
-				rowHeaders = 1;
-			}
-			if (columnLabel != null) {
-				columnHeaders = 1;
-			}
-			try {
-				TableTableElement newTEle = createTable(ownerContainer, rowNumber + rowHeaders, columnNumber
-						+ columnHeaders, rowHeaders, columnHeaders);
-				// append to the end of table container
-				ownerContainer.getTableContainerElement().appendChild(newTEle);
-				Table table = getTableInstance(newTEle);
-				List<Row> rowList = table.getRowList();
-				for (int i = 0; i < rowNumber + rowHeaders; i++) {
-					Row row = rowList.get(i);
-					for (int j = 0; j < columnNumber + columnHeaders; j++) {
-						if ((i == 0) && (j == 0)) {
-							continue;
-						}
-						Cell cell = row.getCellByIndex(j);
-						if (i == 0 && columnLabel != null) // first row, should
-						// fill column
-						// labels
-						{
-							if (j <= columnLabel.length) {
-								cell.setStringValue(columnLabel[j - 1]);
-							} else {
-								cell.setStringValue("");
-							}
-						} else if (j == 0 && rowLabel != null) // first column,
-						// should fill
-						// row labels
-						{
-							if (i <= rowLabel.length) {
-								cell.setStringValue(rowLabel[i - 1]);
-							} else {
-								cell.setStringValue("");
-							}
-						} else {// data
-							if ((data != null) && (i >= rowHeaders) && (j >= columnHeaders)) {
-								cell.setDoubleValue(data[i - rowHeaders][j - columnHeaders]);
-							}
-						}
-					}
-				}
-				return table;
-
-			} catch (DOMException e) {
-				Logger.getLogger(Table.class.getName()).log(Level.SEVERE, e.getMessage(), e);
-			} catch (Exception e) {
-				Logger.getLogger(Table.class.getName()).log(Level.SEVERE, e.getMessage(), e);
-			}
-			return null;
-		}
-
-		/**
-		 * Construct the Table feature with a specified 2 dimension array as the
-		 * data of this table. The value type of each cell is string.
-		 * <p>
-		 * The table will be inserted at the end of the container. An unique
-		 * table name will be given, you may set a custom table name using the
-		 * <code>setTableName</code> method.
-		 * <p>
-		 * If the container is a text document, cell borders will be created by
-		 * default.
-		 * 
-		 * @param rowLabel
-		 *            set as the header row, it can be null if no header row
-		 *            needed
-		 * @param columnLabel
-		 *            set as the header column, it can be null if no header
-		 *            column needed
-		 * @param data
-		 *            the two dimension array of string as the data of this
-		 *            table
-		 * @return a new instance of <code>Table</code>
-		 */
-		public Table newTable(String[] rowLabel, String[] columnLabel, String[][] data) {
-			int rowNumber = DEFAULT_ROW_COUNT;
-			int columnNumber = DEFAULT_COLUMN_COUNT;
-			if (data != null) {
-				rowNumber = data.length;
-				columnNumber = data[0].length;
-			}
-			int rowHeaders = 0, columnHeaders = 0;
-
-			if (rowLabel != null) {
-				rowHeaders = 1;
-			}
-			if (columnLabel != null) {
-				columnHeaders = 1;
-			}
-			try {
-				TableTableElement newTEle = createTable(ownerContainer, rowNumber + rowHeaders, columnNumber
-						+ columnHeaders, rowHeaders, columnHeaders);
-				// append to the end of table container
-				ownerContainer.getTableContainerElement().appendChild(newTEle);
-
-				Table table = getTableInstance(newTEle);
-				List<Row> rowList = table.getRowList();
-				for (int i = 0; i < rowNumber + rowHeaders; i++) {
-					Row row = rowList.get(i);
-					for (int j = 0; j < columnNumber + columnHeaders; j++) {
-						if ((i == 0) && (j == 0)) {
-							continue;
-						}
-						Cell cell = row.getCellByIndex(j);
-						if (i == 0 && columnLabel != null) // first row, should
-						// fill column
-						// labels
-						{
-							if (j <= columnLabel.length) {
-								cell.setStringValue(columnLabel[j - 1]);
-							} else {
-								cell.setStringValue("");
-							}
-						} else if (j == 0 && rowLabel != null) // first column,
-						// should fill
-						// row labels
-						{
-							if (i <= rowLabel.length) {
-								cell.setStringValue(rowLabel[i - 1]);
-							} else {
-								cell.setStringValue("");
-							}
-						} else {
-							if ((data != null) && (i >= rowHeaders) && (j >= columnHeaders)) {
-								cell.setStringValue(data[i - rowHeaders][j - columnHeaders]);
-							}
-						}
-					}
-				}
-				return table;
-
-			} catch (DOMException e) {
-				Logger.getLogger(Table.class.getName()).log(Level.SEVERE, e.getMessage(), e);
-			} catch (Exception e) {
-				Logger.getLogger(Table.class.getName()).log(Level.SEVERE, e.getMessage(), e);
-			}
-			return null;
-		}
-	}
-
-	private Table(TableContainer container, TableTableElement table) {
-		mTableElement = table;
-		mDocument = getOwnerDocument(container);
-		if (mDocument instanceof SpreadsheetDocument) {
-			mIsSpreadsheet = true;
-		} else {
-			mIsSpreadsheet = false;
-		}
-	}
-
-	private static Document getOwnerDocument(TableContainer tableContainer) {
-		OdfElement containerElement = tableContainer.getTableContainerElement();
-		OdfFileDom ownerDocument = (OdfFileDom) containerElement.getOwnerDocument();
-		return (Document) ownerDocument.getDocument();
-	}
-
-	/**
-	 * Get a table feature instance by an instance of
-	 * <code>TableTableElement</code>.
-	 * 
-	 * @param element
-	 *            an instance of <code>TableTableElement</code>
-	 * @return an instance of <code>Table</code> that can represent
-	 *         <code>element</code>
-	 */
-	public static Table getInstance(TableTableElement element) {
-		Document ownerDocument = (Document) ((OdfFileDom) (element.getOwnerDocument())).getDocument();
-		return ownerDocument.getTableBuilder().getTableInstance(element);
-	}
-
-	/**
-	 * Construct the <code>Table</code> feature. The default column count is 5.
-	 * The default row count is 2.
-	 * <p>
-	 * The table will be inserted at the end of the container. An unique table
-	 * name will be given, you may set a custom table name using the
-	 * <code>setTableName</code> method.
-	 * <p>
-	 * If the <code>tableContainer</code> is a text document, cell borders will
-	 * be created by default.
-	 * 
-	 * @param tableContainer
-	 *            the table container that contains this table
-	 * @return the created <code>Table</code> feature instance
-	 */
-	public static Table newTable(TableContainer tableContainer) {
-		return tableContainer.getTableBuilder().newTable();
-	}
-
-	/**
-	 * Construct the <code>Table</code> feature with a specified row number and
-	 * column number.
-	 * <p>
-	 * The table will be inserted at the end of the tableContainer. An unique
-	 * table name will be given, you may set a custom table name using the
-	 * <code>setTableName</code> method.
-	 * <p>
-	 * If the <code>tableContainer</code> is a text document, cell borders will
-	 * be created by default.
-	 * 
-	 * @param tableContainer
-	 *            the table container that contains this table
-	 * @param numRows
-	 *            the row number
-	 * @param numCols
-	 *            the column number
-	 * @return a new instance of <code>Table</code>
-	 */
-	public static Table newTable(TableContainer tableContainer, int numRows, int numCols) {
-		return tableContainer.getTableBuilder().newTable(numRows, numCols);
-	}
-	
-	/**
-	 * Construct the <code>Table</code> feature with a specified row number and
-	 * column number.
-	 * <p>
-	 * The table will be inserted at the end of the tableContainer. An unique
-	 * table name will be given, you may set a custom table name using the
-	 * <code>setTableName</code> method.
-	 * <p>
-	 * If the <code>tableContainer</code> is a text document, cell borders will
-	 * be created by default.
-	 * 
-	 * @param tableContainer
-	 *            the table container that contains this table
-	 * @param numRows
-	 *            the row number
-	 * @param numCols
-	 *            the column number
-	 * @param marginLeft double
-	 * 			  <I>the left table margin in cm (between the left margin of document and the table)</I>
-	 * @param marginRight double
-	 * 			  <I>the right table margin in cm (between the right margin of document and the table)</I>
-	 * @return a new instance of <code>Table</code>
-	 */
-	public static Table newTable(TableContainer tableContainer, int numRows, int numCols, 
-			double marginLeft, double marginRight) {
-		return tableContainer.getTableBuilder().newTable(numRows, numCols, 0, 0, marginLeft, marginRight);
-	}
-
-	/**
-	 * Construct the <code>Table</code> feature with a specified row number,
-	 * column number, header row number, header column number.
-	 * <p>
-	 * The table will be inserted at the end of the tableContainer. An unique
-	 * table name will be given, you may set a custom table name using the
-	 * <code>setTableName</code> method.
-	 * <p>
-	 * If the <code>tableContainer</code> is a text document, cell borders will
-	 * be created by default.
-	 * 
-	 * @param tableContainer
-	 *            the ODF document that contains this feature
-	 * @param numRows
-	 *            the row number
-	 * @param numCols
-	 *            the column number
-	 * @param headerRowNumber
-	 *            the header row number
-	 * @param headerColumnNumber
-	 *            the header column number
-	 * @return a new instance of <code>Table</code>
-	 * */
-	public static Table newTable(TableContainer tableContainer, int numRows, int numCols, int headerRowNumber,
-			int headerColumnNumber) {
-		return tableContainer.getTableBuilder().newTable(numRows, numCols, headerRowNumber, headerColumnNumber);
-	}
-	
-	
-
-	/**
-	 * Construct the Table feature with a specified 2 dimension array as the
-	 * data of this table. The value type of each cell is float.
-	 * <p>
-	 * The table will be inserted at the end of the tableContainer. An unique
-	 * table name will be given, you may set a custom table name using the
-	 * <code>setTableName</code> method.
-	 * <p>
-	 * If the <code>tableContainer</code> is a text document, cell borders will
-	 * be created by default.
-	 * 
-	 * @param tableContainer
-	 *            the table container that contains this table
-	 * @param rowLabel
-	 *            set as the header row, it can be null if no header row needed
-	 * @param columnLabel
-	 *            set as the header column, it can be null if no header column
-	 *            needed
-	 * @param data
-	 *            the two dimension array of double as the data of this table
-	 * @return a new instance of <code>Table</code>
-	 */
-	public static Table newTable(TableContainer tableContainer, String[] rowLabel, String[] columnLabel, double[][] data) {
-		return tableContainer.getTableBuilder().newTable(rowLabel, columnLabel, data);
-	}
-
-	/**
-	 * Construct the Table feature with a specified 2 dimension array as the
-	 * data of this table. The value type of each cell is string.
-	 * <p>
-	 * The table will be inserted at the end of the tableContainer. An unique
-	 * table name will be given, you may set a custom table name using the
-	 * <code>setTableName</code> method.
-	 * <p>
-	 * If the <code>tableContainer</code> is a text document, cell borders will
-	 * be created by default.
-	 * 
-	 * @param tableContainer
-	 *            the table container that contains this table
-	 * @param rowLabel
-	 *            set as the header row, it can be null if no header row needed
-	 * @param columnLabel
-	 *            set as the header column, it can be null if no header column
-	 *            needed
-	 * @param data
-	 *            the two dimension array of string as the data of this table
-	 * @return a new instance of <code>Table</code>
-	 */
-	public static Table newTable(TableContainer tableContainer, String[] rowLabel, String[] columnLabel, String[][] data) {
-		return tableContainer.getTableBuilder().newTable(rowLabel, columnLabel, data);
-	}
-
-	Cell getCellInstance(TableTableCellElementBase cell, int repeatedColIndex, int repeatedRowIndex) {
-		if (mCellRepository.containsKey(cell)) {
-			Vector<Cell> list = mCellRepository.get(cell);
-			Cell fCell = null;
-			for (int i = 0; i < list.size(); i++) {
-				if (list.get(i).getOdfElement() == cell && list.get(i).mnRepeatedColIndex == repeatedColIndex
-						&& list.get(i).mnRepeatedRowIndex == repeatedRowIndex) {
-					fCell = list.get(i);
-					break;
-				}
-			}
-			if (fCell == null) {
-				fCell = new Cell(cell, repeatedColIndex, repeatedRowIndex);
-				list.add(fCell);
-			}
-			return fCell;
-		} else {
-			Cell newCell = new Cell(cell, repeatedColIndex, repeatedRowIndex);
-			Vector<Cell> list = new Vector<Cell>();
-			list.add(newCell);
-			mCellRepository.put(cell, list);
-			return newCell;
-		}
-	}
-
-	Row getRowInstance(TableTableRowElement row, int repeatedRowIndex) {
-		if (mRowRepository.containsKey(row)) {
-			Vector<Row> list = mRowRepository.get(row);
-			if (list.size() <= repeatedRowIndex) {
-				list.setSize(repeatedRowIndex + 1);
-			}
-			Row fCell = list.get(repeatedRowIndex);
-			if (fCell == null) {
-				fCell = new Row(row, repeatedRowIndex);
-				list.set(repeatedRowIndex, fCell);
-			}
-			return fCell;
-		} else {
-			Row newRow = new Row(row, repeatedRowIndex);
-			int size = (repeatedRowIndex > 7) ? (repeatedRowIndex + 1) : 8;
-			Vector<Row> list = new Vector<Row>(size);
-			list.setSize(repeatedRowIndex + 1);
-			list.set(repeatedRowIndex, newRow);
-			mRowRepository.put(row, list);
-			return newRow;
-		}
-	}
-
-	Column getColumnInstance(TableTableColumnElement col, int repeatedColIndex) {
-		if (mColumnRepository.containsKey(col)) {
-			Vector<Column> list = mColumnRepository.get(col);
-			if (list.size() <= repeatedColIndex) {
-				list.setSize(repeatedColIndex + 1);
-			}
-			Column fClm = list.get(repeatedColIndex);
-			if (fClm == null) {
-				fClm = new Column(col, repeatedColIndex);
-				list.set(repeatedColIndex, fClm);
-			}
-			return fClm;
-		} else {
-			Column newColumn = new Column(col, repeatedColIndex);
-			int size = (repeatedColIndex > 7) ? (repeatedColIndex + 1) : 8;
-			Vector<Column> list = new Vector<Column>(size);
-			list.setSize(repeatedColIndex + 1);
-			list.set(repeatedColIndex, newColumn);
-			mColumnRepository.put(col, list);
-			return newColumn;
-		}
-	}
-
-	TableTableColumnElement getColumnElementByIndex(int colIndex) {
-		int result = 0;
-		TableTableColumnElement columnEle = null;
-		for (Node n : new DomNodeList(mTableElement.getChildNodes())) {
-			if (n instanceof TableTableHeaderColumnsElement) {
-				TableTableHeaderColumnsElement headers = (TableTableHeaderColumnsElement) n;
-				for (Node m : new DomNodeList(headers.getChildNodes())) {
-					if (m instanceof TableTableColumnElement) {
-						columnEle = (TableTableColumnElement) m;
-						if (columnEle.getTableNumberColumnsRepeatedAttribute() == null) {
-							result += 1;
-						} else {
-							result += columnEle.getTableNumberColumnsRepeatedAttribute();
-						}
-					}
-					if (result > colIndex) {
-						break;
-					}
-				}
-			}
-			if (n instanceof TableTableColumnElement) {
-				columnEle = (TableTableColumnElement) n;
-				if (columnEle.getTableNumberColumnsRepeatedAttribute() == null) {
-					result += 1;
-				} else {
-					result += columnEle.getTableNumberColumnsRepeatedAttribute();
-				}
-			}
-			if (result > colIndex) {
-				break;
-			}
-		}
-		return columnEle;
-	}
-
-	TableTableRowElement getRowElementByIndex(int rowIndex) {
-		int result = 0;
-		TableTableRowElement rowEle = null;
-		for (Node n : new DomNodeList(mTableElement.getChildNodes())) {
-			if (n instanceof TableTableHeaderRowsElement) {
-				TableTableHeaderRowsElement headers = (TableTableHeaderRowsElement) n;
-				for (Node m : new DomNodeList(headers.getChildNodes())) {
-					if (m instanceof TableTableRowElement) {
-						rowEle = (TableTableRowElement) m;
-						result += rowEle.getTableNumberRowsRepeatedAttribute();
-					}
-					if (result > rowIndex) {
-						break;
-					}
-				}
-			}
-			if (n instanceof TableTableRowElement) {
-				rowEle = (TableTableRowElement) n;
-				result += ((TableTableRowElement) n).getTableNumberRowsRepeatedAttribute();
-			}
-			if (result > rowIndex) {
-				break;
-			}
-		}
-		return rowEle;
-	}
-
-	/**
-	 * Get the width of the table (in Millimeter).
-	 * <p>
-	 * Throw an UnsupportedOperationException if the table is one sheet of a
-	 * spreadsheet document. because the sheet doesn't have an attribute of
-	 * table width.
-	 * 
-	 * @return the width of the current table (in Millimeter).
-	 *         <p>
-	 *         An UnsupportedOperationException will be thrown if the table is
-	 *         in the spreadsheet document.
-	 */
-	public double getWidth() {
-		if (!mIsSpreadsheet) {
-			String sWidth = mTableElement.getProperty(OdfTableProperties.Width);
-			if (sWidth == null) {
-				int colCount = getColumnCount();
-				double tableWidth = 0;
-				for (int i = 0; i < colCount; i++) {
-					Column col = getColumnByIndex(i);
-					tableWidth += col.getWidth();
-				}
-				return tableWidth;
-			} else{
-				return PositiveLength.parseDouble(sWidth, Unit.MILLIMETER);
-			}
-		} else {
-			throw new UnsupportedOperationException();
-		}
-	}
-
-	/**
-	 * Set the width of the table (in Millimeter).
-	 * <p>
-	 * Throw an UnsupportedOperationException if the table is part of a
-	 * spreadsheet document that does not allow to change the table size,
-	 * because spreadsheet is not allow user to set the table size.
-	 * 
-	 * @param width
-	 *            the width that need to set (in Millimeter).
-	 *            <p>
-	 *            An UnsupportedOperationException will be thrown if the table
-	 *            is in the spreadsheet document.
-	 */
-	public void setWidth(double width) {
-		if (!mIsSpreadsheet) {
-			double roundingFactor = 10000.0;
-			//TODO:need refactor to PositiveLength.
-			double inValue = Math.round(roundingFactor * width / Unit.INCH.unitInMillimiter()) / roundingFactor;
-			String sWidthIN = String.valueOf(inValue) + Unit.INCH.abbr();
-			mTableElement.setProperty(OdfTableProperties.Width, sWidthIN);
-			// if the width is changed, we should also change the table:align
-			// properties if it is "margins"
-			// otherwise the width seems not changed
-			String alineStyle = mTableElement.getProperty(StyleTablePropertiesElement.Align);
-			if (TableAlignAttribute.Value.MARGINS.toString().equals(alineStyle)) {
-				mTableElement.setProperty(StyleTablePropertiesElement.Align, TableAlignAttribute.Value.LEFT.toString());
-			}
-		} else {
-			throw new UnsupportedOperationException();
-		}
-	}
-
-	static void setLeftTopBorderStyleProperties(OdfStyle style) {
-		style.setProperty(StyleTableCellPropertiesElement.Padding, "0.0382in");
-		style.setProperty(StyleTableCellPropertiesElement.BorderLeft, "0.0007in solid #000000");
-		style.setProperty(StyleTableCellPropertiesElement.BorderRight, "none");
-		style.setProperty(StyleTableCellPropertiesElement.BorderTop, "0.0007in solid #000000");
-		style.setProperty(StyleTableCellPropertiesElement.BorderBottom, "0.0007in solid #000000");
-	}
-
-	static void setRightTopBorderStyleProperties(OdfStyle style) {
-		style.setProperty(StyleTableCellPropertiesElement.Padding, "0.0382in");
-		style.setProperty(StyleTableCellPropertiesElement.Border, "0.0007in solid #000000");
-	}
-
-	static void setLeftBottomBorderStylesProperties(OdfStyle style) {
-		style.setProperty(StyleTableCellPropertiesElement.Padding, "0.0382in");
-		style.setProperty(StyleTableCellPropertiesElement.BorderLeft, "0.0007in solid #000000");
-		style.setProperty(StyleTableCellPropertiesElement.BorderRight, "none");
-		style.setProperty(StyleTableCellPropertiesElement.BorderTop, "none");
-		style.setProperty(StyleTableCellPropertiesElement.BorderBottom, "0.0007in solid #000000");
-
-	}
-
-	static void setRightBottomBorderStylesProperties(OdfStyle style) {
-		style.setProperty(StyleTableCellPropertiesElement.Padding, "0.0382in");
-		style.setProperty(StyleTableCellPropertiesElement.Border, "0.0007in solid #000000");
-		style.setProperty(StyleTableCellPropertiesElement.BorderTop, "none");
-		style.setProperty(StyleTableCellPropertiesElement.BorderBottom, "0.0007in solid #000000");
-	}
-	
-	private static TableTableElement createTable(TableContainer container, int numRows, int numCols,
-			int headerRowNumber, int headerColumnNumber) throws Exception {
-		return createTable(container, numRows, numCols, headerRowNumber, headerColumnNumber, 0, 0);
-	}
-
-	private static TableTableElement createTable(TableContainer container, int numRows, int numCols,
-			int headerRowNumber, int headerColumnNumber, double marginLeft, double marginRight) throws Exception {
-		Document document = getOwnerDocument(container);
-		OdfElement containerElement = container.getTableContainerElement();
-		OdfFileDom dom = (OdfFileDom) containerElement.getOwnerDocument();
-		double tableWidth = getTableWidth(container, marginLeft, marginRight);
-
-		boolean isTextDocument = document instanceof TextDocument;
-
-		// check arguments
-		if (numRows < 1 || numCols < 1 || headerRowNumber < 0 || headerColumnNumber < 0 || headerRowNumber > numRows
-				|| headerColumnNumber > numCols) {
-			throw new IllegalArgumentException("Can not create table with the given parameters:\n" + "Rows " + numRows
-					+ ", Columns " + numCols + ", HeaderRows " + headerRowNumber + ", HeaderColumns "
-					+ headerColumnNumber);
-		}
-		OdfOfficeAutomaticStyles styles = null;
-		if (dom instanceof OdfContentDom) {
-			styles = ((OdfContentDom) dom).getAutomaticStyles();
-		} else if (dom instanceof OdfStylesDom) {
-			styles = ((OdfStylesDom) dom).getAutomaticStyles();
-		}
-		// 1. create table element
-		TableTableElement newTEle = (TableTableElement) OdfXMLFactory.newOdfElement(dom, OdfName.newName(
-				OdfDocumentNamespace.TABLE, "table"));
-		String tablename = getUniqueTableName(container);
-		newTEle.setTableNameAttribute(tablename);
-		// create style
-		OdfStyle tableStyle = styles.newStyle(OdfStyleFamily.Table);
-		String stylename = tableStyle.getStyleNameAttribute();
-		tableStyle.setProperty(StyleTablePropertiesElement.Width, tableWidth + "in");
-		tableStyle.setProperty(StyleTablePropertiesElement.Align, DEFAULT_TABLE_ALIGN);
-		if (marginLeft != 0) {
-			tableStyle.setProperty(StyleTablePropertiesElement.MarginLeft, (new DecimalFormat("#0.##")
-					.format(marginLeft) + Unit.CENTIMETER.abbr()).replace(",", "."));
-		}
-		if (marginRight != 0) {
-			tableStyle.setProperty(StyleTablePropertiesElement.MarginRight, (new DecimalFormat("#0.##")
-					.format(marginRight) + Unit.CENTIMETER.abbr()).replace(",", "."));
-		}
-		newTEle.setStyleName(stylename);
-
-		// 2. create column elements
-		// 2.0 create column style
-		OdfStyle columnStyle = styles.newStyle(OdfStyleFamily.TableColumn);
-		String columnStylename = columnStyle.getStyleNameAttribute();
-		// for spreadsheet document, no need compute column width.
-		if (isTextDocument) {
-			columnStyle.setProperty(StyleTableColumnPropertiesElement.ColumnWidth, IN_FORMAT.format(tableWidth
-					/ numCols)
-					+ "in");
-			columnStyle.setProperty(StyleTableColumnPropertiesElement.RelColumnWidth, Math
-					.round(DEFAULT_REL_TABLE_WIDTH / numCols)
-					+ "*");
-		}
-		// 2.1 create header column elements
-		if (headerColumnNumber > 0) {
-			TableTableHeaderColumnsElement headercolumns = (TableTableHeaderColumnsElement) OdfXMLFactory
-					.newOdfElement(dom, OdfName.newName(OdfDocumentNamespace.TABLE, "table-header-columns"));
-			TableTableColumnElement headercolumn = (TableTableColumnElement) OdfXMLFactory.newOdfElement(dom, OdfName
-					.newName(OdfDocumentNamespace.TABLE, "table-column"));
-			if (headerColumnNumber > 1) {
-				headercolumn.setTableNumberColumnsRepeatedAttribute(headerColumnNumber);
-			} else {
-				headercolumn.removeAttributeNS(OdfDocumentNamespace.TABLE.getUri(), "number-columns-repeated");
-			}
-			headercolumns.appendChild(headercolumn);
-			newTEle.appendChild(headercolumns);
-			headercolumn.setStyleName(columnStylename);
-		}
-		// 2.2 create common column elements
-		TableTableColumnElement columns = (TableTableColumnElement) OdfXMLFactory.newOdfElement(dom, OdfName.newName(
-				OdfDocumentNamespace.TABLE, "table-column"));
-		int tableNumberColumnsRepeatedValue = numCols - headerColumnNumber;
-		if (tableNumberColumnsRepeatedValue > 1) {
-			columns.setTableNumberColumnsRepeatedAttribute(tableNumberColumnsRepeatedValue);
-		}
-		columns.setStyleName(columnStylename);
-		newTEle.appendChild(columns);
-
-		// 3. create row elements
-		// 3.0 create 4 kinds of styles
-		OdfStyle lefttopStyle = null, leftbottomStyle = null, righttopStyle = null, rightbottomStyle = null;
-
-		if (isTextDocument) {
-			lefttopStyle = styles.newStyle(OdfStyleFamily.TableCell);
-			setLeftTopBorderStyleProperties(lefttopStyle);
-
-			leftbottomStyle = styles.newStyle(OdfStyleFamily.TableCell);
-			setLeftBottomBorderStylesProperties(leftbottomStyle);
-
-			righttopStyle = styles.newStyle(OdfStyleFamily.TableCell);
-			setRightTopBorderStyleProperties(righttopStyle);
-
-			rightbottomStyle = styles.newStyle(OdfStyleFamily.TableCell);
-			setRightBottomBorderStylesProperties(rightbottomStyle);
-		}
-
-		// 3.1 create header row elements
-		if (headerRowNumber > 0) {
-			TableTableHeaderRowsElement headerrows = (TableTableHeaderRowsElement) OdfXMLFactory.newOdfElement(dom,
-					OdfName.newName(OdfDocumentNamespace.TABLE, "table-header-rows"));
-			for (int i = 0; i < headerRowNumber; i++) {
-				TableTableRowElement aRow = (TableTableRowElement) OdfXMLFactory.newOdfElement(dom, OdfName.newName(
-						OdfDocumentNamespace.TABLE, "table-row"));
-				for (int j = 0; j < numCols; j++) {
-					TableTableCellElement aCell = (TableTableCellElement) OdfXMLFactory.newOdfElement(dom, OdfName
-							.newName(OdfDocumentNamespace.TABLE, "table-cell"));
-					if (isTextDocument) {
-						if ((j + 1 == numCols) && (i == 0)) {
-							aCell.setStyleName(righttopStyle.getStyleNameAttribute());
-						} else if (i == 0) {
-							aCell.setStyleName(lefttopStyle.getStyleNameAttribute());
-						} else if ((j + 1 == numCols) && (i > 0)) {
-							aCell.setStyleName(rightbottomStyle.getStyleNameAttribute());
-						} else {
-							aCell.setStyleName(leftbottomStyle.getStyleNameAttribute());
-						}
-					}
-					aRow.appendChild(aCell);
-				}
-				headerrows.appendChild(aRow);
-			}
-			newTEle.appendChild(headerrows);
-		}
-
-		// 3.2 create common row elements
-		for (int i = headerRowNumber; i < numRows; i++) {
-			TableTableRowElement aRow = (TableTableRowElement) OdfXMLFactory.newOdfElement(dom, OdfName.newName(
-					OdfDocumentNamespace.TABLE, "table-row"));
-			for (int j = 0; j < numCols; j++) {
-				TableTableCellElement aCell = (TableTableCellElement) OdfXMLFactory.newOdfElement(dom, OdfName.newName(
-						OdfDocumentNamespace.TABLE, "table-cell"));
-				if (isTextDocument) {
-					if ((j + 1 == numCols) && (i == 0)) {
-						aCell.setStyleName(righttopStyle.getStyleNameAttribute());
-					} else if (i == 0) {
-						aCell.setStyleName(lefttopStyle.getStyleNameAttribute());
-					} else if ((j + 1 == numCols) && (i > 0)) {
-						aCell.setStyleName(rightbottomStyle.getStyleNameAttribute());
-					} else {
-						aCell.setStyleName(leftbottomStyle.getStyleNameAttribute());
-					}
-				}
-				aRow.appendChild(aCell);
-			}
-			newTEle.appendChild(aRow);
-		}
-
-		return newTEle;
-	}
-
-	/**
-	 * Apply the formatting specified in the template to corresponding table
-	 * cells.
-	 * <p>
-	 * A table can only be formatted as one type of styles: even-odd-rows or
-	 * even-odd-columns. The rule is to check the style of odd rows and even
-	 * rows in the template, only if they have one different properties, table:
-	 * style-name or table:paragraph-style-name, the table template will be
-	 * treated as a even-odd-columns styled table.
-	 * <p>
-	 * If one style in the template is null, the style of corresponding cells
-	 * will be removed. An empty template can be used to remove all the styles
-	 * in a table.
-	 * 
-	 * @param template
-	 * @throws IllegalArgumentException
-	 *             if the given template is null
-	 * @throws Exception
-	 *             if content DOM could not be initialized
-	 */
-	public void applyStyle(TableTemplate template) throws Exception {
-
-		if (template == null)
-			throw new IllegalArgumentException(
-					"The template cannot null to be applied to a table.");
-
-		Document doc = this.getOwnerDocument();
-		OdfOfficeAutomaticStyles styles = doc.getContentDom()
-				.getAutomaticStyles();
-
-		// decide row style or column style
-		boolean isEqualTableStyle = true;
-		boolean isEqualParaStyle = true;
-		OdfStyle evenRowsTableStyle = styles.getStyle(template
-				.getTableEvenRowsTableStyle(), OdfStyleFamily.TableCell);
-		OdfStyle oddRowsTableStyle = styles.getStyle(template
-				.getTableOddRowsTableStyle(), OdfStyleFamily.TableCell);
-		OdfStyle evenRowsParagraphStyle = styles.getStyle(template
-				.getTableEvenRowsParagraphStyle(), OdfStyleFamily.Paragraph);
-		OdfStyle oddRowsParagraphStyle = styles.getStyle(template
-				.getTableOddRowsParagraphStyle(), OdfStyleFamily.Paragraph);
-		if (evenRowsTableStyle != null || oddRowsTableStyle != null)
-			isEqualTableStyle = evenRowsTableStyle.compareTo(oddRowsTableStyle) == 0;
-		if (evenRowsParagraphStyle != null || oddRowsParagraphStyle != null)
-			isEqualParaStyle = evenRowsParagraphStyle
-					.compareTo(oddRowsParagraphStyle) == 0;
-
-		Iterator<Row> rowIterator = this.getRowIterator();
-
-		if (rowIterator.hasNext()) { // first row
-			Row currentRow = rowIterator.next();
-			String firstCellTableStyle = template
-					.getExtendedTableStyleByType(TableTemplate.ExtendedStyleType.FIRSTROWSTARTCOLUM);
-			String firstCellParagraphStyle = template
-					.getExtendedParagraphStyleByType(TableTemplate.ExtendedStyleType.FIRSTROWSTARTCOLUM);
-			String lastCellTableStyle = template
-					.getExtendedTableStyleByType(TableTemplate.ExtendedStyleType.FIRSTROWENDCOLUMN);
-			String lastCellParagraphStyle = template
-					.getExtendedParagraphStyleByType(TableTemplate.ExtendedStyleType.FIRSTROWENDCOLUMN);
-			String evenCellTableStyle = template.getTableFirstRowTableStyle();
-			String evenCellParagraphStyle = template
-					.getTableFirstRowParagraphStyle();
-			String oddCellTableStyle = evenCellTableStyle;
-			String oddCellParagraphStyle = evenCellParagraphStyle;
-
-			applyStyleToRow(template, currentRow, firstCellTableStyle,
-					oddCellTableStyle, evenCellTableStyle, lastCellTableStyle,
-					firstCellParagraphStyle, oddCellParagraphStyle,
-					evenCellParagraphStyle, lastCellParagraphStyle);
-
-			int line = 0;
-			while (rowIterator.hasNext()) {
-				currentRow = rowIterator.next();
-				line++;
-
-				if (!rowIterator.hasNext()) { // last row
-					firstCellTableStyle = template
-							.getExtendedTableStyleByType(TableTemplate.ExtendedStyleType.LASTROWSTARTCOLUMN);
-					firstCellParagraphStyle = template
-							.getExtendedParagraphStyleByType(TableTemplate.ExtendedStyleType.LASTROWSTARTCOLUMN);
-					lastCellTableStyle = template
-							.getExtendedTableStyleByType(TableTemplate.ExtendedStyleType.LASTROWENDCOLUMN);
-					lastCellParagraphStyle = template
-							.getExtendedParagraphStyleByType(TableTemplate.ExtendedStyleType.LASTROWENDCOLUMN);
-					oddCellTableStyle = evenCellTableStyle = template
-							.getTableLastRowTableStyle();
-					oddCellParagraphStyle = evenCellParagraphStyle = template
-							.getTableLastRowParagraphStyle();
-
-					applyStyleToRow(template, currentRow, firstCellTableStyle,
-							oddCellTableStyle, evenCellTableStyle,
-							lastCellTableStyle, firstCellParagraphStyle,
-							oddCellParagraphStyle, evenCellParagraphStyle,
-							lastCellParagraphStyle);
-
-				} else if (!isEqualTableStyle || !isEqualParaStyle) {
-					firstCellTableStyle = template
-							.getTableFirstColumnTableStyle();
-					firstCellParagraphStyle = template
-							.getTableFirstColumnParagraphStyle();
-					lastCellTableStyle = template
-							.getTableLastColumnTableStyle();
-					lastCellParagraphStyle = template
-							.getTableLastColumnParagraphStyle();
-
-					if (line % 2 != 0) { // odd row
-
-						oddCellTableStyle = evenCellTableStyle = template
-								.getTableOddRowsTableStyle();
-						oddCellParagraphStyle = evenCellParagraphStyle = template
-								.getTableOddRowsParagraphStyle();
-						applyStyleToRow(template, currentRow,
-								firstCellTableStyle, oddCellTableStyle,
-								evenCellTableStyle, lastCellTableStyle,
-								firstCellParagraphStyle, oddCellParagraphStyle,
-								evenCellParagraphStyle, lastCellParagraphStyle);
-					} else { // even row
-
-						oddCellTableStyle = evenCellTableStyle = template
-								.getTableEvenRowsTableStyle();
-						oddCellParagraphStyle = evenCellParagraphStyle = template
-								.getTableEvenRowsParagraphStyle();
-
-						applyStyleToRow(template, currentRow,
-								firstCellTableStyle, oddCellTableStyle,
-								evenCellTableStyle, lastCellTableStyle,
-								firstCellParagraphStyle, oddCellParagraphStyle,
-								evenCellParagraphStyle, lastCellParagraphStyle);
-					}
-
-				} else { // even&odd column
-					firstCellTableStyle = template
-							.getTableFirstColumnTableStyle();
-					firstCellParagraphStyle = template
-							.getTableFirstColumnParagraphStyle();
-					lastCellTableStyle = template
-							.getTableLastColumnTableStyle();
-					lastCellParagraphStyle = template
-							.getTableLastColumnParagraphStyle();
-					evenCellTableStyle = template
-							.getTableEvenColumnsTableStyle();
-					evenCellParagraphStyle = template
-							.getTableEvenColumnsParagraphStyle();
-					oddCellTableStyle = template.getTableOddColumnsTableStyle();
-					oddCellParagraphStyle = template
-							.getTableOddColumnsParagraphStyle();
-					applyStyleToRow(template, currentRow, firstCellTableStyle,
-							oddCellTableStyle, evenCellTableStyle,
-							lastCellTableStyle, firstCellParagraphStyle,
-							oddCellParagraphStyle, evenCellParagraphStyle,
-							lastCellParagraphStyle);
-				}
-			}
-
-		}
-
-	}
-
-	private void applyStyleToRow(TableTemplate template, Row row,
-			String firstCellTableStyle, String oddCellTableStyle,
-			String evenCellTableStyle, String lastCellTableStyle,
-			String firstCellParagraphStyle, String oddCellParagraphStyle,
-			String evenCellParagraphStyle, String lastCellParagraphStyle) {
-		int cellIndex = 0;
-		int mnRepeatedIndex = row.getRowsRepeatedNumber();
-		int lastIndex = row.getCellCount() - 1;
-		Cell cell;
-		String tableStyle, paraStyle;
-		for (Node n : new DomNodeList(row.getOdfElement().getChildNodes())) {
-			if (n instanceof TableTableCellElementBase) {
-				cell = this.getCellInstance((TableTableCellElementBase) n, 0,
-						mnRepeatedIndex);
-				if (cell.getColumnsRepeatedNumber() > 1)
-					lastIndex -= cell.getColumnsRepeatedNumber() - 1;
-				if (cellIndex == 0) {
-					tableStyle = firstCellTableStyle;
-					paraStyle = firstCellParagraphStyle;
-				} else if (cellIndex == lastIndex) {
-					tableStyle = lastCellTableStyle;
-					paraStyle = lastCellParagraphStyle;
-				} else if (cellIndex % 2 == 0) {
-					tableStyle = evenCellTableStyle;
-					paraStyle = evenCellParagraphStyle;
-				} else {
-					tableStyle = oddCellTableStyle;
-					paraStyle = oddCellParagraphStyle;
-				}
-				cell.setCellStyleName(tableStyle);
-				Iterator<Paragraph> paraIterator = cell.getParagraphIterator();
-				while (paraIterator.hasNext()) {
-					Paragraph t = paraIterator.next();
-					t.getOdfElement().setStyleName(paraStyle);
-				}
-				cellIndex++;
-			}
-		}
-	}
-
-	private static String getUniqueTableName(TableContainer container) {
-		List<Table> tableList = container.getTableList();
-		boolean notUnique = true;
-
-		String tablename = "Table" + (tableList.size() + 1);
-
-		while (notUnique) {
-			notUnique = false;
-			for (int i = 0; i < tableList.size(); i++) {
-				if (tableList.get(i).getTableName() != null) {
-					if (tableList.get(i).getTableName().equalsIgnoreCase(tablename)) {
-						notUnique = true;
-						break;
-					}
-				}
-			}
-			if (notUnique) {
-				tablename = tablename + Math.round(Math.random() * 10);
-			}
-		}
-
-		return tablename;
-
-	}
-
-	/**
-	 * Get the row count of this table.
-	 * 
-	 * @return total count of rows
-	 */
-	public int getRowCount() {
-		int result = 0;
-		for (Node n : new DomNodeList(mTableElement.getChildNodes())) {
-			if (n instanceof TableTableHeaderRowsElement) {
-				result += getHeaderRowCount((TableTableHeaderRowsElement) n);
-			}
-			if (n instanceof TableTableRowElement) {
-				result += ((TableTableRowElement) n).getTableNumberRowsRepeatedAttribute();
-			}
-			if (n instanceof TableTableRowsElement) {
-				for (Node nn : new DomNodeList(n.getChildNodes())) {
-					if (nn instanceof TableTableRowElement) {
-						result += ((TableTableRowElement) nn).getTableNumberRowsRepeatedAttribute();
-					}
-				}
-			}
-		}
-		return result;
-	}
-
-	/**
-	 * Get the column count of this table.
-	 * 
-	 * @return total count of columns
-	 */
-	public int getColumnCount() {
-		int result = 0;
-		for (Node n : new DomNodeList(mTableElement.getChildNodes())) {
-			// TODO: how about <table:table-column-group>
-			if (n instanceof TableTableHeaderColumnsElement) {
-				result += getHeaderColumnCount((TableTableHeaderColumnsElement) n);
-			}
-
-			// <table:table-columns>
-			if (n instanceof TableTableColumnsElement) {
-				result += getColumnsCount((TableTableColumnsElement) n);
-			}
-
-			if (n instanceof TableTableColumnElement) {
-				result += ((TableTableColumnElement) n).getTableNumberColumnsRepeatedAttribute();
-			}
-			// as different type of elements appear in order, so if n is one of
-			// the the following elements, computing will stop. It's helpful
-			// when the table has lots of rows.
-			if (n instanceof TableTableHeaderRowsElement || n instanceof TableTableRowsElement
-					|| n instanceof TableTableRowGroupElement || n instanceof TableTableRowElement) {
-				break;
-			}
-		}
-		return result;
-	}
-
-	/**
-	 * This method is invoked by appendRow. When a table has no row, the first
-	 * row is a default row.
-	 */
-	private TableTableRowElement createDefaultRow(int columnCount, boolean createRepeatedCell) {
-		OdfFileDom dom = (OdfFileDom) mTableElement.getOwnerDocument();
-		TableTableRowElement aRow = (TableTableRowElement) OdfXMLFactory.newOdfElement(dom, OdfName.newName(
-				OdfDocumentNamespace.TABLE, "table-row"));
-		if (createRepeatedCell) {
-			TableTableCellElement aCell = (TableTableCellElement) OdfXMLFactory.newOdfElement(dom, OdfName.newName(
-					OdfDocumentNamespace.TABLE, "table-cell"));
-			if (columnCount > 1) {
-				aCell.setTableNumberColumnsRepeatedAttribute(columnCount);
-			}
-			if (!mIsSpreadsheet) {
-				OdfOfficeAutomaticStyles automaticStyles = mTableElement.getAutomaticStyles();
-				OdfStyle borderStyle = automaticStyles.newStyle(OdfStyleFamily.TableCell);
-				setRightTopBorderStyleProperties(borderStyle);
-				aCell.setStyleName(borderStyle.getStyleNameAttribute());
-			}
-			aRow.appendChild(aCell);
-		} else {
-			OdfStyle lefttopStyle = null, righttopStyle = null;
-			// create 2 kinds of styles
-			if (!mIsSpreadsheet) {
-				OdfOfficeAutomaticStyles automaticStyles = mTableElement.getAutomaticStyles();
-				lefttopStyle = automaticStyles.newStyle(OdfStyleFamily.TableCell);
-				setLeftTopBorderStyleProperties(lefttopStyle);
-				righttopStyle = automaticStyles.newStyle(OdfStyleFamily.TableCell);
-				setRightTopBorderStyleProperties(righttopStyle);
-			}
-			for (int j = 0; j < columnCount; j++) {
-				TableTableCellElement aCell = (TableTableCellElement) OdfXMLFactory.newOdfElement(dom, OdfName.newName(
-						OdfDocumentNamespace.TABLE, "table-cell"));
-				if (!mIsSpreadsheet) {
-					if (j + 1 == columnCount) {
-						aCell.setStyleName(righttopStyle.getStyleNameAttribute());
-					} else {
-						aCell.setStyleName(lefttopStyle.getStyleNameAttribute());
-					}
-				}
-				aRow.appendChild(aCell);
-			}
-		}
-		return aRow;
-	}
-
-	/**
-	 * Append a row to the end of the table. The style of new row is same with
-	 * the last row in the table.
-	 * <p>
-	 * Since SIMPLE supports automatic table expansion. Whenever a cell outside
-	 * the current table is addressed the table is instantly expanded. Method
-	 * <code>getCellByPosition</code> can randomly access any cell, no matter it
-	 * in or out of the table original range.
-	 * 
-	 * @return a new appended row
-	 * @see #appendRows(int)
-	 * @see #getRowByIndex(int)
-	 * @see #getCellByPosition(int, int)
-	 * @see #getCellByPosition(String)
-	 */
-	public Row appendRow() {
-		// find append position
-		Node childNode = mTableElement.getLastChild();
-		// where is the new row inserted before.
-		Node positionNode = null;
-		// row style and structure clone from.
-		TableTableRowElement refRowElement = null;
-		TableTableRowElement newRow = null;
-		if (childNode instanceof TableNamedExpressionsElement) {
-			childNode = childNode.getPreviousSibling();
-			positionNode = childNode;
-		}
-		if (childNode instanceof TableTableRowElement) {
-			refRowElement = (TableTableRowElement) childNode;
-		}
-		// TODO: what about childNode instanceof TableTableHeaderRowsElement,
-		// TableTableRowsElement or TableTableRowGroupElement
-		int columnCount = getColumnCount();
-		// no row, create a default row
-		if (refRowElement == null) {
-			newRow = createDefaultRow(columnCount, true);
-			mTableElement.appendChild(newRow);
-		} else {
-			newRow = (TableTableRowElement) OdfXMLFactory.newOdfElement((OdfFileDom) mTableElement.getOwnerDocument(),
-					OdfName.newName(OdfDocumentNamespace.TABLE, "table-row"));
-			TableTableCellElementBase cellElement = (TableTableCellElementBase) refRowElement.getFirstChild();
-			int i = 1;
-			while (cellElement != null && i <= columnCount) {
-				// covered element
-				String tableNameSpace = OdfDocumentNamespace.TABLE.getUri();
-				if (cellElement instanceof TableCoveredTableCellElement) {
-					TableCoveredTableCellElement coveredCellEle = (TableCoveredTableCellElement) cellElement;
-					// find cover cell element
-					TableTableRowElement aRowEle = (TableTableRowElement) (coveredCellEle.getParentNode()
-							.getPreviousSibling());
-					while (aRowEle != null) {
-						// the cover cell and the first covered cell must have
-						// the same column index.
-						TableTableCellElementBase coverCellEle = (TableTableCellElementBase) (aRowEle.getFirstChild());
-						int j = coverCellEle.getTableNumberColumnsRepeatedAttribute();
-						while (j < i) {
-							coverCellEle = (TableTableCellElementBase) (coverCellEle.getNextSibling());
-							if (coverCellEle instanceof TableTableCellElement) {
-								j += (coverCellEle.getTableNumberColumnsRepeatedAttribute() * (((TableTableCellElement) coverCellEle)
-										.getTableNumberColumnsSpannedAttribute()));
-							} else {
-								j += coverCellEle.getTableNumberColumnsRepeatedAttribute();
-							}
-						}
-						// find the cover cell, now start cell clone.
-						if (coverCellEle instanceof TableTableCellElement) {
-							TableTableCellElement newCellEle = (TableTableCellElement) (coverCellEle.cloneNode(true));
-							cleanCell(newCellEle);
-							newCellEle.removeAttributeNS(tableNameSpace, "number-rows-spanned");
-							newRow.appendChild(newCellEle);
-							// deal with the following covered cell, spread
-							// sheet need change these covered cell to cell.
-							if (mIsSpreadsheet) {
-								// update column repeated number.
-								int columnsSpannedNumber = newCellEle.getTableNumberColumnsSpannedAttribute();
-								newCellEle.removeAttributeNS(tableNameSpace, "number-columns-spanned");
-								int newColumnRepeatedNumber = newCellEle.getTableNumberColumnsRepeatedAttribute()
-										* columnsSpannedNumber;
-								if (newColumnRepeatedNumber > 1) {
-									newCellEle.setTableNumberColumnsRepeatedAttribute(newColumnRepeatedNumber);
-								} else {
-									newCellEle.removeAttributeNS(tableNameSpace, "number-columns-repeated");
-								}
-								// ignore the following covered cell of
-								// reference row.
-								// added by Daisy because of a bug in demo4
-								// cellElement is a covered cell. coverCellEle
-								// is its cover cell.
-								// below codes will count
-								// newColumnRepeatedNumber covered cell.
-								int tempi = newColumnRepeatedNumber;
-								while (tempi > 0) {
-									int iColumnRepeatedNumber = cellElement.getTableNumberColumnsRepeatedAttribute();
-									if (iColumnRepeatedNumber > tempi) {
-										// split covered cell
-										if (cellElement instanceof TableCoveredTableCellElement) {
-											cellElement.setTableNumberColumnsRepeatedAttribute(iColumnRepeatedNumber
-													- tempi);
-											TableTableCellElementBase newCoveredCellEle = (TableTableCellElementBase) cellElement
-													.cloneNode(true);
-											cleanCell(newCoveredCellEle);
-											if (tempi > 1) {
-												newCoveredCellEle.setTableNumberColumnsRepeatedAttribute(tempi);
-											} else {
-												newCoveredCellEle.removeAttributeNS(
-														OdfDocumentNamespace.TABLE.getUri(), "number-columns-repeated");
-											}
-											refRowElement.insertBefore(newCoveredCellEle, cellElement);
-											cellElement = newCoveredCellEle;
-										}
-									}
-									tempi = tempi - cellElement.getTableNumberColumnsRepeatedAttribute();
-									i = i + cellElement.getTableNumberColumnsRepeatedAttribute();
-									if (!(cellElement instanceof TableCoveredTableCellElement) && (tempi > 0)){
-										Logger.getLogger(Table.class.getName()).log(Level.FINE,	"Not covered cell was ignored");
-									}
-									cellElement = (TableTableCellElementBase) (cellElement.getNextSibling());
-									// while ((cellElement != null) &&
-									// (cellElement instanceof
-									// TableCoveredTableCellElement)) {
-									// cellElement = (TableTableCellElementBase)
-									// (cellElement.getNextSibling());
-									// }
-								}
-								// i += newColumnRepeatedNumber;
-							} else {
-								// clone the following covered cell of reference
-								// row.
-								// added by Daisy because of a bug in demo4
-								cellElement = (TableTableCellElementBase) cellElement.getNextSibling();
-								i += cellElement.getTableNumberColumnsRepeatedAttribute();
-								int newColumnSpanNumber = newCellEle.getTableNumberColumnsSpannedAttribute();
-								while ((cellElement != null) && (cellElement instanceof TableCoveredTableCellElement)
-										&& (newColumnSpanNumber > 1)) {
-									TableCoveredTableCellElement newCoveredCellElement = (TableCoveredTableCellElement) cellElement
-											.cloneNode(true);
-									cleanCell(newCoveredCellElement);
-									newRow.appendChild(newCoveredCellElement);
-									i += cellElement.getTableNumberColumnsRepeatedAttribute();
-									cellElement = (TableTableCellElementBase) cellElement.getNextSibling();
-									newColumnSpanNumber--;
-								}
-							}
-							break;
-						}
-						// continue find cover cell
-						Node preNode = aRowEle.getPreviousSibling();
-						if (preNode instanceof TableTableRowElement) {
-							aRowEle = (TableTableRowElement) preNode;
-						} else {
-							// </table:table-header-rows>
-							aRowEle = (TableTableRowElement) (preNode.getLastChild());
-						}
-					}
-				} else {
-					TableTableCellElement newCellEle = (TableTableCellElement) cellElement.cloneNode(true);
-					cleanCell(newCellEle);
-					newRow.appendChild(newCellEle);
-					Integer tableNumberColumnsRepeated = newCellEle.getTableNumberColumnsRepeatedAttribute();
-					Integer tableNumberColumnsSpanned = newCellEle.getTableNumberColumnsSpannedAttribute();
-					i += tableNumberColumnsRepeated * tableNumberColumnsSpanned;
-					cellElement = (TableTableCellElementBase) cellElement.getNextSibling();
-					if (tableNumberColumnsSpanned > 1) {
-						int j = 1;
-						if (mIsSpreadsheet) {
-							newCellEle.removeAttributeNS(tableNameSpace, "number-columns-spanned");
-							int newColumnRepeatedNumber = tableNumberColumnsRepeated * tableNumberColumnsSpanned;
-							if (newColumnRepeatedNumber > 1) {
-								newCellEle.setTableNumberColumnsRepeatedAttribute(newColumnRepeatedNumber);
-							} else {
-								newCellEle.removeAttributeNS(tableNameSpace, "number-columns-repeated");
-							}
-							// cellElement is not a covered cell.
-							// below codes will count
-							// (newColumnRepeatedNumber-1) covered cell.
-							int tempi = newColumnRepeatedNumber;
-							while (tempi > 1) {
-								int iColumnRepeatedNumber = cellElement.getTableNumberColumnsRepeatedAttribute();
-								if (iColumnRepeatedNumber > tempi + 1) {
-									// split covered cell
-									if (cellElement instanceof TableCoveredTableCellElement) {
-										cellElement.setTableNumberColumnsRepeatedAttribute(iColumnRepeatedNumber
-												- tempi + 1);
-										TableTableCellElementBase newCoveredCellEle = (TableTableCellElementBase) cellElement
-												.cloneNode(true);
-										cleanCell(newCoveredCellEle);
-										newCoveredCellEle.setTableNumberColumnsRepeatedAttribute(tempi - 1);
-										refRowElement.insertBefore(newCoveredCellEle, cellElement);
-										cellElement = newCoveredCellEle;
-									}
-								}
-								tempi = tempi - cellElement.getTableNumberColumnsRepeatedAttribute();
-								if (!(cellElement instanceof TableCoveredTableCellElement) && (tempi > 1)){
-									Logger.getLogger(Table.class.getName()).log(Level.FINE,	"Not covered cell was ignored");
-								}
-								cellElement = (TableTableCellElementBase) (cellElement.getNextSibling());
-							}
-						} else {
-							while ((j < tableNumberColumnsSpanned) && (cellElement != null)) {
-								int iColumnRepeatedNumber = cellElement.getTableNumberColumnsRepeatedAttribute();
-								if (iColumnRepeatedNumber > tableNumberColumnsSpanned - j) {
-									// split covered cell
-									if (cellElement instanceof TableCoveredTableCellElement) {
-										cellElement.setTableNumberColumnsRepeatedAttribute(iColumnRepeatedNumber
-												- tableNumberColumnsSpanned + j);
-										TableTableCellElementBase newCoveredCellEle = (TableTableCellElementBase) cellElement
-												.cloneNode(true);
-										cleanCell(newCoveredCellEle);
-										newCoveredCellEle
-												.setTableNumberColumnsRepeatedAttribute(tableNumberColumnsSpanned - j);
-										refRowElement.insertBefore(newCoveredCellEle, cellElement);
-										cellElement = newCoveredCellEle;
-									}
-								}
-								TableTableCellElementBase newCoveredCellEle = (TableTableCellElementBase) cellElement
-										.cloneNode(true);
-								cleanCell(newCoveredCellEle);
-								newRow.appendChild(newCoveredCellEle);
-								j += newCoveredCellEle.getTableNumberColumnsRepeatedAttribute();
-								cellElement = (TableTableCellElementBase) cellElement.getNextSibling();
-							}
-						}
-					}
-				}
-			}
-			if (positionNode == null) {
-				mTableElement.appendChild(newRow);
-			} else {
-				mTableElement.insertBefore(newRow, positionNode);
-			}
-		}
-		return getRowInstance(newRow, 0);
-	}
-
-	/**
-	 * Append a specific number of rows to the end of the table. The style of
-	 * new rows are same with the last row in the table.
-	 * <p>
-	 * Since SIMPLE supports automatic table expansion. Whenever a cell outside
-	 * the current table is addressed the table is instantly expanded. Method
-	 * <code>getCellByPosition</code> can randomly access any cell, no matter it
-	 * in or out of the table original range.
-	 * 
-	 * @param rowCount
-	 *            is the number of rows to be appended.
-	 * @return a list of new appended rows
-	 * @see #appendRow()
-	 * @see #getRowByIndex(int)
-	 * @see #getCellByPosition(int, int)
-	 * @see #getCellByPosition(String)
-	 */
-	public List<Row> appendRows(int rowCount) {
-		return appendRows(rowCount, false);
-	}
-
-	List<Row> appendRows(int rowCount, boolean isCleanStyle) {
-		List<Row> resultList = new ArrayList<Row>();
-		if (rowCount <= 0) {
-			return resultList;
-		}
-		if (isUseRepeat()) {
-			Row firstRow = appendRow();
-			resultList.add(firstRow);
-			if (rowCount > 1) {
-				firstRow.setRowsRepeatedNumber(rowCount);
-				TableTableRowElement firstRowEle = firstRow.getOdfElement();
-				for (int i = 1; i < rowCount; i++) {
-					Row row = getRowInstance(firstRowEle, i);
-					resultList.add(row);
-				}
-			}
-		} else {
-			for (int i = 0; i < rowCount; i++) {
-				Row firstRow = appendRow();
-				resultList.add(firstRow);
-			}
-		}
-		if (isCleanStyle) {
-			// clean style name
-			String tableNameSpace = OdfDocumentNamespace.TABLE.getUri();
-			for (Row row : resultList) {
-				Node cellE = row.getOdfElement().getFirstChild();
-				while (cellE != null) {
-					((TableTableCellElementBase) cellE).removeAttributeNS(tableNameSpace, "style-name");
-					cellE = cellE.getNextSibling();
-				}
-			}
-		}
-		return resultList;
-	}
-
-	/**
-	 * Append a column at the end of the table. The style of new column is same
-	 * with the last column in the table.
-	 * <p>
-	 * Since SIMPLE supports automatic table expansion. Whenever a cell outside
-	 * the current table is addressed the table is instantly expanded. Method
-	 * <code>getCellByPosition</code> can randomly access any cell, no matter it
-	 * in or out of the table original range.
-	 * 
-	 * @return a new appended column
-	 * @see #appendColumns(int)
-	 * @see #getColumnByIndex(int)
-	 * @see #getCellByPosition(int, int)
-	 * @see #getCellByPosition(String)
-	 */
-	public Column appendColumn() {
-		List<Column> columnList = getColumnList();
-		int columnCount = columnList.size();
-
-		TableTableColumnElement newColumn;
-		OdfElement positonElement = getRowElementByIndex(0);
-		if (positonElement.getParentNode() instanceof TableTableHeaderRowsElement) {
-			positonElement = (OdfElement) positonElement.getParentNode();
-		}
-
-		// Moved before column elements inserted
-		// insert cells firstly
-		// Or else, wrong column number will be gotten in updateCellRepository,
-		// which will cause a NPE.
-		// insertCellBefore()->splitRepeatedRows()->updateRowRepository()->updateCellRepository()
-		List<Row> rowList = getRowList();
-		for (int i = 0; i < rowList.size();) {
-			Row row1 = rowList.get(i);
-			row1.insertCellBefore(row1.getCellByIndex(columnCount - 1), null);
-			i = i + row1.getRowsRepeatedNumber();
-		}
-
-		// insert columns secondly
-		if (columnList.size() == 0) // no column, create a new column
-		{
-			OdfStyle columnStyle = mTableElement.getAutomaticStyles().newStyle(OdfStyleFamily.TableColumn);
-			String columnStylename = columnStyle.getStyleNameAttribute();
-			columnStyle.setProperty(StyleTableColumnPropertiesElement.ColumnWidth, DEFAULT_TABLE_WIDTH + "in");
-			columnStyle.setProperty(StyleTableColumnPropertiesElement.RelColumnWidth, DEFAULT_REL_TABLE_WIDTH + "*");
-
-			newColumn = (TableTableColumnElement) OdfXMLFactory.newOdfElement((OdfFileDom) mTableElement
-					.getOwnerDocument(), OdfName.newName(OdfDocumentNamespace.TABLE, "table-column"));
-			newColumn.setStyleName(columnStylename);
-			mTableElement.insertBefore(newColumn, positonElement);
-		} else { // has column, append a same column as the last one.
-			TableTableColumnElement refColumn = columnList.get(columnList.size() - 1).getOdfElement();
-			newColumn = (TableTableColumnElement) refColumn.cloneNode(true);
-			String tableNameSpace = OdfDocumentNamespace.TABLE.getUri();
-			newColumn.removeAttributeNS(tableNameSpace, "number-columns-repeated");
-			mTableElement.insertBefore(newColumn, positonElement);
-		}
-
-		return getColumnInstance(newColumn, 0);
-	}
-
-	/**
-	 * Append a specific number of columns to the right of the table. The style
-	 * of new columns are same with the rightmost column in the table.
-	 * <p>
-	 * Since SIMPLE supports automatic table expansion. Whenever a cell outside
-	 * the current table is addressed the table is instantly expanded. Method
-	 * <code>getCellByPosition</code> can randomly access any cell, no matter it
-	 * in or out of the table original range.
-	 * 
-	 * @param columnCount
-	 *            is the number of columns to be appended.
-	 * @return a list of new appended columns
-	 * @see #appendColumn()
-	 * @see #getColumnByIndex(int)
-	 * @see #getCellByPosition(int, int)
-	 * @see #getCellByPosition(String)
-	 */
-	public List<Column> appendColumns(int columnCount) {
-		return appendColumns(columnCount, false);
-	}
-
-	List<Column> appendColumns(int columnCount, boolean isCleanStyle) {
-		List<Column> resultList = new ArrayList<Column>();
-		if (columnCount <= 0) {
-			return resultList;
-		}
-		Column firstClm = appendColumn();
-		resultList.add(firstClm);
-		if (columnCount > 1) {
-			List<Column> list = insertColumnsBefore((getColumnCount() - 1), (columnCount - 1));
-			resultList.addAll(list);
-		}
-		// clean style name
-		if (isCleanStyle) {
-			for (Column column : resultList) {
-				int length = column.getCellCount();
-				for (int i = 0; i < length; i++) {
-					TableTableCellElementBase cellElement = column.getCellByIndex(i).mCellElement;
-					cellElement.removeAttributeNS(OdfDocumentNamespace.TABLE.getUri(), "style-name");
-				}
-			}
-		}
-		return resultList;
-	}
-
-	/**
-	 * This method is to insert a numbers of row
-	 */
-	private List<Row> insertMultipleRowsBefore(Row refRow, Row positionRow, int count) {
-		List<Row> resultList = new ArrayList<Row>();
-		int j = 1;
-
-		if (count <= 0) {
-			return resultList;
-		}
-
-		Row firstRow = insertRowBefore(refRow, positionRow, getColumnCount());
-		resultList.add(firstRow);
-
-		if (count == 1) {
-			return resultList;
-		}
-		TableTableRowElement rowEle = firstRow.getOdfElement();
-		for (int i = 0; i < getColumnCount();) {
-			Cell refCell = refRow.getCellByIndex(i);
-			if (!refCell.isCoveredElement()) {
-				int coveredHeigth = refCell.getRowSpannedNumber();
-				if (coveredHeigth > 1) {
-					refCell.setRowSpannedNumber(coveredHeigth + 1);
-				}
-			}
-			i += refCell.getColumnsRepeatedNumber();
-		}
-		if (isUseRepeat()) {
-			firstRow.setRowsRepeatedNumber(count);
-			while (j < count) {
-				resultList.add(getRowInstance(rowEle, j));
-				j++;
-			}
-		} else {
-			while (j < count) {
-				TableTableRowElement newRowEle = (TableTableRowElement) rowEle.cloneNode(true);
-				newRowEle.removeAttributeNS(OdfDocumentNamespace.TABLE.getUri(), "number-rows-repeated");
-				mTableElement.insertBefore(newRowEle, positionRow.getOdfElement());
-				resultList.add(getRowInstance(newRowEle, 0));
-				j++;
-			}
-		}
-		return resultList;
-	}
-
-	// only insert one Row
-	private Row insertRowBefore(Row refRow, Row positionRow, int columnCount) {
-		TableTableRowElement aRow = (TableTableRowElement) OdfXMLFactory.newOdfElement((OdfFileDom) mTableElement
-				.getOwnerDocument(), OdfName.newName(OdfDocumentNamespace.TABLE, "table-row"));
-		int coveredLength = 0, coveredHeigth = 0;
-		for (int i = 0; i < columnCount;) {
-			Cell refCell = refRow.getCellByIndex(i);
-			int columnsRepeatedNumber = refCell.getColumnsRepeatedNumber();
-			if (!refCell.isCoveredElement()) // not cover element
-			{
-				TableTableCellElement aCellEle = (TableTableCellElement) refCell.getOdfElement();
-				coveredHeigth = aCellEle.getTableNumberRowsSpannedAttribute();
-				if (coveredHeigth == 1) {
-					TableTableCellElement newCellEle = (TableTableCellElement) aCellEle.cloneNode(true);
-					cleanCell(newCellEle);
-					aRow.appendChild(newCellEle);
-				} else { // cover more rows
-					aCellEle.setTableNumberRowsSpannedAttribute(coveredHeigth + 1);
-					TableCoveredTableCellElement newCellEle = (TableCoveredTableCellElement) OdfXMLFactory
-							.newOdfElement((OdfFileDom) mTableElement.getOwnerDocument(), OdfName.newName(
-									OdfDocumentNamespace.TABLE, "covered-table-cell"));
-					if (columnsRepeatedNumber > 1) {
-						newCellEle.setTableNumberColumnsRepeatedAttribute(columnsRepeatedNumber);
-					} else {
-						newCellEle.removeAttributeNS(OdfDocumentNamespace.TABLE.getUri(), "number-columns-repeated");
-					}
-					aRow.appendChild(newCellEle);
-				}
-
-				coveredLength = aCellEle.getTableNumberColumnsSpannedAttribute() - columnsRepeatedNumber;
-				i = i + columnsRepeatedNumber;
-			} else {
-				TableCoveredTableCellElement aCellEle = (TableCoveredTableCellElement) refCell.getOdfElement();
-				if (coveredLength >= 1) {
-					TableCoveredTableCellElement newCellEle = (TableCoveredTableCellElement) aCellEle.cloneNode(true);
-					aRow.appendChild(newCellEle);
-					coveredLength -= newCellEle.getTableNumberColumnsRepeatedAttribute();
-				} else {
-					TableTableCellElement coveredCell = (TableTableCellElement) refCell.getCoverCell().getOdfElement();
-					TableTableCellElement newCellEle = (TableTableCellElement) coveredCell.cloneNode(true);
-					cleanCell(newCellEle);
-					newCellEle.removeAttributeNS(OdfDocumentNamespace.TABLE.getUri(), "number-rows-spanned");
-					aRow.appendChild(newCellEle);
-					coveredLength = coveredCell.getTableNumberColumnsSpannedAttribute() - columnsRepeatedNumber;
-				}
-				i = i + columnsRepeatedNumber;
-			}
-		}
-		if (positionRow == null) {
-			mTableElement.appendChild(aRow);
-		} else {
-			mTableElement.insertBefore(aRow, positionRow.getOdfElement());
-		}
-
-		return getRowInstance(aRow, 0);
-	}
-
-	void cleanCell(TableTableCellElementBase newCellEle) {
-		String officeNameSpaceURI = OdfDocumentNamespace.OFFICE.getUri();
-		String tableNameSpaceURI = OdfDocumentNamespace.TABLE.getUri();
-		newCellEle.removeAttributeNS(officeNameSpaceURI, "value");
-		newCellEle.removeAttributeNS(officeNameSpaceURI, "date-value");
-		newCellEle.removeAttributeNS(officeNameSpaceURI, "time-value");
-		newCellEle.removeAttributeNS(officeNameSpaceURI, "boolean-value");
-		newCellEle.removeAttributeNS(officeNameSpaceURI, "string-value");
-		newCellEle.removeAttributeNS(tableNameSpaceURI, "formula");
-		newCellEle.removeAttributeNS(officeNameSpaceURI, "value-type");
-		if (!isCellStyleInheritance()) {
-			newCellEle.removeAttributeNS(tableNameSpaceURI, "style-name");
-		}
-		Node n = newCellEle.getFirstChild();
-		while (n != null) {
-			Node m = n.getNextSibling();
-			if (n instanceof TextPElement || n instanceof TextHElement || n instanceof TextListElement
-					|| n instanceof OfficeAnnotationElement) {
-				newCellEle.removeChild(n);
-			}
-			n = m;
-		}
-	}
-
-	/**
-	 * Return an instance of <code>TableTableElement</code> which represents
-	 * this feature.
-	 * 
-	 * @return an instance of <code>TableTableElement</code>
-	 */
-	public TableTableElement getOdfElement() {
-		return mTableElement;
-	}
-
-	/**
-	 * Insert a specific number of columns before the column whose index is
-	 * <code>index</code>.
-	 * 
-	 * @param index
-	 *            is the index of the column to insert before.
-	 * @param columnCount
-	 *            is the number of columns to insert.
-	 * @return a list of new inserted columns
-	 */
-	public List<Column> insertColumnsBefore(int index, int columnCount) {
-		Column refColumn, positionCol;
-		String tableNameSpace = OdfDocumentNamespace.TABLE.getUri();
-		ArrayList<Column> list = new ArrayList<Column>();
-		int columncount = getColumnCount();
-
-		if (index >= columncount) {
-			throw new IndexOutOfBoundsException();
-		}
-
-		if (index == 0) {
-			int iRowCount = getRowCount();
-			for (int i = 0; i < iRowCount; i++) {
-				Row row = getRowByIndex(i);
-				row.insertCellByIndex(index, columnCount);
-			}
-			refColumn = getColumnByIndex(index);
-			positionCol = refColumn;
-			// add a single column element to describe columns.
-			if (isUseRepeat()) {
-				TableTableColumnElement newColumnEle = (TableTableColumnElement) refColumn.getOdfElement().cloneNode(
-						true);
-				if (columnCount > 1) {
-					newColumnEle.setTableNumberColumnsRepeatedAttribute(columnCount);
-				} else {
-					newColumnEle.removeAttributeNS(tableNameSpace, "number-columns-repeated");
-				}
-				mTableElement.insertBefore(newColumnEle, positionCol.getOdfElement());
-				for (int i = 0; i < columnCount; i++) {
-					list.add(getColumnInstance(newColumnEle, i));
-				}
-			} else {
-				for (int i = 0; i < columnCount; i++) {
-					TableTableColumnElement newColumnEle = (TableTableColumnElement) refColumn.getOdfElement()
-							.cloneNode(true);
-					mTableElement.insertBefore(newColumnEle, positionCol.getOdfElement());
-					newColumnEle.removeAttributeNS(tableNameSpace, "number-columns-repeated");
-					list.add(getColumnInstance(newColumnEle, 0));
-				}
-			}
-			return list;
-		}
-
-		// 1. insert the cell
-		int iRowCount = getRowCount();
-		for (int i = iRowCount - 1; i >= 0;) {
-			Row row = getRowByIndex(i);
-			Cell refCell = row.getCellByIndex(index - 1);
-			Cell positionCell = null;
-			positionCell = row.getCellByIndex(index);
-			row.insertCellBefore(refCell, positionCell, columnCount);
-			i = i - row.getRowsRepeatedNumber();
-		}
-
-		refColumn = getColumnByIndex(index - 1);
-		positionCol = getColumnByIndex(index);
-		// 2. insert a <table:table-column>
-		if (refColumn.getOdfElement() == positionCol.getOdfElement()) {
-			TableTableColumnElement column = refColumn.getOdfElement();
-			int repeatedCount = column.getTableNumberColumnsRepeatedAttribute();
-			TableTableColumnElement columnEle = positionCol.getOdfElement();
-			// add a single column element to describe columns.
-			if (isUseRepeat()) {
-				column.setTableNumberColumnsRepeatedAttribute(repeatedCount + columnCount);
-				Column startCol = getColumnInstance(positionCol.getOdfElement(), 0);
-				for (int i = repeatedCount + columnCount - 1; i >= columnCount + (index - startCol.getColumnIndex()); i--) {
-					updateColumnRepository(columnEle, i - columnCount, columnEle, i);
-				}
-				for (int i = 0; i < columnCount; i++) {
-					list.add(getColumnInstance(column, refColumn.mnRepeatedIndex + 1 + i));
-				}
-			} else {
-				TableTableColumnElement newBeforeColumnEle = (TableTableColumnElement) refColumn.getOdfElement()
-						.cloneNode(true);
-				if (index > 1) {
-					newBeforeColumnEle.setTableNumberColumnsRepeatedAttribute(index);
-				} else {
-					newBeforeColumnEle.removeAttributeNS(tableNameSpace, "number-columns-repeated");
-				}
-				mTableElement.insertBefore(newBeforeColumnEle, positionCol.getOdfElement());
-				for (int i = 0; i < index; i++) {
-					updateColumnRepository(columnEle, i, newBeforeColumnEle, i);
-				}
-				int newAfterCount = repeatedCount - index;
-				if (newAfterCount > 1) {
-					positionCol.setColumnsRepeatedNumber(newAfterCount);
-				} else {
-					positionCol.getOdfElement().removeAttributeNS(tableNameSpace, "number-columns-repeated");
-				}
-				for (int i = repeatedCount - 1; i >= index; i--) {
-					updateColumnRepository(columnEle, i, columnEle, i - index);
-				}
-				for (int i = 0; i < columnCount; i++) {
-					TableTableColumnElement newColumnEle = (TableTableColumnElement) refColumn.getOdfElement()
-							.cloneNode(true);
-					newColumnEle.removeAttributeNS(tableNameSpace, "number-columns-repeated");
-					mTableElement.insertBefore(newColumnEle, positionCol.getOdfElement());
-					list.add(getColumnInstance(newColumnEle, 0));
-				}
-			}
-		} else {
-			// add a single column element to describe columns.
-			if (isUseRepeat()) {
-				TableTableColumnElement newColumnEle = (TableTableColumnElement) refColumn.getOdfElement().cloneNode(
-						true);
-				if (columnCount > 1) {
-					newColumnEle.setTableNumberColumnsRepeatedAttribute(columnCount);
-				} else {
-					newColumnEle.removeAttributeNS(tableNameSpace, "number-columns-repeated");
-				}
-				mTableElement.insertBefore(newColumnEle, positionCol.getOdfElement());
-				for (int i = 0; i < columnCount; i++) {
-					list.add(getColumnInstance(newColumnEle, i));
-				}
-			} else {
-				for (int i = 0; i < columnCount; i++) {
-					TableTableColumnElement newColumnEle = (TableTableColumnElement) refColumn.getOdfElement()
-							.cloneNode(true);
-					newColumnEle.removeAttributeNS(tableNameSpace, "number-columns-repeated");
-					mTableElement.insertBefore(newColumnEle, positionCol.getOdfElement());
-					list.add(getColumnInstance(newColumnEle, 0));
-				}
-			}
-		}
-		return list;
-	}
-
-	/**
-	 * Remove a specific number of columns, starting from the column at
-	 * <code>index</code>.
-	 * 
-	 * @param startIndex
-	 *            is the index of the first column to delete.
-	 * @param deleteColCount
-	 *            is the number of columns to delete.
-	 */
-	public void removeColumnsByIndex(int startIndex, int deleteColCount) {
-		// 0. verify the index
-		if (deleteColCount <= 0) {
-			return;
-		}
-		if (startIndex < 0) {
-			throw new IllegalArgumentException("startIndex of the deleted columns should not be negative");
-		}
-		int colCount = getColumnCount();
-		if (startIndex >= colCount) {
-			throw new IndexOutOfBoundsException("Start column index is out of bound");
-		}
-		if (startIndex + deleteColCount >= colCount) {
-			deleteColCount = colCount - startIndex;
-		}
-
-		// 1. remove cell
-		for (int i = 0; i < getRowCount(); i++) {
-			Row aRow = getRowByIndex(i);
-			aRow.removeCellByIndex(startIndex, deleteColCount);
-		}
-
-		// 2. remove column
-		Column firstColumn;
-		for (int i = 0; i < deleteColCount; i++) {
-			firstColumn = getColumnByIndex(startIndex);
-			int repeatedAttr = firstColumn.getColumnsRepeatedNumber();
-			if (repeatedAttr == 1) {
-				TableTableColumnElement columnEle = OdfElement.findNextChildNode(TableTableColumnElement.class,
-						firstColumn.getOdfElement());
-				mTableElement.removeChild(firstColumn.getOdfElement());
-				if (i < (deleteColCount - 1)) {
-					firstColumn = this.getColumnInstance(columnEle, 0);
-				}
-			} else {
-				if (repeatedAttr > firstColumn.mnRepeatedIndex) {
-					firstColumn.setColumnsRepeatedNumber(repeatedAttr - 1);
-					Column startCol = this.getColumnInstance(firstColumn.getOdfElement(), 0);
-					updateColumnRepository(firstColumn.getOdfElement(), startIndex - startCol.getColumnIndex(), null, 0);
-				}
-			}
-		}
-
-	}
-	
-	/**
-	 * Calculates the width between the left and right margins of the table
-	 * container.
-	 * 
-	 * @param container
-	 *            TableContainer
-	 * @param marginLeft
-	 *            space between left margin and the table
-	 * @param marginRight
-	 *            space between right margin and the table
-	 * @return width that can be attributed at the table (in)
-	 */
-	private static double getTableWidth(TableContainer container, double marginLeft, double marginRight) {
-		String pageWidthStr = null;
-		double pageWidth = 0;
-		double tableWidth = DEFAULT_TABLE_WIDTH;
-		OdfOfficeAutomaticStyles automaticStyles = null;
-		try {
-			automaticStyles = getOwnerDocument(container).getStylesDom().getAutomaticStyles();
-		} catch (Exception e) {
-			Logger.getLogger(Table.class.getName()).log(Level.SEVERE,	e.getMessage(), e);
-		}
-		OdfStylePageLayout pageLayout = automaticStyles.getPageLayout("pm1");
-		if (pageLayout == null) {
-			pageLayout = automaticStyles.getPageLayout("Mpm1");
-		}
-		if (pageLayout != null) {
-			pageWidthStr = pageLayout.getProperty(StylePageLayoutPropertiesElement.PageWidth);
-			if (pageWidthStr != null) {
-				pageWidth = Length.parseDouble(pageWidthStr, Unit.CENTIMETER);
-			}
-			// margins
-			double dLeftPageMargin = 0;
-			double dRightPageMargin = 0;
-			String leftPageMargin = pageLayout.getProperty(StylePageLayoutPropertiesElement.MarginLeft);
-			String rightPageMargin = pageLayout.getProperty(StylePageLayoutPropertiesElement.MarginRight);
-			if (leftPageMargin != null && rightPageMargin != null) {
-				dLeftPageMargin = Length.parseDouble(leftPageMargin, Unit.CENTIMETER);
-				dRightPageMargin = Length.parseDouble(rightPageMargin, Unit.CENTIMETER);
-			}
-			tableWidth = (pageWidth - (dLeftPageMargin + dRightPageMargin + marginLeft + marginRight)) / 2.5399;
-			if (tableWidth <= 0) {
-				tableWidth = DEFAULT_TABLE_WIDTH;
-			}
-		}
-		return Double.valueOf(new DecimalFormat("#0.###").format(tableWidth).replace(",", ".")).doubleValue();
-	}
-
-	private void reviseStyleFromTopRowToMediumRow(Row oldTopRow) {
-		if (mIsSpreadsheet)
-			return;
-		int length = getColumnCount();
-
-		for (int i = 0; i < length;) {
-			Cell cell = oldTopRow.getCellByIndex(i);
-			if (cell.isCoveredElement()) {
-				i = i + cell.getColumnsRepeatedNumber();
-				continue;
-			}
-			OdfStyle styleEle = cell.getStyleHandler().getStyleElementForWrite();
-			if (i < length - 1) {
-				setLeftBottomBorderStylesProperties(styleEle);
-			} else {
-				setRightBottomBorderStylesProperties(styleEle);
-			}
-			i = i + cell.getColumnsRepeatedNumber();
-		}
-	}
-
-	private void reviseStyleFromMediumRowToTopRow(Row newTopRow) {
-		if (mIsSpreadsheet) {
-			return;
-		}
-		int length = getColumnCount();
-
-		for (int i = 0; i < length;) {
-			Cell cell = newTopRow.getCellByIndex(i);
-			if (cell.isCoveredElement()) {
-				i = i + cell.getColumnsRepeatedNumber();
-				continue;
-			}
-			OdfStyle styleEle = cell.getStyleHandler().getStyleElementForWrite();
-			if (i < length - 1) {
-				setLeftTopBorderStyleProperties(styleEle);
-			} else {
-				setRightTopBorderStyleProperties(styleEle);
-			}
-			i = i + cell.getColumnsRepeatedNumber();
-		}
-	}
-
-	/**
-	 * Insert a specific number of rows before the row at <code>index</code>.
-	 * 
-	 * @param index
-	 *            is the index of the row to insert before.
-	 * @param rowCount
-	 *            is the number of rows to insert.
-	 * @return a list of new inserted rows
-	 */
-	public List<Row> insertRowsBefore(int index, int rowCount) {
-		if (index >= getRowCount()) {
-			throw new IndexOutOfBoundsException();
-		}
-		ArrayList<Row> list = new ArrayList<Row>();
-		if (index == 0) {
-			Row refRow = getRowByIndex(index);
-			Row positionRow = refRow;
-			// add first row
-			Row newFirstRow = insertRowBefore(refRow, positionRow, getColumnCount());
-			reviseStyleFromTopRowToMediumRow(refRow);
-			list.add(newFirstRow);
-			List<Row> rowList = insertMultipleRowsBefore(refRow, refRow, rowCount - 1);
-			for (int i = 0; i < rowList.size(); i++) {
-				list.add(rowList.get(i));
-			}
-			return list;
-		}
-
-		Row refRow = getRowByIndex(index - 1);
-		Row positionRow = getRowByIndex(index);
-		// 1. insert a <table:table-row>
-		if (refRow.getOdfElement() == positionRow.getOdfElement()) {
-			TableTableRowElement row = refRow.getOdfElement();
-			int repeatedCount = refRow.getRowsRepeatedNumber();
-			refRow.setRowsRepeatedNumber(repeatedCount + rowCount);
-			TableTableRowElement rowEle = positionRow.getOdfElement();
-			Row startRow = getRowInstance(positionRow.getOdfElement(), 0);
-			for (int i = repeatedCount + rowCount - 1; i >= rowCount + (index - startRow.getRowIndex()); i--) {
-				updateRowRepository(rowEle, i - rowCount, rowEle, i);
-			}
-			for (int i = 0; i < rowCount; i++) {
-				list.add(getRowInstance(row, refRow.mnRepeatedIndex + 1 + i));
-			}
-		} else {
-			List<Row> newRowList = insertMultipleRowsBefore(refRow, positionRow, rowCount);
-			if (index - 1 == 0) {
-				// correct styles
-				reviseStyleFromTopRowToMediumRow(newRowList.get(0));
-			}
-			for (int i = 0; i < newRowList.size(); i++) {
-				list.add(newRowList.get(i));
-			}
-		}
-
-		return list;
-	}
-
-	/**
-	 * Return a list of columns in the current table.
-	 * 
-	 * @return a list of table columns
-	 */
-	public List<Column> getColumnList() {
-		ArrayList<Column> list = new ArrayList<Column>();
-		TableTableColumnElement colEle = null;
-		for (Node n : new DomNodeList(mTableElement.getChildNodes())) {
-			if (n instanceof TableTableHeaderColumnsElement) {
-				TableTableHeaderColumnsElement headers = (TableTableHeaderColumnsElement) n;
-				for (Node m : new DomNodeList(headers.getChildNodes())) {
-					if (m instanceof TableTableColumnElement) {
-						colEle = (TableTableColumnElement) m;
-						int columnsRepeatedNumber = colEle.getTableNumberColumnsRepeatedAttribute();
-						for (int i = 0; i < columnsRepeatedNumber; i++) {
-							list.add(getColumnInstance(colEle, i));
-						}
-					}
-				}
-			}
-			if (n instanceof TableTableColumnElement) {
-				colEle = (TableTableColumnElement) n;
-				int columnsRepeatedNumber = colEle.getTableNumberColumnsRepeatedAttribute();

[... 4742 lines stripped ...]