/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 2008 jOpenDocument, by ILM Informatique. All rights reserved.
 * 
 * The contents of this file are subject to the terms of the GNU
 * General Public License Version 3 only ("GPL").  
 * You may not use this file except in compliance with the License. 
 * You can obtain a copy of the License at http://www.gnu.org/licenses/gpl-3.0.html
 * See the License for the specific language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each file.
 * 
 */

package org.jopendocument.dom.spreadsheet;

import static java.util.Arrays.asList;
import org.jopendocument.dom.ODPackage;
import org.jopendocument.dom.ODSingleXMLDocument;
import org.jopendocument.dom.XMLVersion;
import org.jopendocument.dom.spreadsheet.CellStyle.Side;
import org.jopendocument.dom.spreadsheet.SheetTableModel.MutableTableModel;
import org.jopendocument.dom.text.Paragraph;
import org.jopendocument.dom.text.ParagraphStyle;
import org.jopendocument.util.Tuple2;

import java.awt.Color;
import java.awt.Point;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.Map;

import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

import junit.framework.TestCase;

import org.jdom.Element;

public class SheetTest extends TestCase {

    static final DefaultTableModel tm;
    static {
        tm = new DefaultTableModel();
        tm.addColumn("col1");
        tm.addColumn("col2");
        tm.addColumn("col3");

        // trailing 0 to test precision (i.e. not equals to -5.32)
        tm.addRow(new Object[] { "un1", new BigDecimal("-5.320"), new Integer(123) });
    }

    private Sheet sheet;
    private Sheet realSheet;

    protected void setUp() throws Exception {
        this.sheet = SpreadSheet.createEmpty(tm, XMLVersion.getOOo()).getSheet(0);
        this.realSheet = SpreadSheet.create(new ODPackage(this.getClass().getResourceAsStream("test.ods"))).getSheet(0);
    }

    protected void tearDown() throws Exception {
        this.sheet = null;
        this.realSheet = null;
    }

    public void testCreate() throws IOException {
        // save
        final TableModel model = new DefaultTableModel(new Object[][] { { "Data", "DataCol2" } }, new Object[] { "Col1", "Col2" });
        final SpreadSheet created = SpreadSheet.createEmpty(model);
        assertValid(created);

        final File saved = created.saveAs(File.createTempFile("testCreate", null));
        saved.deleteOnExit();
        // then read
        final Sheet sheetRead = SpreadSheet.createFromFile(saved).getSheet(0);
        // and check that the data is correct
        assertEquals(2, sheetRead.getRowCount());
        assertEquals("Col1", sheetRead.getValueAt("A1"));
        // data w/o column names
        final SheetTableModel<SpreadSheet> tmRead = sheetRead.getTableModel(0, 1);
        assertEquals(2, tmRead.getColumnCount());
        assertEquals(1, tmRead.getRowCount());
        assertEquals("DataCol2", tmRead.getValueAt(0, 1));
    }

