Merged revisions 698039 via svnmerge from

https://svn.apache.org/repos/asf/poi/trunk

........
  r698039 | josh | 2008-09-22 16:43:50 -0700 (Mon, 22 Sep 2008) | 1 line
  
  Some clean-up in BoundSheetRecord
........


git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@698282 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2008-09-23 18:52:14 +00:00
parent 9ce7ae4a9f
commit 8433f6f7b3
6 changed files with 349 additions and 579 deletions

View File

@ -326,15 +326,14 @@ public final class Workbook implements Model {
int nBoundSheets = 1; // now just do 1 int nBoundSheets = 1; // now just do 1
for ( int k = 0; k < nBoundSheets; k++ ) { for ( int k = 0; k < nBoundSheets; k++ ) {
BoundSheetRecord bsr = BoundSheetRecord bsr = retval.createBoundSheet(k);
(BoundSheetRecord) retval.createBoundSheet( k );
records.add( bsr ); records.add(bsr);
retval.boundsheets.add( bsr ); retval.boundsheets.add(bsr);
retval.records.setBspos( records.size() - 1 ); retval.records.setBspos(records.size() - 1);
} }
// retval.records.supbookpos = retval.records.bspos + 1; // retval.records.supbookpos = retval.records.bspos + 1;
// retval.records.namepos = retval.records.supbookpos + 2; // retval.records.namepos = retval.records.supbookpos + 2;
records.add( retval.createCountry() ); records.add( retval.createCountry() );
for ( int k = 0; k < nBoundSheets; k++ ) { for ( int k = 0; k < nBoundSheets; k++ ) {
retval.getOrCreateLinkTable().checkExternSheet(k); retval.getOrCreateLinkTable().checkExternSheet(k);
@ -498,7 +497,6 @@ public final class Workbook implements Model {
checkSheets(sheetnum); checkSheets(sheetnum);
BoundSheetRecord sheet = (BoundSheetRecord)boundsheets.get( sheetnum ); BoundSheetRecord sheet = (BoundSheetRecord)boundsheets.get( sheetnum );
sheet.setSheetname(sheetname); sheet.setSheetname(sheetname);
sheet.setSheetnameLength( (byte)sheetname.length() );
} }
/** /**
@ -518,22 +516,6 @@ public final class Workbook implements Model {
} }
return false; return false;
} }
/**
* sets the name for a given sheet forcing the encoding. This is STILL A BAD IDEA.
* Poi now automatically detects unicode
*
*@deprecated 3-Jan-06 Simply use setSheetNam e(int sheetnum, String sheetname)
* @param sheetnum the sheet number (0 based)
* @param sheetname the name for the sheet
*/
public void setSheetName(int sheetnum, String sheetname, short encoding ) {
checkSheets(sheetnum);
BoundSheetRecord sheet = getBoundSheetRec(sheetnum);
sheet.setSheetname(sheetname);
sheet.setSheetnameLength( (byte)sheetname.length() );
sheet.setCompressedUnicodeFlag( (byte)encoding );
}
/** /**
* sets the order of appearance for a given sheet. * sets the order of appearance for a given sheet.
@ -643,13 +625,12 @@ public final class Workbook implements Model {
* if we're trying to address one more sheet than we have, go ahead and add it! if we're * if we're trying to address one more sheet than we have, go ahead and add it! if we're
* trying to address >1 more than we have throw an exception! * trying to address >1 more than we have throw an exception!
*/ */
private void checkSheets(int sheetnum) { private void checkSheets(int sheetnum) {
if ((boundsheets.size()) <= sheetnum) { // if we're short one add another.. if ((boundsheets.size()) <= sheetnum) { // if we're short one add another..
if ((boundsheets.size() + 1) <= sheetnum) { if ((boundsheets.size() + 1) <= sheetnum) {
throw new RuntimeException("Sheet number out of bounds!"); throw new RuntimeException("Sheet number out of bounds!");
} }
BoundSheetRecord bsr = (BoundSheetRecord ) createBoundSheet(sheetnum); BoundSheetRecord bsr = createBoundSheet(sheetnum);
records.add(records.getBspos()+1, bsr); records.add(records.getBspos()+1, bsr);
records.setBspos( records.getBspos() + 1 ); records.setBspos( records.getBspos() + 1 );
@ -1860,37 +1841,8 @@ public final class Workbook implements Model {
* @see org.apache.poi.hssf.record.BoundSheetRecord * @see org.apache.poi.hssf.record.BoundSheetRecord
* @see org.apache.poi.hssf.record.Record * @see org.apache.poi.hssf.record.Record
*/ */
private static BoundSheetRecord createBoundSheet(int id) {
protected Record createBoundSheet(int id) { // 1,2,3 sheets return new BoundSheetRecord("Sheet" + (id+1));
BoundSheetRecord retval = new BoundSheetRecord();
switch (id) {
case 0 :
retval.setPositionOfBof(0x0); // should be set later
retval.setOptionFlags(( short ) 0);
retval.setSheetnameLength(( byte ) 0x6);
retval.setCompressedUnicodeFlag(( byte ) 0);
retval.setSheetname("Sheet1");
break;
case 1 :
retval.setPositionOfBof(0x0); // should be set later
retval.setOptionFlags(( short ) 0);
retval.setSheetnameLength(( byte ) 0x6);
retval.setCompressedUnicodeFlag(( byte ) 0);
retval.setSheetname("Sheet2");
break;
case 2 :
retval.setPositionOfBof(0x0); // should be set later
retval.setOptionFlags(( short ) 0);
retval.setSheetnameLength(( byte ) 0x6);
retval.setCompressedUnicodeFlag(( byte ) 0);
retval.setSheetname("Sheet3");
break;
}
return retval;
} }
/** /**

View File

@ -23,6 +23,7 @@ import java.util.List;
import org.apache.poi.util.BitField; import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.StringUtil; import org.apache.poi.util.StringUtil;
@ -37,327 +38,215 @@ import org.apache.poi.util.StringUtil;
* @version 2.0-pre * @version 2.0-pre
*/ */
public final class BoundSheetRecord extends Record { public final class BoundSheetRecord extends Record {
public final static short sid = 0x0085; public final static short sid = 0x0085;
private static final BitField hiddenFlag = BitFieldFactory.getInstance(0x01); private static final BitField hiddenFlag = BitFieldFactory.getInstance(0x01);
private static final BitField veryHiddenFlag = BitFieldFactory.getInstance(0x02); private static final BitField veryHiddenFlag = BitFieldFactory.getInstance(0x02);
private int field_1_position_of_BOF; private int field_1_position_of_BOF;
private short field_2_option_flags; private int field_2_option_flags;
private byte field_3_sheetname_length; private int field_4_isMultibyteUnicode;
private byte field_4_compressed_unicode_flag; // not documented private String field_5_sheetname;
private String field_5_sheetname;
public BoundSheetRecord() public BoundSheetRecord(String sheetname) {
{ field_2_option_flags = 0;
} setSheetname(sheetname);
}
/** /**
* Constructs a BoundSheetRecord and sets its fields appropriately * Constructs a BoundSheetRecord and sets its fields appropriately
* *
* @param in the RecordInputstream to read the record from * @param in the RecordInputstream to read the record from
*/ */
public BoundSheetRecord(RecordInputStream in) {
super(in);
}
public BoundSheetRecord( RecordInputStream in ) protected void validateSid(short id) {
{ if (id != sid) {
super( in ); throw new RecordFormatException("NOT A Bound Sheet RECORD");
} }
}
protected void validateSid( short id ) /**
{ * UTF8: sid + len + bof + flags + len(str) + unicode + str 2 + 2 + 4 + 2 +
if ( id != sid ) * 1 + 1 + len(str)
{ *
throw new RecordFormatException( "NOT A Bound Sheet RECORD" ); * UNICODE: sid + len + bof + flags + len(str) + unicode + str 2 + 2 + 4 + 2 +
} * 1 + 1 + 2 * len(str)
} *
*/
protected void fillFields(RecordInputStream in) {
field_1_position_of_BOF = in.readInt();
field_2_option_flags = in.readUShort();
int field_3_sheetname_length = in.readUByte();
field_4_isMultibyteUnicode = in.readByte();
/** if (isMultibyte()) {
* UTF8: field_5_sheetname = in.readUnicodeLEString(field_3_sheetname_length);
* sid + len + bof + flags + len(str) + unicode + str } else {
* 2 + 2 + 4 + 2 + 1 + 1 + len(str) field_5_sheetname = in.readCompressedUnicode(field_3_sheetname_length);
* }
* UNICODE: }
* sid + len + bof + flags + len(str) + unicode + str
* 2 + 2 + 4 + 2 + 1 + 1 + 2 * len(str)
*
*/
protected void fillFields( RecordInputStream in ) /**
{ * set the offset in bytes of the Beginning of File Marker within the HSSF
field_1_position_of_BOF = in.readInt(); // bof * Stream part of the POIFS file
field_2_option_flags = in.readShort(); // flags *
field_3_sheetname_length = in.readByte(); // len(str) * @param pos
field_4_compressed_unicode_flag = in.readByte(); // unicode * offset in bytes
*/
public void setPositionOfBof(int pos) {
field_1_position_of_BOF = pos;
}
int nameLength = LittleEndian.ubyteToInt( field_3_sheetname_length ); /**
if ( ( field_4_compressed_unicode_flag & 0x01 ) == 1 ) * Set the sheetname for this sheet. (this appears in the tabs at the bottom)
{ * @param sheetName the name of the sheet
field_5_sheetname = in.readUnicodeLEString(nameLength); * @throws IllegalArgumentException if sheet name will cause excel to crash.
} */
else public void setSheetname(String sheetName) {
{
field_5_sheetname = in.readCompressedUnicode(nameLength); validateSheetName(sheetName);
} field_5_sheetname = sheetName;
} field_4_isMultibyteUnicode = StringUtil.hasMultibyte(sheetName) ? 1 : 0;
}
/** private static void validateSheetName(String sheetName) {
* set the offset in bytes of the Beginning of File Marker within the HSSF Stream part of the POIFS file if (sheetName == null) {
* throw new IllegalArgumentException("sheetName must not be null");
* @param pos offset in bytes }
*/ int len = sheetName.length();
if (len < 1 || len > 31) {
throw new IllegalArgumentException("sheetName '" + sheetName
+ "' is invalid - must be 1-30 characters long");
}
for (int i=0; i<len; i++) {
char ch = sheetName.charAt(i);
switch (ch) {
case '/':
case '\\':
case '?':
case '*':
case ']':
case '[':
break;
default:
// all other chars OK
continue;
}
throw new IllegalArgumentException("Invalid char (" + ch
+ ") found at index (" + i + ") in sheet name '" + sheetName + "'");
}
}
public void setPositionOfBof( int pos ) /**
{ * get the offset in bytes of the Beginning of File Marker within the HSSF Stream part of the POIFS file
field_1_position_of_BOF = pos; *
} * @return offset in bytes
*/
public int getPositionOfBof() {
return field_1_position_of_BOF;
}
/** private boolean isMultibyte() {
* set the option flags (unimportant for HSSF supported sheets) return (field_4_isMultibyteUnicode & 0x01) != 0;
* }
* @param flags to set
*/
public void setOptionFlags( short flags ) /**
{ * get the sheetname for this sheet. (this appears in the tabs at the bottom)
field_2_option_flags = flags; * @return sheetname the name of the sheet
} */
public String getSheetname() {
return field_5_sheetname;
}
/** public String toString() {
* Set the length of the sheetname in characters StringBuffer buffer = new StringBuffer();
*
* @param len number of characters in the sheet name
* @see #setSheetname(String)
*/
public void setSheetnameLength( byte len ) buffer.append("[BOUNDSHEET]\n");
{ buffer.append(" .bof = ").append(HexDump.intToHex(getPositionOfBof())).append("\n");
field_3_sheetname_length = len; buffer.append(" .options = ").append(HexDump.shortToHex(field_2_option_flags)).append("\n");
} buffer.append(" .unicodeflag= ").append(HexDump.byteToHex(field_4_isMultibyteUnicode)).append("\n");
buffer.append(" .sheetname = ").append(field_5_sheetname).append("\n");
buffer.append("[/BOUNDSHEET]\n");
return buffer.toString();
}
private int getDataSize() {
return 8 + field_5_sheetname.length() * (isMultibyte() ? 2 : 1);
}
/** public int serialize(int offset, byte[] data) {
* set whether or not to interperate the Sheetname as compressed unicode (8/16 bit) int dataSize = getDataSize();
* (This is undocumented but can be found as Q187919 on the Microsoft(tm) Support site) LittleEndian.putUShort(data, 0 + offset, sid);
* @param flag (0/1) 0- compressed, 1 - uncompressed (16-bit) LittleEndian.putUShort(data, 2 + offset, dataSize);
*/ LittleEndian.putInt(data, 4 + offset, getPositionOfBof());
LittleEndian.putUShort(data, 8 + offset, field_2_option_flags);
public void setCompressedUnicodeFlag( byte flag ) String name = field_5_sheetname;
{ LittleEndian.putByte(data, 10 + offset, name.length());
field_4_compressed_unicode_flag = flag; LittleEndian.putByte(data, 11 + offset, field_4_isMultibyteUnicode);
}
/** if (isMultibyte()) {
* Set the sheetname for this sheet. (this appears in the tabs at the bottom) StringUtil.putUnicodeLE(name, data, 12 + offset);
* @param sheetname the name of the sheet } else {
* @throws IllegalArgumentException if sheet name will cause excel to crash. StringUtil.putCompressedUnicode(name, data, 12 + offset);
*/ }
return 4 + dataSize;
}
public void setSheetname( String sheetname ) public int getRecordSize() {
{ return 4 + getDataSize();
}
if ((sheetname == null) || (sheetname.length()==0)
|| (sheetname.length()>31)
|| (sheetname.indexOf("/") > -1)
|| (sheetname.indexOf("\\") > -1)
|| (sheetname.indexOf("?") > -1)
|| (sheetname.indexOf("*") > -1)
|| (sheetname.indexOf("]") > -1)
|| (sheetname.indexOf("[") > -1) ){
throw new IllegalArgumentException("Sheet name cannot be blank, greater than 31 chars, or contain any of /\\*?[]");
}
field_5_sheetname = sheetname;
setCompressedUnicodeFlag(StringUtil.hasMultibyte(sheetname) ? (byte)1 : (byte)0);
}
/** public short getSid() {
* get the offset in bytes of the Beginning of File Marker within the HSSF Stream part of the POIFS file return sid;
* }
* @return offset in bytes
*/
public int getPositionOfBof() /**
{ * Is the sheet hidden? Different from very hidden
return field_1_position_of_BOF; */
} public boolean isHidden() {
return hiddenFlag.isSet(field_2_option_flags);
}
/** /**
* get the option flags (unimportant for HSSF supported sheets) * Is the sheet hidden? Different from very hidden
* */
* @return flags to set public void setHidden(boolean hidden) {
*/ field_2_option_flags = hiddenFlag.setBoolean(field_2_option_flags, hidden);
}
public short getOptionFlags() /**
{ * Is the sheet very hidden? Different from (normal) hidden
return field_2_option_flags; */
} public boolean isVeryHidden() {
return veryHiddenFlag.isSet(field_2_option_flags);
}
/** /**
* get the length of the sheetname in characters * Is the sheet very hidden? Different from (normal) hidden
* */
* @return number of characters in the sheet name public void setVeryHidden(boolean veryHidden) {
* @see #getSheetname() field_2_option_flags = veryHiddenFlag.setBoolean(field_2_option_flags, veryHidden);
*/ }
public byte getSheetnameLength() /**
{ * Converts a List of {@link BoundSheetRecord}s to an array and sorts by the position of their
return field_3_sheetname_length; * BOFs.
} */
public static BoundSheetRecord[] orderByBofPosition(List boundSheetRecords) {
/** BoundSheetRecord[] bsrs = new BoundSheetRecord[boundSheetRecords.size()];
* get the length of the raw sheetname in characters boundSheetRecords.toArray(bsrs);
* the length depends on the unicode flag Arrays.sort(bsrs, BOFComparator);
* return bsrs;
* @return number of characters in the raw sheet name }
*/ private static final Comparator BOFComparator = new Comparator() {
public byte getRawSheetnameLength()
{
return (byte) ( ( ( field_4_compressed_unicode_flag & 0x01 ) == 1 )
? 2 * field_3_sheetname_length
: field_3_sheetname_length );
}
/**
* get whether or not to interperate the Sheetname as compressed unicode (8/16 bit)
* (This is undocumented but can be found as Q187919 on the Microsoft(tm) Support site)
* @return flag (0/1) 0- compressed, 1 - uncompressed (16-bit)
*/
public byte getCompressedUnicodeFlag()
{
return field_4_compressed_unicode_flag;
}
/**
* get the sheetname for this sheet. (this appears in the tabs at the bottom)
* @return sheetname the name of the sheet
*/
public String getSheetname()
{
return field_5_sheetname;
}
public String toString()
{
StringBuffer buffer = new StringBuffer();
buffer.append( "[BOUNDSHEET]\n" );
buffer.append( " .bof = " )
.append( Integer.toHexString( getPositionOfBof() ) ).append( "\n" );
buffer.append( " .optionflags = " )
.append( Integer.toHexString( getOptionFlags() ) ).append( "\n" );
buffer.append( " .sheetname length= " )
.append( Integer.toHexString( getSheetnameLength() ) ).append( "\n" );
buffer.append( " .unicodeflag = " )
.append( Integer.toHexString( getCompressedUnicodeFlag() ) )
.append( "\n" );
buffer.append( " .sheetname = " ).append( getSheetname() )
.append( "\n" );
buffer.append( "[/BOUNDSHEET]\n" );
return buffer.toString();
}
public int serialize( int offset, byte[] data )
{
LittleEndian.putShort( data, 0 + offset, sid );
LittleEndian.putShort( data, 2 + offset, (short) ( 8 + getRawSheetnameLength() ) );
LittleEndian.putInt( data, 4 + offset, getPositionOfBof() );
LittleEndian.putShort( data, 8 + offset, getOptionFlags() );
data[10 + offset] = (byte) ( getSheetnameLength() );
data[11 + offset] = getCompressedUnicodeFlag();
if ( ( field_4_compressed_unicode_flag & 0x01 ) == 1 )
StringUtil.putUnicodeLE( getSheetname(), data, 12 + offset );
else
StringUtil.putCompressedUnicode( getSheetname(), data, 12 + offset );
return getRecordSize();
/*
byte[] fake = new byte[] { (byte)0x85, 0x00, // sid
0x1a, 0x00, // length
0x3C, 0x09, 0x00, 0x00, // bof
0x00, 0x00, // flags
0x09, // len( str )
0x01, // unicode
// <str>
0x21, 0x04, 0x42, 0x04, 0x40, 0x04, 0x30, 0x04, 0x3D,
0x04, 0x38, 0x04, 0x47, 0x04, 0x3A, 0x04, 0x30, 0x04
// </str>
};
sid + len + bof + flags + len(str) + unicode + str
2 + 2 + 4 + 2 + 1 + 1 + len(str)
System.arraycopy( fake, 0, data, offset, fake.length );
return fake.length;
*/
}
public int getRecordSize()
{
// Includes sid length + size length
return 12 + getRawSheetnameLength();
}
public short getSid()
{
return sid;
}
/**
* Is the sheet hidden? Different from very hidden
*/
public boolean isHidden() {
return hiddenFlag.isSet(field_2_option_flags);
}
/**
* Is the sheet hidden? Different from very hidden
*/
public void setHidden(boolean hidden) {
field_2_option_flags = hiddenFlag.setShortBoolean(field_2_option_flags, hidden);
}
/**
* Is the sheet very hidden? Different from (normal) hidden
*/
public boolean isVeryHidden() {
return veryHiddenFlag.isSet(field_2_option_flags);
}
/**
* Is the sheet very hidden? Different from (normal) hidden
*/
public void setVeryHidden(boolean veryHidden) {
field_2_option_flags = veryHiddenFlag.setShortBoolean(field_2_option_flags, veryHidden);
}
/**
* Takes a list of BoundSheetRecords, and returns the all
* ordered by the position of their BOFs.
*/
public static BoundSheetRecord[] orderByBofPosition(List boundSheetRecords) {
BoundSheetRecord[] bsrs = (BoundSheetRecord[])boundSheetRecords.toArray(
new BoundSheetRecord[boundSheetRecords.size()]);
// Sort
Arrays.sort(bsrs, new BOFComparator());
// All done
return bsrs;
}
private static class BOFComparator implements Comparator {
public int compare(Object bsr1, Object bsr2) { public int compare(Object bsr1, Object bsr2) {
return compare((BoundSheetRecord)bsr1, (BoundSheetRecord)bsr2); return compare((BoundSheetRecord)bsr1, (BoundSheetRecord)bsr2);
} }
public int compare(BoundSheetRecord bsr1, BoundSheetRecord bsr2) { public int compare(BoundSheetRecord bsr1, BoundSheetRecord bsr2) {
if(bsr1.field_1_position_of_BOF < bsr2.field_1_position_of_BOF) return bsr1.getPositionOfBof() - bsr2.getPositionOfBof();
return -1;
if(bsr1.field_1_position_of_BOF == bsr2.field_1_position_of_BOF)
return 0;
return 1;
} }
} };
} }

View File

@ -515,18 +515,6 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
return (short) getFirstVisibleTab(); return (short) getFirstVisibleTab();
} }
/**
* @deprecated POI will now properly handle unicode strings without
* forceing an encoding
*/
public final static byte ENCODING_COMPRESSED_UNICODE = 0;
/**
* @deprecated POI will now properly handle unicode strings without
* forceing an encoding
*/
public final static byte ENCODING_UTF_16 = 1;
/** /**
* set the sheet name. * set the sheet name.
* Will throw IllegalArgumentException if the name is greater than 31 chars * Will throw IllegalArgumentException if the name is greater than 31 chars
@ -542,35 +530,6 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
workbook.setSheetName(sheetIx, name); workbook.setSheetName(sheetIx, name);
} }
/**
* set the sheet name forcing the encoding. Forcing the encoding IS A BAD IDEA!!!
* @deprecated 3-Jan-2006 POI now automatically detects unicode and sets the encoding
* appropriately. Simply use setSheetName(int sheet, String encoding)
* @throws IllegalArgumentException if the name is greater than 31 chars
* or contains /\?*[]
* @param sheet number (0 based)
*/
public void setSheetName(int sheetIx, String name, short encoding)
{
if (workbook.doesContainsSheetName( name, sheetIx )) {
throw new IllegalArgumentException( "The workbook already contains a sheet with this name" );
}
validateSheetIndex(sheetIx);
switch ( encoding ) {
case ENCODING_COMPRESSED_UNICODE:
case ENCODING_UTF_16:
break;
default:
// TODO java.io.UnsupportedEncodingException
throw new RuntimeException( "Unsupported encoding" );
}
workbook.setSheetName( sheetIx, name, encoding );
}
/** /**
* get the sheet name * get the sheet name
* @param sheetIx Number * @param sheetIx Number

View File

@ -18,7 +18,6 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList;
import junit.framework.AssertionFailedError; import junit.framework.AssertionFailedError;
import junit.framework.TestCase; import junit.framework.TestCase;
@ -39,24 +38,4 @@ public final class TestBOFRecord extends TestCase {
throw new AssertionFailedError("Identified bug 42794"); throw new AssertionFailedError("Identified bug 42794");
} }
} }
public void testOrdering() throws Exception {
BoundSheetRecord bs1 = new BoundSheetRecord();
BoundSheetRecord bs2 = new BoundSheetRecord();
BoundSheetRecord bs3 = new BoundSheetRecord();
bs1.setPositionOfBof(11);
bs2.setPositionOfBof(33);
bs3.setPositionOfBof(22);
ArrayList l = new ArrayList();
l.add(bs1);
l.add(bs2);
l.add(bs3);
BoundSheetRecord[] r = BoundSheetRecord.orderByBofPosition(l);
assertEquals(3, r.length);
assertEquals(bs1, r[0]);
assertEquals(bs3, r[1]);
assertEquals(bs2, r[2]);
}
} }

View File

@ -1,4 +1,3 @@
/* ==================================================================== /* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
@ -15,10 +14,12 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import java.util.ArrayList;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase; import junit.framework.TestCase;
/** /**
@ -28,53 +29,77 @@ import junit.framework.TestCase;
* *
* @author Glen Stampoultzis (glens at apache.org) * @author Glen Stampoultzis (glens at apache.org)
*/ */
public class TestBoundSheetRecord public final class TestBoundSheetRecord extends TestCase {
extends TestCase
{
public TestBoundSheetRecord( String s ) public void testRecordLength() {
{ BoundSheetRecord record = new BoundSheetRecord("Sheet1");
super( s ); assertEquals(18, record.getRecordSize());
} }
public void testRecordLength() public void testWideRecordLength() {
throws Exception BoundSheetRecord record = new BoundSheetRecord("Sheet\u20ac");
{ assertEquals(24, record.getRecordSize());
BoundSheetRecord record = new BoundSheetRecord();
record.setCompressedUnicodeFlag((byte)0x00);
record.setSheetname("Sheet1");
record.setSheetnameLength((byte)6);
assertEquals(" 2 + 2 + 4 + 2 + 1 + 1 + len(str)", 18, record.getRecordSize());
} }
public void testWideRecordLength()
throws Exception
{
BoundSheetRecord record = new BoundSheetRecord();
record.setSheetname("Sheet\u20ac");
record.setSheetnameLength((byte)6);
assertEquals(" 2 + 2 + 4 + 2 + 1 + 1 + len(str) * 2", 24, record.getRecordSize());
}
public void testName() { public void testName() {
BoundSheetRecord record = new BoundSheetRecord(); BoundSheetRecord record = new BoundSheetRecord("1234567890223456789032345678904");
record.setSheetname("1234567890223456789032345678904");
assertTrue("Success", true);
try { try {
record.setSheetname("12345678902234567890323456789042"); record.setSheetname("12345678902234567890323456789042");
assertTrue("Should have thrown IllegalArgumentException, but didnt", false); throw new AssertionFailedError("Should have thrown IllegalArgumentException, but didnt");
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
assertTrue("succefully threw exception",true); // expected
} }
try { try {
record.setSheetname("s//*s"); record.setSheetname("s//*s");
assertTrue("Should have thrown IllegalArgumentException, but didnt", false); throw new AssertionFailedError("Should have thrown IllegalArgumentException, but didnt");
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
assertTrue("succefully threw exception",true); // expected
} }
} }
public void testDeserializeUnicode() {
byte[] data = {
// (byte)0x85, 0x00, // sid
// 0x1a, 0x00, // length
0x3C, 0x09, 0x00, 0x00, // bof
0x00, 0x00, // flags
0x09, // len( str )
0x01, // unicode
// <str>
0x21, 0x04, 0x42, 0x04, 0x40, 0x04,
0x30, 0x04, 0x3D, 0x04, 0x38, 0x04,
0x47, 0x04, 0x3A, 0x04, 0x30, 0x04
// </str>
};
RecordInputStream in = new TestcaseRecordInputStream(BoundSheetRecord.sid, data);
BoundSheetRecord bsr = new BoundSheetRecord(in);
// sheet name is unicode Russian for 'minor page'
assertEquals("\u0421\u0442\u0440\u0430\u043D\u0438\u0447\u043A\u0430", bsr.getSheetname());
}
public void testOrdering() {
BoundSheetRecord bs1 = new BoundSheetRecord("SheetB");
BoundSheetRecord bs2 = new BoundSheetRecord("SheetC");
BoundSheetRecord bs3 = new BoundSheetRecord("SheetA");
bs1.setPositionOfBof(11);
bs2.setPositionOfBof(33);
bs3.setPositionOfBof(22);
ArrayList l = new ArrayList();
l.add(bs1);
l.add(bs2);
l.add(bs3);
BoundSheetRecord[] r = BoundSheetRecord.orderByBofPosition(l);
assertEquals(3, r.length);
assertEquals(bs1, r[0]);
assertEquals(bs3, r[1]);
assertEquals(bs2, r[2]);
}
} }

