fix 47563 - Exception when working with table

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1143802 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Sergey Vladimirov 2011-07-07 12:52:57 +00:00
parent 299da44a4d
commit 7edecc34bf
5 changed files with 228 additions and 135 deletions

View File

@ -34,6 +34,7 @@
<changes>
<release version="3.8-beta4" date="2011-??-??">
<action dev="poi-developers" type="fix">47563 - Exception when working with table</action>
<action dev="poi-developers" type="fix">47287 - StringIndexOutOfBoundsException in CharacterRun.replaceText()</action>
<action dev="poi-developers" type="fix">46817 - Regression: Text from some table cells missing</action>
<action dev="poi-developers" type="add">Add getOverallRange() method to HWPFDocumentCore</action>

View File

@ -1046,7 +1046,7 @@ public class Range { // TODO -instantiable superclass
/**
* resets the list indexes.
*/
private void reset() {
protected void reset() {
_textRangeFound = false;
_charRangeFound = false;
_parRangeFound = false;
@ -1141,4 +1141,38 @@ public class Range { // TODO -instantiable superclass
return "Range from " + getStartOffset() + " to " + getEndOffset()
+ " (chars)";
}
/**
* Method for debug purposes. Checks that all resolved elements are inside
* of current range.
*/
public void sanityCheck()
{
if ( _charRangeFound )
{
for ( int c = _charStart; c < _charEnd; c++ )
{
CHPX chpx = _characters.get( c );
int left = Math.max( this._start, chpx.getStart() );
int right = Math.min( this._end, chpx.getEnd() );
if ( left >= right )
throw new AssertionError();
}
}
if ( _parRangeFound )
{
for ( int p = _parStart; p < _parEnd; p++ )
{
PAPX papx = _paragraphs.get( p );
int left = Math.max( this._start, papx.getStart() );
int right = Math.min( this._end, papx.getEnd() );
if ( left >= right )
throw new AssertionError();
}
}
}
}

View File

@ -23,32 +23,21 @@ public final class Table extends Range
{
private ArrayList<TableRow> _rows;
private boolean _rowsFound = false;
private int _tableLevel;
Table( int startIdxInclusive, int endIdxExclusive, Range parent, int levelNum )
Table( int startIdxInclusive, int endIdxExclusive, Range parent,
int levelNum )
{
super( startIdxInclusive, endIdxExclusive, Range.TYPE_PARAGRAPH, parent );
_rows = new ArrayList<TableRow>();
_tableLevel = levelNum;
int rowStart = 0;
int rowEnd = 0;
int numParagraphs = numParagraphs();
while ( rowEnd < numParagraphs )
{
Paragraph p = getParagraph( rowEnd );
rowEnd++;
if ( p.isTableRowEnd() && p.getTableLevel() == levelNum )
{
_rows.add( new TableRow( rowStart, rowEnd, this, levelNum ) );
rowStart = rowEnd;
}
}
initRows();
}
public TableRow getRow( int index )
{
initRows();
return _rows.get( index );
}
@ -57,11 +46,41 @@ public final class Table extends Range
return _tableLevel;
}
private void initRows()
{
if ( _rowsFound )
return;
_rows = new ArrayList<TableRow>();
int rowStart = 0;
int rowEnd = 0;
int numParagraphs = numParagraphs();
while ( rowEnd < numParagraphs )
{
Paragraph p = getParagraph( rowEnd );
rowEnd++;
if ( p.isTableRowEnd() && p.getTableLevel() == _tableLevel )
{
_rows.add( new TableRow( rowStart, rowEnd, this, _tableLevel ) );
rowStart = rowEnd;
}
}
_rowsFound = true;
}
public int numRows()
{
initRows();
return _rows.size();
}
@Override
protected void reset()
{
_rowsFound = false;
}
public int type()
{
return TYPE_TABLE;

View File

@ -26,20 +26,22 @@ import org.apache.poi.util.POILogger;
public final class TableRow extends Paragraph
{
private final static char TABLE_CELL_MARK = '\u0007';
private final static short SPRM_TJC = 0x5400;
private final static short SPRM_DXAGAPHALF = (short) 0x9602;
private final static short SPRM_FCANTSPLIT = 0x3403;
private final static short SPRM_FTABLEHEADER = 0x3404;
private final static short SPRM_DYAROWHEIGHT = (short) 0x9407;
private static final POILogger logger = POILogFactory
.getLogger( TableRow.class );
private final static short SPRM_DXAGAPHALF = (short) 0x9602;
private final static short SPRM_DYAROWHEIGHT = (short) 0x9407;
private final static short SPRM_FCANTSPLIT = 0x3403;
private final static short SPRM_FTABLEHEADER = 0x3404;
private final static short SPRM_TJC = 0x5400;
private final static char TABLE_CELL_MARK = '\u0007';
private TableCell[] _cells;
private boolean _cellsFound = false;
int _levelNum;
private TableProperties _tprops;
private TableCell[] _cells;
public TableRow( int startIdxInclusive, int endIdxExclusive, Table parent,
int levelNum )
@ -48,19 +50,88 @@ public final class TableRow extends Paragraph
_tprops = TableSprmUncompressor.uncompressTAP( _papx.toByteArray(), 2 );
_levelNum = levelNum;
initCells();
}
public boolean cantSplit()
{
return _tprops.getFCantSplit();
}
public BorderCode getBarBorder()
{
throw new UnsupportedOperationException( "not applicable for TableRow" );
}
public BorderCode getBottomBorder()
{
return _tprops.getBrcBottom();
}
public TableCell getCell( int index )
{
initCells();
return _cells[index];
}
public int getGapHalf()
{
return _tprops.getDxaGapHalf();
}
public BorderCode getHorizontalBorder()
{
return _tprops.getBrcHorizontal();
}
public BorderCode getLeftBorder()
{
return _tprops.getBrcLeft();
}
public BorderCode getRightBorder()
{
return _tprops.getBrcRight();
}
public int getRowHeight()
{
return _tprops.getDyaRowHeight();
}
public int getRowJustification()
{
return _tprops.getJc();
}
public BorderCode getTopBorder()
{
return _tprops.getBrcBottom();
}
public BorderCode getVerticalBorder()
{
return _tprops.getBrcVertical();
}
private void initCells()
{
if ( _cellsFound )
return;
final short expectedCellsCount = _tprops.getItcMac();
int lastCellStart = 0;
List<TableCell> cells = new ArrayList<TableCell>(
expectedCellsCount + 1 );
for ( int p = 0; p < ( endIdxExclusive - startIdxInclusive ); p++ )
for ( int p = 0; p < numParagraphs(); p++ )
{
Paragraph paragraph = getParagraph( p );
String s = paragraph.text();
if ( ( ( s.length() > 0 && s.charAt( s.length() - 1 ) == TABLE_CELL_MARK ) || paragraph
.isEmbeddedCellMark() )
&& paragraph.getTableLevel() == levelNum )
&& paragraph.getTableLevel() == _levelNum )
{
TableCellDescriptor tableCellDescriptor = _tprops.getRgtc() != null
&& _tprops.getRgtc().length > cells.size() ? _tprops
@ -73,14 +144,14 @@ public final class TableRow extends Paragraph
.getRgdxaCenter()[cells.size() + 1] : 0;
TableCell tableCell = new TableCell( lastCellStart, p + 1,
this, levelNum, tableCellDescriptor, leftEdge,
this, _levelNum, tableCellDescriptor, leftEdge,
rightEdge - leftEdge );
cells.add( tableCell );
lastCellStart = p + 1;
}
}
if ( lastCellStart < ( endIdxExclusive - startIdxInclusive - 1 ) )
if ( lastCellStart < ( numParagraphs() - 1 ) )
{
TableCellDescriptor tableCellDescriptor = _tprops.getRgtc() != null
&& _tprops.getRgtc().length > cells.size() ? _tprops
@ -93,9 +164,8 @@ public final class TableRow extends Paragraph
.getRgdxaCenter()[cells.size() + 1] : 0;
TableCell tableCell = new TableCell( lastCellStart,
( endIdxExclusive - startIdxInclusive - 1 ), this,
levelNum, tableCellDescriptor, leftEdge, rightEdge
- leftEdge );
( numParagraphs() - 1 ), this, _levelNum,
tableCellDescriptor, leftEdge, rightEdge - leftEdge );
cells.add( tableCell );
}
@ -119,44 +189,24 @@ public final class TableRow extends Paragraph
}
_cells = cells.toArray( new TableCell[cells.size()] );
_cellsFound = true;
}
public int getRowJustification()
public boolean isTableHeader()
{
return _tprops.getJc();
return _tprops.getFTableHeader();
}
public void setRowJustification( int jc )
public int numCells()
{
_tprops.setJc( (short) jc );
_papx.updateSprm( SPRM_TJC, (short) jc );
initCells();
return _cells.length;
}
public int getGapHalf()
@Override
protected void reset()
{
return _tprops.getDxaGapHalf();
}
public void setGapHalf( int dxaGapHalf )
{
_tprops.setDxaGapHalf( dxaGapHalf );
_papx.updateSprm( SPRM_DXAGAPHALF, (short) dxaGapHalf );
}
public int getRowHeight()
{
return _tprops.getDyaRowHeight();
}
public void setRowHeight( int dyaRowHeight )
{
_tprops.setDyaRowHeight( dyaRowHeight );
_papx.updateSprm( SPRM_DYAROWHEIGHT, (short) dyaRowHeight );
}
public boolean cantSplit()
{
return _tprops.getFCantSplit();
_cellsFound = false;
}
public void setCantSplit( boolean cantSplit )
@ -165,9 +215,22 @@ public final class TableRow extends Paragraph
_papx.updateSprm( SPRM_FCANTSPLIT, (byte) ( cantSplit ? 1 : 0 ) );
}
public boolean isTableHeader()
public void setGapHalf( int dxaGapHalf )
{
return _tprops.getFTableHeader();
_tprops.setDxaGapHalf( dxaGapHalf );
_papx.updateSprm( SPRM_DXAGAPHALF, (short) dxaGapHalf );
}
public void setRowHeight( int dyaRowHeight )
{
_tprops.setDyaRowHeight( dyaRowHeight );
_papx.updateSprm( SPRM_DYAROWHEIGHT, (short) dyaRowHeight );
}
public void setRowJustification( int jc )
{
_tprops.setJc( (short) jc );
_papx.updateSprm( SPRM_TJC, (short) jc );
}
public void setTableHeader( boolean tableHeader )
@ -176,49 +239,4 @@ public final class TableRow extends Paragraph
_papx.updateSprm( SPRM_FTABLEHEADER, (byte) ( tableHeader ? 1 : 0 ) );
}
public int numCells()
{
return _cells.length;
}
public TableCell getCell( int index )
{
return _cells[index];
}
public BorderCode getTopBorder()
{
return _tprops.getBrcBottom();
}
public BorderCode getBottomBorder()
{
return _tprops.getBrcBottom();
}
public BorderCode getLeftBorder()
{
return _tprops.getBrcLeft();
}
public BorderCode getRightBorder()
{
return _tprops.getBrcRight();
}
public BorderCode getHorizontalBorder()
{
return _tprops.getBrcHorizontal();
}
public BorderCode getVerticalBorder()
{
return _tprops.getBrcVertical();
}
public BorderCode getBarBorder()
{
throw new UnsupportedOperationException( "not applicable for TableRow" );
}
}