    public void testName() throws Exception {
        final String n = "users";
        final SpreadSheet realSpread = this.realSheet.getSpreadSheet();
        assertEquals(n, realSpread.getSheet(n).getName());

        // the sheet can be accessed with a changed name
        final String newName = "newName";
        assertFalse(newName.equals(this.realSheet.getName()));
        this.realSheet.setName(newName);
        assertTrue(newName.equals(this.realSheet.getName()));
        assertSame(this.realSheet, realSpread.getSheet(newName));

        // test add

        assertEquals(2, realSpread.getSheetCount());
        final Sheet sheet0 = realSpread.getSheet(0);
        final Sheet sheet1 = realSpread.getSheet(1);
        // add at the end since we used to have a bug that added table:table at the very end of
        // body, e.g. after table:named-expressions.
        final Sheet addSheet = realSpread.addSheet(2, "newSheet");
        assertEquals(3, realSpread.getSheetCount());
        assertSame(addSheet, realSpread.getSheet("newSheet"));
        assertSame(sheet0, realSpread.getSheet(0));
        assertSame(sheet1, realSpread.getSheet(1));
        assertSame(addSheet, realSpread.getSheet(2));

        assertValid(this.realSheet.getSpreadSheet());

        // test move
        addSheet.move(0);
        assertEquals(3, realSpread.getSheetCount());
        assertSame(addSheet, realSpread.getSheet("newSheet"));
        assertSame(addSheet, realSpread.getSheet(0));
        assertSame(sheet0, realSpread.getSheet(1));
        assertSame(sheet1, realSpread.getSheet(2));

        assertValid(this.realSheet.getSpreadSheet());

        // test copy
        final Sheet copiedSheet = addSheet.copy(2, "copiedSheet");
        assertEquals(4, realSpread.getSheetCount());
        assertSame(copiedSheet, realSpread.getSheet("copiedSheet"));
        assertSame(addSheet, realSpread.getSheet(0));
        assertSame(sheet0, realSpread.getSheet(1));
        assertSame(copiedSheet, realSpread.getSheet(2));
        assertSame(sheet1, realSpread.getSheet(3));

        assertValid(this.realSheet.getSpreadSheet());

        // test rm
        final int count = realSpread.getSheetCount();
        assertSame(sheet0, this.realSheet);
        this.realSheet.detach();
        assertNull(realSpread.getSheet(this.realSheet.getName()));
        assertEquals(count - 1, realSpread.getSheetCount());
        assertSame(addSheet, realSpread.getSheet(0));
        assertSame(copiedSheet, realSpread.getSheet(1));
        assertSame(sheet1, realSpread.getSheet(2));

        assertValid(this.realSheet.getSpreadSheet());
    }

    /*
     * Test method for 'org.jopendocument.dom.spreadsheet.Sheet.setValueAt(Object, int, int)'
     */
    public void testSetValueAt() throws Exception {
        assertEquals("col1", this.sheet.getValueAt(0, 0));
        this.sheet.setValueAt("test", 0, 0);
        assertEquals("test", this.sheet.getValueAt(0, 0));

        this.sheet.setValueAt(60001399.1523, 0, 0);
        assertEquals(new BigDecimal("60001399.1523"), this.sheet.getValueAt(0, 0));

        final Calendar now = Calendar.getInstance();
        this.sheet.setValueAt(now.getTime(), 0, 0);
        final Object valueAt = this.sheet.getValueAt(0, 0);
        // OpenDocument can encode time up to the ms
        assertEquals(now.getTime(), valueAt);
        assertValid(this.sheet.getSpreadSheet());

        try {
            this.realSheet.getCellAt("C3");
            fail("should have failed since C3 is covered");
        } catch (IllegalArgumentException e) {
            // ok
        }
        this.realSheet.getCellAt("B3").unmerge();
        // should now succeed
        this.realSheet.getCellAt("C3").setValue(new Date());

        // preserve style
        {
            // test with odt (it has always worked in ods since text:p cannot have style, it is on
            // the cell)
            final ODSingleXMLDocument doc = new ODPackage(this.getClass().getResourceAsStream("../test.odt")).toSingle();
            final Table<ODSingleXMLDocument> t = new Table<ODSingleXMLDocument>(doc, doc.getDescendantByName("table:table", "JODTestTable"));
            final MutableCell<ODSingleXMLDocument> cell = t.getCellAt(2, 1);
            assertEquals("end", getFirstPStyle(cell).getAlignment());
            cell.setValue("somethingElse");
            assertEquals("end", getFirstPStyle(cell).getAlignment());
        }

        assertValid(this.realSheet.getSpreadSheet());
    }

    private final ParagraphStyle getFirstPStyle(final Cell<ODSingleXMLDocument> cell) {
        final Paragraph p = new Paragraph(cell.getElement().getChild("p", cell.getNS().getTEXT()));
        p.setDocument(cell.getODDocument());
        return p.getStyle();
    }

