From 948b0e8f08c05f475ec92f94f127878c6bc5f37b Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Mon, 18 Nov 2019 08:56:06 +0000 Subject: [PATCH] convert tabs to spaces git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1869962 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/hssf/record/HyperlinkRecord.java | 294 +- .../apache/poi/hssf/usermodel/HSSFChart.java | 2552 ++++++++--------- .../src/org/apache/poi/hdgf/chunks/Chunk.java | 542 ++-- 3 files changed, 1693 insertions(+), 1695 deletions(-) diff --git a/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java b/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java index e4454bcf66..4f51179b01 100644 --- a/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java +++ b/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java @@ -42,52 +42,52 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { static final class GUID { - /* - * this class is currently only used here, but could be moved to a - * common package if needed - */ - private static final int TEXT_FORMAT_LENGTH = 36; - - public static final int ENCODED_SIZE = 16; - - /** 4 bytes - little endian */ - private final int _d1; - /** 2 bytes - little endian */ - private final int _d2; - /** 2 bytes - little endian */ - private final int _d3; - /** - * 8 bytes - serialized as big endian, stored with inverted endianness here - */ - private final long _d4; - - public GUID(LittleEndianInput in) { - this(in.readInt(), in.readUShort(), in.readUShort(), in.readLong()); - } - - public GUID(int d1, int d2, int d3, long d4) { - _d1 = d1; - _d2 = d2; - _d3 = d3; - _d4 = d4; - } - - public void serialize(LittleEndianOutput out) { - out.writeInt(_d1); - out.writeShort(_d2); - out.writeShort(_d3); - out.writeLong(_d4); - } - - @Override - public boolean equals(Object obj) { + /* + * this class is currently only used here, but could be moved to a + * common package if needed + */ + private static final int TEXT_FORMAT_LENGTH = 36; + + public static final int ENCODED_SIZE = 16; + + /** 4 bytes - little endian */ + private final int _d1; + /** 2 bytes - little endian */ + private final int _d2; + /** 2 bytes - little endian */ + private final int _d3; + /** + * 8 bytes - serialized as big endian, stored with inverted endianness here + */ + private final long _d4; + + public GUID(LittleEndianInput in) { + this(in.readInt(), in.readUShort(), in.readUShort(), in.readLong()); + } + + public GUID(int d1, int d2, int d3, long d4) { + _d1 = d1; + _d2 = d2; + _d3 = d3; + _d4 = d4; + } + + public void serialize(LittleEndianOutput out) { + out.writeInt(_d1); + out.writeShort(_d2); + out.writeShort(_d3); + out.writeLong(_d4); + } + + @Override + public boolean equals(Object obj) { if (!(obj instanceof GUID)) { return false; } - GUID other = (GUID) obj; - return _d1 == other._d1 && _d2 == other._d2 - && _d3 == other._d3 && _d4 == other._d4; - } + GUID other = (GUID) obj; + return _d1 == other._d1 && _d2 == other._d2 + && _d3 == other._d3 && _d4 == other._d4; + } @Override public int hashCode() { @@ -96,108 +96,108 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { } public int getD1() { - return _d1; - } - - public int getD2() { - return _d2; - } - - public int getD3() { - return _d3; - } - - public long getD4() { - byte[] result = new byte[Long.SIZE/Byte.SIZE]; - long l = _d4; - for (int i = result.length-1; i >= 0; i--) { - result[i] = (byte)(l & 0xFF); - l >>= 8; - } - - return LittleEndian.getLong(result, 0); - } - - public String formatAsString() { - - StringBuilder sb = new StringBuilder(36); - - int PREFIX_LEN = "0x".length(); - sb.append(HexDump.intToHex(_d1).substring(PREFIX_LEN)); - sb.append("-"); - sb.append(HexDump.shortToHex(_d2).substring(PREFIX_LEN)); - sb.append("-"); - sb.append(HexDump.shortToHex(_d3).substring(PREFIX_LEN)); - sb.append("-"); - String d4Chars = HexDump.longToHex(getD4()); - sb.append(d4Chars, PREFIX_LEN, PREFIX_LEN+4); - sb.append("-"); - sb.append(d4Chars.substring(PREFIX_LEN+4)); - return sb.toString(); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(64); - sb.append(getClass().getName()).append(" ["); - sb.append(formatAsString()); - sb.append("]"); - return sb.toString(); - } - - /** - * Read a GUID in standard text form e.g.
- * 13579BDF-0246-8ACE-0123-456789ABCDEF - *
->
- * 0x13579BDF, 0x0246, 0x8ACE 0x0123456789ABCDEF - */ - public static GUID parse(String rep) { - char[] cc = rep.toCharArray(); - if (cc.length != TEXT_FORMAT_LENGTH) { - throw new RecordFormatException("supplied text is the wrong length for a GUID"); - } - int d0 = (parseShort(cc, 0) << 16) + (parseShort(cc, 4) << 0); - int d1 = parseShort(cc, 9); - int d2 = parseShort(cc, 14); + return _d1; + } + + public int getD2() { + return _d2; + } + + public int getD3() { + return _d3; + } + + public long getD4() { + byte[] result = new byte[Long.SIZE/Byte.SIZE]; + long l = _d4; + for (int i = result.length-1; i >= 0; i--) { + result[i] = (byte)(l & 0xFF); + l >>= 8; + } + + return LittleEndian.getLong(result, 0); + } + + public String formatAsString() { + + StringBuilder sb = new StringBuilder(36); + + int PREFIX_LEN = "0x".length(); + sb.append(HexDump.intToHex(_d1).substring(PREFIX_LEN)); + sb.append("-"); + sb.append(HexDump.shortToHex(_d2).substring(PREFIX_LEN)); + sb.append("-"); + sb.append(HexDump.shortToHex(_d3).substring(PREFIX_LEN)); + sb.append("-"); + String d4Chars = HexDump.longToHex(getD4()); + sb.append(d4Chars, PREFIX_LEN, PREFIX_LEN+4); + sb.append("-"); + sb.append(d4Chars.substring(PREFIX_LEN+4)); + return sb.toString(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(64); + sb.append(getClass().getName()).append(" ["); + sb.append(formatAsString()); + sb.append("]"); + return sb.toString(); + } + + /** + * Read a GUID in standard text form e.g.
+ * 13579BDF-0246-8ACE-0123-456789ABCDEF + *
->
+ * 0x13579BDF, 0x0246, 0x8ACE 0x0123456789ABCDEF + */ + public static GUID parse(String rep) { + char[] cc = rep.toCharArray(); + if (cc.length != TEXT_FORMAT_LENGTH) { + throw new RecordFormatException("supplied text is the wrong length for a GUID"); + } + int d0 = (parseShort(cc, 0) << 16) + (parseShort(cc, 4) << 0); + int d1 = parseShort(cc, 9); + int d2 = parseShort(cc, 14); System.arraycopy(cc, 19, cc, 20, 4); - long d3 = parseLELong(cc, 20); - - return new GUID(d0, d1, d2, d3); - } - - private static long parseLELong(char[] cc, int startIndex) { - long acc = 0; - for (int i = startIndex + 14; i >= startIndex; i -= 2) { - acc <<= 4; - acc += parseHexChar(cc[i + 0]); - acc <<= 4; - acc += parseHexChar(cc[i + 1]); - } - return acc; - } - - private static int parseShort(char[] cc, int startIndex) { - int acc = 0; - for (int i = 0; i < 4; i++) { - acc <<= 4; - acc += parseHexChar(cc[startIndex + i]); - } - return acc; - } - - private static int parseHexChar(char c) { - if (c >= '0' && c <= '9') { - return c - '0'; - } - if (c >= 'A' && c <= 'F') { - return c - 'A' + 10; - } - if (c >= 'a' && c <= 'f') { - return c - 'a' + 10; - } - throw new RecordFormatException("Bad hex char '" + c + "'"); - } - } + long d3 = parseLELong(cc, 20); + + return new GUID(d0, d1, d2, d3); + } + + private static long parseLELong(char[] cc, int startIndex) { + long acc = 0; + for (int i = startIndex + 14; i >= startIndex; i -= 2) { + acc <<= 4; + acc += parseHexChar(cc[i + 0]); + acc <<= 4; + acc += parseHexChar(cc[i + 1]); + } + return acc; + } + + private static int parseShort(char[] cc, int startIndex) { + int acc = 0; + for (int i = 0; i < 4; i++) { + acc <<= 4; + acc += parseHexChar(cc[startIndex + i]); + } + return acc; + } + + private static int parseHexChar(char c) { + if (c >= '0' && c <= '9') { + return c - '0'; + } + if (c >= 'A' && c <= 'F') { + return c - 'A' + 10; + } + if (c >= 'a' && c <= 'f') { + return c - 'a' + 10; + } + throw new RecordFormatException("Bad hex char '" + c + "'"); + } + } /** * Link flags @@ -628,7 +628,7 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { size += 4; //address length size += _address.length()*2; if (_uninterpretedTail != null) { - size += TAIL_SIZE; + size += TAIL_SIZE; } } else if (FILE_MONIKER.equals(_moniker)){ size += 2; //file_opts @@ -652,8 +652,8 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { private static byte[] readTail(byte[] expectedTail, LittleEndianInput in) { - byte[] result = new byte[TAIL_SIZE]; - in.readFully(result); + byte[] result = new byte[TAIL_SIZE]; + in.readFully(result); // if (false) { // Quite a few examples in the unit tests which don't have the exact expected tail // for (int i = 0; i < expectedTail.length; i++) { // if (expectedTail[i] != result[i]) { diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFChart.java b/src/java/org/apache/poi/hssf/usermodel/HSSFChart.java index c08511fa46..0895fe94f1 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFChart.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFChart.java @@ -78,1294 +78,1294 @@ import org.apache.poi.ss.util.CellRangeAddressBase; * @author Glen Stampoultzis (glens at apache.org) */ public final class HSSFChart { - private HSSFSheet sheet; - private ChartRecord chartRecord; + private HSSFSheet sheet; + private ChartRecord chartRecord; - private LegendRecord legendRecord; - @SuppressWarnings("unused") + private LegendRecord legendRecord; + @SuppressWarnings("unused") private ChartTitleFormatRecord chartTitleFormat; - private SeriesTextRecord chartTitleText; - private List valueRanges = new ArrayList<>(); - - private HSSFChartType type = HSSFChartType.Unknown; - - private List series = new ArrayList<>(); - - public enum HSSFChartType { - Area { - @Override - public short getSid() { - return 0x101A; - } - }, - Bar { - @Override - public short getSid() { - return 0x1017; - } - }, - Line { - @Override - public short getSid() { - return 0x1018; - } - }, - Pie { - @Override - public short getSid() { - return 0x1019; - } - }, - Scatter { - @Override - public short getSid() { - return 0x101B; - } - }, - Unknown { - @Override - public short getSid() { - return 0; - } - }; - - public abstract short getSid(); - } - - private HSSFChart(HSSFSheet sheet, ChartRecord chartRecord) { - this.chartRecord = chartRecord; - this.sheet = sheet; - } - - /** - * Creates a bar chart. API needs some work. :) - *

- * NOTE: Does not yet work... checking it in just so others - * can take a look. - */ - public void createBarChart( HSSFWorkbook workbook, HSSFSheet parentSheet ) - { - - List records = new ArrayList<>(); - records.add( createMSDrawingObjectRecord() ); - records.add( createOBJRecord() ); - records.add( createBOFRecord() ); - records.add(new HeaderRecord("")); - records.add(new FooterRecord("")); - records.add( createHCenterRecord() ); - records.add( createVCenterRecord() ); - records.add( createPrintSetupRecord() ); - // unknown 33 - records.add( createFontBasisRecord1() ); - records.add( createFontBasisRecord2() ); - records.add(new ProtectRecord(false)); - records.add( createUnitsRecord() ); - records.add( createChartRecord( 0, 0, 30434904, 19031616 ) ); - records.add( createBeginRecord() ); - records.add( createSCLRecord( (short) 1, (short) 1 ) ); - records.add( createPlotGrowthRecord( 65536, 65536 ) ); - records.add( createFrameRecord1() ); - records.add( createBeginRecord() ); - records.add( createLineFormatRecord(true) ); - records.add( createAreaFormatRecord1() ); - records.add( createEndRecord() ); - records.add( createSeriesRecord() ); - records.add( createBeginRecord() ); - records.add( createTitleLinkedDataRecord() ); - records.add( createValuesLinkedDataRecord() ); - records.add( createCategoriesLinkedDataRecord() ); - records.add( createDataFormatRecord() ); - // records.add(createBeginRecord()); - // unknown - // records.add(createEndRecord()); - records.add( createSeriesToChartGroupRecord() ); - records.add( createEndRecord() ); - records.add( createSheetPropsRecord() ); - records.add( createDefaultTextRecord( DefaultDataLabelTextPropertiesRecord.CATEGORY_DATA_TYPE_ALL_TEXT_CHARACTERISTIC ) ); - records.add( createAllTextRecord() ); - records.add( createBeginRecord() ); - // unknown - records.add( createFontIndexRecord( 5 ) ); - records.add( createDirectLinkRecord() ); - records.add( createEndRecord() ); - records.add( createDefaultTextRecord( (short) 3 ) ); // eek, undocumented text type - records.add( createUnknownTextRecord() ); - records.add( createBeginRecord() ); - records.add( createFontIndexRecord( (short) 6 ) ); - records.add( createDirectLinkRecord() ); - records.add( createEndRecord() ); - - records.add( createAxisUsedRecord( (short) 1 ) ); - createAxisRecords( records ); - - records.add( createEndRecord() ); - records.add( createDimensionsRecord() ); - records.add( createSeriesIndexRecord(2) ); - records.add( createSeriesIndexRecord(1) ); - records.add( createSeriesIndexRecord(3) ); - records.add(EOFRecord.instance); - - - - parentSheet.insertChartRecords( records ); - workbook.insertChartRecord(); - } - - /** - * Returns all the charts for the given sheet. - * - * NOTE: You won't be able to do very much with - * these charts yet, as this is very limited support - */ - public static HSSFChart[] getSheetCharts(HSSFSheet sheet) { - List charts = new ArrayList<>(); - HSSFChart lastChart = null; - HSSFSeries lastSeries = null; - // Find records of interest - List records = sheet.getSheet().getRecords(); - for(RecordBase r : records) { - - if(r instanceof ChartRecord) { - lastSeries = null; - lastChart = new HSSFChart(sheet,(ChartRecord)r); - charts.add(lastChart); + private SeriesTextRecord chartTitleText; + private List valueRanges = new ArrayList<>(); + + private HSSFChartType type = HSSFChartType.Unknown; + + private List series = new ArrayList<>(); + + public enum HSSFChartType { + Area { + @Override + public short getSid() { + return 0x101A; + } + }, + Bar { + @Override + public short getSid() { + return 0x1017; + } + }, + Line { + @Override + public short getSid() { + return 0x1018; + } + }, + Pie { + @Override + public short getSid() { + return 0x1019; + } + }, + Scatter { + @Override + public short getSid() { + return 0x101B; + } + }, + Unknown { + @Override + public short getSid() { + return 0; + } + }; + + public abstract short getSid(); + } + + private HSSFChart(HSSFSheet sheet, ChartRecord chartRecord) { + this.chartRecord = chartRecord; + this.sheet = sheet; + } + + /** + * Creates a bar chart. API needs some work. :) + *

+ * NOTE: Does not yet work... checking it in just so others + * can take a look. + */ + public void createBarChart( HSSFWorkbook workbook, HSSFSheet parentSheet ) + { + + List records = new ArrayList<>(); + records.add( createMSDrawingObjectRecord() ); + records.add( createOBJRecord() ); + records.add( createBOFRecord() ); + records.add(new HeaderRecord("")); + records.add(new FooterRecord("")); + records.add( createHCenterRecord() ); + records.add( createVCenterRecord() ); + records.add( createPrintSetupRecord() ); + // unknown 33 + records.add( createFontBasisRecord1() ); + records.add( createFontBasisRecord2() ); + records.add(new ProtectRecord(false)); + records.add( createUnitsRecord() ); + records.add( createChartRecord( 0, 0, 30434904, 19031616 ) ); + records.add( createBeginRecord() ); + records.add( createSCLRecord( (short) 1, (short) 1 ) ); + records.add( createPlotGrowthRecord( 65536, 65536 ) ); + records.add( createFrameRecord1() ); + records.add( createBeginRecord() ); + records.add( createLineFormatRecord(true) ); + records.add( createAreaFormatRecord1() ); + records.add( createEndRecord() ); + records.add( createSeriesRecord() ); + records.add( createBeginRecord() ); + records.add( createTitleLinkedDataRecord() ); + records.add( createValuesLinkedDataRecord() ); + records.add( createCategoriesLinkedDataRecord() ); + records.add( createDataFormatRecord() ); + // records.add(createBeginRecord()); + // unknown + // records.add(createEndRecord()); + records.add( createSeriesToChartGroupRecord() ); + records.add( createEndRecord() ); + records.add( createSheetPropsRecord() ); + records.add( createDefaultTextRecord( DefaultDataLabelTextPropertiesRecord.CATEGORY_DATA_TYPE_ALL_TEXT_CHARACTERISTIC ) ); + records.add( createAllTextRecord() ); + records.add( createBeginRecord() ); + // unknown + records.add( createFontIndexRecord( 5 ) ); + records.add( createDirectLinkRecord() ); + records.add( createEndRecord() ); + records.add( createDefaultTextRecord( (short) 3 ) ); // eek, undocumented text type + records.add( createUnknownTextRecord() ); + records.add( createBeginRecord() ); + records.add( createFontIndexRecord( (short) 6 ) ); + records.add( createDirectLinkRecord() ); + records.add( createEndRecord() ); + + records.add( createAxisUsedRecord( (short) 1 ) ); + createAxisRecords( records ); + + records.add( createEndRecord() ); + records.add( createDimensionsRecord() ); + records.add( createSeriesIndexRecord(2) ); + records.add( createSeriesIndexRecord(1) ); + records.add( createSeriesIndexRecord(3) ); + records.add(EOFRecord.instance); + + + + parentSheet.insertChartRecords( records ); + workbook.insertChartRecord(); + } + + /** + * Returns all the charts for the given sheet. + * + * NOTE: You won't be able to do very much with + * these charts yet, as this is very limited support + */ + public static HSSFChart[] getSheetCharts(HSSFSheet sheet) { + List charts = new ArrayList<>(); + HSSFChart lastChart = null; + HSSFSeries lastSeries = null; + // Find records of interest + List records = sheet.getSheet().getRecords(); + for(RecordBase r : records) { + + if(r instanceof ChartRecord) { + lastSeries = null; + lastChart = new HSSFChart(sheet,(ChartRecord)r); + charts.add(lastChart); } else if (r instanceof LinkedDataRecord) { LinkedDataRecord linkedDataRecord = (LinkedDataRecord) r; if (lastSeries != null) { lastSeries.insertData(linkedDataRecord); } - } + } if (lastChart == null) { continue; } if (r instanceof LegendRecord) { - lastChart.legendRecord = (LegendRecord)r; - } else if(r instanceof SeriesRecord) { - HSSFSeries series = new HSSFSeries( (SeriesRecord)r ); - lastChart.series.add(series); - lastSeries = series; - } else if(r instanceof ChartTitleFormatRecord) { - lastChart.chartTitleFormat = (ChartTitleFormatRecord)r; - } else if(r instanceof SeriesTextRecord) { - // Applies to a series, unless we've seen a legend already - SeriesTextRecord str = (SeriesTextRecord)r; - if(lastChart.legendRecord == null && lastChart.series.size() > 0) { - HSSFSeries series = lastChart.series.get(lastChart.series.size()-1); - series.seriesTitleText = str; - } else { - lastChart.chartTitleText = str; - } - } else if(r instanceof ValueRangeRecord){ - lastChart.valueRanges.add((ValueRangeRecord)r); - } else if (r instanceof Record) { - Record record = (Record) r; - for (HSSFChartType type : HSSFChartType.values()) { - if (type == HSSFChartType.Unknown) { - continue; - } - if (record.getSid() == type.getSid()) { - lastChart.type = type; - break; - } - } - } - } - - return charts.toArray(new HSSFChart[0]); - } - - /** Get the X offset of the chart */ - public int getChartX() { return chartRecord.getX(); } - /** Get the Y offset of the chart */ - public int getChartY() { return chartRecord.getY(); } - /** Get the width of the chart. {@link ChartRecord} */ - public int getChartWidth() { return chartRecord.getWidth(); } - /** Get the height of the chart. {@link ChartRecord} */ - public int getChartHeight() { return chartRecord.getHeight(); } - - /** Sets the X offset of the chart */ - public void setChartX(int x) { chartRecord.setX(x); } - /** Sets the Y offset of the chart */ - public void setChartY(int y) { chartRecord.setY(y); } - /** Sets the width of the chart. {@link ChartRecord} */ - public void setChartWidth(int width) { chartRecord.setWidth(width); } - /** Sets the height of the chart. {@link ChartRecord} */ - public void setChartHeight(int height) { chartRecord.setHeight(height); } - - /** - * Returns the series of the chart - */ - public HSSFSeries[] getSeries() { - return series.toArray(new HSSFSeries[0]); - } - - /** - * Returns the chart's title, if there is one, - * or null if not - */ - public String getChartTitle() { - if(chartTitleText != null) { - return chartTitleText.getText(); - } - return null; - } - - /** - * Changes the chart's title, but only if there - * was one already. - * TODO - add in the records if not - */ - public void setChartTitle(String title) { - if(chartTitleText != null) { - chartTitleText.setText(title); - } else { - throw new IllegalStateException("No chart title found to change"); - } - } - - /** - * Set value range (basic Axis Options) - * @param axisIndex 0 - primary axis, 1 - secondary axis - * @param minimum minimum value; Double.NaN - automatic; null - no change - * @param maximum maximum value; Double.NaN - automatic; null - no change - * @param majorUnit major unit value; Double.NaN - automatic; null - no change - * @param minorUnit minor unit value; Double.NaN - automatic; null - no change - */ - public void setValueRange( int axisIndex, Double minimum, Double maximum, Double majorUnit, Double minorUnit){ - ValueRangeRecord valueRange = valueRanges.get( axisIndex ); - if( valueRange == null ) return; - if( minimum != null ){ - valueRange.setAutomaticMinimum(minimum.isNaN()); - valueRange.setMinimumAxisValue(minimum); - } - if( maximum != null ){ - valueRange.setAutomaticMaximum(maximum.isNaN()); - valueRange.setMaximumAxisValue(maximum); - } - if( majorUnit != null ){ - valueRange.setAutomaticMajor(majorUnit.isNaN()); - valueRange.setMajorIncrement(majorUnit); - } - if( minorUnit != null ){ - valueRange.setAutomaticMinor(minorUnit.isNaN()); - valueRange.setMinorIncrement(minorUnit); - } - } - - private SeriesIndexRecord createSeriesIndexRecord( int index ) - { - SeriesIndexRecord r = new SeriesIndexRecord(); - r.setIndex((short)index); - return r; - } - - private DimensionsRecord createDimensionsRecord() - { - DimensionsRecord r = new DimensionsRecord(); - r.setFirstRow(0); - r.setLastRow(31); - r.setFirstCol((short)0); - r.setLastCol((short)1); - return r; - } - - private HCenterRecord createHCenterRecord() - { - HCenterRecord r = new HCenterRecord(); - r.setHCenter(false); - return r; - } - - private VCenterRecord createVCenterRecord() - { - VCenterRecord r = new VCenterRecord(); - r.setVCenter(false); - return r; - } - - private PrintSetupRecord createPrintSetupRecord() - { - PrintSetupRecord r = new PrintSetupRecord(); - r.setPaperSize((short)0); - r.setScale((short)18); - r.setPageStart((short)1); - r.setFitWidth((short)1); - r.setFitHeight((short)1); - r.setLeftToRight(false); - r.setLandscape(false); - r.setValidSettings(true); - r.setNoColor(false); - r.setDraft(false); - r.setNotes(false); - r.setNoOrientation(false); - r.setUsePage(false); - r.setHResolution((short)0); - r.setVResolution((short)0); - r.setHeaderMargin(0.5); - r.setFooterMargin(0.5); - r.setCopies((short)15); // what the ?? - return r; - } - - private FontBasisRecord createFontBasisRecord1() - { - FontBasisRecord r = new FontBasisRecord(); - r.setXBasis((short)9120); - r.setYBasis((short)5640); - r.setHeightBasis((short)200); - r.setScale((short)0); - r.setIndexToFontTable((short)5); - return r; - } - - private FontBasisRecord createFontBasisRecord2() - { - FontBasisRecord r = createFontBasisRecord1(); - r.setIndexToFontTable((short)6); - return r; - } - - private BOFRecord createBOFRecord() - { - BOFRecord r = new BOFRecord(); - r.setVersion((short)600); - r.setType((short)20); - r.setBuild((short)0x1CFE); - r.setBuildYear((short)1997); - r.setHistoryBitMask(0x40C9); - r.setRequiredVersion(106); - return r; - } - - private UnknownRecord createOBJRecord() - { - byte[] data = { - (byte) 0x15, (byte) 0x00, (byte) 0x12, (byte) 0x00, (byte) 0x05, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x11, (byte) 0x60, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xB8, (byte) 0x03, - (byte) 0x87, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - }; - - return new UnknownRecord( (short) 0x005D, data ); - } - - private UnknownRecord createMSDrawingObjectRecord() - { - // Since we haven't created this object yet we'll just put in the raw - // form for the moment. - - byte[] data = { - (byte)0x0F, (byte)0x00, (byte)0x02, (byte)0xF0, (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x10, (byte)0x00, (byte)0x08, (byte)0xF0, (byte)0x08, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x02, (byte)0x04, (byte)0x00, (byte)0x00, (byte)0x0F, (byte)0x00, (byte)0x03, (byte)0xF0, (byte)0xA8, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x0F, (byte)0x00, (byte)0x04, (byte)0xF0, (byte)0x28, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x09, (byte)0xF0, (byte)0x10, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x02, (byte)0x00, (byte)0x0A, (byte)0xF0, (byte)0x08, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x04, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x0F, (byte)0x00, (byte)0x04, (byte)0xF0, (byte)0x70, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x92, (byte)0x0C, (byte)0x0A, (byte)0xF0, (byte)0x08, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x02, (byte)0x04, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0A, (byte)0x00, (byte)0x00, (byte)0x93, (byte)0x00, (byte)0x0B, (byte)0xF0, (byte)0x36, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x7F, (byte)0x00, (byte)0x04, (byte)0x01, (byte)0x04, (byte)0x01, (byte)0xBF, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x81, (byte)0x01, (byte)0x4E, (byte)0x00, - (byte)0x00, (byte)0x08, (byte)0x83, (byte)0x01, (byte)0x4D, (byte)0x00, (byte)0x00, (byte)0x08, (byte)0xBF, (byte)0x01, (byte)0x10, (byte)0x00, (byte)0x11, (byte)0x00, (byte)0xC0, (byte)0x01, - (byte)0x4D, (byte)0x00, (byte)0x00, (byte)0x08, (byte)0xFF, (byte)0x01, (byte)0x08, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x3F, (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x02, (byte)0x00, - (byte)0xBF, (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x10, (byte)0xF0, (byte)0x12, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x04, (byte)0x00, (byte)0xC0, (byte)0x02, (byte)0x0A, (byte)0x00, (byte)0xF4, (byte)0x00, (byte)0x0E, (byte)0x00, (byte)0x66, (byte)0x01, (byte)0x20, (byte)0x00, (byte)0xE9, (byte)0x00, - (byte)0x00, (byte)0x00, (byte)0x11, (byte)0xF0, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 - }; - - return new UnknownRecord((short)0x00EC, data); - } - - private void createAxisRecords( List records ) - { - records.add( createAxisParentRecord() ); - records.add( createBeginRecord() ); - records.add( createAxisRecord( AxisRecord.AXIS_TYPE_CATEGORY_OR_X_AXIS ) ); - records.add( createBeginRecord() ); - records.add( createCategorySeriesAxisRecord() ); - records.add( createAxisOptionsRecord() ); - records.add( createTickRecord1() ); - records.add( createEndRecord() ); - records.add( createAxisRecord( AxisRecord.AXIS_TYPE_VALUE_AXIS ) ); - records.add( createBeginRecord() ); - records.add( createValueRangeRecord() ); - records.add( createTickRecord2() ); - records.add( createAxisLineFormatRecord( AxisLineFormatRecord.AXIS_TYPE_MAJOR_GRID_LINE ) ); - records.add( createLineFormatRecord(false) ); - records.add( createEndRecord() ); - records.add( createPlotAreaRecord() ); - records.add( createFrameRecord2() ); - records.add( createBeginRecord() ); - records.add( createLineFormatRecord2() ); - records.add( createAreaFormatRecord2() ); - records.add( createEndRecord() ); - records.add( createChartFormatRecord() ); - records.add( createBeginRecord() ); - records.add( createBarRecord() ); - // unknown 1022 - records.add( createLegendRecord() ); - records.add( createBeginRecord() ); - // unknown 104f - records.add( createTextRecord() ); - records.add( createBeginRecord() ); - // unknown 104f - records.add( createLinkedDataRecord() ); - records.add( createEndRecord() ); - records.add( createEndRecord() ); - records.add( createEndRecord() ); - records.add( createEndRecord() ); - } - - private LinkedDataRecord createLinkedDataRecord() - { - LinkedDataRecord r = new LinkedDataRecord(); - r.setLinkType(LinkedDataRecord.LINK_TYPE_TITLE_OR_TEXT); - r.setReferenceType(LinkedDataRecord.REFERENCE_TYPE_DIRECT); - r.setCustomNumberFormat(false); - r.setIndexNumberFmtRecord((short)0); - r.setFormulaOfLink(null); - return r; - } - - private TextRecord createTextRecord() - { - TextRecord r = new TextRecord(); - r.setHorizontalAlignment(TextRecord.HORIZONTAL_ALIGNMENT_CENTER); - r.setVerticalAlignment(TextRecord.VERTICAL_ALIGNMENT_CENTER); - r.setDisplayMode((short)1); - r.setRgbColor(0x00000000); - r.setX(-37); - r.setY(-60); - r.setWidth(0); - r.setHeight(0); - r.setAutoColor(true); - r.setShowKey(false); - r.setShowValue(false); - r.setVertical(false); - r.setAutoGeneratedText(true); - r.setGenerated(true); - r.setAutoLabelDeleted(false); - r.setAutoBackground(true); - r.setRotation((short)0); - r.setShowCategoryLabelAsPercentage(false); - r.setShowValueAsPercentage(false); - r.setShowBubbleSizes(false); - r.setShowLabel(false); - r.setIndexOfColorValue((short)77); - r.setDataLabelPlacement((short)0); - r.setTextRotation((short)0); - return r; - } - - private LegendRecord createLegendRecord() - { - LegendRecord r = new LegendRecord(); - r.setXAxisUpperLeft(3542); - r.setYAxisUpperLeft(1566); - r.setXSize(437); - r.setYSize(213); - r.setType(LegendRecord.TYPE_RIGHT); - r.setSpacing(LegendRecord.SPACING_MEDIUM); - r.setAutoPosition(true); - r.setAutoSeries(true); - r.setAutoXPositioning(true); - r.setAutoYPositioning(true); - r.setVertical(true); - r.setDataTable(false); - return r; - } - - private BarRecord createBarRecord() - { - BarRecord r = new BarRecord(); - r.setBarSpace((short)0); - r.setCategorySpace((short)150); - r.setHorizontal(false); - r.setStacked(false); - r.setDisplayAsPercentage(false); - r.setShadow(false); - return r; - } - - private ChartFormatRecord createChartFormatRecord() - { - ChartFormatRecord r = new ChartFormatRecord(); - r.setXPosition(0); - r.setYPosition(0); - r.setWidth(0); - r.setHeight(0); - r.setVaryDisplayPattern(false); - return r; - } - - private PlotAreaRecord createPlotAreaRecord() - { + lastChart.legendRecord = (LegendRecord)r; + } else if(r instanceof SeriesRecord) { + HSSFSeries series = new HSSFSeries( (SeriesRecord)r ); + lastChart.series.add(series); + lastSeries = series; + } else if(r instanceof ChartTitleFormatRecord) { + lastChart.chartTitleFormat = (ChartTitleFormatRecord)r; + } else if(r instanceof SeriesTextRecord) { + // Applies to a series, unless we've seen a legend already + SeriesTextRecord str = (SeriesTextRecord)r; + if(lastChart.legendRecord == null && lastChart.series.size() > 0) { + HSSFSeries series = lastChart.series.get(lastChart.series.size()-1); + series.seriesTitleText = str; + } else { + lastChart.chartTitleText = str; + } + } else if(r instanceof ValueRangeRecord){ + lastChart.valueRanges.add((ValueRangeRecord)r); + } else if (r instanceof Record) { + Record record = (Record) r; + for (HSSFChartType type : HSSFChartType.values()) { + if (type == HSSFChartType.Unknown) { + continue; + } + if (record.getSid() == type.getSid()) { + lastChart.type = type; + break; + } + } + } + } + + return charts.toArray(new HSSFChart[0]); + } + + /** Get the X offset of the chart */ + public int getChartX() { return chartRecord.getX(); } + /** Get the Y offset of the chart */ + public int getChartY() { return chartRecord.getY(); } + /** Get the width of the chart. {@link ChartRecord} */ + public int getChartWidth() { return chartRecord.getWidth(); } + /** Get the height of the chart. {@link ChartRecord} */ + public int getChartHeight() { return chartRecord.getHeight(); } + + /** Sets the X offset of the chart */ + public void setChartX(int x) { chartRecord.setX(x); } + /** Sets the Y offset of the chart */ + public void setChartY(int y) { chartRecord.setY(y); } + /** Sets the width of the chart. {@link ChartRecord} */ + public void setChartWidth(int width) { chartRecord.setWidth(width); } + /** Sets the height of the chart. {@link ChartRecord} */ + public void setChartHeight(int height) { chartRecord.setHeight(height); } + + /** + * Returns the series of the chart + */ + public HSSFSeries[] getSeries() { + return series.toArray(new HSSFSeries[0]); + } + + /** + * Returns the chart's title, if there is one, + * or null if not + */ + public String getChartTitle() { + if(chartTitleText != null) { + return chartTitleText.getText(); + } + return null; + } + + /** + * Changes the chart's title, but only if there + * was one already. + * TODO - add in the records if not + */ + public void setChartTitle(String title) { + if(chartTitleText != null) { + chartTitleText.setText(title); + } else { + throw new IllegalStateException("No chart title found to change"); + } + } + + /** + * Set value range (basic Axis Options) + * @param axisIndex 0 - primary axis, 1 - secondary axis + * @param minimum minimum value; Double.NaN - automatic; null - no change + * @param maximum maximum value; Double.NaN - automatic; null - no change + * @param majorUnit major unit value; Double.NaN - automatic; null - no change + * @param minorUnit minor unit value; Double.NaN - automatic; null - no change + */ + public void setValueRange( int axisIndex, Double minimum, Double maximum, Double majorUnit, Double minorUnit){ + ValueRangeRecord valueRange = valueRanges.get( axisIndex ); + if( valueRange == null ) return; + if( minimum != null ){ + valueRange.setAutomaticMinimum(minimum.isNaN()); + valueRange.setMinimumAxisValue(minimum); + } + if( maximum != null ){ + valueRange.setAutomaticMaximum(maximum.isNaN()); + valueRange.setMaximumAxisValue(maximum); + } + if( majorUnit != null ){ + valueRange.setAutomaticMajor(majorUnit.isNaN()); + valueRange.setMajorIncrement(majorUnit); + } + if( minorUnit != null ){ + valueRange.setAutomaticMinor(minorUnit.isNaN()); + valueRange.setMinorIncrement(minorUnit); + } + } + + private SeriesIndexRecord createSeriesIndexRecord( int index ) + { + SeriesIndexRecord r = new SeriesIndexRecord(); + r.setIndex((short)index); + return r; + } + + private DimensionsRecord createDimensionsRecord() + { + DimensionsRecord r = new DimensionsRecord(); + r.setFirstRow(0); + r.setLastRow(31); + r.setFirstCol((short)0); + r.setLastCol((short)1); + return r; + } + + private HCenterRecord createHCenterRecord() + { + HCenterRecord r = new HCenterRecord(); + r.setHCenter(false); + return r; + } + + private VCenterRecord createVCenterRecord() + { + VCenterRecord r = new VCenterRecord(); + r.setVCenter(false); + return r; + } + + private PrintSetupRecord createPrintSetupRecord() + { + PrintSetupRecord r = new PrintSetupRecord(); + r.setPaperSize((short)0); + r.setScale((short)18); + r.setPageStart((short)1); + r.setFitWidth((short)1); + r.setFitHeight((short)1); + r.setLeftToRight(false); + r.setLandscape(false); + r.setValidSettings(true); + r.setNoColor(false); + r.setDraft(false); + r.setNotes(false); + r.setNoOrientation(false); + r.setUsePage(false); + r.setHResolution((short)0); + r.setVResolution((short)0); + r.setHeaderMargin(0.5); + r.setFooterMargin(0.5); + r.setCopies((short)15); // what the ?? + return r; + } + + private FontBasisRecord createFontBasisRecord1() + { + FontBasisRecord r = new FontBasisRecord(); + r.setXBasis((short)9120); + r.setYBasis((short)5640); + r.setHeightBasis((short)200); + r.setScale((short)0); + r.setIndexToFontTable((short)5); + return r; + } + + private FontBasisRecord createFontBasisRecord2() + { + FontBasisRecord r = createFontBasisRecord1(); + r.setIndexToFontTable((short)6); + return r; + } + + private BOFRecord createBOFRecord() + { + BOFRecord r = new BOFRecord(); + r.setVersion((short)600); + r.setType((short)20); + r.setBuild((short)0x1CFE); + r.setBuildYear((short)1997); + r.setHistoryBitMask(0x40C9); + r.setRequiredVersion(106); + return r; + } + + private UnknownRecord createOBJRecord() + { + byte[] data = { + (byte) 0x15, (byte) 0x00, (byte) 0x12, (byte) 0x00, (byte) 0x05, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x11, (byte) 0x60, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xB8, (byte) 0x03, + (byte) 0x87, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + }; + + return new UnknownRecord( (short) 0x005D, data ); + } + + private UnknownRecord createMSDrawingObjectRecord() + { + // Since we haven't created this object yet we'll just put in the raw + // form for the moment. + + byte[] data = { + (byte)0x0F, (byte)0x00, (byte)0x02, (byte)0xF0, (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x10, (byte)0x00, (byte)0x08, (byte)0xF0, (byte)0x08, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x02, (byte)0x04, (byte)0x00, (byte)0x00, (byte)0x0F, (byte)0x00, (byte)0x03, (byte)0xF0, (byte)0xA8, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x0F, (byte)0x00, (byte)0x04, (byte)0xF0, (byte)0x28, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x09, (byte)0xF0, (byte)0x10, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x02, (byte)0x00, (byte)0x0A, (byte)0xF0, (byte)0x08, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x04, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x0F, (byte)0x00, (byte)0x04, (byte)0xF0, (byte)0x70, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x92, (byte)0x0C, (byte)0x0A, (byte)0xF0, (byte)0x08, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x02, (byte)0x04, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0A, (byte)0x00, (byte)0x00, (byte)0x93, (byte)0x00, (byte)0x0B, (byte)0xF0, (byte)0x36, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x7F, (byte)0x00, (byte)0x04, (byte)0x01, (byte)0x04, (byte)0x01, (byte)0xBF, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x81, (byte)0x01, (byte)0x4E, (byte)0x00, + (byte)0x00, (byte)0x08, (byte)0x83, (byte)0x01, (byte)0x4D, (byte)0x00, (byte)0x00, (byte)0x08, (byte)0xBF, (byte)0x01, (byte)0x10, (byte)0x00, (byte)0x11, (byte)0x00, (byte)0xC0, (byte)0x01, + (byte)0x4D, (byte)0x00, (byte)0x00, (byte)0x08, (byte)0xFF, (byte)0x01, (byte)0x08, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x3F, (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x02, (byte)0x00, + (byte)0xBF, (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x10, (byte)0xF0, (byte)0x12, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x04, (byte)0x00, (byte)0xC0, (byte)0x02, (byte)0x0A, (byte)0x00, (byte)0xF4, (byte)0x00, (byte)0x0E, (byte)0x00, (byte)0x66, (byte)0x01, (byte)0x20, (byte)0x00, (byte)0xE9, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x11, (byte)0xF0, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 + }; + + return new UnknownRecord((short)0x00EC, data); + } + + private void createAxisRecords( List records ) + { + records.add( createAxisParentRecord() ); + records.add( createBeginRecord() ); + records.add( createAxisRecord( AxisRecord.AXIS_TYPE_CATEGORY_OR_X_AXIS ) ); + records.add( createBeginRecord() ); + records.add( createCategorySeriesAxisRecord() ); + records.add( createAxisOptionsRecord() ); + records.add( createTickRecord1() ); + records.add( createEndRecord() ); + records.add( createAxisRecord( AxisRecord.AXIS_TYPE_VALUE_AXIS ) ); + records.add( createBeginRecord() ); + records.add( createValueRangeRecord() ); + records.add( createTickRecord2() ); + records.add( createAxisLineFormatRecord( AxisLineFormatRecord.AXIS_TYPE_MAJOR_GRID_LINE ) ); + records.add( createLineFormatRecord(false) ); + records.add( createEndRecord() ); + records.add( createPlotAreaRecord() ); + records.add( createFrameRecord2() ); + records.add( createBeginRecord() ); + records.add( createLineFormatRecord2() ); + records.add( createAreaFormatRecord2() ); + records.add( createEndRecord() ); + records.add( createChartFormatRecord() ); + records.add( createBeginRecord() ); + records.add( createBarRecord() ); + // unknown 1022 + records.add( createLegendRecord() ); + records.add( createBeginRecord() ); + // unknown 104f + records.add( createTextRecord() ); + records.add( createBeginRecord() ); + // unknown 104f + records.add( createLinkedDataRecord() ); + records.add( createEndRecord() ); + records.add( createEndRecord() ); + records.add( createEndRecord() ); + records.add( createEndRecord() ); + } + + private LinkedDataRecord createLinkedDataRecord() + { + LinkedDataRecord r = new LinkedDataRecord(); + r.setLinkType(LinkedDataRecord.LINK_TYPE_TITLE_OR_TEXT); + r.setReferenceType(LinkedDataRecord.REFERENCE_TYPE_DIRECT); + r.setCustomNumberFormat(false); + r.setIndexNumberFmtRecord((short)0); + r.setFormulaOfLink(null); + return r; + } + + private TextRecord createTextRecord() + { + TextRecord r = new TextRecord(); + r.setHorizontalAlignment(TextRecord.HORIZONTAL_ALIGNMENT_CENTER); + r.setVerticalAlignment(TextRecord.VERTICAL_ALIGNMENT_CENTER); + r.setDisplayMode((short)1); + r.setRgbColor(0x00000000); + r.setX(-37); + r.setY(-60); + r.setWidth(0); + r.setHeight(0); + r.setAutoColor(true); + r.setShowKey(false); + r.setShowValue(false); + r.setVertical(false); + r.setAutoGeneratedText(true); + r.setGenerated(true); + r.setAutoLabelDeleted(false); + r.setAutoBackground(true); + r.setRotation((short)0); + r.setShowCategoryLabelAsPercentage(false); + r.setShowValueAsPercentage(false); + r.setShowBubbleSizes(false); + r.setShowLabel(false); + r.setIndexOfColorValue((short)77); + r.setDataLabelPlacement((short)0); + r.setTextRotation((short)0); + return r; + } + + private LegendRecord createLegendRecord() + { + LegendRecord r = new LegendRecord(); + r.setXAxisUpperLeft(3542); + r.setYAxisUpperLeft(1566); + r.setXSize(437); + r.setYSize(213); + r.setType(LegendRecord.TYPE_RIGHT); + r.setSpacing(LegendRecord.SPACING_MEDIUM); + r.setAutoPosition(true); + r.setAutoSeries(true); + r.setAutoXPositioning(true); + r.setAutoYPositioning(true); + r.setVertical(true); + r.setDataTable(false); + return r; + } + + private BarRecord createBarRecord() + { + BarRecord r = new BarRecord(); + r.setBarSpace((short)0); + r.setCategorySpace((short)150); + r.setHorizontal(false); + r.setStacked(false); + r.setDisplayAsPercentage(false); + r.setShadow(false); + return r; + } + + private ChartFormatRecord createChartFormatRecord() + { + ChartFormatRecord r = new ChartFormatRecord(); + r.setXPosition(0); + r.setYPosition(0); + r.setWidth(0); + r.setHeight(0); + r.setVaryDisplayPattern(false); + return r; + } + + private PlotAreaRecord createPlotAreaRecord() + { return new PlotAreaRecord( ); - } - - private AxisLineFormatRecord createAxisLineFormatRecord( short format ) - { - AxisLineFormatRecord r = new AxisLineFormatRecord(); - r.setAxisType( format ); - return r; - } - - private ValueRangeRecord createValueRangeRecord() - { - ValueRangeRecord r = new ValueRangeRecord(); - r.setMinimumAxisValue( 0.0 ); - r.setMaximumAxisValue( 0.0 ); - r.setMajorIncrement( 0 ); - r.setMinorIncrement( 0 ); - r.setCategoryAxisCross( 0 ); - r.setAutomaticMinimum( true ); - r.setAutomaticMaximum( true ); - r.setAutomaticMajor( true ); - r.setAutomaticMinor( true ); - r.setAutomaticCategoryCrossing( true ); - r.setLogarithmicScale( false ); - r.setValuesInReverse( false ); - r.setCrossCategoryAxisAtMaximum( false ); - r.setReserved( true ); // what's this do?? - return r; - } - - private TickRecord createTickRecord1() - { - TickRecord r = new TickRecord(); - r.setMajorTickType( (byte) 2 ); - r.setMinorTickType( (byte) 0 ); - r.setLabelPosition( (byte) 3 ); - r.setBackground( (byte) 1 ); - r.setLabelColorRgb( 0 ); - r.setZero1( (short) 0 ); - r.setZero2( (short) 0 ); - r.setZero3( (short) 45 ); - r.setAutorotate( true ); - r.setAutoTextBackground( true ); - r.setRotation( (short) 0 ); - r.setAutorotate( true ); - r.setTickColor( (short) 77 ); - return r; - } - - private TickRecord createTickRecord2() - { - TickRecord r = createTickRecord1(); - r.setZero3((short)0); - return r; - } - - private AxisOptionsRecord createAxisOptionsRecord() - { - AxisOptionsRecord r = new AxisOptionsRecord(); - r.setMinimumCategory( (short) -28644 ); - r.setMaximumCategory( (short) -28715 ); - r.setMajorUnitValue( (short) 2 ); - r.setMajorUnit( (short) 0 ); - r.setMinorUnitValue( (short) 1 ); - r.setMinorUnit( (short) 0 ); - r.setBaseUnit( (short) 0 ); - r.setCrossingPoint( (short) -28644 ); - r.setDefaultMinimum( true ); - r.setDefaultMaximum( true ); - r.setDefaultMajor( true ); - r.setDefaultMinorUnit( true ); - r.setIsDate( true ); - r.setDefaultBase( true ); - r.setDefaultCross( true ); - r.setDefaultDateSettings( true ); - return r; - } - - private CategorySeriesAxisRecord createCategorySeriesAxisRecord() - { - CategorySeriesAxisRecord r = new CategorySeriesAxisRecord(); - r.setCrossingPoint( (short) 1 ); - r.setLabelFrequency( (short) 1 ); - r.setTickMarkFrequency( (short) 1 ); - r.setValueAxisCrossing( true ); - r.setCrossesFarRight( false ); - r.setReversed( false ); - return r; - } - - private AxisRecord createAxisRecord( short axisType ) - { - AxisRecord r = new AxisRecord(); - r.setAxisType( axisType ); - return r; - } - - private AxisParentRecord createAxisParentRecord() - { - AxisParentRecord r = new AxisParentRecord(); - r.setAxisType( AxisParentRecord.AXIS_TYPE_MAIN ); - r.setX( 479 ); - r.setY( 221 ); - r.setWidth( 2995 ); - r.setHeight( 2902 ); - return r; - } - - private AxisUsedRecord createAxisUsedRecord( short numAxis ) - { - AxisUsedRecord r = new AxisUsedRecord(); - r.setNumAxis( numAxis ); - return r; - } - - private LinkedDataRecord createDirectLinkRecord() - { - LinkedDataRecord r = new LinkedDataRecord(); - r.setLinkType( LinkedDataRecord.LINK_TYPE_TITLE_OR_TEXT ); - r.setReferenceType( LinkedDataRecord.REFERENCE_TYPE_DIRECT ); - r.setCustomNumberFormat( false ); - r.setIndexNumberFmtRecord( (short) 0 ); - r.setFormulaOfLink(null); - return r; - } - - private FontIndexRecord createFontIndexRecord( int index ) - { - FontIndexRecord r = new FontIndexRecord(); - r.setFontIndex( (short) index ); - return r; - } - - private TextRecord createAllTextRecord() - { - TextRecord r = new TextRecord(); - r.setHorizontalAlignment( TextRecord.HORIZONTAL_ALIGNMENT_CENTER ); - r.setVerticalAlignment( TextRecord.VERTICAL_ALIGNMENT_CENTER ); - r.setDisplayMode( TextRecord.DISPLAY_MODE_TRANSPARENT ); - r.setRgbColor( 0 ); - r.setX( -37 ); - r.setY( -60 ); - r.setWidth( 0 ); - r.setHeight( 0 ); - r.setAutoColor( true ); - r.setShowKey( false ); - r.setShowValue( true ); - r.setVertical( false ); - r.setAutoGeneratedText( true ); - r.setGenerated( true ); - r.setAutoLabelDeleted( false ); - r.setAutoBackground( true ); - r.setRotation( (short) 0 ); - r.setShowCategoryLabelAsPercentage( false ); - r.setShowValueAsPercentage( false ); - r.setShowBubbleSizes( false ); - r.setShowLabel( false ); - r.setIndexOfColorValue( (short) 77 ); - r.setDataLabelPlacement( (short) 0 ); - r.setTextRotation( (short) 0 ); - return r; - } - - private TextRecord createUnknownTextRecord() - { - TextRecord r = new TextRecord(); - r.setHorizontalAlignment( TextRecord.HORIZONTAL_ALIGNMENT_CENTER ); - r.setVerticalAlignment( TextRecord.VERTICAL_ALIGNMENT_CENTER ); - r.setDisplayMode( TextRecord.DISPLAY_MODE_TRANSPARENT ); - r.setRgbColor( 0 ); - r.setX( -37 ); - r.setY( -60 ); - r.setWidth( 0 ); - r.setHeight( 0 ); - r.setAutoColor( true ); - r.setShowKey( false ); - r.setShowValue( false ); - r.setVertical( false ); - r.setAutoGeneratedText( true ); - r.setGenerated( true ); - r.setAutoLabelDeleted( false ); - r.setAutoBackground( true ); - r.setRotation( (short) 0 ); - r.setShowCategoryLabelAsPercentage( false ); - r.setShowValueAsPercentage( false ); - r.setShowBubbleSizes( false ); - r.setShowLabel( false ); - r.setIndexOfColorValue( (short) 77 ); - r.setDataLabelPlacement( (short) 11088 ); - r.setTextRotation( (short) 0 ); - return r; - } - - private DefaultDataLabelTextPropertiesRecord createDefaultTextRecord( short categoryDataType ) - { - DefaultDataLabelTextPropertiesRecord r = new DefaultDataLabelTextPropertiesRecord(); - r.setCategoryDataType( categoryDataType ); - return r; - } - - private SheetPropertiesRecord createSheetPropsRecord() - { - SheetPropertiesRecord r = new SheetPropertiesRecord(); - r.setChartTypeManuallyFormatted( false ); - r.setPlotVisibleOnly( true ); - r.setDoNotSizeWithWindow( false ); - r.setDefaultPlotDimensions( true ); - r.setAutoPlotArea( false ); - return r; - } - - private SeriesToChartGroupRecord createSeriesToChartGroupRecord() - { - return new SeriesToChartGroupRecord(); - } - - private DataFormatRecord createDataFormatRecord() - { - DataFormatRecord r = new DataFormatRecord(); - r.setPointNumber( (short) -1 ); - r.setSeriesIndex( (short) 0 ); - r.setSeriesNumber( (short) 0 ); - r.setUseExcel4Colors( false ); - return r; - } - - private LinkedDataRecord createCategoriesLinkedDataRecord() - { - LinkedDataRecord r = new LinkedDataRecord(); - r.setLinkType( LinkedDataRecord.LINK_TYPE_CATEGORIES ); - r.setReferenceType( LinkedDataRecord.REFERENCE_TYPE_WORKSHEET ); - r.setCustomNumberFormat( false ); - r.setIndexNumberFmtRecord( (short) 0 ); - Area3DPtg p = new Area3DPtg(0, 31, 1, 1, - false, false, false, false, 0); - r.setFormulaOfLink(new Ptg[] { p, }); - return r; - } - - private LinkedDataRecord createValuesLinkedDataRecord() - { - LinkedDataRecord r = new LinkedDataRecord(); - r.setLinkType( LinkedDataRecord.LINK_TYPE_VALUES ); - r.setReferenceType( LinkedDataRecord.REFERENCE_TYPE_WORKSHEET ); - r.setCustomNumberFormat( false ); - r.setIndexNumberFmtRecord( (short) 0 ); - Area3DPtg p = new Area3DPtg(0, 31, 0, 0, - false, false, false, false, 0); - r.setFormulaOfLink(new Ptg[] { p, }); - return r; - } - - private LinkedDataRecord createTitleLinkedDataRecord() - { - LinkedDataRecord r = new LinkedDataRecord(); - r.setLinkType( LinkedDataRecord.LINK_TYPE_TITLE_OR_TEXT ); - r.setReferenceType( LinkedDataRecord.REFERENCE_TYPE_DIRECT ); - r.setCustomNumberFormat( false ); - r.setIndexNumberFmtRecord( (short) 0 ); - r.setFormulaOfLink(null); - return r; - } - - private SeriesRecord createSeriesRecord() - { - SeriesRecord r = new SeriesRecord(); - r.setCategoryDataType( SeriesRecord.CATEGORY_DATA_TYPE_NUMERIC ); - r.setValuesDataType( SeriesRecord.VALUES_DATA_TYPE_NUMERIC ); - r.setNumCategories( (short) 32 ); - r.setNumValues( (short) 31 ); - r.setBubbleSeriesType( SeriesRecord.BUBBLE_SERIES_TYPE_NUMERIC ); - r.setNumBubbleValues( (short) 0 ); - return r; - } - - private EndRecord createEndRecord() - { - return new EndRecord(); - } - - private AreaFormatRecord createAreaFormatRecord1() - { - AreaFormatRecord r = new AreaFormatRecord(); - r.setForegroundColor( 16777215 ); // RGB Color - r.setBackgroundColor( 0 ); // RGB Color - r.setPattern( (short) 1 ); // TODO: Add Pattern constants to record - r.setAutomatic( true ); - r.setInvert( false ); - r.setForecolorIndex( (short) 78 ); - r.setBackcolorIndex( (short) 77 ); - return r; - } - - private AreaFormatRecord createAreaFormatRecord2() - { - AreaFormatRecord r = new AreaFormatRecord(); - r.setForegroundColor(0x00c0c0c0); - r.setBackgroundColor(0x00000000); - r.setPattern((short)1); - r.setAutomatic(false); - r.setInvert(false); - r.setForecolorIndex((short)22); - r.setBackcolorIndex((short)79); - return r; - } - - private LineFormatRecord createLineFormatRecord( boolean drawTicks ) - { - LineFormatRecord r = new LineFormatRecord(); - r.setLineColor( 0 ); - r.setLinePattern( LineFormatRecord.LINE_PATTERN_SOLID ); - r.setWeight( (short) -1 ); - r.setAuto( true ); - r.setDrawTicks( drawTicks ); - r.setColourPaletteIndex( (short) 77 ); // what colour is this? - return r; - } - - private LineFormatRecord createLineFormatRecord2() - { - LineFormatRecord r = new LineFormatRecord(); - r.setLineColor( 0x00808080 ); - r.setLinePattern( (short) 0 ); - r.setWeight( (short) 0 ); - r.setAuto( false ); - r.setDrawTicks( false ); - r.setUnknown( false ); - r.setColourPaletteIndex( (short) 23 ); - return r; - } - - private FrameRecord createFrameRecord1() - { - FrameRecord r = new FrameRecord(); - r.setBorderType( FrameRecord.BORDER_TYPE_REGULAR ); - r.setAutoSize( false ); - r.setAutoPosition( true ); - return r; - } - - private FrameRecord createFrameRecord2() - { - FrameRecord r = new FrameRecord(); - r.setBorderType( FrameRecord.BORDER_TYPE_REGULAR ); - r.setAutoSize( true ); - r.setAutoPosition( true ); - return r; - } - - private PlotGrowthRecord createPlotGrowthRecord( int horizScale, int vertScale ) - { - PlotGrowthRecord r = new PlotGrowthRecord(); - r.setHorizontalScale( horizScale ); - r.setVerticalScale( vertScale ); - return r; - } - - private SCLRecord createSCLRecord( short numerator, short denominator ) - { - SCLRecord r = new SCLRecord(); - r.setDenominator( denominator ); - r.setNumerator( numerator ); - return r; - } - - private BeginRecord createBeginRecord() - { - return new BeginRecord(); - } - - private ChartRecord createChartRecord( int x, int y, int width, int height ) - { - ChartRecord r = new ChartRecord(); - r.setX( x ); - r.setY( y ); - r.setWidth( width ); - r.setHeight( height ); - return r; - } - - private UnitsRecord createUnitsRecord() - { - UnitsRecord r = new UnitsRecord(); - r.setUnits( (short) 0 ); - return r; - } - - - /** - * A series in a chart - */ - public static class HSSFSeries { - private SeriesRecord series; - private SeriesTextRecord seriesTitleText; - private LinkedDataRecord dataName; - private LinkedDataRecord dataValues; - private LinkedDataRecord dataCategoryLabels; - private LinkedDataRecord dataSecondaryCategoryLabels; - - /* package */ HSSFSeries(SeriesRecord series) { - this.series = series; - } - - /* package */ void insertData(LinkedDataRecord data){ - switch(data.getLinkType()){ - - case LinkedDataRecord.LINK_TYPE_TITLE_OR_TEXT: - dataName = data; - break; - case LinkedDataRecord.LINK_TYPE_VALUES: - dataValues = data; - break; - case LinkedDataRecord.LINK_TYPE_CATEGORIES: - dataCategoryLabels = data; - break; - case LinkedDataRecord.LINK_TYPE_SECONDARY_CATEGORIES: - dataSecondaryCategoryLabels = data; - break; - default: - throw new IllegalStateException("Invalid link type: " + data.getLinkType()); - } - } - - /* package */ void setSeriesTitleText(SeriesTextRecord seriesTitleText) - { - this.seriesTitleText = seriesTitleText; - } - - public short getNumValues() { - return series.getNumValues(); - } - /** - * See {@link SeriesRecord} - */ - public short getValueType() { - return series.getValuesDataType(); - } - - /** - * Returns the series' title, if there is one, - * or null if not - */ - public String getSeriesTitle() { - if(seriesTitleText != null) { - return seriesTitleText.getText(); - } - return null; - } - - /** - * Changes the series' title, but only if there - * was one already. - * TODO - add in the records if not - */ - public void setSeriesTitle(String title) { - if(seriesTitleText != null) { - seriesTitleText.setText(title); - } else { - throw new IllegalStateException("No series title found to change"); - } - } - - /** - * @return record with data names - */ - public LinkedDataRecord getDataName(){ - return dataName; - } - - /** - * @return record with data values - */ - public LinkedDataRecord getDataValues(){ - return dataValues; - } - - /** - * @return record with data category labels - */ - public LinkedDataRecord getDataCategoryLabels(){ - return dataCategoryLabels; - } - - /** - * @return record with data secondary category labels - */ - public LinkedDataRecord getDataSecondaryCategoryLabels() { - return dataSecondaryCategoryLabels; - } - - /** - * @return record with series - */ - public SeriesRecord getSeries() { - return series; - } - - private CellRangeAddressBase getCellRange(LinkedDataRecord linkedDataRecord) { - if (linkedDataRecord == null) - { - return null ; - } - - int firstRow = 0; - int lastRow = 0; - int firstCol = 0; - int lastCol = 0; - - for (Ptg ptg : linkedDataRecord.getFormulaOfLink()) { - if (ptg instanceof AreaPtgBase) { - AreaPtgBase areaPtg = (AreaPtgBase) ptg; - - firstRow = areaPtg.getFirstRow(); - lastRow = areaPtg.getLastRow(); - - firstCol = areaPtg.getFirstColumn(); - lastCol = areaPtg.getLastColumn(); - } - } - - return new CellRangeAddress(firstRow, lastRow, firstCol, lastCol); - } - - public CellRangeAddressBase getValuesCellRange() { - return getCellRange(dataValues); - } - - public CellRangeAddressBase getCategoryLabelsCellRange() { - return getCellRange(dataCategoryLabels); - } - - private Integer setVerticalCellRange(LinkedDataRecord linkedDataRecord, - CellRangeAddressBase range) { - if (linkedDataRecord == null) - { - return null; - } - - List ptgList = new ArrayList<>(); - - int rowCount = (range.getLastRow() - range.getFirstRow()) + 1; - int colCount = (range.getLastColumn() - range.getFirstColumn()) + 1; - - for (Ptg ptg : linkedDataRecord.getFormulaOfLink()) { - if (ptg instanceof AreaPtgBase) { - AreaPtgBase areaPtg = (AreaPtgBase) ptg; - - areaPtg.setFirstRow(range.getFirstRow()); - areaPtg.setLastRow(range.getLastRow()); - - areaPtg.setFirstColumn(range.getFirstColumn()); - areaPtg.setLastColumn(range.getLastColumn()); - ptgList.add(areaPtg); - } - } - - linkedDataRecord.setFormulaOfLink(ptgList.toArray(new Ptg[0])); - - return rowCount * colCount; - } - - public void setValuesCellRange(CellRangeAddressBase range) { - Integer count = setVerticalCellRange(dataValues, range); - if (count == null) - { - return; - } - - series.setNumValues((short)(int)count); - } - - public void setCategoryLabelsCellRange(CellRangeAddressBase range) { - Integer count = setVerticalCellRange(dataCategoryLabels, range); - if (count == null) - { - return; - } - - series.setNumCategories((short)(int)count); - } - } - - public HSSFSeries createSeries() throws Exception { - ArrayList seriesTemplate = new ArrayList<>(); - boolean seriesTemplateFilled = false; - - int idx = 0; - int deep = 0; - int chartRecordIdx = -1; - int chartDeep = -1; - int lastSeriesDeep = -1; - int endSeriesRecordIdx = -1; - int seriesIdx = 0; - final List records = sheet.getSheet().getRecords(); - - /* store first series as template and find last series index */ - for(final RecordBase record : records) { - - idx++; - - if (record instanceof BeginRecord) { - deep++; - } else if (record instanceof EndRecord) { - deep--; - - if (lastSeriesDeep == deep) { - lastSeriesDeep = -1; - endSeriesRecordIdx = idx; - if (!seriesTemplateFilled) { - seriesTemplate.add(record); - seriesTemplateFilled = true; - } - } - - if (chartDeep == deep) { - break; - } - } - - if (record instanceof ChartRecord) { - if (record == chartRecord) { - chartRecordIdx = idx; - chartDeep = deep; - } - } else if (record instanceof SeriesRecord) { - if (chartRecordIdx != -1) { - seriesIdx++; - lastSeriesDeep = deep; - } - } - - if (lastSeriesDeep != -1 && !seriesTemplateFilled) { - seriesTemplate.add(record) ; - } - } - - /* check if a series was found */ - if (endSeriesRecordIdx == -1) { - return null; - } - - /* next index in the records list where the new series can be inserted */ - idx = endSeriesRecordIdx + 1; - - HSSFSeries newSeries = null; - - /* duplicate record of the template series */ - ArrayList clonedRecords = new ArrayList<>(); - for(final RecordBase record : seriesTemplate) { - - Record newRecord = null; - - if (record instanceof BeginRecord) { - newRecord = new BeginRecord(); - } else if (record instanceof EndRecord) { - newRecord = new EndRecord(); - } else if (record instanceof SeriesRecord) { - SeriesRecord seriesRecord = (SeriesRecord) ((SeriesRecord)record).clone(); - newSeries = new HSSFSeries(seriesRecord); - newRecord = seriesRecord; - } else if (record instanceof LinkedDataRecord) { - LinkedDataRecord linkedDataRecord = ((LinkedDataRecord)record).clone(); - if (newSeries != null) { - newSeries.insertData(linkedDataRecord); - } - newRecord = linkedDataRecord; - } else if (record instanceof DataFormatRecord) { - DataFormatRecord dataFormatRecord = ((DataFormatRecord)record).clone(); - - dataFormatRecord.setSeriesIndex((short)seriesIdx) ; - dataFormatRecord.setSeriesNumber((short)seriesIdx) ; - - newRecord = dataFormatRecord; - } else if (record instanceof SeriesTextRecord) { - SeriesTextRecord seriesTextRecord = (SeriesTextRecord) ((SeriesTextRecord)record).clone(); - if (newSeries != null) { - newSeries.setSeriesTitleText(seriesTextRecord); - } - newRecord = seriesTextRecord; - } else if (record instanceof Record) { - newRecord = (Record) ((Record)record).clone(); - } - - if (newRecord != null) - { - clonedRecords.add(newRecord); - } - } - - /* check if a user model series object was created */ - if (newSeries == null) - { - return null; - } - - /* transfer series to record list */ - for(final RecordBase record : clonedRecords) { - records.add(idx++, record); - } - - return newSeries; - } - - public boolean removeSeries(HSSFSeries remSeries) { - int deep = 0; - int chartDeep = -1; - int lastSeriesDeep = -1; - int seriesIdx = -1; - boolean removeSeries = false; - boolean chartEntered = false; - boolean result = false; - final List records = sheet.getSheet().getRecords(); - - /* store first series as template and find last series index */ - Iterator iter = records.iterator(); - while (iter.hasNext()) { - RecordBase record = iter.next(); - - if (record instanceof BeginRecord) { - deep++; - } else if (record instanceof EndRecord) { - deep--; - - if (lastSeriesDeep == deep) { - lastSeriesDeep = -1; - - if (removeSeries) { - removeSeries = false; - result = true; - iter.remove(); - } - } - - if (chartDeep == deep) { - break; - } - } - - if (record instanceof ChartRecord) { - if (record == chartRecord) { - chartDeep = deep; - chartEntered = true; - } - } else if (record instanceof SeriesRecord) { - if (chartEntered) { - if (remSeries.series == record) { - lastSeriesDeep = deep; - removeSeries = true; - } else { - seriesIdx++; - } - } - } else if (record instanceof DataFormatRecord) { - if (chartEntered && !removeSeries) { - DataFormatRecord dataFormatRecord = (DataFormatRecord) record; - dataFormatRecord.setSeriesIndex((short) seriesIdx); - dataFormatRecord.setSeriesNumber((short) seriesIdx); - } - } - - if (removeSeries) { - iter.remove(); - } - } - - return result; - } - - public HSSFChartType getType() { - return type; - } + } + + private AxisLineFormatRecord createAxisLineFormatRecord( short format ) + { + AxisLineFormatRecord r = new AxisLineFormatRecord(); + r.setAxisType( format ); + return r; + } + + private ValueRangeRecord createValueRangeRecord() + { + ValueRangeRecord r = new ValueRangeRecord(); + r.setMinimumAxisValue( 0.0 ); + r.setMaximumAxisValue( 0.0 ); + r.setMajorIncrement( 0 ); + r.setMinorIncrement( 0 ); + r.setCategoryAxisCross( 0 ); + r.setAutomaticMinimum( true ); + r.setAutomaticMaximum( true ); + r.setAutomaticMajor( true ); + r.setAutomaticMinor( true ); + r.setAutomaticCategoryCrossing( true ); + r.setLogarithmicScale( false ); + r.setValuesInReverse( false ); + r.setCrossCategoryAxisAtMaximum( false ); + r.setReserved( true ); // what's this do?? + return r; + } + + private TickRecord createTickRecord1() + { + TickRecord r = new TickRecord(); + r.setMajorTickType( (byte) 2 ); + r.setMinorTickType( (byte) 0 ); + r.setLabelPosition( (byte) 3 ); + r.setBackground( (byte) 1 ); + r.setLabelColorRgb( 0 ); + r.setZero1( (short) 0 ); + r.setZero2( (short) 0 ); + r.setZero3( (short) 45 ); + r.setAutorotate( true ); + r.setAutoTextBackground( true ); + r.setRotation( (short) 0 ); + r.setAutorotate( true ); + r.setTickColor( (short) 77 ); + return r; + } + + private TickRecord createTickRecord2() + { + TickRecord r = createTickRecord1(); + r.setZero3((short)0); + return r; + } + + private AxisOptionsRecord createAxisOptionsRecord() + { + AxisOptionsRecord r = new AxisOptionsRecord(); + r.setMinimumCategory( (short) -28644 ); + r.setMaximumCategory( (short) -28715 ); + r.setMajorUnitValue( (short) 2 ); + r.setMajorUnit( (short) 0 ); + r.setMinorUnitValue( (short) 1 ); + r.setMinorUnit( (short) 0 ); + r.setBaseUnit( (short) 0 ); + r.setCrossingPoint( (short) -28644 ); + r.setDefaultMinimum( true ); + r.setDefaultMaximum( true ); + r.setDefaultMajor( true ); + r.setDefaultMinorUnit( true ); + r.setIsDate( true ); + r.setDefaultBase( true ); + r.setDefaultCross( true ); + r.setDefaultDateSettings( true ); + return r; + } + + private CategorySeriesAxisRecord createCategorySeriesAxisRecord() + { + CategorySeriesAxisRecord r = new CategorySeriesAxisRecord(); + r.setCrossingPoint( (short) 1 ); + r.setLabelFrequency( (short) 1 ); + r.setTickMarkFrequency( (short) 1 ); + r.setValueAxisCrossing( true ); + r.setCrossesFarRight( false ); + r.setReversed( false ); + return r; + } + + private AxisRecord createAxisRecord( short axisType ) + { + AxisRecord r = new AxisRecord(); + r.setAxisType( axisType ); + return r; + } + + private AxisParentRecord createAxisParentRecord() + { + AxisParentRecord r = new AxisParentRecord(); + r.setAxisType( AxisParentRecord.AXIS_TYPE_MAIN ); + r.setX( 479 ); + r.setY( 221 ); + r.setWidth( 2995 ); + r.setHeight( 2902 ); + return r; + } + + private AxisUsedRecord createAxisUsedRecord( short numAxis ) + { + AxisUsedRecord r = new AxisUsedRecord(); + r.setNumAxis( numAxis ); + return r; + } + + private LinkedDataRecord createDirectLinkRecord() + { + LinkedDataRecord r = new LinkedDataRecord(); + r.setLinkType( LinkedDataRecord.LINK_TYPE_TITLE_OR_TEXT ); + r.setReferenceType( LinkedDataRecord.REFERENCE_TYPE_DIRECT ); + r.setCustomNumberFormat( false ); + r.setIndexNumberFmtRecord( (short) 0 ); + r.setFormulaOfLink(null); + return r; + } + + private FontIndexRecord createFontIndexRecord( int index ) + { + FontIndexRecord r = new FontIndexRecord(); + r.setFontIndex( (short) index ); + return r; + } + + private TextRecord createAllTextRecord() + { + TextRecord r = new TextRecord(); + r.setHorizontalAlignment( TextRecord.HORIZONTAL_ALIGNMENT_CENTER ); + r.setVerticalAlignment( TextRecord.VERTICAL_ALIGNMENT_CENTER ); + r.setDisplayMode( TextRecord.DISPLAY_MODE_TRANSPARENT ); + r.setRgbColor( 0 ); + r.setX( -37 ); + r.setY( -60 ); + r.setWidth( 0 ); + r.setHeight( 0 ); + r.setAutoColor( true ); + r.setShowKey( false ); + r.setShowValue( true ); + r.setVertical( false ); + r.setAutoGeneratedText( true ); + r.setGenerated( true ); + r.setAutoLabelDeleted( false ); + r.setAutoBackground( true ); + r.setRotation( (short) 0 ); + r.setShowCategoryLabelAsPercentage( false ); + r.setShowValueAsPercentage( false ); + r.setShowBubbleSizes( false ); + r.setShowLabel( false ); + r.setIndexOfColorValue( (short) 77 ); + r.setDataLabelPlacement( (short) 0 ); + r.setTextRotation( (short) 0 ); + return r; + } + + private TextRecord createUnknownTextRecord() + { + TextRecord r = new TextRecord(); + r.setHorizontalAlignment( TextRecord.HORIZONTAL_ALIGNMENT_CENTER ); + r.setVerticalAlignment( TextRecord.VERTICAL_ALIGNMENT_CENTER ); + r.setDisplayMode( TextRecord.DISPLAY_MODE_TRANSPARENT ); + r.setRgbColor( 0 ); + r.setX( -37 ); + r.setY( -60 ); + r.setWidth( 0 ); + r.setHeight( 0 ); + r.setAutoColor( true ); + r.setShowKey( false ); + r.setShowValue( false ); + r.setVertical( false ); + r.setAutoGeneratedText( true ); + r.setGenerated( true ); + r.setAutoLabelDeleted( false ); + r.setAutoBackground( true ); + r.setRotation( (short) 0 ); + r.setShowCategoryLabelAsPercentage( false ); + r.setShowValueAsPercentage( false ); + r.setShowBubbleSizes( false ); + r.setShowLabel( false ); + r.setIndexOfColorValue( (short) 77 ); + r.setDataLabelPlacement( (short) 11088 ); + r.setTextRotation( (short) 0 ); + return r; + } + + private DefaultDataLabelTextPropertiesRecord createDefaultTextRecord( short categoryDataType ) + { + DefaultDataLabelTextPropertiesRecord r = new DefaultDataLabelTextPropertiesRecord(); + r.setCategoryDataType( categoryDataType ); + return r; + } + + private SheetPropertiesRecord createSheetPropsRecord() + { + SheetPropertiesRecord r = new SheetPropertiesRecord(); + r.setChartTypeManuallyFormatted( false ); + r.setPlotVisibleOnly( true ); + r.setDoNotSizeWithWindow( false ); + r.setDefaultPlotDimensions( true ); + r.setAutoPlotArea( false ); + return r; + } + + private SeriesToChartGroupRecord createSeriesToChartGroupRecord() + { + return new SeriesToChartGroupRecord(); + } + + private DataFormatRecord createDataFormatRecord() + { + DataFormatRecord r = new DataFormatRecord(); + r.setPointNumber( (short) -1 ); + r.setSeriesIndex( (short) 0 ); + r.setSeriesNumber( (short) 0 ); + r.setUseExcel4Colors( false ); + return r; + } + + private LinkedDataRecord createCategoriesLinkedDataRecord() + { + LinkedDataRecord r = new LinkedDataRecord(); + r.setLinkType( LinkedDataRecord.LINK_TYPE_CATEGORIES ); + r.setReferenceType( LinkedDataRecord.REFERENCE_TYPE_WORKSHEET ); + r.setCustomNumberFormat( false ); + r.setIndexNumberFmtRecord( (short) 0 ); + Area3DPtg p = new Area3DPtg(0, 31, 1, 1, + false, false, false, false, 0); + r.setFormulaOfLink(new Ptg[] { p, }); + return r; + } + + private LinkedDataRecord createValuesLinkedDataRecord() + { + LinkedDataRecord r = new LinkedDataRecord(); + r.setLinkType( LinkedDataRecord.LINK_TYPE_VALUES ); + r.setReferenceType( LinkedDataRecord.REFERENCE_TYPE_WORKSHEET ); + r.setCustomNumberFormat( false ); + r.setIndexNumberFmtRecord( (short) 0 ); + Area3DPtg p = new Area3DPtg(0, 31, 0, 0, + false, false, false, false, 0); + r.setFormulaOfLink(new Ptg[] { p, }); + return r; + } + + private LinkedDataRecord createTitleLinkedDataRecord() + { + LinkedDataRecord r = new LinkedDataRecord(); + r.setLinkType( LinkedDataRecord.LINK_TYPE_TITLE_OR_TEXT ); + r.setReferenceType( LinkedDataRecord.REFERENCE_TYPE_DIRECT ); + r.setCustomNumberFormat( false ); + r.setIndexNumberFmtRecord( (short) 0 ); + r.setFormulaOfLink(null); + return r; + } + + private SeriesRecord createSeriesRecord() + { + SeriesRecord r = new SeriesRecord(); + r.setCategoryDataType( SeriesRecord.CATEGORY_DATA_TYPE_NUMERIC ); + r.setValuesDataType( SeriesRecord.VALUES_DATA_TYPE_NUMERIC ); + r.setNumCategories( (short) 32 ); + r.setNumValues( (short) 31 ); + r.setBubbleSeriesType( SeriesRecord.BUBBLE_SERIES_TYPE_NUMERIC ); + r.setNumBubbleValues( (short) 0 ); + return r; + } + + private EndRecord createEndRecord() + { + return new EndRecord(); + } + + private AreaFormatRecord createAreaFormatRecord1() + { + AreaFormatRecord r = new AreaFormatRecord(); + r.setForegroundColor( 16777215 ); // RGB Color + r.setBackgroundColor( 0 ); // RGB Color + r.setPattern( (short) 1 ); // TODO: Add Pattern constants to record + r.setAutomatic( true ); + r.setInvert( false ); + r.setForecolorIndex( (short) 78 ); + r.setBackcolorIndex( (short) 77 ); + return r; + } + + private AreaFormatRecord createAreaFormatRecord2() + { + AreaFormatRecord r = new AreaFormatRecord(); + r.setForegroundColor(0x00c0c0c0); + r.setBackgroundColor(0x00000000); + r.setPattern((short)1); + r.setAutomatic(false); + r.setInvert(false); + r.setForecolorIndex((short)22); + r.setBackcolorIndex((short)79); + return r; + } + + private LineFormatRecord createLineFormatRecord( boolean drawTicks ) + { + LineFormatRecord r = new LineFormatRecord(); + r.setLineColor( 0 ); + r.setLinePattern( LineFormatRecord.LINE_PATTERN_SOLID ); + r.setWeight( (short) -1 ); + r.setAuto( true ); + r.setDrawTicks( drawTicks ); + r.setColourPaletteIndex( (short) 77 ); // what colour is this? + return r; + } + + private LineFormatRecord createLineFormatRecord2() + { + LineFormatRecord r = new LineFormatRecord(); + r.setLineColor( 0x00808080 ); + r.setLinePattern( (short) 0 ); + r.setWeight( (short) 0 ); + r.setAuto( false ); + r.setDrawTicks( false ); + r.setUnknown( false ); + r.setColourPaletteIndex( (short) 23 ); + return r; + } + + private FrameRecord createFrameRecord1() + { + FrameRecord r = new FrameRecord(); + r.setBorderType( FrameRecord.BORDER_TYPE_REGULAR ); + r.setAutoSize( false ); + r.setAutoPosition( true ); + return r; + } + + private FrameRecord createFrameRecord2() + { + FrameRecord r = new FrameRecord(); + r.setBorderType( FrameRecord.BORDER_TYPE_REGULAR ); + r.setAutoSize( true ); + r.setAutoPosition( true ); + return r; + } + + private PlotGrowthRecord createPlotGrowthRecord( int horizScale, int vertScale ) + { + PlotGrowthRecord r = new PlotGrowthRecord(); + r.setHorizontalScale( horizScale ); + r.setVerticalScale( vertScale ); + return r; + } + + private SCLRecord createSCLRecord( short numerator, short denominator ) + { + SCLRecord r = new SCLRecord(); + r.setDenominator( denominator ); + r.setNumerator( numerator ); + return r; + } + + private BeginRecord createBeginRecord() + { + return new BeginRecord(); + } + + private ChartRecord createChartRecord( int x, int y, int width, int height ) + { + ChartRecord r = new ChartRecord(); + r.setX( x ); + r.setY( y ); + r.setWidth( width ); + r.setHeight( height ); + return r; + } + + private UnitsRecord createUnitsRecord() + { + UnitsRecord r = new UnitsRecord(); + r.setUnits( (short) 0 ); + return r; + } + + + /** + * A series in a chart + */ + public static class HSSFSeries { + private SeriesRecord series; + private SeriesTextRecord seriesTitleText; + private LinkedDataRecord dataName; + private LinkedDataRecord dataValues; + private LinkedDataRecord dataCategoryLabels; + private LinkedDataRecord dataSecondaryCategoryLabels; + + /* package */ HSSFSeries(SeriesRecord series) { + this.series = series; + } + + /* package */ void insertData(LinkedDataRecord data){ + switch(data.getLinkType()){ + + case LinkedDataRecord.LINK_TYPE_TITLE_OR_TEXT: + dataName = data; + break; + case LinkedDataRecord.LINK_TYPE_VALUES: + dataValues = data; + break; + case LinkedDataRecord.LINK_TYPE_CATEGORIES: + dataCategoryLabels = data; + break; + case LinkedDataRecord.LINK_TYPE_SECONDARY_CATEGORIES: + dataSecondaryCategoryLabels = data; + break; + default: + throw new IllegalStateException("Invalid link type: " + data.getLinkType()); + } + } + + /* package */ void setSeriesTitleText(SeriesTextRecord seriesTitleText) + { + this.seriesTitleText = seriesTitleText; + } + + public short getNumValues() { + return series.getNumValues(); + } + /** + * See {@link SeriesRecord} + */ + public short getValueType() { + return series.getValuesDataType(); + } + + /** + * Returns the series' title, if there is one, + * or null if not + */ + public String getSeriesTitle() { + if(seriesTitleText != null) { + return seriesTitleText.getText(); + } + return null; + } + + /** + * Changes the series' title, but only if there + * was one already. + * TODO - add in the records if not + */ + public void setSeriesTitle(String title) { + if(seriesTitleText != null) { + seriesTitleText.setText(title); + } else { + throw new IllegalStateException("No series title found to change"); + } + } + + /** + * @return record with data names + */ + public LinkedDataRecord getDataName(){ + return dataName; + } + + /** + * @return record with data values + */ + public LinkedDataRecord getDataValues(){ + return dataValues; + } + + /** + * @return record with data category labels + */ + public LinkedDataRecord getDataCategoryLabels(){ + return dataCategoryLabels; + } + + /** + * @return record with data secondary category labels + */ + public LinkedDataRecord getDataSecondaryCategoryLabels() { + return dataSecondaryCategoryLabels; + } + + /** + * @return record with series + */ + public SeriesRecord getSeries() { + return series; + } + + private CellRangeAddressBase getCellRange(LinkedDataRecord linkedDataRecord) { + if (linkedDataRecord == null) + { + return null ; + } + + int firstRow = 0; + int lastRow = 0; + int firstCol = 0; + int lastCol = 0; + + for (Ptg ptg : linkedDataRecord.getFormulaOfLink()) { + if (ptg instanceof AreaPtgBase) { + AreaPtgBase areaPtg = (AreaPtgBase) ptg; + + firstRow = areaPtg.getFirstRow(); + lastRow = areaPtg.getLastRow(); + + firstCol = areaPtg.getFirstColumn(); + lastCol = areaPtg.getLastColumn(); + } + } + + return new CellRangeAddress(firstRow, lastRow, firstCol, lastCol); + } + + public CellRangeAddressBase getValuesCellRange() { + return getCellRange(dataValues); + } + + public CellRangeAddressBase getCategoryLabelsCellRange() { + return getCellRange(dataCategoryLabels); + } + + private Integer setVerticalCellRange(LinkedDataRecord linkedDataRecord, + CellRangeAddressBase range) { + if (linkedDataRecord == null) + { + return null; + } + + List ptgList = new ArrayList<>(); + + int rowCount = (range.getLastRow() - range.getFirstRow()) + 1; + int colCount = (range.getLastColumn() - range.getFirstColumn()) + 1; + + for (Ptg ptg : linkedDataRecord.getFormulaOfLink()) { + if (ptg instanceof AreaPtgBase) { + AreaPtgBase areaPtg = (AreaPtgBase) ptg; + + areaPtg.setFirstRow(range.getFirstRow()); + areaPtg.setLastRow(range.getLastRow()); + + areaPtg.setFirstColumn(range.getFirstColumn()); + areaPtg.setLastColumn(range.getLastColumn()); + ptgList.add(areaPtg); + } + } + + linkedDataRecord.setFormulaOfLink(ptgList.toArray(new Ptg[0])); + + return rowCount * colCount; + } + + public void setValuesCellRange(CellRangeAddressBase range) { + Integer count = setVerticalCellRange(dataValues, range); + if (count == null) + { + return; + } + + series.setNumValues((short)(int)count); + } + + public void setCategoryLabelsCellRange(CellRangeAddressBase range) { + Integer count = setVerticalCellRange(dataCategoryLabels, range); + if (count == null) + { + return; + } + + series.setNumCategories((short)(int)count); + } + } + + public HSSFSeries createSeries() throws Exception { + ArrayList seriesTemplate = new ArrayList<>(); + boolean seriesTemplateFilled = false; + + int idx = 0; + int deep = 0; + int chartRecordIdx = -1; + int chartDeep = -1; + int lastSeriesDeep = -1; + int endSeriesRecordIdx = -1; + int seriesIdx = 0; + final List records = sheet.getSheet().getRecords(); + + /* store first series as template and find last series index */ + for(final RecordBase record : records) { + + idx++; + + if (record instanceof BeginRecord) { + deep++; + } else if (record instanceof EndRecord) { + deep--; + + if (lastSeriesDeep == deep) { + lastSeriesDeep = -1; + endSeriesRecordIdx = idx; + if (!seriesTemplateFilled) { + seriesTemplate.add(record); + seriesTemplateFilled = true; + } + } + + if (chartDeep == deep) { + break; + } + } + + if (record instanceof ChartRecord) { + if (record == chartRecord) { + chartRecordIdx = idx; + chartDeep = deep; + } + } else if (record instanceof SeriesRecord) { + if (chartRecordIdx != -1) { + seriesIdx++; + lastSeriesDeep = deep; + } + } + + if (lastSeriesDeep != -1 && !seriesTemplateFilled) { + seriesTemplate.add(record) ; + } + } + + /* check if a series was found */ + if (endSeriesRecordIdx == -1) { + return null; + } + + /* next index in the records list where the new series can be inserted */ + idx = endSeriesRecordIdx + 1; + + HSSFSeries newSeries = null; + + /* duplicate record of the template series */ + ArrayList clonedRecords = new ArrayList<>(); + for(final RecordBase record : seriesTemplate) { + + Record newRecord = null; + + if (record instanceof BeginRecord) { + newRecord = new BeginRecord(); + } else if (record instanceof EndRecord) { + newRecord = new EndRecord(); + } else if (record instanceof SeriesRecord) { + SeriesRecord seriesRecord = (SeriesRecord) ((SeriesRecord)record).clone(); + newSeries = new HSSFSeries(seriesRecord); + newRecord = seriesRecord; + } else if (record instanceof LinkedDataRecord) { + LinkedDataRecord linkedDataRecord = ((LinkedDataRecord)record).clone(); + if (newSeries != null) { + newSeries.insertData(linkedDataRecord); + } + newRecord = linkedDataRecord; + } else if (record instanceof DataFormatRecord) { + DataFormatRecord dataFormatRecord = ((DataFormatRecord)record).clone(); + + dataFormatRecord.setSeriesIndex((short)seriesIdx) ; + dataFormatRecord.setSeriesNumber((short)seriesIdx) ; + + newRecord = dataFormatRecord; + } else if (record instanceof SeriesTextRecord) { + SeriesTextRecord seriesTextRecord = (SeriesTextRecord) ((SeriesTextRecord)record).clone(); + if (newSeries != null) { + newSeries.setSeriesTitleText(seriesTextRecord); + } + newRecord = seriesTextRecord; + } else if (record instanceof Record) { + newRecord = (Record) ((Record)record).clone(); + } + + if (newRecord != null) + { + clonedRecords.add(newRecord); + } + } + + /* check if a user model series object was created */ + if (newSeries == null) + { + return null; + } + + /* transfer series to record list */ + for(final RecordBase record : clonedRecords) { + records.add(idx++, record); + } + + return newSeries; + } + + public boolean removeSeries(HSSFSeries remSeries) { + int deep = 0; + int chartDeep = -1; + int lastSeriesDeep = -1; + int seriesIdx = -1; + boolean removeSeries = false; + boolean chartEntered = false; + boolean result = false; + final List records = sheet.getSheet().getRecords(); + + /* store first series as template and find last series index */ + Iterator iter = records.iterator(); + while (iter.hasNext()) { + RecordBase record = iter.next(); + + if (record instanceof BeginRecord) { + deep++; + } else if (record instanceof EndRecord) { + deep--; + + if (lastSeriesDeep == deep) { + lastSeriesDeep = -1; + + if (removeSeries) { + removeSeries = false; + result = true; + iter.remove(); + } + } + + if (chartDeep == deep) { + break; + } + } + + if (record instanceof ChartRecord) { + if (record == chartRecord) { + chartDeep = deep; + chartEntered = true; + } + } else if (record instanceof SeriesRecord) { + if (chartEntered) { + if (remSeries.series == record) { + lastSeriesDeep = deep; + removeSeries = true; + } else { + seriesIdx++; + } + } + } else if (record instanceof DataFormatRecord) { + if (chartEntered && !removeSeries) { + DataFormatRecord dataFormatRecord = (DataFormatRecord) record; + dataFormatRecord.setSeriesIndex((short) seriesIdx); + dataFormatRecord.setSeriesNumber((short) seriesIdx); + } + } + + if (removeSeries) { + iter.remove(); + } + } + + return result; + } + + public HSSFChartType getType() { + return type; + } } diff --git a/src/scratchpad/src/org/apache/poi/hdgf/chunks/Chunk.java b/src/scratchpad/src/org/apache/poi/hdgf/chunks/Chunk.java index 56417bce75..fda72d7ebb 100644 --- a/src/scratchpad/src/org/apache/poi/hdgf/chunks/Chunk.java +++ b/src/scratchpad/src/org/apache/poi/hdgf/chunks/Chunk.java @@ -28,283 +28,281 @@ import org.apache.poi.util.POILogger; * Base of all chunks, which hold data, flags etc */ public final class Chunk { - /** - * The contents of the chunk, excluding the header, - * trailer and separator - */ - private byte[] contents; - private ChunkHeader header; - /** May be null */ - private ChunkTrailer trailer; - /** May be null */ - private ChunkSeparator separator; - /** The possible different commands we can hold */ - protected CommandDefinition[] commandDefinitions; - /** The command+value pairs we hold */ - private Command[] commands; - /* The blocks (if any) we hold */ - //private Block[] blocks - /** The name of the chunk, as found from the commandDefinitions */ - private String name; - - /** For logging warnings about the structure of the file */ - private POILogger logger = POILogFactory.getLogger(Chunk.class); - - public Chunk(ChunkHeader header, ChunkTrailer trailer, ChunkSeparator separator, byte[] contents) { - this.header = header; - this.trailer = trailer; - this.separator = separator; - this.contents = contents.clone(); - } - - public byte[] _getContents() { - return contents; - } - - public ChunkHeader getHeader() { - return header; - } - - /** - * Gets the separator between this chunk and the next, if it exists - * - * @return the separator - */ - public ChunkSeparator getSeparator() { - return separator; - } - - /** - * Gets the trailer for this chunk, if it exists - * - * @return the trailer - */ - public ChunkTrailer getTrailer() { - return trailer; - } - - /** - * Gets the command definitions, which define and describe much - * of the data held by the chunk. - * - * @return the command definitions - */ - public CommandDefinition[] getCommandDefinitions() { - return commandDefinitions; - } - - public Command[] getCommands() { - return commands; - } - - /** - * Get the name of the chunk, as found from the CommandDefinitions - * - * @return the name of the chunk - */ - public String getName() { - return name; - } - - /** - * Returns the size of the chunk, including any - * headers, trailers and separators. - * - * @return the size of the chunk - */ - public int getOnDiskSize() { - int size = header.getSizeInBytes() + contents.length; - if(trailer != null) { - size += trailer.getTrailerData().length; - } - if(separator != null) { - size += separator.separatorData.length; - } - return size; - } - - /** - * Uses our CommandDefinitions to process the commands - * our chunk type has, and figure out the - * values for them. - */ - protected void processCommands() { - if(commandDefinitions == null) { - throw new IllegalStateException("You must supply the command definitions before calling processCommands!"); - } - - // Loop over the definitions, building the commands - // and getting their values - ArrayList commandList = new ArrayList<>(); - for(CommandDefinition cdef : commandDefinitions) { - int type = cdef.getType(); - int offset = cdef.getOffset(); - - // Handle virtual commands - if(type == 10) { - name = cdef.getName(); - continue; - } else if(type == 18) { - continue; - } - - - // Build the appropriate command for the type - Command command; - if(type == 11 || type == 21) { - command = new BlockOffsetCommand(cdef); - } else { - command = new Command(cdef); - } - - // Bizarrely, many of the offsets are from the start of the - // header, not from the start of the chunk body - switch(type) { - case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: - case 11: case 21: - case 12: case 16: case 17: case 18: case 28: case 29: - // Offset is from start of chunk - break; - default: - // Offset is from start of header! - if(offset >= 19) { - offset -= 19; - } - } - - // Check we seem to have enough data - if(offset >= contents.length) { - logger.log(POILogger.WARN, - "Command offset " + offset + " past end of data at " + contents.length - ); - continue; - } - - try { - // Process - switch(type) { - // Types 0->7 = a flat at bit 0->7 - case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: - int val = contents[offset] & (1< 0); - break; - case 8: - command.value = Byte.valueOf(contents[offset]); - break; - case 9: - command.value = Double.valueOf( - LittleEndian.getDouble(contents, offset) - ); - break; - case 12: - // A Little Endian String - // Starts 8 bytes into the data segment - // Ends at end of data, or 00 00 - - // Ensure we have enough data - if(contents.length < 8) { - command.value = ""; - break; - } - - // Find the end point - int startsAt = 8; - int endsAt = startsAt; - for(int j=startsAt; j commandList = new ArrayList<>(); + for(CommandDefinition cdef : commandDefinitions) { + int type = cdef.getType(); + int offset = cdef.getOffset(); + + // Handle virtual commands + if(type == 10) { + name = cdef.getName(); + continue; + } else if(type == 18) { + continue; + } + + + // Build the appropriate command for the type + Command command; + if(type == 11 || type == 21) { + command = new BlockOffsetCommand(cdef); + } else { + command = new Command(cdef); + } + + // Bizarrely, many of the offsets are from the start of the + // header, not from the start of the chunk body + switch(type) { + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: + case 11: case 21: + case 12: case 16: case 17: case 18: case 28: case 29: + // Offset is from start of chunk + break; + default: + // Offset is from start of header! + if(offset >= 19) { + offset -= 19; + } + } + + // Check we seem to have enough data + if(offset >= contents.length) { + logger.log(POILogger.WARN, + "Command offset " + offset + " past end of data at " + contents.length + ); + continue; + } + + try { + // Process + switch(type) { + // Types 0->7 = a flat at bit 0->7 + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: + int val = contents[offset] & (1< 0); + break; + case 8: + command.value = Byte.valueOf(contents[offset]); + break; + case 9: + command.value = Double.valueOf(LittleEndian.getDouble(contents, offset)); + break; + case 12: + // A Little Endian String + // Starts 8 bytes into the data segment + // Ends at end of data, or 00 00 + + // Ensure we have enough data + if(contents.length < 8) { + command.value = ""; + break; + } + + // Find the end point + int startsAt = 8; + int endsAt = startsAt; + for(int j=startsAt; j