/*
* 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));
// assert that the new sheet is functional
addSheet.ensureRowCount(8);
// (was throwing a NPE in Table.updateWidth())
addSheet.ensureColumnCount(10);
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 8; j++) {
addSheet.setValueAt(i + "," + j, i, j);
}
}
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());
// assert that getPrivateStyle() works even w/o a style
final Table<?> addSheet = this.realSheet.getSpreadSheet().addSheet("testEmptyStyle");
assertNull(addSheet.getColumn(0).getStyle());
addSheet.getColumn(0).setWidth(20);
final ColumnStyle createdStyle = addSheet.getColumn(0).getStyle();
assertNotNull(createdStyle);
assertEquals(createdStyle.getName(), addSheet.getColumn(0).getPrivateStyle().getName());
assertEquals(20.0f, addSheet.getColumn(0).getWidth());
}
// 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());
}
}