    /*
     * Test method for 'org.jopendocument.dom.spreadsheet.Sheet.getValueAt(int, int)'
     */
    public void testGetValueAt() {
        assertEquals(new BigDecimal(123), this.sheet.getValueAt(2, 1));
        // testGetValueAtString()
        assertEquals(new BigDecimal(123), this.sheet.getValueAt("C2"));

        final Calendar c = Calendar.getInstance();
        c.clear();
        c.set(2008, 11, 25);
        final Cell<SpreadSheet> dateCell = this.realSheet.getImmutableCellAt("F3");
        assertEquals(c.getTime(), dateCell.getValue());
        assertEquals("25 déc. 2008", dateCell.getTextValue());

        final Cell textCell = this.realSheet.getImmutableCellAt("B3");
        assertEquals("Gestion\tdes droits\nnouvelle  arborescence ", textCell.getValue());
        assertEquals("Gestion\tdes droits\nnouvelle  arborescence ", textCell.getTextValue(true));
        // test std mode
        // <cell>
        // <text:p>
        // Paragraph
        // </text:p>
        // </cell>
        textCell.getElement().removeContent();
        final Element p = new Element("p", textCell.getElement().getNamespace("text"));
        p.addContent("\n\t\tGestion \t des droits");
        textCell.getElement().addContent("\n\t").addContent(p).addContent("\n");
        assertEquals("Gestion des droits", textCell.getTextValue(false));

        assertSame(this.realSheet.getCellAt("F3"), this.realSheet.getSpreadSheet().getCellAt(this.realSheet.getName() + ".$F$3"));
    }

    /*
     * Test method for 'org.jopendocument.dom.spreadsheet.Sheet.getRowCount()'
     */
    public void testGetCount() {
        // col labels + 1 row
        assertEquals(2, this.sheet.getRowCount());
        assertEquals(3, this.sheet.getColumnCount());
    }

    /*
     * Test method for 'org.jopendocument.dom.spreadsheet.Sheet.ensureColumnCount(int)'
     */
    public void testEnsureColumnCount() {
        final int before = this.sheet.getColumnCount();
        final int newSize = before - 2;
        this.sheet.ensureColumnCount(newSize);
        assertEquals(before, this.sheet.getColumnCount());
    }

