Created ChartSubstreamRecordAggregate to manage chart sub-streams. Not fully incorporated yet.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@773434 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2009-05-10 23:54:29 +00:00
parent e2793ef74b
commit 98524ddaf8
5 changed files with 139 additions and 47 deletions

View File

@ -50,7 +50,6 @@ import org.apache.poi.hssf.record.PrintHeadersRecord;
import org.apache.poi.hssf.record.ProtectRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordBase;
import org.apache.poi.hssf.record.RecordFormatException;
import org.apache.poi.hssf.record.RefModeRecord;
import org.apache.poi.hssf.record.RowRecord;
import org.apache.poi.hssf.record.SCLRecord;
@ -61,6 +60,7 @@ import org.apache.poi.hssf.record.UncalcedRecord;
import org.apache.poi.hssf.record.UnknownRecord;
import org.apache.poi.hssf.record.WSBoolRecord;
import org.apache.poi.hssf.record.WindowTwoRecord;
import org.apache.poi.hssf.record.aggregates.ChartSubstreamRecordAggregate;
import org.apache.poi.hssf.record.aggregates.ColumnInfoRecordsAggregate;
import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable;
import org.apache.poi.hssf.record.aggregates.DataValidityTable;
@ -71,8 +71,8 @@ import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
import org.apache.poi.hssf.record.aggregates.RecordAggregate.PositionTrackingVisitor;
import org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor;
import org.apache.poi.hssf.record.formula.FormulaShifter;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.hssf.util.PaneInformation;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
@ -165,19 +165,16 @@ public final class Sheet implements Model {
RowRecordsAggregate rra = null;
records = new ArrayList<RecordBase>(128);
// TODO - take chart streams off into separate java objects
int bofEofNestingLevel = 1; // nesting level can only get to 2 (when charts are present)
int dimsloc = -1;
if (rs.peekNextSid() == BOFRecord.sid) {
if (rs.peekNextSid() != BOFRecord.sid) {
throw new RuntimeException("BOF record expected");
}
BOFRecord bof = (BOFRecord) rs.getNext();
if (bof.getType() != BOFRecord.TYPE_WORKSHEET) {
// TODO - fix junit tests throw new RuntimeException("Bad BOF record type");
}
records.add(bof);
} else {
throw new RuntimeException("BOF record expected");
}
while (rs.hasNext()) {
int recSid = rs.peekNextSid();
@ -198,7 +195,7 @@ public final class Sheet implements Model {
continue;
}
if (RecordOrderer.isRowBlockRecord(recSid) && bofEofNestingLevel == 1 ) {
if (RecordOrderer.isRowBlockRecord(recSid)) {
//only add the aggregate once
if (rra != null) {
throw new RuntimeException("row/cell records found in the wrong place");
@ -218,13 +215,7 @@ public final class Sheet implements Model {
records.add(psb);
continue;
}
if (bofEofNestingLevel == 2) {
psb = new PageSettingsBlock(rs);
// It's normal for a chart to have its own PageSettingsBlock
// Fall through and add psb here, because chart records
// are stored loose among the sheet records.
// this latest psb does not clash with _psBlock
} else if (windowTwo != null) {
if (windowTwo != null) {
// probably 'Custom View Settings' sub-stream which is found between
// USERSVIEWBEGIN(01AA) and USERSVIEWEND(01AB)
// TODO - create UsersViewAggregate to hold these sub-streams, and simplify this code a bit
@ -263,6 +254,17 @@ public final class Sheet implements Model {
continue;
}
if (recSid == BOFRecord.sid) {
ChartSubstreamRecordAggregate chartAgg = new ChartSubstreamRecordAggregate(rs);
if (false) {
// TODO - would like to keep the chart aggregate packed, but one unit test needs attention
records.add(chartAgg);
} else {
spillAggregate(chartAgg, records);
}
continue;
}
Record rec = rs.getNext();
if ( recSid == IndexRecord.sid ) {
// ignore INDEX record because it is only needed by Excel,
@ -277,28 +279,12 @@ public final class Sheet implements Model {
continue;
}
if (recSid == BOFRecord.sid)
{
bofEofNestingLevel++;
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "Hit BOF record. Nesting increased to " + bofEofNestingLevel);
BOFRecord bof = (BOFRecord)rec;
// TODO - extract chart sub-stream into record aggregate
if (bof.getType() != BOFRecord.TYPE_CHART) {
throw new RecordFormatException("Bad BOF record type: " + bof.getType());
}
}
else if (recSid == EOFRecord.sid)
{
--bofEofNestingLevel;
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "Hit EOF record. Nesting decreased to " + bofEofNestingLevel);
if (bofEofNestingLevel == 0) {
if (recSid == EOFRecord.sid) {
records.add(rec);
break;
}
}
else if (recSid == DimensionsRecord.sid)
if (recSid == DimensionsRecord.sid)
{
// Make a columns aggregate if one hasn't ready been created.
if (_columnInfos == null)
@ -386,6 +372,12 @@ public final class Sheet implements Model {
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "sheet createSheet (existing file) exited");
}
private static void spillAggregate(RecordAggregate ra, final List<RecordBase> recs) {
ra.visitContainedRecords(new RecordVisitor() {
public void visitRecord(Record r) {
recs.add(r);
}});
}
/**
* Hack to recover from the situation where the page settings block has been split by
* an intervening {@link WSBoolRecord}

View File

@ -43,6 +43,7 @@ import org.apache.poi.hssf.model.CommentShape;
import org.apache.poi.hssf.model.ConvertAnchor;
import org.apache.poi.hssf.model.DrawingManager2;
import org.apache.poi.hssf.model.TextboxShape;
import org.apache.poi.hssf.record.aggregates.RecordAggregate;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFPatriarch;
import org.apache.poi.hssf.usermodel.HSSFShape;
@ -884,7 +885,11 @@ public final class EscherAggregate extends AbstractEscherHolderRecord {
private static short sid( List records, int loc )
{
return ( (Record) records.get( loc ) ).getSid();
Object obj = records.get( loc );
if (obj instanceof RecordAggregate) {
return -1;
}
return ( (Record) obj ).getSid();
}

View File

@ -17,6 +17,7 @@
package org.apache.poi.hssf.record;
import org.apache.poi.hssf.record.aggregates.PageSettingsBlock;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianOutput;
@ -35,6 +36,12 @@ public final class UnknownRecord extends StandardRecord {
/*
* Some Record IDs used by POI as 'milestones' in the record stream
*/
/**
* seems to be part of the {@link PageSettingsBlock}. Not interpreted by POI.
* The name 'PRINTSIZE' was taken from OOO source.<br/>
* The few POI test samples with this record have data { 0x03, 0x00 }.
*/
public static final int PRINTSIZE_0033 = 0x0033;
public static final int PLS_004D = 0x004D;
public static final int SHEETPR_0081 = 0x0081;
public static final int STANDARDWIDTH_0099 = 0x0099;
@ -123,6 +130,7 @@ public final class UnknownRecord extends StandardRecord {
// Make sure you delete the corresponding entry from
// this method any time a new Record subclass is created.
switch (sid) {
case PRINTSIZE_0033: return "PRINTSIZE";
case PLS_004D: return "PLS";
case 0x0050: return "DCON"; // Data Consolidation Information
case 0x007F: return "IMDATA";

View File

@ -0,0 +1,81 @@
/* ====================================================================
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.aggregates;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.hssf.model.RecordStream;
import org.apache.poi.hssf.record.BOFRecord;
import org.apache.poi.hssf.record.EOFRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordBase;
/**
* Manages the all the records associated with a chart sub-stream.<br/>
* Includes the initial {@link BOFRecord} and final {@link EOFRecord}.
*
* @author Josh Micich
*/
public final class ChartSubstreamRecordAggregate extends RecordAggregate {
private final BOFRecord _bofRec;
/**
* All the records between BOF and EOF
*/
private final List<RecordBase> _recs;
private PageSettingsBlock _psBlock;
public ChartSubstreamRecordAggregate(RecordStream rs) {
_bofRec = (BOFRecord) rs.getNext();
List<RecordBase> temp = new ArrayList<RecordBase>();
while (rs.peekNextClass() != EOFRecord.class) {
if (PageSettingsBlock.isComponentRecord(rs.peekNextSid())) {
if (_psBlock != null) {
throw new IllegalStateException(
"Found more than one PageSettingsBlock in chart sub-stream");
}
_psBlock = new PageSettingsBlock(rs);
temp.add(_psBlock);
continue;
}
temp.add(rs.getNext());
}
_recs = temp;
Record eof = rs.getNext(); // no need to save EOF in field
if (!(eof instanceof EOFRecord)) {
throw new IllegalStateException("Bad chart EOF");
}
}
public void visitContainedRecords(RecordVisitor rv) {
if (_recs.isEmpty()) {
return;
}
rv.visitRecord(_bofRec);
for (int i = 0; i < _recs.size(); i++) {
RecordBase rb = _recs.get(i);
if (rb instanceof RecordAggregate) {
((RecordAggregate) rb).visitContainedRecords(rv);
} else {
rv.visitRecord((Record) rb);
}
}
rv.visitRecord(EOFRecord.instance);
}
}

View File

@ -70,9 +70,10 @@ public final class PageSettingsBlock extends RecordAggregate {
* include any trailing {@link ContinueRecord}s.
*/
private List<ContinueRecord> _plsContinues;
private PrintSetupRecord printSetup;
private PrintSetupRecord _printSetup;
private Record _bitmap;
private Record _headerFooter;
private Record _printSize;
public PageSettingsBlock(RecordStream rs) {
while(true) {
@ -92,7 +93,7 @@ public final class PageSettingsBlock extends RecordAggregate {
_footer = new FooterRecord("");
_hCenter = createHCenter();
_vCenter = createVCenter();
printSetup = createPrintSetup();
_printSetup = createPrintSetup();
}
/**
@ -114,6 +115,7 @@ public final class PageSettingsBlock extends RecordAggregate {
case UnknownRecord.PLS_004D:
case PrintSetupRecord.sid:
case UnknownRecord.BITMAP_00E9:
case UnknownRecord.PRINTSIZE_0033:
case UnknownRecord.HEADER_FOOTER_089C: // extra header/footer settings supported by Excel 2007
return true;
}
@ -162,11 +164,14 @@ public final class PageSettingsBlock extends RecordAggregate {
}
break;
case PrintSetupRecord.sid:
printSetup = (PrintSetupRecord)rs.getNext();
_printSetup = (PrintSetupRecord)rs.getNext();
break;
case UnknownRecord.BITMAP_00E9:
_bitmap = rs.getNext();
break;
case UnknownRecord.PRINTSIZE_0033:
_printSize = rs.getNext();
break;
case UnknownRecord.HEADER_FOOTER_089C:
_headerFooter = rs.getNext();
break;
@ -228,8 +233,9 @@ public final class PageSettingsBlock extends RecordAggregate {
visitIfPresent(cr, rv);
}
}
visitIfPresent(printSetup, rv);
visitIfPresent(_printSetup, rv);
visitIfPresent(_bitmap, rv);
visitIfPresent(_printSize, rv);
visitIfPresent(_headerFooter, rv);
}
private static void visitIfPresent(Record r, RecordVisitor rv) {
@ -333,7 +339,7 @@ public final class PageSettingsBlock extends RecordAggregate {
*/
public PrintSetupRecord getPrintSetup ()
{
return printSetup;
return _printSetup;
}
/**
@ -342,7 +348,7 @@ public final class PageSettingsBlock extends RecordAggregate {
*/
public void setPrintSetup (PrintSetupRecord newPrintSetup)
{
printSetup = newPrintSetup;
_printSetup = newPrintSetup;
}