From c41dee931f95c3d9747c5747316b49504bd15477 Mon Sep 17 00:00:00 2001
From: Andreas Beeker
Date: Sun, 19 Apr 2020 20:33:54 +0000
Subject: [PATCH] #63745 - Add traversing and debugging interface to HSSF
a few more HSSF / Old Excel classes
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1876732 13f79535-47bb-0310-9956-ffa450edef68
---
.../apache/poi/hssf/record/OldCellRecord.java | 66 ++---
.../poi/hssf/record/OldFormulaRecord.java | 20 +-
.../poi/hssf/record/OldLabelRecord.java | 17 +-
.../poi/hssf/record/OldSheetRecord.java | 41 ++-
.../poi/hssf/record/OldStringRecord.java | 26 +-
.../record/aggregates/CFRecordsAggregate.java | 31 +-
.../poi/hssf/record/cf/BorderFormatting.java | 43 +--
.../record/cf/ColorGradientFormatting.java | 34 ++-
.../record/cf/ColorGradientThreshold.java | 12 +-
.../poi/hssf/record/cf/DataBarFormatting.java | 54 ++--
.../poi/hssf/record/cf/FontFormatting.java | 278 ++++++------------
.../record/cf/IconMultiStateFormatting.java | 63 ++--
.../poi/hssf/record/cf/PatternFormatting.java | 31 +-
.../apache/poi/hssf/record/cf/Threshold.java | 25 +-
.../poi/hssf/record/common/ExtendedColor.java | 32 +-
.../usermodel/IconMultiStateFormatting.java | 32 +-
.../BaseTestConditionalFormatting.java | 4 +-
17 files changed, 400 insertions(+), 409 deletions(-)
diff --git a/src/java/org/apache/poi/hssf/record/OldCellRecord.java b/src/java/org/apache/poi/hssf/record/OldCellRecord.java
index 76f2dd300d..308cf43475 100644
--- a/src/java/org/apache/poi/hssf/record/OldCellRecord.java
+++ b/src/java/org/apache/poi/hssf/record/OldCellRecord.java
@@ -17,16 +17,21 @@
package org.apache.poi.hssf.record;
-import org.apache.poi.util.HexDump;
+import java.util.Map;
+import java.util.function.Supplier;
+
+import org.apache.poi.common.usermodel.GenericRecord;
+import org.apache.poi.util.GenericRecordJsonWriter;
+import org.apache.poi.util.GenericRecordUtil;
/**
- * Base class for all old (Biff 2 - Biff 4) cell value records
+ * Base class for all old (Biff 2 - Biff 4) cell value records
* (implementors of {@link CellValueRecordInterface}).
* Subclasses are expected to manage the cell data values (of various types).
*/
-public abstract class OldCellRecord {
+public abstract class OldCellRecord implements GenericRecord {
private final short sid;
- private final boolean isBiff2;
+ private final boolean isBiff2;
private final int field_1_row;
private final short field_2_column;
private int field_3_cell_attrs; // Biff 2
@@ -37,7 +42,7 @@ public abstract class OldCellRecord {
this.isBiff2 = isBiff2;
field_1_row = in.readUShort();
field_2_column = in.readShort();
-
+
if (isBiff2) {
field_3_cell_attrs = in.readUShort() << 8;
field_3_cell_attrs += in.readUByte();
@@ -63,7 +68,7 @@ public abstract class OldCellRecord {
public final short getXFIndex() {
return field_3_xf_index;
}
-
+
public int getCellAttrs()
{
return field_3_cell_attrs;
@@ -71,49 +76,30 @@ public abstract class OldCellRecord {
/**
* Is this a Biff2 record, or newer?
- *
+ *
* @return true, if this is a Biff2 record or newer
*/
public boolean isBiff2() {
return isBiff2;
}
-
+
public short getSid() {
return sid;
}
-
+
+ @Override
+ public Map> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "row", this::getRow,
+ "column", this::getColumn,
+ "biff2", this::isBiff2,
+ "biff2CellAttrs", this::getCellAttrs,
+ "xfIndex", this::getXFIndex
+ );
+ }
+
@Override
public final String toString() {
- StringBuilder sb = new StringBuilder();
- String recordName = getRecordName();
-
- sb.append("[").append(recordName).append("]\n");
- sb.append(" .row = ").append(HexDump.shortToHex(getRow())).append("\n");
- sb.append(" .col = ").append(HexDump.shortToHex(getColumn())).append("\n");
- if (isBiff2()) {
- sb.append(" .cellattrs = ").append(HexDump.shortToHex(getCellAttrs())).append("\n");
- } else {
- sb.append(" .xfindex = ").append(HexDump.shortToHex(getXFIndex())).append("\n");
- }
- appendValueText(sb);
- sb.append("\n");
- sb.append("[/").append(recordName).append("]\n");
- return sb.toString();
+ return GenericRecordJsonWriter.marshal(this);
}
-
- /**
- * Append specific debug info (used by {@link #toString()} for the value
- * contained in this record. Trailing new-line should not be appended
- * (superclass does that).
- *
- * @param sb the StringBuilder to append to
- */
- protected abstract void appendValueText(StringBuilder sb);
-
- /**
- * Gets the debug info BIFF record type name (used by {@link #toString()}.
- *
- * @return the debug info BIFF record type name
- */
- protected abstract String getRecordName();
}
diff --git a/src/java/org/apache/poi/hssf/record/OldFormulaRecord.java b/src/java/org/apache/poi/hssf/record/OldFormulaRecord.java
index f6b2914606..e1755eb188 100644
--- a/src/java/org/apache/poi/hssf/record/OldFormulaRecord.java
+++ b/src/java/org/apache/poi/hssf/record/OldFormulaRecord.java
@@ -17,9 +17,13 @@
package org.apache.poi.hssf.record;
+import java.util.Map;
+import java.util.function.Supplier;
+
import org.apache.poi.ss.formula.Formula;
import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.util.GenericRecordUtil;
/**
* Formula Record (0x0006 / 0x0206 / 0x0406) - holds a formula in
@@ -103,10 +107,18 @@ public final class OldFormulaRecord extends OldCellRecord {
return field_6_parsed_expr;
}
- protected void appendValueText(StringBuilder sb) {
- sb.append(" .value = ").append(getValue()).append("\n");
+ @Override
+ public HSSFRecordTypes getGenericRecordType() {
+ return HSSFRecordTypes.FORMULA;
}
- protected String getRecordName() {
- return "Old Formula";
+
+ @Override
+ public Map> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "base", super::getGenericProperties,
+ "options", this::getOptions,
+ "formula", this::getFormula,
+ "value", this::getValue
+ );
}
}
diff --git a/src/java/org/apache/poi/hssf/record/OldLabelRecord.java b/src/java/org/apache/poi/hssf/record/OldLabelRecord.java
index 6dd80e911e..8a4697ff12 100644
--- a/src/java/org/apache/poi/hssf/record/OldLabelRecord.java
+++ b/src/java/org/apache/poi/hssf/record/OldLabelRecord.java
@@ -17,6 +17,10 @@
package org.apache.poi.hssf.record;
+import java.util.Map;
+import java.util.function.Supplier;
+
+import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.POILogFactory;
@@ -104,13 +108,16 @@ public final class OldLabelRecord extends OldCellRecord {
}
@Override
- protected void appendValueText(StringBuilder sb) {
- sb.append(" .string_len= ").append(HexDump.shortToHex(field_4_string_len)).append("\n");
- sb.append(" .value = ").append(getValue()).append("\n");
+ public HSSFRecordTypes getGenericRecordType() {
+ return HSSFRecordTypes.LABEL;
}
@Override
- protected String getRecordName() {
- return "OLD LABEL";
+ public Map> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "base", super::getGenericProperties,
+ "stringLength", this::getStringLength,
+ "value", this::getValue
+ );
}
}
diff --git a/src/java/org/apache/poi/hssf/record/OldSheetRecord.java b/src/java/org/apache/poi/hssf/record/OldSheetRecord.java
index 2abec6cb8c..9f2120c393 100644
--- a/src/java/org/apache/poi/hssf/record/OldSheetRecord.java
+++ b/src/java/org/apache/poi/hssf/record/OldSheetRecord.java
@@ -18,8 +18,12 @@
package org.apache.poi.hssf.record;
import java.io.IOException;
+import java.util.Map;
+import java.util.function.Supplier;
-import org.apache.poi.util.HexDump;
+import org.apache.poi.common.usermodel.GenericRecord;
+import org.apache.poi.util.GenericRecordJsonWriter;
+import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.RecordFormatException;
@@ -29,17 +33,17 @@ import org.apache.poi.util.RecordFormatException;
* and tells where the Beginning of file record is within the HSSF
* file.
*/
-public final class OldSheetRecord {
+public final class OldSheetRecord implements GenericRecord {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
public static final short sid = 0x0085;
- private int field_1_position_of_BOF;
- private int field_2_visibility;
- private int field_3_type;
- private byte[] field_5_sheetname;
+ private final int field_1_position_of_BOF;
+ private final int field_2_visibility;
+ private final int field_3_type;
+ private final byte[] field_5_sheetname;
private CodepageRecord codepage;
public OldSheetRecord(RecordInputStream in) {
@@ -89,15 +93,22 @@ public final class OldSheetRecord {
return OldStringRecord.getString(field_5_sheetname, codepage);
}
- public String toString() {
- StringBuilder buffer = new StringBuilder();
+ @Override
+ public HSSFRecordTypes getGenericRecordType() {
+ return HSSFRecordTypes.BOUND_SHEET;
+ }
- buffer.append("[BOUNDSHEET]\n");
- buffer.append(" .bof = ").append(HexDump.intToHex(getPositionOfBof())).append("\n");
- buffer.append(" .visibility = ").append(HexDump.shortToHex(field_2_visibility)).append("\n");
- buffer.append(" .type = ").append(HexDump.byteToHex(field_3_type)).append("\n");
- buffer.append(" .sheetname = ").append(getSheetname()).append("\n");
- buffer.append("[/BOUNDSHEET]\n");
- return buffer.toString();
+ @Override
+ public Map> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "bof", this::getPositionOfBof,
+ "visibility", () -> field_2_visibility,
+ "type", () -> field_3_type,
+ "sheetName", this::getSheetname
+ );
+ }
+
+ public String toString() {
+ return GenericRecordJsonWriter.marshal(this);
}
}
diff --git a/src/java/org/apache/poi/hssf/record/OldStringRecord.java b/src/java/org/apache/poi/hssf/record/OldStringRecord.java
index 87140b7fc9..e81a2aa4b8 100644
--- a/src/java/org/apache/poi/hssf/record/OldStringRecord.java
+++ b/src/java/org/apache/poi/hssf/record/OldStringRecord.java
@@ -18,9 +18,14 @@
package org.apache.poi.hssf.record;
import java.io.UnsupportedEncodingException;
+import java.util.Map;
+import java.util.function.Supplier;
+import org.apache.poi.common.usermodel.GenericRecord;
import org.apache.poi.hpsf.Property;
import org.apache.poi.util.CodePageUtil;
+import org.apache.poi.util.GenericRecordJsonWriter;
+import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.IOUtils;
@@ -28,7 +33,7 @@ import org.apache.poi.util.IOUtils;
* Biff2 - Biff 4 Label Record (0x0007 / 0x0207) - read only support for
* formula string results.
*/
-public final class OldStringRecord {
+public final class OldStringRecord implements GenericRecord {
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
@@ -90,14 +95,17 @@ public final class OldStringRecord {
}
}
- public String toString()
- {
- StringBuilder buffer = new StringBuilder();
+ @Override
+ public HSSFRecordTypes getGenericRecordType() {
+ return HSSFRecordTypes.STRING;
+ }
- buffer.append("[OLD STRING]\n");
- buffer.append(" .string = ")
- .append(getString()).append("\n");
- buffer.append("[/OLD STRING]\n");
- return buffer.toString();
+ @Override
+ public Map> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties("string", this::getString);
+ }
+
+ public String toString() {
+ return GenericRecordJsonWriter.marshal(this);
}
}
diff --git a/src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java
index 87c5798df8..42b9ada2e4 100644
--- a/src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java
+++ b/src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java
@@ -19,7 +19,10 @@ package org.apache.poi.hssf.record.aggregates;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
+import java.util.function.Supplier;
+import org.apache.poi.common.usermodel.GenericRecord;
import org.apache.poi.hssf.model.RecordStream;
import org.apache.poi.hssf.record.CFHeader12Record;
import org.apache.poi.hssf.record.CFHeaderBase;
@@ -32,6 +35,8 @@ import org.apache.poi.ss.formula.FormulaShifter;
import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.ss.usermodel.helpers.BaseRowColShifter;
import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.util.GenericRecordJsonWriter;
+import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.RecordFormatException;
@@ -44,7 +49,7 @@ import org.apache.poi.util.RecordFormatException;
* unlimited numbers, as can Apache OpenOffice. This is an Excel limitation,
* not a file format one.
*/
-public final class CFRecordsAggregate extends RecordAggregate {
+public final class CFRecordsAggregate extends RecordAggregate implements GenericRecord {
/** Excel 97-2003 allows up to 3 conditional formating rules */
private static final int MAX_97_2003_CONDTIONAL_FORMAT_RULES = 3;
private static final POILogger logger = POILogFactory.getLogger(CFRecordsAggregate.class);
@@ -188,25 +193,19 @@ public final class CFRecordsAggregate extends RecordAggregate {
return rules.size();
}
+ @Override
+ public Map> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "header", this::getHeader,
+ "rules", () -> rules
+ );
+ }
+
/**
* String representation of CFRecordsAggregate
*/
public String toString() {
- StringBuilder buffer = new StringBuilder();
- String type = "CF";
- if (header instanceof CFHeader12Record) {
- type = "CF12";
- }
-
- buffer.append("[").append(type).append("]\n");
- if( header != null ) {
- buffer.append(header);
- }
- for (CFRuleBase cfRule : rules) {
- buffer.append(cfRule);
- }
- buffer.append("[/").append(type).append("]\n");
- return buffer.toString();
+ return GenericRecordJsonWriter.marshal(this);
}
public void visitContainedRecords(RecordVisitor rv) {
diff --git a/src/java/org/apache/poi/hssf/record/cf/BorderFormatting.java b/src/java/org/apache/poi/hssf/record/cf/BorderFormatting.java
index a87a24a81b..f1dd9ec413 100644
--- a/src/java/org/apache/poi/hssf/record/cf/BorderFormatting.java
+++ b/src/java/org/apache/poi/hssf/record/cf/BorderFormatting.java
@@ -17,9 +17,16 @@
package org.apache.poi.hssf.record.cf;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.function.Supplier;
+
import org.apache.poi.common.Duplicatable;
+import org.apache.poi.common.usermodel.GenericRecord;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
+import org.apache.poi.util.GenericRecordJsonWriter;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput;
@@ -28,7 +35,7 @@ import org.apache.poi.util.Removal;
/**
* Border Formatting Block of the Conditional Formatting Rule Record.
*/
-public final class BorderFormatting implements Duplicatable {
+public final class BorderFormatting implements Duplicatable, GenericRecord {
/** No border */
public static final short BORDER_NONE = 0x0;
/** Thin border */
@@ -436,26 +443,28 @@ public final class BorderFormatting implements Duplicatable {
return bordTlBrLineOnOff.isSet(field_13_border_styles1);
}
+ @Override
+ public Map> getGenericProperties() {
+ final Map> m = new LinkedHashMap<>();
+ m.put("borderLeft", this::getBorderLeft);
+ m.put("borderRight", this::getBorderRight);
+ m.put("borderTop", this::getBorderTop);
+ m.put("borderBottom", this::getBorderBottom);
+ m.put("leftBorderColor", this::getLeftBorderColor);
+ m.put("rightBorderColor", this::getRightBorderColor);
+ m.put("topBorderColor", this::getTopBorderColor);
+ m.put("bottomBorderColor", this::getBottomBorderColor);
+ m.put("forwardDiagonalOn", this::isForwardDiagonalOn);
+ m.put("backwardDiagonalOn", this::isBackwardDiagonalOn);
+ return Collections.unmodifiableMap(m);
+ }
public String toString() {
- StringBuilder buffer = new StringBuilder();
- buffer.append(" [Border Formatting]\n");
- buffer.append(" .lftln = ").append(Integer.toHexString(getBorderLeft())).append("\n");
- buffer.append(" .rgtln = ").append(Integer.toHexString(getBorderRight())).append("\n");
- buffer.append(" .topln = ").append(Integer.toHexString(getBorderTop())).append("\n");
- buffer.append(" .btmln = ").append(Integer.toHexString(getBorderBottom())).append("\n");
- buffer.append(" .leftborder= ").append(Integer.toHexString(getLeftBorderColor())).append("\n");
- buffer.append(" .rghtborder= ").append(Integer.toHexString(getRightBorderColor())).append("\n");
- buffer.append(" .topborder= ").append(Integer.toHexString(getTopBorderColor())).append("\n");
- buffer.append(" .bottomborder= ").append(Integer.toHexString(getBottomBorderColor())).append("\n");
- buffer.append(" .fwdiag= ").append(isForwardDiagonalOn()).append("\n");
- buffer.append(" .bwdiag= ").append(isBackwardDiagonalOn()).append("\n");
- buffer.append(" [/Border Formatting]\n");
- return buffer.toString();
+ return GenericRecordJsonWriter.marshal(this);
}
@Override
- @SuppressWarnings("squid:S2975")
+ @SuppressWarnings({"squid:S2975", "MethodDoesntCallSuperMethod"})
@Deprecated
@Removal(version = "5.0.0")
public BorderFormatting clone() {
@@ -467,7 +476,7 @@ public final class BorderFormatting implements Duplicatable {
}
public int serialize(int offset, byte [] data) {
- LittleEndian.putInt(data, offset+0, field_13_border_styles1);
+ LittleEndian.putInt(data, offset, field_13_border_styles1);
LittleEndian.putInt(data, offset+4, field_14_border_styles2);
return 8;
}
diff --git a/src/java/org/apache/poi/hssf/record/cf/ColorGradientFormatting.java b/src/java/org/apache/poi/hssf/record/cf/ColorGradientFormatting.java
index 830d24fd73..26c18b50de 100644
--- a/src/java/org/apache/poi/hssf/record/cf/ColorGradientFormatting.java
+++ b/src/java/org/apache/poi/hssf/record/cf/ColorGradientFormatting.java
@@ -17,12 +17,17 @@
package org.apache.poi.hssf.record.cf;
+import java.util.Map;
+import java.util.function.Supplier;
import java.util.stream.Stream;
import org.apache.poi.common.Duplicatable;
+import org.apache.poi.common.usermodel.GenericRecord;
import org.apache.poi.hssf.record.common.ExtendedColor;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
+import org.apache.poi.util.GenericRecordJsonWriter;
+import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.POILogFactory;
@@ -34,13 +39,13 @@ import org.apache.poi.util.Removal;
* (Called Color Gradient in the file format docs, but more commonly
* Color Scale in the UI)
*/
-public final class ColorGradientFormatting implements Duplicatable {
+public final class ColorGradientFormatting implements Duplicatable, GenericRecord {
private static final POILogger log = POILogFactory.getLogger(ColorGradientFormatting.class);
private static final BitField clamp = BitFieldFactory.getInstance(0x01);
private static final BitField background = BitFieldFactory.getInstance(0x02);
- private byte options;
+ private final byte options;
private ColorGradientThreshold[] thresholds;
private ExtendedColor[] colors;
@@ -132,23 +137,22 @@ public final class ColorGradientFormatting implements Duplicatable {
}
}
+ @Override
+ public Map> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "clampToCurve", this::isClampToCurve,
+ "background", this::isAppliesToBackground,
+ "thresholds", this::getThresholds,
+ "colors", this::getColors
+ );
+ }
+
public String toString() {
- StringBuilder buffer = new StringBuilder();
- buffer.append(" [Color Gradient Formatting]\n");
- buffer.append(" .clamp = ").append(isClampToCurve()).append("\n");
- buffer.append(" .background= ").append(isAppliesToBackground()).append("\n");
- for (Threshold t : thresholds) {
- buffer.append(t);
- }
- for (ExtendedColor c : colors) {
- buffer.append(c);
- }
- buffer.append(" [/Color Gradient Formatting]\n");
- return buffer.toString();
+ return GenericRecordJsonWriter.marshal(this);
}
@Override
- @SuppressWarnings("squid:S2975")
+ @SuppressWarnings({"squid:S2975", "MethodDoesntCallSuperMethod"})
@Deprecated
@Removal(version = "5.0.0")
public ColorGradientFormatting clone() {
diff --git a/src/java/org/apache/poi/hssf/record/cf/ColorGradientThreshold.java b/src/java/org/apache/poi/hssf/record/cf/ColorGradientThreshold.java
index 9c41995dbd..6335237813 100644
--- a/src/java/org/apache/poi/hssf/record/cf/ColorGradientThreshold.java
+++ b/src/java/org/apache/poi/hssf/record/cf/ColorGradientThreshold.java
@@ -17,7 +17,12 @@
package org.apache.poi.hssf.record.cf;
+import java.util.Map;
+import java.util.function.Supplier;
+
import org.apache.poi.common.Duplicatable;
+import org.apache.poi.common.usermodel.GenericRecord;
+import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
@@ -26,7 +31,7 @@ import org.apache.poi.util.Removal;
* Color Gradient / Color Scale specific Threshold / value (CFVO),
* for changes in Conditional Formatting
*/
-public final class ColorGradientThreshold extends Threshold implements Duplicatable {
+public final class ColorGradientThreshold extends Threshold implements Duplicatable, GenericRecord {
private double position;
public ColorGradientThreshold() {
@@ -72,4 +77,9 @@ public final class ColorGradientThreshold extends Threshold implements Duplicata
super.serialize(out);
out.writeDouble(position);
}
+
+ @Override
+ public Map> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties("position", this::getPosition);
+ }
}
diff --git a/src/java/org/apache/poi/hssf/record/cf/DataBarFormatting.java b/src/java/org/apache/poi/hssf/record/cf/DataBarFormatting.java
index 466fad4990..a0f29b1d05 100644
--- a/src/java/org/apache/poi/hssf/record/cf/DataBarFormatting.java
+++ b/src/java/org/apache/poi/hssf/record/cf/DataBarFormatting.java
@@ -17,10 +17,18 @@
package org.apache.poi.hssf.record.cf;
+import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;
+
+import java.util.Map;
+import java.util.function.Supplier;
+
import org.apache.poi.common.Duplicatable;
+import org.apache.poi.common.usermodel.GenericRecord;
import org.apache.poi.hssf.record.common.ExtendedColor;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
+import org.apache.poi.util.GenericRecordJsonWriter;
+import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.POILogFactory;
@@ -30,11 +38,11 @@ import org.apache.poi.util.Removal;
/**
* Data Bar Conditional Formatting Rule Record.
*/
-public final class DataBarFormatting implements Duplicatable {
- private static POILogger log = POILogFactory.getLogger(DataBarFormatting.class);
+public final class DataBarFormatting implements Duplicatable, GenericRecord {
+ private static final POILogger LOG = POILogFactory.getLogger(DataBarFormatting.class);
- private static final BitField iconOnly = BitFieldFactory.getInstance(0x01);
- private static final BitField reversed = BitFieldFactory.getInstance(0x04);
+ private static final BitField ICON_ONLY = BitFieldFactory.getInstance(0x01);
+ private static final BitField REVERSED = BitFieldFactory.getInstance(0x04);
private byte options;
private byte percentMin;
@@ -64,9 +72,9 @@ public final class DataBarFormatting implements Duplicatable {
percentMin = in.readByte();
percentMax = in.readByte();
if (percentMin < 0 || percentMin > 100)
- log.log(POILogger.WARN, "Inconsistent Minimum Percentage found " + percentMin);
+ LOG.log(POILogger.WARN, "Inconsistent Minimum Percentage found " + percentMin);
if (percentMax < 0 || percentMax > 100)
- log.log(POILogger.WARN, "Inconsistent Minimum Percentage found " + percentMin);
+ LOG.log(POILogger.WARN, "Inconsistent Minimum Percentage found " + percentMin);
color = new ExtendedColor(in);
thresholdMin = new DataBarThreshold(in);
@@ -74,22 +82,22 @@ public final class DataBarFormatting implements Duplicatable {
}
public boolean isIconOnly() {
- return getOptionFlag(iconOnly);
+ return getOptionFlag(ICON_ONLY);
}
public void setIconOnly(boolean only) {
- setOptionFlag(only, iconOnly);
+ setOptionFlag(only, ICON_ONLY);
}
public boolean isReversed() {
- return getOptionFlag(reversed);
+ return getOptionFlag(REVERSED);
}
public void setReversed(boolean rev) {
- setOptionFlag(rev, reversed);
+ setOptionFlag(rev, REVERSED);
}
private boolean getOptionFlag(BitField field) {
int value = field.getValue(options);
- return value==0 ? false : true;
+ return value != 0;
}
private void setOptionFlag(boolean option, BitField field) {
options = field.setByteBoolean(options, option);
@@ -130,20 +138,24 @@ public final class DataBarFormatting implements Duplicatable {
this.thresholdMax = thresholdMax;
}
+ @Override
+ public Map> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "options", getBitsAsString(() -> options, new BitField[]{ICON_ONLY, REVERSED}, new String[]{"ICON_ONLY", "REVERSED"}),
+ "color", this::getColor,
+ "percentMin", this::getPercentMin,
+ "percentMax", this::getPercentMax,
+ "thresholdMin", this::getThresholdMin,
+ "thresholdMax", this::getThresholdMax
+ );
+ }
+
public String toString() {
- StringBuilder buffer = new StringBuilder();
- buffer.append(" [Data Bar Formatting]\n");
- buffer.append(" .icon_only= ").append(isIconOnly()).append("\n");
- buffer.append(" .reversed = ").append(isReversed()).append("\n");
- buffer.append(color);
- buffer.append(thresholdMin);
- buffer.append(thresholdMax);
- buffer.append(" [/Data Bar Formatting]\n");
- return buffer.toString();
+ return GenericRecordJsonWriter.marshal(this);
}
@Override
- @SuppressWarnings("squid:S2975")
+ @SuppressWarnings({"squid:S2975", "MethodDoesntCallSuperMethod"})
@Deprecated
@Removal(version = "5.0.0")
public DataBarFormatting clone() {
diff --git a/src/java/org/apache/poi/hssf/record/cf/FontFormatting.java b/src/java/org/apache/poi/hssf/record/cf/FontFormatting.java
index d8b2d11275..afed4f1e02 100644
--- a/src/java/org/apache/poi/hssf/record/cf/FontFormatting.java
+++ b/src/java/org/apache/poi/hssf/record/cf/FontFormatting.java
@@ -18,19 +18,27 @@
package org.apache.poi.hssf.record.cf;
-import java.util.Locale;
+import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;
+import static org.apache.poi.util.GenericRecordUtil.getEnumBitsAsString;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.function.Supplier;
import org.apache.poi.common.Duplicatable;
+import org.apache.poi.common.usermodel.GenericRecord;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
+import org.apache.poi.util.GenericRecordJsonWriter;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.Removal;
/**
* Font Formatting Block of the Conditional Formatting Rule Record.
*/
-public final class FontFormatting implements Duplicatable {
+public final class FontFormatting implements Duplicatable, GenericRecord {
private static final int OFFSET_FONT_NAME = 0;
private static final int OFFSET_FONT_HEIGHT = 64;
private static final int OFFSET_FONT_OPTIONS = 68;
@@ -51,18 +59,12 @@ public final class FontFormatting implements Duplicatable {
public static final int FONT_CELL_HEIGHT_PRESERVED = 0xFFFFFFFF;
- // FONT OPTIONS MASKS
- private static final BitField posture = BitFieldFactory.getInstance(0x00000002);
- private static final BitField outline = BitFieldFactory.getInstance(0x00000008);
- private static final BitField shadow = BitFieldFactory.getInstance(0x00000010);
- private static final BitField cancellation = BitFieldFactory.getInstance(0x00000080);
-
- // OPTION FLAGS MASKS
-
- private static final BitField styleModified = BitFieldFactory.getInstance(0x00000002);
- private static final BitField outlineModified = BitFieldFactory.getInstance(0x00000008);
- private static final BitField shadowModified = BitFieldFactory.getInstance(0x00000010);
- private static final BitField cancellationModified = BitFieldFactory.getInstance(0x00000080);
+ // option flags and font options masks
+ // in the options flags, a true bit activates the overriding and in the font option the bit sets the state
+ private static final BitField POSTURE = BitFieldFactory.getInstance(0x00000002);
+ private static final BitField OUTLINE = BitFieldFactory.getInstance(0x00000008);
+ private static final BitField SHADOW = BitFieldFactory.getInstance(0x00000010);
+ private static final BitField CANCELLATION = BitFieldFactory.getInstance(0x00000080);
/**
* Escapement type - None
@@ -166,7 +168,7 @@ public final class FontFormatting implements Duplicatable {
}
public FontFormatting(FontFormatting other) {
- System.arraycopy(other._rawData, 0, _rawData, 0, _rawData.length);
+ System.arraycopy(other._rawData, 0, _rawData, 0, RAW_DATA_SIZE);
}
public FontFormatting(RecordInputStream in) {
@@ -202,8 +204,7 @@ public final class FontFormatting implements Duplicatable {
* @param height fontheight (in points/20); or -1 to preserve the cell font height
*/
- public void setFontHeight(int height)
- {
+ public void setFontHeight(int height) {
setInt(OFFSET_FONT_HEIGHT, height);
}
@@ -212,20 +213,17 @@ public final class FontFormatting implements Duplicatable {
*
* @return fontheight (in points/20); or -1 if not modified
*/
- public int getFontHeight()
- {
+ public int getFontHeight() {
return getInt(OFFSET_FONT_HEIGHT);
}
- private void setFontOption(boolean option, BitField field)
- {
+ private void setFontOption(boolean option, BitField field) {
int options = getInt(OFFSET_FONT_OPTIONS);
options = field.setBoolean(options, option);
setInt(OFFSET_FONT_OPTIONS, options);
}
- private boolean getFontOption(BitField field)
- {
+ private boolean getFontOption(BitField field) {
int options = getInt(OFFSET_FONT_OPTIONS);
return field.isSet(options);
}
@@ -237,9 +235,8 @@ public final class FontFormatting implements Duplicatable {
* @see #setFontOption(boolean, org.apache.poi.util.BitField)
*/
- public void setItalic(boolean italic)
- {
- setFontOption(italic, posture);
+ public void setItalic(boolean italic) {
+ setFontOption(italic, POSTURE);
}
/**
@@ -249,29 +246,24 @@ public final class FontFormatting implements Duplicatable {
* @see #getFontOption(org.apache.poi.util.BitField)
*/
- public boolean isItalic()
- {
- return getFontOption(posture);
+ public boolean isItalic() {
+ return getFontOption(POSTURE);
}
- public void setOutline(boolean on)
- {
- setFontOption(on, outline);
+ public void setOutline(boolean on) {
+ setFontOption(on, OUTLINE);
}
- public boolean isOutlineOn()
- {
- return getFontOption(outline);
+ public boolean isOutlineOn() {
+ return getFontOption(OUTLINE);
}
- public void setShadow(boolean on)
- {
- setFontOption(on, shadow);
+ public void setShadow(boolean on) {
+ setFontOption(on, SHADOW);
}
- public boolean isShadowOn()
- {
- return getFontOption(shadow);
+ public boolean isShadowOn() {
+ return getFontOption(SHADOW);
}
/**
@@ -279,9 +271,8 @@ public final class FontFormatting implements Duplicatable {
*
* @param strike - whether the font is stricken out or not
*/
- public void setStrikeout(boolean strike)
- {
- setFontOption(strike, cancellation);
+ public void setStrikeout(boolean strike) {
+ setFontOption(strike, CANCELLATION);
}
/**
@@ -290,9 +281,8 @@ public final class FontFormatting implements Duplicatable {
* @return strike - whether the font is stricken out or not
* @see #getFontOption(org.apache.poi.util.BitField)
*/
- public boolean isStruckout()
- {
- return getFontOption(cancellation);
+ public boolean isStruckout() {
+ return getFontOption(CANCELLATION);
}
/**
@@ -301,7 +291,6 @@ public final class FontFormatting implements Duplicatable {
*
* @param bw - a number between 100-1000 for the fonts "boldness"
*/
-
private void setFontWeight(short bw) {
setShort(OFFSET_FONT_WEIGHT, Math.max(100, Math.min(1000, bw)));
}
@@ -311,8 +300,7 @@ public final class FontFormatting implements Duplicatable {
*
* @param bold - set font weight to bold if true; to normal otherwise
*/
- public void setBold(boolean bold)
- {
+ public void setBold(boolean bold) {
setFontWeight(bold?FONT_WEIGHT_BOLD:FONT_WEIGHT_NORMAL);
}
@@ -322,9 +310,7 @@ public final class FontFormatting implements Duplicatable {
*
* @return bw - a number between 100-1000 for the fonts "boldness"
*/
-
- public short getFontWeight()
- {
+ public short getFontWeight() {
return getShort(OFFSET_FONT_WEIGHT);
}
@@ -333,9 +319,7 @@ public final class FontFormatting implements Duplicatable {
*
* @return bold - whether the font is bold or not
*/
-
- public boolean isBold()
- {
+ public boolean isBold() {
return getFontWeight()==FONT_WEIGHT_BOLD;
}
@@ -347,8 +331,7 @@ public final class FontFormatting implements Duplicatable {
* @see org.apache.poi.ss.usermodel.Font#SS_SUPER
* @see org.apache.poi.ss.usermodel.Font#SS_SUB
*/
- public short getEscapementType()
- {
+ public short getEscapementType() {
return getShort(OFFSET_ESCAPEMENT_TYPE);
}
@@ -360,8 +343,7 @@ public final class FontFormatting implements Duplicatable {
* @see org.apache.poi.ss.usermodel.Font#SS_SUPER
* @see org.apache.poi.ss.usermodel.Font#SS_SUB
*/
- public void setEscapementType( short escapementType)
- {
+ public void setEscapementType( short escapementType) {
setShort(OFFSET_ESCAPEMENT_TYPE, escapementType);
}
@@ -376,8 +358,7 @@ public final class FontFormatting implements Duplicatable {
* @see org.apache.poi.ss.usermodel.Font#U_SINGLE_ACCOUNTING
* @see org.apache.poi.ss.usermodel.Font#U_DOUBLE_ACCOUNTING
*/
- public short getUnderlineType()
- {
+ public short getUnderlineType() {
return getShort(OFFSET_UNDERLINE_TYPE);
}
@@ -392,19 +373,16 @@ public final class FontFormatting implements Duplicatable {
* @see org.apache.poi.ss.usermodel.Font#U_SINGLE_ACCOUNTING
* @see org.apache.poi.ss.usermodel.Font#U_DOUBLE_ACCOUNTING
*/
- public void setUnderlineType( short underlineType)
- {
+ public void setUnderlineType( short underlineType) {
setShort(OFFSET_UNDERLINE_TYPE, underlineType);
}
- public short getFontColorIndex()
- {
+ public short getFontColorIndex() {
return (short)getInt(OFFSET_FONT_COLOR_INDEX);
}
- public void setFontColorIndex(short fci )
- {
+ public void setFontColorIndex(short fci ) {
setInt(OFFSET_FONT_COLOR_INDEX,fci);
}
@@ -414,8 +392,7 @@ public final class FontFormatting implements Duplicatable {
return value == 0;
}
- private void setOptionFlag(boolean modified, BitField field)
- {
+ private void setOptionFlag(boolean modified, BitField field) {
int value = modified? 0 : 1;
int optionFlags = getInt(OFFSET_OPTION_FLAGS);
optionFlags = field.setValue(optionFlags, value);
@@ -423,161 +400,92 @@ public final class FontFormatting implements Duplicatable {
}
- public boolean isFontStyleModified()
- {
- return getOptionFlag(styleModified);
+ public boolean isFontStyleModified() {
+ return getOptionFlag(POSTURE);
}
- public void setFontStyleModified(boolean modified)
- {
- setOptionFlag(modified, styleModified);
+ public void setFontStyleModified(boolean modified) {
+ setOptionFlag(modified, POSTURE);
}
- public boolean isFontOutlineModified()
- {
- return getOptionFlag(outlineModified);
+ public boolean isFontOutlineModified() {
+ return getOptionFlag(OUTLINE);
}
- public void setFontOutlineModified(boolean modified)
- {
- setOptionFlag(modified, outlineModified);
+ public void setFontOutlineModified(boolean modified) {
+ setOptionFlag(modified, OUTLINE);
}
- public boolean isFontShadowModified()
- {
- return getOptionFlag(shadowModified);
+ public boolean isFontShadowModified() {
+ return getOptionFlag(SHADOW);
}
- public void setFontShadowModified(boolean modified)
- {
- setOptionFlag(modified, shadowModified);
+ public void setFontShadowModified(boolean modified) {
+ setOptionFlag(modified, SHADOW);
}
- public void setFontCancellationModified(boolean modified)
- {
- setOptionFlag(modified, cancellationModified);
+ public void setFontCancellationModified(boolean modified) {
+ setOptionFlag(modified, CANCELLATION);
}
- public boolean isFontCancellationModified()
- {
- return getOptionFlag(cancellationModified);
+ public boolean isFontCancellationModified() {
+ return getOptionFlag(CANCELLATION);
}
- public void setEscapementTypeModified(boolean modified)
- {
+ public void setEscapementTypeModified(boolean modified) {
int value = modified? 0 : 1;
setInt(OFFSET_ESCAPEMENT_TYPE_MODIFIED, value);
}
- public boolean isEscapementTypeModified()
- {
+
+ public boolean isEscapementTypeModified() {
int escapementModified = getInt(OFFSET_ESCAPEMENT_TYPE_MODIFIED);
return escapementModified == 0;
}
- public void setUnderlineTypeModified(boolean modified)
- {
+ public void setUnderlineTypeModified(boolean modified) {
int value = modified? 0 : 1;
setInt(OFFSET_UNDERLINE_TYPE_MODIFIED, value);
}
- public boolean isUnderlineTypeModified()
- {
+ public boolean isUnderlineTypeModified() {
int underlineModified = getInt(OFFSET_UNDERLINE_TYPE_MODIFIED);
return underlineModified == 0;
}
- public void setFontWieghtModified(boolean modified)
- {
+ public void setFontWieghtModified(boolean modified) {
int value = modified? 0 : 1;
setInt(OFFSET_FONT_WEIGHT_MODIFIED, value);
}
- public boolean isFontWeightModified()
- {
+ public boolean isFontWeightModified() {
int fontStyleModified = getInt(OFFSET_FONT_WEIGHT_MODIFIED);
return fontStyleModified == 0;
}
- public String toString()
- {
- StringBuilder buffer = new StringBuilder();
- buffer.append(" [Font Formatting]\n");
+ @Override
+ public Map> getGenericProperties() {
+ final Map> m = new LinkedHashMap<>();
+ m.put("fontHeight", this::getFontHeight);
+ m.put("options", getBitsAsString(() -> getInt(OFFSET_OPTION_FLAGS),
+ new BitField[]{POSTURE,OUTLINE,SHADOW,CANCELLATION},
+ new String[]{"POSTURE_MODIFIED","OUTLINE_MODIFIED","SHADOW_MODIFIED","STRUCKOUT_MODIFIED"}));
+ m.put("fontOptions", getBitsAsString(() -> getInt(OFFSET_FONT_OPTIONS),
+ new BitField[]{POSTURE,OUTLINE,SHADOW,CANCELLATION},
+ new String[]{"ITALIC","OUTLINE","SHADOW","STRUCKOUT"}));
+ m.put("fontWEightModified", this::isFontWeightModified);
+ m.put("fontWeight", getEnumBitsAsString(this::getFontWeight,
+ new int[]{FONT_WEIGHT_NORMAL,FONT_WEIGHT_BOLD},
+ new String[]{"NORMAL","BOLD"}));
+ m.put("escapementTypeModified", this::isEscapementTypeModified);
+ m.put("escapementType", this::getEscapementType);
+ m.put("underlineTypeModified", this::isUnderlineTypeModified);
+ m.put("underlineType", this::getUnderlineType);
+ m.put("colorIndex", this::getFontColorIndex);
+ return Collections.unmodifiableMap(m);
+ }
- buffer.append(" .font height = ").append(getFontHeight()).append(" twips\n");
-
- if( isFontStyleModified() )
- {
- buffer.append(" .font posture = ").append(isItalic()?"Italic":"Normal").append("\n");
- }
- else
- {
- buffer.append(" .font posture = ]not modified]").append("\n");
- }
-
- if( isFontOutlineModified() )
- {
- buffer.append(" .font outline = ").append(isOutlineOn()).append("\n");
- }
- else
- {
- buffer.append(" .font outline is not modified\n");
- }
-
- if( isFontShadowModified() )
- {
- buffer.append(" .font shadow = ").append(isShadowOn()).append("\n");
- }
- else
- {
- buffer.append(" .font shadow is not modified\n");
- }
-
- if( isFontCancellationModified() )
- {
- buffer.append(" .font strikeout = ").append(isStruckout()).append("\n");
- }
- else
- {
- buffer.append(" .font strikeout is not modified\n");
- }
-
- if( isFontStyleModified() )
- {
- buffer.append(" .font weight = ").
- append(getFontWeight()).
- append(
- getFontWeight() == FONT_WEIGHT_NORMAL ? "(Normal)"
- : getFontWeight() == FONT_WEIGHT_BOLD ? "(Bold)"
- : "0x"+Integer.toHexString(getFontWeight())).
- append("\n");
- }
- else
- {
- buffer.append(" .font weight = ]not modified]").append("\n");
- }
-
- if( isEscapementTypeModified() )
- {
- buffer.append(" .escapement type = ").append(getEscapementType()).append("\n");
- }
- else
- {
- buffer.append(" .escapement type is not modified\n");
- }
-
- if( isUnderlineTypeModified() )
- {
- buffer.append(" .underline type = ").append(getUnderlineType()).append("\n");
- }
- else
- {
- buffer.append(" .underline type is not modified\n");
- }
- buffer.append(" .color index = ").append("0x")
- .append(Integer.toHexString(getFontColorIndex()).toUpperCase(Locale.ROOT)).append('\n');
-
- buffer.append(" [/Font Formatting]\n");
- return buffer.toString();
+ public String toString() {
+ return GenericRecordJsonWriter.marshal(this);
}
@Override
diff --git a/src/java/org/apache/poi/hssf/record/cf/IconMultiStateFormatting.java b/src/java/org/apache/poi/hssf/record/cf/IconMultiStateFormatting.java
index 08d3ea04f6..85ffc30056 100644
--- a/src/java/org/apache/poi/hssf/record/cf/IconMultiStateFormatting.java
+++ b/src/java/org/apache/poi/hssf/record/cf/IconMultiStateFormatting.java
@@ -17,12 +17,17 @@
package org.apache.poi.hssf.record.cf;
+import java.util.Map;
+import java.util.function.Supplier;
import java.util.stream.Stream;
import org.apache.poi.common.Duplicatable;
+import org.apache.poi.common.usermodel.GenericRecord;
import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
+import org.apache.poi.util.GenericRecordJsonWriter;
+import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.POILogFactory;
@@ -32,16 +37,16 @@ import org.apache.poi.util.Removal;
/**
* Icon / Multi-State Conditional Formatting Rule Record.
*/
-public final class IconMultiStateFormatting implements Duplicatable {
- private static final POILogger log = POILogFactory.getLogger(IconMultiStateFormatting.class);
+public final class IconMultiStateFormatting implements Duplicatable, GenericRecord {
+ private static final POILogger LOG = POILogFactory.getLogger(IconMultiStateFormatting.class);
+
+ private static BitField ICON_ONLY = BitFieldFactory.getInstance(0x01);
+ private static BitField REVERSED = BitFieldFactory.getInstance(0x04);
private IconSet iconSet;
private byte options;
private Threshold[] thresholds;
- private static BitField iconOnly = BitFieldFactory.getInstance(0x01);
- private static BitField reversed = BitFieldFactory.getInstance(0x04);
-
public IconMultiStateFormatting() {
iconSet = IconSet.GYR_3_TRAFFIC_LIGHTS;
options = 0;
@@ -63,7 +68,7 @@ public final class IconMultiStateFormatting implements Duplicatable {
int set = in.readByte();
iconSet = IconSet.byId(set);
if (iconSet.num != num) {
- log.log(POILogger.WARN, "Inconsistent Icon Set defintion, found " + iconSet + " but defined as " + num + " entries");
+ LOG.log(POILogger.WARN, "Inconsistent Icon Set defintion, found " + iconSet + " but defined as " + num + " entries");
}
options = in.readByte();
@@ -88,42 +93,36 @@ public final class IconMultiStateFormatting implements Duplicatable {
}
public boolean isIconOnly() {
- return getOptionFlag(iconOnly);
+ return ICON_ONLY.isSet(options);
}
public void setIconOnly(boolean only) {
- setOptionFlag(only, iconOnly);
+ options = ICON_ONLY.setByteBoolean(options, only);
}
public boolean isReversed() {
- return getOptionFlag(reversed);
+ return REVERSED.isSet(options);
}
+
public void setReversed(boolean rev) {
- setOptionFlag(rev, reversed);
- }
-
- private boolean getOptionFlag(BitField field) {
- int value = field.getValue(options);
- return value==0 ? false : true;
- }
- private void setOptionFlag(boolean option, BitField field) {
- options = field.setByteBoolean(options, option);
- }
-
- public String toString() {
- StringBuilder buffer = new StringBuilder();
- buffer.append(" [Icon Formatting]\n");
- buffer.append(" .icon_set = ").append(iconSet).append("\n");
- buffer.append(" .icon_only= ").append(isIconOnly()).append("\n");
- buffer.append(" .reversed = ").append(isReversed()).append("\n");
- for (Threshold t : thresholds) {
- buffer.append(t);
- }
- buffer.append(" [/Icon Formatting]\n");
- return buffer.toString();
+ options = REVERSED.setByteBoolean(options, rev);
}
@Override
- @SuppressWarnings("squid:S2975")
+ public Map> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "iconSet", this::getIconSet,
+ "iconOnly", this::isIconOnly,
+ "reversed", this::isReversed,
+ "thresholds", this::getThresholds
+ );
+ }
+
+ public String toString() {
+ return GenericRecordJsonWriter.marshal(this);
+ }
+
+ @Override
+ @SuppressWarnings({"squid:S2975", "MethodDoesntCallSuperMethod"})
@Deprecated
@Removal(version = "5.0.0")
public IconMultiStateFormatting clone() {
diff --git a/src/java/org/apache/poi/hssf/record/cf/PatternFormatting.java b/src/java/org/apache/poi/hssf/record/cf/PatternFormatting.java
index e03e652698..b495d6183d 100644
--- a/src/java/org/apache/poi/hssf/record/cf/PatternFormatting.java
+++ b/src/java/org/apache/poi/hssf/record/cf/PatternFormatting.java
@@ -17,9 +17,17 @@
package org.apache.poi.hssf.record.cf;
+import static org.apache.poi.util.GenericRecordUtil.getEnumBitsAsString;
+
+import java.util.Map;
+import java.util.function.Supplier;
+
import org.apache.poi.common.Duplicatable;
+import org.apache.poi.common.usermodel.GenericRecord;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
+import org.apache.poi.util.GenericRecordJsonWriter;
+import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
@@ -27,7 +35,7 @@ import org.apache.poi.util.Removal;
/**
* Pattern Formatting Block of the Conditional Formatting Rule Record.
*/
-public final class PatternFormatting implements Duplicatable {
+public final class PatternFormatting implements Duplicatable, GenericRecord {
/** No background */
public static final short NO_FILL = 0 ;
/** Solidly filled */
@@ -162,18 +170,23 @@ public final class PatternFormatting implements Duplicatable {
return patternColorIndex.getValue(field_16_pattern_color_indexes);
}
+ @Override
+ public Map> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "fillPattern", getEnumBitsAsString(this::getFillPattern,
+ new int[]{NO_FILL, SOLID_FOREGROUND, FINE_DOTS, ALT_BARS, SPARSE_DOTS, THICK_HORZ_BANDS, THICK_VERT_BANDS, THICK_BACKWARD_DIAG, THICK_FORWARD_DIAG, BIG_SPOTS, BRICKS, THIN_HORZ_BANDS, THIN_VERT_BANDS, THIN_BACKWARD_DIAG, THIN_FORWARD_DIAG, SQUARES, DIAMONDS, LESS_DOTS, LEAST_DOTS},
+ new String[]{"NO_FILL", "SOLID_FOREGROUND", "FINE_DOTS", "ALT_BARS", "SPARSE_DOTS", "THICK_HORZ_BANDS", "THICK_VERT_BANDS", "THICK_BACKWARD_DIAG", "THICK_FORWARD_DIAG", "BIG_SPOTS", "BRICKS", "THIN_HORZ_BANDS", "THIN_VERT_BANDS", "THIN_BACKWARD_DIAG", "THIN_FORWARD_DIAG", "SQUARES", "DIAMONDS", "LESS_DOTS", "LEAST_DOTS"}),
+ "fillForegroundColor", this::getFillForegroundColor,
+ "fillBackgroundColor", this::getFillForegroundColor
+ );
+ }
+
public String toString() {
- StringBuilder buffer = new StringBuilder();
- buffer.append(" [Pattern Formatting]\n");
- buffer.append(" .fillpattern= ").append(Integer.toHexString(getFillPattern())).append("\n");
- buffer.append(" .fgcoloridx= ").append(Integer.toHexString(getFillForegroundColor())).append("\n");
- buffer.append(" .bgcoloridx= ").append(Integer.toHexString(getFillBackgroundColor())).append("\n");
- buffer.append(" [/Pattern Formatting]\n");
- return buffer.toString();
+ return GenericRecordJsonWriter.marshal(this);
}
@Override
- @SuppressWarnings("squid:S2975")
+ @SuppressWarnings({"squid:S2975", "MethodDoesntCallSuperMethod"})
@Deprecated
@Removal(version = "5.0.0")
public PatternFormatting clone() {
diff --git a/src/java/org/apache/poi/hssf/record/cf/Threshold.java b/src/java/org/apache/poi/hssf/record/cf/Threshold.java
index 4ce6a1e107..6c161d7927 100644
--- a/src/java/org/apache/poi/hssf/record/cf/Threshold.java
+++ b/src/java/org/apache/poi/hssf/record/cf/Threshold.java
@@ -17,18 +17,22 @@
package org.apache.poi.hssf.record.cf;
-import java.util.Arrays;
+import java.util.Map;
+import java.util.function.Supplier;
+import org.apache.poi.common.usermodel.GenericRecord;
import org.apache.poi.ss.formula.Formula;
import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold.RangeType;
+import org.apache.poi.util.GenericRecordJsonWriter;
+import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput;
/**
* Threshold / value (CFVO) for changes in Conditional Formatting
*/
-public abstract class Threshold {
+public abstract class Threshold implements GenericRecord {
private byte type;
private Formula formula;
private Double value;
@@ -107,14 +111,17 @@ public abstract class Threshold {
return len;
}
+ @Override
+ public Map> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "type", this::getType,
+ "formula", this::getFormula,
+ "value", this::getValue
+ );
+ }
+
public String toString() {
- StringBuilder buffer = new StringBuilder();
- buffer.append(" [CF Threshold]\n");
- buffer.append(" .type = ").append(Integer.toHexString(type)).append("\n");
- buffer.append(" .formula = ").append(Arrays.toString(formula.getTokens())).append("\n");
- buffer.append(" .value = ").append(value).append("\n");
- buffer.append(" [/CF Threshold]\n");
- return buffer.toString();
+ return GenericRecordJsonWriter.marshal(this);
}
public void serialize(LittleEndianOutput out) {
diff --git a/src/java/org/apache/poi/hssf/record/common/ExtendedColor.java b/src/java/org/apache/poi/hssf/record/common/ExtendedColor.java
index 145b2e2085..af6e889a7a 100644
--- a/src/java/org/apache/poi/hssf/record/common/ExtendedColor.java
+++ b/src/java/org/apache/poi/hssf/record/common/ExtendedColor.java
@@ -17,8 +17,13 @@
package org.apache.poi.hssf.record.common;
+import java.util.Map;
+import java.util.function.Supplier;
+
import org.apache.poi.common.Duplicatable;
-import org.apache.poi.util.HexDump;
+import org.apache.poi.common.usermodel.GenericRecord;
+import org.apache.poi.util.GenericRecordJsonWriter;
+import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
@@ -32,7 +37,7 @@ import org.apache.poi.util.Removal;
* Formatting, Sheet Extensions), this XSSF-style color record
* can be used.
*/
-public final class ExtendedColor implements Duplicatable {
+public final class ExtendedColor implements Duplicatable, GenericRecord {
public static final int TYPE_AUTO = 0;
public static final int TYPE_INDEXED = 1;
public static final int TYPE_RGB = 2;
@@ -147,20 +152,23 @@ public final class ExtendedColor implements Duplicatable {
this.tint = tint;
}
+ @Override
+ public Map> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "type", this::getType,
+ "tint", this::getTint,
+ "colorIndex", this::getColorIndex,
+ "rgba", this::getRGBA,
+ "themeIndex", this::getThemeIndex
+ );
+ }
+
public String toString() {
- StringBuilder buffer = new StringBuilder();
- buffer.append(" [Extended Color]\n");
- buffer.append(" .type = ").append(type).append("\n");
- buffer.append(" .tint = ").append(tint).append("\n");
- buffer.append(" .c_idx = ").append(colorIndex).append("\n");
- buffer.append(" .rgba = ").append(HexDump.toHex(rgba)).append("\n");
- buffer.append(" .t_idx = ").append(themeIndex).append("\n");
- buffer.append(" [/Extended Color]\n");
- return buffer.toString();
+ return GenericRecordJsonWriter.marshal(this);
}
@Override
- @SuppressWarnings("squid:S2975")
+ @SuppressWarnings({"squid:S2975", "MethodDoesntCallSuperMethod"})
@Deprecated
@Removal(version = "5.0.0")
public ExtendedColor clone() {
diff --git a/src/java/org/apache/poi/ss/usermodel/IconMultiStateFormatting.java b/src/java/org/apache/poi/ss/usermodel/IconMultiStateFormatting.java
index 24eebdf201..d99630996f 100644
--- a/src/java/org/apache/poi/ss/usermodel/IconMultiStateFormatting.java
+++ b/src/java/org/apache/poi/ss/usermodel/IconMultiStateFormatting.java
@@ -20,11 +20,11 @@
package org.apache.poi.ss.usermodel;
/**
- * High level representation for the Icon / Multi-State Formatting
+ * High level representation for the Icon / Multi-State Formatting
* component of Conditional Formatting settings
*/
public interface IconMultiStateFormatting {
- public enum IconSet {
+ enum IconSet {
/** Green Up / Yellow Side / Red Down arrows */
GYR_3_ARROW(0, 3, "3Arrows"),
/** Grey Up / Side / Down arrows */
@@ -33,11 +33,11 @@ public interface IconMultiStateFormatting {
GYR_3_FLAGS(2, 3, "3Flags"),
/** Green / Yellow / Red traffic lights (no background). Default */
GYR_3_TRAFFIC_LIGHTS(3, 3, "3TrafficLights1"),
- /** Green / Yellow / Red traffic lights on a black square background.
+ /** Green / Yellow / Red traffic lights on a black square background.
* Note, MS-XLS docs v20141018 say this is id=5 but seems to be id=4 */
GYR_3_TRAFFIC_LIGHTS_BOX(4, 3, "3TrafficLights2"),
/** Green Circle / Yellow Triangle / Red Diamond.
- * Note, MS-XLS docs v20141018 say this is id=4 but seems to be id=5 */
+ * Note, MS-XLS docs v20141018 say this is id=4 but seems to be id=5 */
GYR_3_SHAPES(5, 3, "3Signs"),
/** Green Tick / Yellow ! / Red Cross on a circle background */
GYR_3_SYMBOLS_CIRCLE(6, 3, "3Symbols"),
@@ -56,20 +56,18 @@ public interface IconMultiStateFormatting {
GREY_5_ARROWS(0xE, 5, "5ArrowsGray"),
RATINGS_5(0xF, 5, "5Rating"),
QUARTERS_5(0x10, 5, "5Quarters");
-
- protected static final IconSet DEFAULT_ICONSET = IconSet.GYR_3_TRAFFIC_LIGHTS;
-
+
/** Numeric ID of the icon set */
public final int id;
/** How many icons in the set */
public final int num;
/** Name (system) of the set */
public final String name;
-
+
public String toString() {
return id + " - " + name;
}
-
+
public static IconSet byId(int id) {
return values()[id];
}
@@ -79,26 +77,26 @@ public interface IconMultiStateFormatting {
}
return null;
}
-
- private IconSet(int id, int num, String name) {
+
+ IconSet(int id, int num, String name) {
this.id = id; this.num = num; this.name = name;
}
}
-
+
/**
* Get the Icon Set used
*/
IconSet getIconSet();
-
+
/**
* Changes the Icon Set used
- *
+ *
* If the new Icon Set has a different number of
* icons to the old one, you must update the
* thresholds before saving!
*/
void setIconSet(IconSet set);
-
+
/**
* Should Icon + Value be displayed, or only the Icon?
*/
@@ -107,10 +105,10 @@ public interface IconMultiStateFormatting {
* Control if only the Icon is shown, or Icon + Value
*/
void setIconOnly(boolean only);
-
+
boolean isReversed();
void setReversed(boolean reversed);
-
+
/**
* Gets the list of thresholds
*/
diff --git a/src/testcases/org/apache/poi/ss/usermodel/BaseTestConditionalFormatting.java b/src/testcases/org/apache/poi/ss/usermodel/BaseTestConditionalFormatting.java
index fd33cf0319..5b17cc964d 100644
--- a/src/testcases/org/apache/poi/ss/usermodel/BaseTestConditionalFormatting.java
+++ b/src/testcases/org/apache/poi/ss/usermodel/BaseTestConditionalFormatting.java
@@ -563,8 +563,8 @@ public abstract class BaseTestConditionalFormatting {
ConditionalFormatting cf = sheetCF.getConditionalFormattingAt(i);
if (cf instanceof HSSFConditionalFormatting) {
String str = cf.toString();
- if (str.contains("[CF]")) fCF++;
- if (str.contains("[CF12]")) fCF12++;
+ if (str.contains("/* CF_RULE */")) fCF++;
+ if (str.contains("/* CF_RULE_12 */")) fCF12++;
if (str.contains("[CFEX]")) fCFEX++;
} else {
ConditionType type = cf.getRule(cf.getNumberOfRules() - 1).getConditionType();