    public void testSetColumnCount() throws Exception {
        // test in-memory
        final int newSize = this.sheet.getColumnCount() + 5;
        try {
            this.sheet.setValueAt("test", newSize - 1, 0);
            fail("should have thrown IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException exn) {
            // normal
        }
        this.sheet.setColumnCount(newSize);
        this.sheet.setValueAt("test", newSize - 1, 0);

        // test with real file
        final int origCount = this.realSheet.getColumnCount();
        try {
            this.realSheet.setValueAt("over", origCount + 10 - 1, 1);
            fail("should throw exn since we try to write past the limit");
        } catch (RuntimeException e) {
            // ok
        }
        this.realSheet.setColumnCount(origCount + 10);
        this.realSheet.setValueAt("over", origCount + 10 - 1, 1);
        final ByteArrayOutputStream out = new ByteArrayOutputStream(1024 * 15);
        this.realSheet.getSpreadSheet().getPackage().save(out);
        final SpreadSheet reRead = SpreadSheet.create(new ODPackage(new ByteArrayInputStream(out.toByteArray())));
        assertEquals("over", reRead.getSheet(0).getValueAt(origCount + 10 - 1, 1));

        assertValid(this.realSheet.getSpreadSheet());
    }

    public void testRemoveCol() throws Exception {
        this.realSheet.setColumnCount(9, -1, true);
        assertEquals(9, this.realSheet.getColumnCount());
        assertFalse(this.realSheet.getImmutableCellAt("C3").isValid());
        this.realSheet.removeColumn(1, true);
        assertEquals(8, this.realSheet.getColumnCount());
        // B3 was covering C3, but since the B column is gone C3 is incovered
        assertTrue(this.realSheet.getImmutableCellAt("C3").isValid());

        final ODSingleXMLDocument doc = new ODPackage(this.getClass().getResourceAsStream("../test.odt")).toSingle();
        final Table<ODSingleXMLDocument> t = new Table<ODSingleXMLDocument>(doc, doc.getDescendantByName("table:table", "JODTestTable"));
        final float colW = t.getColumn(1).getWidth();
        float tableW = t.getWidth();
        t.removeColumn(1, false);
        // normal float error
        assertTrue(Math.abs(tableW - colW - t.getWidth()) <= Math.ulp(t.getWidth()));

        tableW = t.getWidth();
        t.removeColumn(1, true);
        assertEquals(tableW, t.getWidth());
    }

    public void testSetRowCount() throws IOException {
        this.realSheet.setRowCount(3);
        final SpreadSheet reParsed = new SpreadSheet(this.realSheet.getODDocument().getContent(), null);
        assertEquals(3, reParsed.getSheet(0).getRowCount());
        assertValid(this.realSheet.getSpreadSheet());
    }

    /*
     * Test method for 'org.jopendocument.dom.spreadsheet.Sheet.getTableModel(int, int)'
     */
    public void testGetTableModel() {
        SheetTableModel<SpreadSheet> t = this.sheet.getTableModel(1, 0);
        assertEquals(tm.getColumnCount() - 1, t.getColumnCount());
        // +1: col labels
        assertEquals(tm.getRowCount() + 1, t.getRowCount());
        assertEquals(new BigDecimal("-5.320"), t.getValueAt(1, 0));

        // empty hence no style
        assertNull(t.getImmutableCellAt(0, 0).getStyle());
        try {
            t.getValueAt(1, t.getColumnCount());
            fail("should have thrown exn");
        } catch (IndexOutOfBoundsException e) {
            // ok
        }
    }

    /*
     * Test method for 'org.jopendocument.dom.spreadsheet.Sheet.getMutableTableModel(int, int)'
     */
    public void testGetMutableTableModel() {
        this.sheet.getMutableTableModel(1, 0).setValueAt("test", 0, 1);
        assertEquals("test", this.sheet.getCellAt("C1").getValue());

        final MutableTableModel<SpreadSheet> tm = this.realSheet.getSpreadSheet().getTableModel("rights");
        assertEquals("K1", tm.getValueAt(13, 6));

        assertEquals(Color.CYAN, tm.getCellAt(0, 0).getStyle().getBackgroundColor());
        assertEquals("#ffcc99", tm.getCellAt(1, 2).getStyle().getTableCellProperties().getRawBackgroundColor());

        try {
            tm.setValueAt("foo", 0, tm.getColumnCount());
            fail("should have thrown exn");
        } catch (IndexOutOfBoundsException e) {
            // ok
        }
    }

    public void testMerge() throws IOException {
        final MutableCell<SpreadSheet> b3 = this.realSheet.getCellAt("B3");
        assertEquals(2, b3.getColumnsSpanned());
        assertEquals(1, b3.getRowsSpanned());

        b3.unmerge();
        assertEquals(1, b3.getColumnsSpanned());
        assertEquals(1, b3.getRowsSpanned());
        assertTrue(this.realSheet.getImmutableCellAt("C3").isValid());
        assertTrue(this.realSheet.getImmutableCellAt("B4").isValid());

        b3.merge(3, 2);
        assertEquals(3, b3.getColumnsSpanned());
        assertEquals(2, b3.getRowsSpanned());
        assertTrue(b3.isValid());
        assertFalse(this.realSheet.getImmutableCellAt("C3").isValid());
        assertFalse(this.realSheet.getImmutableCellAt("B4").isValid());
        // we cannot have overlapping merge since we cannot get to a covered cell
        try {
            this.realSheet.getCellAt("C3");
            fail("should have thrown an exn");
        } catch (Exception e) {
            // ok : we can't modify a covered cell
        }

        // merge more
        b3.merge(3, 3);
        assertEquals(3, b3.getColumnsSpanned());
        assertEquals(3, b3.getRowsSpanned());

        // if we call merge() with less cells it un-merge the rest
        b3.merge(1, 3);
        assertEquals(1, b3.getColumnsSpanned());
        assertEquals(3, b3.getRowsSpanned());
        assertTrue(b3.isValid());
        assertTrue(this.realSheet.getImmutableCellAt("C3").isValid());
        assertFalse(this.realSheet.getImmutableCellAt("B4").isValid());

        try {
            this.realSheet.getCellAt(0, 0).merge(2, 4);
            fail("Allowed overlapping merge");
        } catch (Exception e) {
            // ok
        }
        // the document was unchanged by the failed attempt
        assertFalse(this.realSheet.getImmutableCellAt(0, 0).coversOtherCells());
        assertTrue(this.realSheet.getImmutableCellAt(0, 1).isValid());
        assertValid(this.realSheet.getSpreadSheet());
    }

    public void testResolve() {
        assertEquals(new Point(0, 22), Sheet.resolve("A23"));
        assertEquals(new Point(26, 33), Sheet.resolve("AA34"));
        assertNull(Sheet.resolve("A23A"));
        assertNull(Sheet.resolve("test"));
        assertNull(Sheet.resolve("23"));

        assertEquals(77, Sheet.toInt("BZ"));
    }

    public void testDuplicateRows() throws Exception {
        this.realSheet.duplicateRows(8, 3, 2);
        assertEquals(this.realSheet.getValueAt("B11"), this.realSheet.getValueAt("B14"));
        assertEquals("Comptabilité", this.realSheet.getValueAt("H9"));
        // two copies
        assertEquals(this.realSheet.getValueAt("H9"), this.realSheet.getValueAt("H12"));
        assertEquals(this.realSheet.getValueAt("H9"), this.realSheet.getValueAt("H15"));

        assertValid(this.realSheet.getSpreadSheet());

        assertEquals(2, this.sheet.getRowCount());
        // test cloning of last row
        this.sheet.duplicateRows(1, 1, 3);
        assertEquals(5, this.sheet.getRowCount());
        assertEquals(this.sheet.getValueAt("C2"), this.sheet.getValueAt("C4"));
    }

    public void testXY() throws Exception {
        final int y = 35;
        {
            final MutableCell c = this.realSheet.getCellAt(2, y);
            assertEquals("LECTURE SEULE", c.getValue());
            assertEquals(2, c.getX());
            assertEquals(y, c.getY());
        }
        // offset by 6
        this.realSheet.duplicateRows(8, 3, 2);

        {
            final MutableCell c = this.realSheet.getCellAt(2, y + 6);
            assertEquals("LECTURE SEULE", c.getValue());
            assertEquals(2, c.getX());
            assertEquals(y + 6, c.getY());
        }
    }

    public void testStyle() throws Exception {
        // even though the style-name is null
        assertNull(this.realSheet.getImmutableCellAt(2, 10).getStyleAttr());
        final String style = this.realSheet.getStyleNameAt(2, 10);
        assertNotNull(style);
        // the correct style can still be found
        assertEquals(Color.CYAN, this.realSheet.getCellAt(2, 10).getStyle().getBackgroundColor());
        // also from MutableCell
        assertEquals(style, this.realSheet.getCellAt(2, 10).getStyleName());

        // ATTN getStyle().getReferences() is low-level so if the style of a cell is not directly
        // referenced (i.e. it uses the default for its row/column) it won't get found
        final MutableCell<SpreadSheet> cellAt00 = this.realSheet.getCellAt(0, 0);
        assertNull(cellAt00.getStyleAttr());
        assertFalse(cellAt00.getStyle().getReferences().contains(cellAt00.getElement()));
        // unless getStyleReferences() is used
        assertTrue(this.realSheet.getStyleReferences(this.realSheet.getStyleNameAt(0, 0)).contains(Tuple2.create(0, 0)));

        {
            final CellStyle centeredInBold = this.realSheet.getCellAt("B9").getStyle();
            assertTrue(centeredInBold.getReferences().contains(this.realSheet.getCellAt("B9").getElement()));

            assertEquals("center", centeredInBold.getParagraphProperties().getAlignment());
            assertEquals("bold", centeredInBold.getTextProperties().getWeight());
            assertEquals("0.002cm solid #000000", centeredInBold.getTableCellProperties().getBorder(Side.LEFT));
            assertEquals(null, centeredInBold.getTableCellProperties().getBorderLineWidth(Side.LEFT));
            assertEquals(0, centeredInBold.getTableCellProperties().getRotationAngle());
            assertEquals(true, centeredInBold.getTableCellProperties().isContentPrinted());
            assertEquals(false, centeredInBold.getTableCellProperties().isContentRepeated());
            assertEquals(false, centeredInBold.getTableCellProperties().isShrinkToFit());
        }
        {
            final CellStyle notPrinted = this.realSheet.getCellAt("B6").getStyle();
            assertTrue(notPrinted.getReferences().contains(this.realSheet.getCellAt("B6").getElement()));

            assertEquals("start", notPrinted.getParagraphProperties().getAlignment());
            assertEquals(null, notPrinted.getTextProperties().getWeight());
            assertEquals("0.105cm double #000080", notPrinted.getTableCellProperties().getBorder(Side.RIGHT));
            assertEquals("none", notPrinted.getTableCellProperties().getBorder(Side.TOP));
            assertEquals(asList("0.035cm", "0.035cm", "0.035cm"), asList(notPrinted.getTableCellProperties().getBorderLineWidth(Side.RIGHT)));
            assertEquals(333, notPrinted.getTableCellProperties().getRotationAngle());
            assertEquals(false, notPrinted.getTableCellProperties().isContentPrinted());
            assertEquals(false, notPrinted.getTableCellProperties().isContentRepeated());
            assertEquals(true, notPrinted.getTableCellProperties().isShrinkToFit());
        }
        // assert that we don't crash if we ask for an attribute whose namespace is not in our
        // element (here "fo")
        assertNull(CellStyle.DESC.createAutoStyle(this.sheet.getSpreadSheet().getPackage()).getBackgroundColor());

        // column styles
        assertEquals(54.38f, this.realSheet.getColumn(1).getWidth());
        final SpreadSheet sxc = SpreadSheet.create(new ODPackage(this.getClass().getResourceAsStream("test.sxc")));
        assertEquals(33.85f, sxc.getSheet(0).getColumn(1).getWidth());

        // change style
        {
            final Column<SpreadSheet> col1 = this.realSheet.getColumn(9);
            final Column<SpreadSheet> col2 = this.realSheet.getColumn(10);
            // even with shared style
            assertEquals(col1.getStyle().getName(), col2.getStyle().getName());
            assertNotNull(col1.getStyle().getBreakBefore());
            final float initialWidth = col2.getWidth();
            // if we change the width of col1
            col1.setWidth(initialWidth + 15);
            // it only change that
            assertEquals(initialWidth + 15, col1.getWidth());
            assertEquals(initialWidth, col2.getWidth());
            // and nothing else
            assertEquals(col2.getStyle().getBreakBefore(), col1.getStyle().getBreakBefore());

            // new style is only created if needed
            final String newName = col1.getStyle().getName();
            assertFalse(newName.equals(col2.getStyle().getName()));
            col1.setWidth(initialWidth + 17);
            assertEquals(newName, col1.getStyle().getName());
        }
        // change shared style referenced by one XML element
        {
            // both cells have the same style
            assertEquals("Default", this.sheet.getStyleNameAt(0, 0));
            assertEquals("Default", this.sheet.getStyleNameAt(0, 1));

            // create a new cell style and set it as the default for the first column
            final CellStyle cellStyle = CellStyle.DESC.createAutoStyle(this.sheet.getSpreadSheet().getPackage(), "defaultCell");
            final Element col0Elem = this.sheet.getColumn(0).getElement();
            col0Elem.setAttribute("default-cell-style-name", cellStyle.getName(), col0Elem.getNamespace());
            // both cells have thus the new style
            assertEquals(cellStyle.getName(), this.sheet.getStyleNameAt(0, 0));
            assertEquals(cellStyle.getName(), this.sheet.getStyleNameAt(0, 1));
            // although the style is only referenced by the column
            assertEquals(Collections.singletonList(col0Elem), cellStyle.getReferences());

            // changing the background of the first cell from nothing to CYAN
            assertNull(cellStyle.getBackgroundColor());
            this.sheet.getCellAt(0, 0).setBackgroundColor(Color.CYAN);
            // imply that the first cell changes style
            final CellStyle newStyle = this.sheet.getStyleAt(0, 0);
            assertFalse(cellStyle.getName().equals(newStyle.getName()));
            // but not the second one
            assertEquals(cellStyle.getName(), this.sheet.getStyleNameAt(0, 1));
            // the first cell has indeed changed colour
            assertEquals(Color.CYAN, newStyle.getTableCellProperties().getBackgroundColor());
            // but not the second one
            assertNull(this.sheet.getStyleAt(0, 1).getBackgroundColor());

            // changing a second time doesn't create a new style
            this.sheet.getCellAt(0, 0).setBackgroundColor(Color.YELLOW);
            assertEquals(newStyle.getName(), this.sheet.getStyleNameAt(0, 0));
        }

        assertValid(this.sheet.getSpreadSheet());
        assertValid(this.realSheet.getSpreadSheet());
    }

    private void assertValid(SpreadSheet ssheet) {
        final Map<String, String> areSubDocumentsValid = ssheet.getPackage().validateSubDocuments();
        assertTrue(areSubDocumentsValid + "", areSubDocumentsValid.isEmpty());
    }
}