View File

@ -17,13 +17,20 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import junit.framework.TestCase;
import junit.framework.AssertionFailedError;
import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.poi.hssf.record.*; import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.apache.poi.hssf.record.BOFRecord;
import org.apache.poi.hssf.record.BoundSheetRecord;
import org.apache.poi.hssf.record.EOFRecord;
import org.apache.poi.hssf.record.InterfaceHdrRecord;
import org.apache.poi.hssf.record.NameRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.usermodel.SanityChecker.CheckRecord;
/** /**
* A Test case for a test utility class.<br/> * A Test case for a test utility class.<br/>
@ -33,137 +40,96 @@ import org.apache.poi.hssf.record.*;
*/ */
public final class TestSanityChecker extends TestCase { public final class TestSanityChecker extends TestCase {
public void testCheckRecordOrder() { private static BoundSheetRecord createBoundSheetRec() {
final SanityChecker c = new SanityChecker(); return new BoundSheetRecord("Sheet1");
List records = new ArrayList(); }
records.add(new BOFRecord()); public void testCheckRecordOrder() {
records.add(new InterfaceHdrRecord()); final SanityChecker c = new SanityChecker();
records.add(new BoundSheetRecord()); List records = new ArrayList();
records.add(EOFRecord.instance); records.add(new BOFRecord());
final SanityChecker.CheckRecord[] check = { records.add(new InterfaceHdrRecord());
new SanityChecker.CheckRecord(BOFRecord.class, '1'), records.add(createBoundSheetRec());
new SanityChecker.CheckRecord(InterfaceHdrRecord.class, '0'), records.add(EOFRecord.instance);
new SanityChecker.CheckRecord(BoundSheetRecord.class, 'M'), CheckRecord[] check = {
new SanityChecker.CheckRecord(NameRecord.class, '*'), new CheckRecord(BOFRecord.class, '1'),
new SanityChecker.CheckRecord(EOFRecord.class, '1'), new CheckRecord(InterfaceHdrRecord.class, '0'),
}; new CheckRecord(BoundSheetRecord.class, 'M'),
// check pass new CheckRecord(NameRecord.class, '*'),
c.checkRecordOrder(records, check); new CheckRecord(EOFRecord.class, '1'),
records.add(2, new BoundSheetRecord()); };
c.checkRecordOrder(records, check); // check pass
records.remove(1); // optional record missing c.checkRecordOrder(records, check);
c.checkRecordOrder(records, check); records.add(2, createBoundSheetRec());
records.add(3, new NameRecord()); c.checkRecordOrder(records, check);
records.add(3, new NameRecord()); // optional multiple record occurs more than one time records.remove(1); // optional record missing
c.checkRecordOrder(records, check); c.checkRecordOrder(records, check);
records.add(3, new NameRecord());
records.add(3, new NameRecord()); // optional multiple record occurs more than one time
c.checkRecordOrder(records, check);
// check fail // check fail
expectFail( new Runnable() { confirmBadRecordOrder(check, new Record[] {
public void run() new BOFRecord(),
{ createBoundSheetRec(),
// check optional in wrong spot new InterfaceHdrRecord(),
List records = new ArrayList(); EOFRecord.instance,
records.add(new BOFRecord()); });
records.add(new BoundSheetRecord());
records.add(new InterfaceHdrRecord());
records.add(EOFRecord.instance);
c.checkRecordOrder(records, check);
}
});
expectFail( new Runnable() { confirmBadRecordOrder(check, new Record[] {
public void run() new BOFRecord(),
{ new InterfaceHdrRecord(),
// check optional one off occurs more than once createBoundSheetRec(),
List records = new ArrayList(); new InterfaceHdrRecord(),
records.add(new BOFRecord()); EOFRecord.instance,
records.add(new InterfaceHdrRecord()); });
records.add(new BoundSheetRecord());
records.add(new InterfaceHdrRecord());
records.add(EOFRecord.instance);
c.checkRecordOrder(records, check);
}
});
expectFail( new Runnable() { confirmBadRecordOrder(check, new Record[] {
public void run() new BOFRecord(),
{ createBoundSheetRec(),
// check many scattered new NameRecord(),
List records = new ArrayList(); EOFRecord.instance,
records.add(new BOFRecord()); new NameRecord(),
records.add(new BoundSheetRecord()); });
records.add(new NameRecord());
records.add(EOFRecord.instance);
records.add(new NameRecord());
c.checkRecordOrder(records, check);
}
});
expectFail( new Runnable() { confirmBadRecordOrder(check, new Record[] {
public void run() new InterfaceHdrRecord(),
{ createBoundSheetRec(),
// check missing manditory EOFRecord.instance,
List records = new ArrayList(); });
records.add(new InterfaceHdrRecord());
records.add(new BoundSheetRecord());
records.add(EOFRecord.instance);
c.checkRecordOrder(records, check);
}
});
expectFail( new Runnable() { confirmBadRecordOrder(check, new Record[] {
public void run() new BOFRecord(),
{ new InterfaceHdrRecord(),
// check missing 1..many EOFRecord.instance,
List records = new ArrayList(); });
records.add(new BOFRecord());
records.add(new InterfaceHdrRecord());
records.add(EOFRecord.instance);
c.checkRecordOrder(records, check);
}
});
expectFail( new Runnable() { confirmBadRecordOrder(check, new Record[] {
public void run() new InterfaceHdrRecord(),
{ createBoundSheetRec(),
// check wrong order new BOFRecord(),
List records = new ArrayList(); EOFRecord.instance,
records.add(new InterfaceHdrRecord()); });
records.add(new BoundSheetRecord());
records.add(new BOFRecord());
records.add(EOFRecord.instance);
c.checkRecordOrder(records, check);
}
});
expectFail( new Runnable() {
public void run()
{
// check optional record in wrong order
List records = new ArrayList();
records.add(new BOFRecord());
records.add(new BoundSheetRecord());
records.add(new InterfaceHdrRecord());
records.add(EOFRecord.instance);
c.checkRecordOrder(records, check);
}
});
}
private void expectFail( Runnable runnable )
{
boolean fail = false;
try
{
runnable.run();
fail = true;
}
catch (AssertionFailedError pass)
{
}
assertTrue(!fail);
}
confirmBadRecordOrder(check, new Record[] {
new BOFRecord(),
createBoundSheetRec(),
new InterfaceHdrRecord(),
EOFRecord.instance,
});
}
private static void confirmBadRecordOrder(final SanityChecker.CheckRecord[] check, Record[] recs) {
final SanityChecker c = new SanityChecker();
final List records = Arrays.asList(recs);
try {
new Runnable() {
public void run() {
c.checkRecordOrder(records, check);
}
}.run();
} catch (AssertionFailedError pass) {
// expected during normal test
return;
}
throw new AssertionFailedError("Did not get failure exception as expected");
}
} }