More work on FeatRecord/Shared Features. More is still needed though, it's still WIP

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@894018 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2009-12-26 19:57:09 +00:00
parent f1909f578d
commit 0e9861932a
13 changed files with 264 additions and 19 deletions

View File

@ -162,6 +162,8 @@ public final class BiffViewer {
case ExtSSTRecord.sid: return new ExtSSTRecord(in);
case ExtendedFormatRecord.sid: return new ExtendedFormatRecord(in);
case ExternSheetRecord.sid: return new ExternSheetRecord(in);
case FeatRecord.sid: return new FeatRecord(in);
case FeatHdrRecord.sid: return new FeatHdrRecord(in);
case FilePassRecord.sid: return new FilePassRecord(in);
case FileSharingRecord.sid: return new FileSharingRecord(in);
case FnGroupCountRecord.sid: return new FnGroupCountRecord(in);

View File

@ -34,6 +34,7 @@ import org.apache.poi.hssf.record.DimensionsRecord;
import org.apache.poi.hssf.record.DrawingRecord;
import org.apache.poi.hssf.record.DrawingSelectionRecord;
import org.apache.poi.hssf.record.EOFRecord;
import org.apache.poi.hssf.record.FeatRecord;
import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.GridsetRecord;
import org.apache.poi.hssf.record.GutsRecord;
@ -341,7 +342,7 @@ final class RecordOrderer {
switch(sid) {
case UnknownRecord.SHEETEXT_0862:
case UnknownRecord.SHEETPROTECTION_0867:
case UnknownRecord.RANGEPROTECTION_0868:
case FeatRecord.sid:
case EOFRecord.sid:
return true;
}

View File

@ -17,6 +17,7 @@
package org.apache.poi.hssf.record;
import org.apache.poi.hssf.record.common.FtrHeader;
import org.apache.poi.util.LittleEndianOutput;
/**
@ -51,7 +52,8 @@ public final class FeatHdrRecord extends StandardRecord {
public final static short sid = 0x0867;
private FtrHeader futureHeader;
private int isf_sharedFeatureType; // See SHAREDFEATURES_
private byte reserved; // Should always be one
/**
@ -63,6 +65,8 @@ public final class FeatHdrRecord extends StandardRecord {
private byte[] rgbHdrData;
public FeatHdrRecord() {
futureHeader = new FtrHeader();
futureHeader.setRecordType(sid);
}
public short getSid() {
@ -70,9 +74,11 @@ public final class FeatHdrRecord extends StandardRecord {
}
public FeatHdrRecord(RecordInputStream in) {
futureHeader = new FtrHeader(in);
isf_sharedFeatureType = in.readShort();
reserved = in.readByte();
cbHdrData = in.readLong();
cbHdrData = in.readInt();
// Don't process this just yet, need the BOFRecord
rgbHdrData = in.readRemainder();
}
@ -88,13 +94,15 @@ public final class FeatHdrRecord extends StandardRecord {
}
public void serialize(LittleEndianOutput out) {
futureHeader.serialize(out);
out.writeShort(isf_sharedFeatureType);
out.writeByte(reserved);
out.writeLong(cbHdrData);
out.writeInt((int)cbHdrData);
out.write(rgbHdrData);
}
protected int getDataSize() {
return 2+1+4+rgbHdrData.length;
return 12 + 2+1+4+rgbHdrData.length;
}
}

View File

@ -17,6 +17,7 @@
package org.apache.poi.hssf.record;
import org.apache.poi.hssf.record.common.FtrHeader;
import org.apache.poi.hssf.record.common.Ref8U;
import org.apache.poi.util.LittleEndianOutput;
@ -29,14 +30,14 @@ import org.apache.poi.util.LittleEndianOutput;
public final class FeatRecord extends StandardRecord {
public final static short sid = 0x0868;
private FtrHeader futureHeader;
/**
* See SHAREDFEATURES_* on {@link FeatHdrRecord}
*/
private int isf_sharedFeatureType;
private byte reserved1; // Should always be zero
private long reserved2; // Should always be zero
/** The number of refs */
private int cref;
/** Only matters if type is ISFFEC2 */
private long cbFeatData;
private int reserved3; // Should always be zero
@ -45,6 +46,8 @@ public final class FeatRecord extends StandardRecord {
private byte[] rgbFeat;
public FeatRecord() {
futureHeader = new FtrHeader();
futureHeader.setRecordType(sid);
}
public short getSid() {
@ -52,11 +55,13 @@ public final class FeatRecord extends StandardRecord {
}
public FeatRecord(RecordInputStream in) {
futureHeader = new FtrHeader(in);
isf_sharedFeatureType = in.readShort();
reserved1 = in.readByte();
reserved2 = in.readLong();
cref = in.readUShort();
cbFeatData = in.readLong();
reserved2 = in.readInt();
int cref = in.readUShort();
cbFeatData = in.readInt();
reserved3 = in.readShort();
cellRefs = new Ref8U[cref];
@ -69,7 +74,7 @@ public final class FeatRecord extends StandardRecord {
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("[SHARDED FEATURE]\n");
buffer.append("[SHARED FEATURE]\n");
// TODO ...
@ -78,13 +83,23 @@ public final class FeatRecord extends StandardRecord {
}
public void serialize(LittleEndianOutput out) {
futureHeader.serialize(out);
out.writeShort(isf_sharedFeatureType);
out.writeByte(reserved1);
out.writeInt((int)reserved2);
out.writeShort(cellRefs.length);
out.writeInt((int)cbFeatData);
out.writeShort(reserved3);
// TODO ...
for(int i=0; i<cellRefs.length; i++) {
cellRefs[i].serialize(out);
}
out.write(rgbFeat);
}
protected int getDataSize() {
return -1; // TODO
return 12 + 2+1+4+2+4+2+Ref8U.getDataSize()+rgbFeat.length;
}
}

View File

@ -143,6 +143,8 @@ public final class RecordFactory {
ExternalNameRecord.class,
ExternSheetRecord.class,
ExtSSTRecord.class,
FeatRecord.class,
FeatHdrRecord.class,
FilePassRecord.class,
FileSharingRecord.class,
FnGroupCountRecord.class,

View File

@ -234,12 +234,18 @@ public final class RecordInputStream implements LittleEndianInput {
return _dataInput.readShort();
}
/**
* Reads a 32 bit, signed value
*/
public int readInt() {
checkRecordPosition(LittleEndian.INT_SIZE);
_currentDataOffset += LittleEndian.INT_SIZE;
return _dataInput.readInt();
}
/**
* Reads a 64 bit, signed value
*/
public long readLong() {
checkRecordPosition(LittleEndian.LONG_SIZE);
_currentDataOffset += LittleEndian.LONG_SIZE;

View File

@ -56,7 +56,6 @@ public final class UnknownRecord extends StandardRecord {
public static final int QUICKTIP_0800 = 0x0800;
public static final int SHEETEXT_0862 = 0x0862; // OOO calls this SHEETLAYOUT
public static final int SHEETPROTECTION_0867 = 0x0867;
public static final int RANGEPROTECTION_0868 = 0x0868;
public static final int HEADER_FOOTER_089C = 0x089C;
private int _sid;
@ -173,7 +172,6 @@ public final class UnknownRecord extends StandardRecord {
case 0x0863: return "BOOKEXT";
case 0x0864: return "SXADDL"; // Pivot Table Additional Info
case SHEETPROTECTION_0867: return "SHEETPROTECTION";
case RANGEPROTECTION_0868: return "RANGEPROTECTION";
case 0x086B: return "DATALABEXTCONTENTS";
case 0x086C: return "CELLWATCH";
case 0x0874: return "DROPDOWNOBJIDS";

View File

@ -0,0 +1,89 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record.common;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.util.LittleEndianOutput;
/**
* Title: FtrHeader (Future Record Header) common record part
* <P>
* This record part specifies a header for a Ftr (Future)
* style record, which includes extra attributes above and
* beyond those of a traditional record.
*/
public final class FtrHeader {
/** This MUST match the type on the containing record */
private short recordType;
/** This is a FrtFlags */
private short grbitFrt;
/** MUST be 8 bytes and all zero */
private byte[] reserved;
public FtrHeader() {
reserved = new byte[8];
}
public FtrHeader(RecordInputStream in) {
recordType = in.readShort();
grbitFrt = in.readShort();
reserved = new byte[8];
in.read(reserved, 0, 8);
}
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append(" [FUTURE HEADER]\n");
buffer.append(" Type " + recordType);
buffer.append(" Flags " + grbitFrt);
buffer.append(" [/FUTURE HEADER]\n");
return buffer.toString();
}
public void serialize(LittleEndianOutput out) {
out.writeShort(recordType);
out.writeShort(grbitFrt);
out.write(reserved);
}
public static int getDataSize() {
return 12;
}
public short getRecordType() {
return recordType;
}
public void setRecordType(short recordType) {
this.recordType = recordType;
}
public short getGrbitFrt() {
return grbitFrt;
}
public void setGrbitFrt(short grbitFrt) {
this.grbitFrt = grbitFrt;
}
public byte[] getReserved() {
return reserved;
}
public void setReserved(byte[] reserved) {
this.reserved = reserved;
}
}

View File

@ -27,6 +27,7 @@ import org.apache.poi.hssf.record.ContinueRecord;
import org.apache.poi.hssf.record.DVALRecord;
import org.apache.poi.hssf.record.DVRecord;
import org.apache.poi.hssf.record.EOFRecord;
import org.apache.poi.hssf.record.FeatHdrRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.SelectionRecord;
import org.apache.poi.hssf.record.WindowTwoRecord;
@ -86,9 +87,10 @@ public final class TestHSSFEventFactory extends TestCase {
// Check that the last few records are as we expect
// (Makes sure we don't accidently skip the end ones)
int numRec = recs.length;
assertEquals(DVALRecord.class, recs[numRec-3].getClass());
assertEquals(DVRecord.class, recs[numRec-2].getClass());
assertEquals(EOFRecord.class, recs[numRec-1].getClass());
assertEquals(DVALRecord.class, recs[numRec-4].getClass());
assertEquals(DVRecord.class, recs[numRec-3].getClass());
assertEquals(FeatHdrRecord.class, recs[numRec-2].getClass());
assertEquals(EOFRecord.class, recs[numRec-1].getClass());
}
/**
@ -110,7 +112,7 @@ public final class TestHSSFEventFactory extends TestCase {
}
private static class MockHSSFListener implements HSSFListener {
private final List records = new ArrayList();
private final List<Record> records = new ArrayList<Record>();
public MockHSSFListener() {}
public Record[] getRecords() {

View File

@ -0,0 +1,89 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.model.InternalWorkbook;
import org.apache.poi.hssf.usermodel.HSSFTestHelper;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import junit.framework.TestCase;
/**
* Tests for <tt>FeatRecord</tt>
*
* @author Josh Micich
*/
public final class TestFeatRecord extends TestCase {
public void testWithoutFeatRecord() throws Exception {
HSSFWorkbook hssf =
HSSFTestDataSamples.openSampleWorkbook("46136-WithWarnings.xls");
InternalWorkbook wb = HSSFTestHelper.getWorkbookForTest(hssf);
int countFR = 0;
int countFRH = 0;
for(Record r : wb.getRecords()) {
if(r instanceof FeatRecord) {
countFR++;
} else if (r.getSid() == FeatRecord.sid) {
countFR++;
}
if(r instanceof FeatHdrRecord) {
countFRH++;
} else if (r.getSid() == FeatHdrRecord.sid) {
countFRH++;
}
}
assertEquals(0, countFR);
assertEquals(0, countFRH);
}
/**
* TODO - make this work!
* (Need to have the Internal Workbook capture it or something)
*/
public void DISABLEDtestReadFeatRecord() throws Exception {
HSSFWorkbook hssf =
HSSFTestDataSamples.openSampleWorkbook("46136-NoWarnings.xls");
InternalWorkbook wb = HSSFTestHelper.getWorkbookForTest(hssf);
FeatRecord fr = null;
int countFR = 0;
int countFRH = 0;
for(Record r : wb.getRecords()) {
if(r instanceof FeatRecord) {
fr = (FeatRecord)r;
countFR++;
} else if (r.getSid() == FeatRecord.sid) {
fail("FeatRecord SID found but not created correctly!");
}
if(r instanceof FeatHdrRecord) {
countFRH++;
} else if (r.getSid() == FeatHdrRecord.sid) {
fail("FeatHdrRecord SID found but not created correctly!");
}
}
assertEquals(1, countFR);
assertEquals(1, countFRH);
assertNotNull(fr);
// Now check the contents are as expected
}
}

View File

@ -0,0 +1,33 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.usermodel;
import org.apache.poi.hssf.model.InternalWorkbook;
/**
* Helper class for HSSF tests that aren't within the
* HSSF UserModel package, but need to do internal
* UserModel things.
*/
public class HSSFTestHelper {
/**
* Lets non UserModel tests at the low level Workbook
*/
public static InternalWorkbook getWorkbookForTest(HSSFWorkbook wb) {
return wb.getWorkbook();
}
}

Binary file not shown.

Binary file not shown.