View File

@ -599,42 +599,63 @@ public final class TestProblems extends HWPFTestCase {
assertFalse( docText.contains( "1-15" ) );
}
private static void insertTable(int rows, int columns) {
private static void insertTable( int rows, int columns )
{
// POI apparently can't create a document from scratch,
// so we need an existing empty dummy document
HWPFDocument doc = HWPFTestDataSamples.openSampleFile("empty.doc");
HWPFDocument doc = HWPFTestDataSamples.openSampleFile( "empty.doc" );
Range range = doc.getRange();
Table table = range.insertBefore(new TableProperties((short) columns), rows);
Table table = range.insertBefore(
new TableProperties( (short) columns ), rows );
table.sanityCheck();
range.sanityCheck();
for (int rowIdx = 0; rowIdx < table.numRows(); rowIdx++) {
TableRow row = table.getRow(rowIdx);
for (int colIdx = 0; colIdx < row.numCells(); colIdx++) {
TableCell cell = row.getCell(colIdx);
Paragraph par = cell.getParagraph(0);
par.insertBefore("" + (rowIdx * row.numCells() + colIdx));
for ( int rowIdx = 0; rowIdx < table.numRows(); rowIdx++ )
{
TableRow row = table.getRow( rowIdx );
row.sanityCheck();
for ( int colIdx = 0; colIdx < row.numCells(); colIdx++ )
{
TableCell cell = row.getCell( colIdx );
cell.sanityCheck();
Paragraph par = cell.getParagraph( 0 );
par.sanityCheck();
par.insertBefore( "" + ( rowIdx * row.numCells() + colIdx ) );
par.sanityCheck();
cell.sanityCheck();
row.sanityCheck();
table.sanityCheck();
range.sanityCheck();
}
}
String text = range.text();
int mustBeAfter = 0;
for ( int i = 0; i < rows * columns; i++ )
{
int next = text.indexOf( Integer.toString( i ), mustBeAfter );
assertFalse( next == -1 );
mustBeAfter = next;
}
}
/**
* [FAILING] Bug 47563 - HWPF failing while creating tables,
* [RESOLVED FIXED] Bug 47563 - Exception when working with table
*/
public void test47563() {
try {
insertTable(1, 5);
insertTable(1, 6);
insertTable(5, 1);
insertTable(6, 1);
insertTable(2, 2);
insertTable(3, 2);
insertTable(2, 3);
insertTable(3, 3);
fixed("47563");
} catch (Exception e) {
// expected exception
}
public void test47563()
{
insertTable( 1, 5 );
insertTable( 1, 6 );
insertTable( 5, 1 );
insertTable( 6, 1 );
insertTable( 2, 2 );
insertTable( 3, 2 );
insertTable( 2, 3 );
insertTable( 3, 3 );
}
/**