diff options
Diffstat (limited to 'src/java/org')
332 files changed, 7719 insertions, 5565 deletions
diff --git a/src/java/org/apache/poi/common/Duplicatable.java b/src/java/org/apache/poi/common/Duplicatable.java new file mode 100644 index 0000000000..0c2cb14860 --- /dev/null +++ b/src/java/org/apache/poi/common/Duplicatable.java @@ -0,0 +1,39 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.common; + +/** + * This is an alternative to the {@link Cloneable} interface without its side-effects. + * A class implementing Duplicatable provides a deep-copy of itself - usually this is done via a copy-constructor, + * which is invoked with a self-reference by the copy method. + * References to child objects are duplicated - references to parents are kept as-is and + * might need to be replaced by the parent copy operation. + * + * @param <T> the implementing class itself + * + * @see <a href="https://www.artima.com/intv/bloch.html#part13">Copy Constructor versus Cloning</a> + */ +public interface Duplicatable { + // Providing a generics interface Duplicatable<T extends Duplicatable<T>> pushes too many + // changes to the implementing classes and the benefit of providing a subtype-specific copy method + // is not sufficient + /** + * @return a deep copy of the implementing class / instance + */ + Duplicatable copy(); +} diff --git a/src/java/org/apache/poi/ddf/AbstractEscherOptRecord.java b/src/java/org/apache/poi/ddf/AbstractEscherOptRecord.java index 9b5d6409e5..1563363f10 100644 --- a/src/java/org/apache/poi/ddf/AbstractEscherOptRecord.java +++ b/src/java/org/apache/poi/ddf/AbstractEscherOptRecord.java @@ -171,7 +171,4 @@ public abstract class AbstractEscherOptRecord extends EscherRecord { "properties", this::getEscherProperties ); } - - @Override - public abstract AbstractEscherOptRecord copy(); } diff --git a/src/java/org/apache/poi/ddf/EscherContainerRecord.java b/src/java/org/apache/poi/ddf/EscherContainerRecord.java index 8cb07c37e2..0f192937bf 100644 --- a/src/java/org/apache/poi/ddf/EscherContainerRecord.java +++ b/src/java/org/apache/poi/ddf/EscherContainerRecord.java @@ -142,13 +142,9 @@ public final class EscherContainerRecord extends EscherRecord implements Iterabl * @return true, if any child has the given recordId */ public boolean hasChildOfType(short recordId) { - for (EscherRecord r : this) { - if(r.getRecordId() == recordId) { - return true; - } - } - return false; + return _childRecords.stream().anyMatch(r -> r.getRecordId() == recordId); } + @Override public EscherRecord getChild( int index ) { return _childRecords.get(index); @@ -170,6 +166,7 @@ public final class EscherContainerRecord extends EscherRecord implements Iterabl return Collections.unmodifiableList(_childRecords).iterator(); } + /** * replaces the internal child list with the contents of the supplied <tt>childRecords</tt> */ diff --git a/src/java/org/apache/poi/ddf/EscherRecord.java b/src/java/org/apache/poi/ddf/EscherRecord.java index 3877d11e36..cb1b1fea4b 100644 --- a/src/java/org/apache/poi/ddf/EscherRecord.java +++ b/src/java/org/apache/poi/ddf/EscherRecord.java @@ -24,6 +24,7 @@ import java.util.List; 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; @@ -32,12 +33,13 @@ import org.apache.poi.util.GenericRecordUtil; import org.apache.poi.util.GenericRecordXmlWriter; import org.apache.poi.util.Internal; import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.Removal; /** * The base abstract record from which all escher records are defined. Subclasses will need * to define methods for serialization/deserialization and for determining the record size. */ -public abstract class EscherRecord implements Cloneable, GenericRecord { +public abstract class EscherRecord implements Duplicatable, GenericRecord { private static final BitField fInstance = BitFieldFactory.getInstance(0xfff0); private static final BitField fVersion = BitFieldFactory.getInstance(0x000f); @@ -238,9 +240,12 @@ public abstract class EscherRecord implements Cloneable, GenericRecord { * Escher records may need to be clonable in the future. * * @return the cloned object + * @deprecated use {@link #copy()} */ @Override @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public final EscherRecord clone() { return copy(); } @@ -350,5 +355,6 @@ public abstract class EscherRecord implements Cloneable, GenericRecord { ); } + @Override public abstract EscherRecord copy(); }
\ No newline at end of file diff --git a/src/java/org/apache/poi/ddf/EscherTextboxRecord.java b/src/java/org/apache/poi/ddf/EscherTextboxRecord.java index 5f82aff738..b42a669977 100644 --- a/src/java/org/apache/poi/ddf/EscherTextboxRecord.java +++ b/src/java/org/apache/poi/ddf/EscherTextboxRecord.java @@ -31,7 +31,7 @@ import org.apache.poi.util.RecordFormatException; * Escher format. We don't attempt to understand the contents, since * they will be in the parent's format, not Escher format. */ -public final class EscherTextboxRecord extends EscherRecord implements Cloneable { +public final class EscherTextboxRecord extends EscherRecord { //arbitrarily selected; may need to increase private static final int MAX_RECORD_LENGTH = 100_000; diff --git a/src/java/org/apache/poi/ddf/UnknownEscherRecord.java b/src/java/org/apache/poi/ddf/UnknownEscherRecord.java index 55d8e41667..9e0236e7d1 100644 --- a/src/java/org/apache/poi/ddf/UnknownEscherRecord.java +++ b/src/java/org/apache/poi/ddf/UnknownEscherRecord.java @@ -31,7 +31,7 @@ import org.apache.poi.util.LittleEndian; * This record is used whenever a escher record is encountered that * we do not explicitly support. */ -public final class UnknownEscherRecord extends EscherRecord implements Cloneable { +public final class UnknownEscherRecord extends EscherRecord { //arbitrarily selected; may need to increase private static final int MAX_RECORD_LENGTH = 100_000_000; diff --git a/src/java/org/apache/poi/hssf/eventusermodel/dummyrecord/DummyRecordBase.java b/src/java/org/apache/poi/hssf/eventusermodel/dummyrecord/DummyRecordBase.java index ce52b96d6a..02ef1f94e4 100644 --- a/src/java/org/apache/poi/hssf/eventusermodel/dummyrecord/DummyRecordBase.java +++ b/src/java/org/apache/poi/hssf/eventusermodel/dummyrecord/DummyRecordBase.java @@ -23,11 +23,9 @@ import org.apache.poi.util.RecordFormatException; /** */ abstract class DummyRecordBase extends Record { - - protected DummyRecordBase() { - // - } - + + protected DummyRecordBase() {} + public final short getSid() { return -1; } diff --git a/src/java/org/apache/poi/hssf/eventusermodel/dummyrecord/LastCellOfRowDummyRecord.java b/src/java/org/apache/poi/hssf/eventusermodel/dummyrecord/LastCellOfRowDummyRecord.java index bd4afe8900..afd1fa8b4d 100644 --- a/src/java/org/apache/poi/hssf/eventusermodel/dummyrecord/LastCellOfRowDummyRecord.java +++ b/src/java/org/apache/poi/hssf/eventusermodel/dummyrecord/LastCellOfRowDummyRecord.java @@ -25,37 +25,42 @@ package org.apache.poi.hssf.eventusermodel.dummyrecord; public final class LastCellOfRowDummyRecord extends DummyRecordBase { private final int row; private final int lastColumnNumber; - + public LastCellOfRowDummyRecord(int row, int lastColumnNumber) { this.row = row; this.lastColumnNumber = lastColumnNumber; } - + /** * Returns the (0 based) number of the row we are * currently working on. - * + * * @return the (0 based) number of the row */ public int getRow() { return row; } - + /** * Returns the (0 based) number of the last column * seen for this row. You should have already been * called with that record. * This is -1 in the case of there being no columns * for the row. - * + * * @return the (0 based) number of the last column */ public int getLastColumnNumber() { return lastColumnNumber; } - + @Override public String toString() { return "End-of-Row for Row=" + row + " at Column=" + lastColumnNumber; } + + @Override + public LastCellOfRowDummyRecord copy() { + return this; + } } diff --git a/src/java/org/apache/poi/hssf/eventusermodel/dummyrecord/MissingCellDummyRecord.java b/src/java/org/apache/poi/hssf/eventusermodel/dummyrecord/MissingCellDummyRecord.java index 393e21f387..2535818dfa 100644 --- a/src/java/org/apache/poi/hssf/eventusermodel/dummyrecord/MissingCellDummyRecord.java +++ b/src/java/org/apache/poi/hssf/eventusermodel/dummyrecord/MissingCellDummyRecord.java @@ -23,13 +23,18 @@ package org.apache.poi.hssf.eventusermodel.dummyrecord; * but still want to trigger something */ public final class MissingCellDummyRecord extends DummyRecordBase { - private int row; - private int column; - + private final int row; + private final int column; + public MissingCellDummyRecord(int row, int column) { this.row = row; this.column = column; } public int getRow() { return row; } public int getColumn() { return column; } + + @Override + public MissingCellDummyRecord copy() { + return this; + } } diff --git a/src/java/org/apache/poi/hssf/eventusermodel/dummyrecord/MissingRowDummyRecord.java b/src/java/org/apache/poi/hssf/eventusermodel/dummyrecord/MissingRowDummyRecord.java index 4c128bd004..9d7eeddf34 100644 --- a/src/java/org/apache/poi/hssf/eventusermodel/dummyrecord/MissingRowDummyRecord.java +++ b/src/java/org/apache/poi/hssf/eventusermodel/dummyrecord/MissingRowDummyRecord.java @@ -23,12 +23,17 @@ package org.apache.poi.hssf.eventusermodel.dummyrecord; * want to trigger something */ public final class MissingRowDummyRecord extends DummyRecordBase { - private int rowNumber; - + private final int rowNumber; + public MissingRowDummyRecord(int rowNumber) { this.rowNumber = rowNumber; } public int getRowNumber() { return rowNumber; } + + @Override + public MissingRowDummyRecord copy() { + return this; + } } diff --git a/src/java/org/apache/poi/hssf/model/InternalSheet.java b/src/java/org/apache/poi/hssf/model/InternalSheet.java index 1b2531aee7..ea1addabdb 100644 --- a/src/java/org/apache/poi/hssf/model/InternalSheet.java +++ b/src/java/org/apache/poi/hssf/model/InternalSheet.java @@ -132,7 +132,7 @@ public final class InternalSheet { if (rs.peekNextSid() != BOFRecord.sid) { throw new RecordFormatException("BOF record expected"); } - + BOFRecord bof = (BOFRecord) rs.getNext(); if (bof.getType() == BOFRecord.TYPE_WORKSHEET) { // Good, well supported @@ -152,7 +152,7 @@ public final class InternalSheet { throw new UnsupportedBOFType(bof.getType()); } records.add(bof); - + while (rs.hasNext()) { int recSid = rs.peekNextSid(); @@ -339,14 +339,14 @@ public final class InternalSheet { recs.add(r); }}); } - + public static class UnsupportedBOFType extends RecordFormatException { private final int type; protected UnsupportedBOFType(int type) { super("BOF not of a supported type, found " + type); this.type = type; } - + public int getType() { return type; } @@ -360,11 +360,7 @@ public final class InternalSheet { _destList = destList; } public void visitRecord(Record r) { - try { - _destList.add((Record)r.clone()); - } catch (CloneNotSupportedException e) { - throw new RecordFormatException(e); - } + _destList.add(r.copy()); } } @@ -374,7 +370,7 @@ public final class InternalSheet { * can be added to a sheet. The <b>Record</b> object does not implement cloneable. * When adding a new record, implement a public clone method if and only if the record * belongs to a sheet. - * + * * @return the cloned sheet */ public InternalSheet cloneSheet() { @@ -391,12 +387,8 @@ public final class InternalSheet { */ rb = new DrawingRecord(); } - try { - Record rec = (Record) ((Record) rb).clone(); - clonedRecords.add(rec); - } catch (CloneNotSupportedException e) { - throw new RecordFormatException(e); - } + Record rec = ((Record) rb).copy(); + clonedRecords.add(rec); } return createSheet(new RecordStream(clonedRecords, 0)); } @@ -478,7 +470,7 @@ public final class InternalSheet { /** * Updates formulas in cells and conditional formats due to moving of cells - * + * * @param shifter the formular shifter * @param externSheetIndex the externSheet index of this sheet */ @@ -995,7 +987,7 @@ public final class InternalSheet { /** * set the default row height for the sheet (if the rows do not define their own height) - * + * * @param dch the default row height */ public void setDefaultRowHeight(short dch) { @@ -1247,7 +1239,7 @@ public final class InternalSheet { /** * Gets the gridset record for this sheet. - * + * * @return the gridset record for this sheet */ public GridsetRecord getGridsetRecord() @@ -1257,9 +1249,9 @@ public final class InternalSheet { /** * Returns the first occurrence of a record matching a particular sid. - * + * * @param sid the sid to search for - * + * * @return the matching record or {@code null} if it wasn't found */ public Record findFirstRecordBySid(short sid) { @@ -1330,7 +1322,7 @@ public final class InternalSheet { { printGridlines = newPrintGridlines; } - + /** * Returns the PrintHeadersRecord. * @return PrintHeadersRecord for the sheet. @@ -1519,7 +1511,7 @@ public final class InternalSheet { public boolean isDisplayRowColHeadings() { return windowTwo.getDisplayRowColHeadings(); } - + /** * Sets whether the RowColHeadings are shown in a viewer. * @param show whether to show RowColHeadings or not @@ -1681,7 +1673,7 @@ public final class InternalSheet { temp.toArray(result); return result; } - + public int getColumnOutlineLevel(int columnIndex) { return _columnInfos.getOutlineLevel(columnIndex); } diff --git a/src/java/org/apache/poi/hssf/model/RecordStream.java b/src/java/org/apache/poi/hssf/model/RecordStream.java index 23c2d3d61c..7e1f82d380 100644 --- a/src/java/org/apache/poi/hssf/model/RecordStream.java +++ b/src/java/org/apache/poi/hssf/model/RecordStream.java @@ -32,7 +32,7 @@ public final class RecordStream { /** * Creates a RecordStream bounded by startIndex and endIndex - * + * * @param inputList the list to iterate over * @param startIndex the start index within the list * @param endIx the end index within the list, which is the index of the end element + 1 @@ -71,6 +71,13 @@ public final class RecordStream { } /** + * @return the next Record. <code>null</code> if this stream is exhausted. + */ + public Record peekNextRecord() { + return (hasNext()) ? _list.get(_nextIndex) : null; + } + + /** * @return -1 if at end of records */ public int peekNextSid() { diff --git a/src/java/org/apache/poi/hssf/record/AbstractEscherHolderRecord.java b/src/java/org/apache/poi/hssf/record/AbstractEscherHolderRecord.java index b403a0799b..3bcc18430e 100644 --- a/src/java/org/apache/poi/hssf/record/AbstractEscherHolderRecord.java +++ b/src/java/org/apache/poi/hssf/record/AbstractEscherHolderRecord.java @@ -25,14 +25,15 @@ import org.apache.poi.ddf.EscherContainerRecord; import org.apache.poi.ddf.EscherRecord; import org.apache.poi.ddf.EscherRecordFactory; import org.apache.poi.ddf.NullEscherSerializationListener; -import org.apache.poi.util.LittleEndian; import org.apache.poi.hssf.util.LazilyConcatenatedByteArray; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.Removal; /** * The escher container record is used to hold escher records. It is abstract and * must be subclassed for maximum benefit. */ -public abstract class AbstractEscherHolderRecord extends Record implements Cloneable { +public abstract class AbstractEscherHolderRecord extends Record { private static boolean DESERIALISE; static { try { @@ -42,17 +43,17 @@ public abstract class AbstractEscherHolderRecord extends Record implements Clone } } - private final List<EscherRecord> escherRecords; + private final List<EscherRecord> escherRecords = new ArrayList<>(); private final LazilyConcatenatedByteArray rawDataContainer = new LazilyConcatenatedByteArray(); - public AbstractEscherHolderRecord() - { - escherRecords = new ArrayList<>(); + public AbstractEscherHolderRecord() {} + + public AbstractEscherHolderRecord(AbstractEscherHolderRecord other) { + other.escherRecords.stream().map(EscherRecord::copy).forEach(escherRecords::add); + rawDataContainer.concatenate(other.rawDataContainer); } - public AbstractEscherHolderRecord(RecordInputStream in) - { - escherRecords = new ArrayList<>(); + public AbstractEscherHolderRecord(RecordInputStream in) { if (! DESERIALISE ) { rawDataContainer.concatenate(in.readRemainder()); } else { @@ -143,10 +144,16 @@ public abstract class AbstractEscherHolderRecord extends Record implements Clone public abstract short getSid(); @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public AbstractEscherHolderRecord clone() { - return (AbstractEscherHolderRecord)cloneViaReserialise(); + return copy(); } + @Override + public abstract AbstractEscherHolderRecord copy(); + public void addEscherRecord(int index, EscherRecord element) { escherRecords.add( index, element ); @@ -171,7 +178,7 @@ public abstract class AbstractEscherHolderRecord extends Record implements Clone * If we have a EscherContainerRecord as one of our * children (and most top level escher holders do), * then return that. - * + * * @return the EscherContainerRecord or {@code null} if no child is a container record */ public EscherContainerRecord getEscherContainer() { @@ -187,15 +194,15 @@ public abstract class AbstractEscherHolderRecord extends Record implements Clone * Descends into all our children, returning the * first EscherRecord with the given id, or null * if none found - * + * * @param id the record to look for - * + * * @return the record or {@code null} if it can't be found */ public EscherRecord findFirstWithId(short id) { return findFirstWithId(id, getEscherRecords()); } - + private EscherRecord findFirstWithId(short id, List<EscherRecord> records) { // Check at our level for (EscherRecord r : records) { @@ -227,7 +234,7 @@ public abstract class AbstractEscherHolderRecord extends Record implements Clone /** * Big drawing group records are split but it's easier to deal with them * as a whole group so we need to join them together. - * + * * @param record the record data to concatenate to the end */ public void join( AbstractEscherHolderRecord record ) diff --git a/src/java/org/apache/poi/hssf/record/ArrayRecord.java b/src/java/org/apache/poi/hssf/record/ArrayRecord.java index 96830cdbce..fb52ecf361 100644 --- a/src/java/org/apache/poi/hssf/record/ArrayRecord.java +++ b/src/java/org/apache/poi/hssf/record/ArrayRecord.java @@ -17,18 +17,19 @@ package org.apache.poi.hssf.record; -import org.apache.poi.ss.formula.ptg.Ptg; import org.apache.poi.hssf.util.CellRangeAddress8Bit; import org.apache.poi.ss.formula.Formula; +import org.apache.poi.ss.formula.ptg.Ptg; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * ARRAY (0x0221)<p> * * Treated in a similar way to SharedFormulaRecord */ -public final class ArrayRecord extends SharedValueRecordBase implements Cloneable { +public final class ArrayRecord extends SharedValueRecordBase { public final static short sid = 0x0221; private static final int OPT_ALWAYS_RECALCULATE = 0x0001; @@ -38,6 +39,13 @@ public final class ArrayRecord extends SharedValueRecordBase implements Cloneabl private int _field3notUsed; private Formula _formula; + public ArrayRecord(ArrayRecord other) { + super(other); + _options = other._options; + _field3notUsed = other._field3notUsed; + _formula = (other._formula == null) ? null : other._formula.copy(); + } + public ArrayRecord(RecordInputStream in) { super(in); _options = in.readUShort(); @@ -92,16 +100,18 @@ public final class ArrayRecord extends SharedValueRecordBase implements Cloneabl } sb.append("]"); return sb.toString(); - } - - @Override - public ArrayRecord clone() { - ArrayRecord rec = new ArrayRecord(_formula.copy(), getRange()); + } - // they both seem unused, but clone them nevertheless to have an exact copy - rec._options = _options; - rec._field3notUsed = _field3notUsed; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public ArrayRecord clone() { + return copy(); + } - return rec; + @Override + public ArrayRecord copy() { + return new ArrayRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/AutoFilterInfoRecord.java b/src/java/org/apache/poi/hssf/record/AutoFilterInfoRecord.java index ae0005bd67..ccb2d17bae 100644 --- a/src/java/org/apache/poi/hssf/record/AutoFilterInfoRecord.java +++ b/src/java/org/apache/poi/hssf/record/AutoFilterInfoRecord.java @@ -20,27 +20,28 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * The AutoFilterInfo record specifies the number of columns that have AutoFilter enabled * and indicates the beginning of the collection of AutoFilter records. - * - * @author Yegor Kozlov */ -public final class AutoFilterInfoRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x9D; +public final class AutoFilterInfoRecord extends StandardRecord { + public static final short sid = 0x9D; /** * Number of AutoFilter drop-down arrows on the sheet */ - private short _cEntries; // = 0; + private short _cEntries; - public AutoFilterInfoRecord() - { + public AutoFilterInfoRecord() {} + + public AutoFilterInfoRecord(AutoFilterInfoRecord other) { + super(other); + _cEntries = other._cEntries; } - public AutoFilterInfoRecord(RecordInputStream in) - { + public AutoFilterInfoRecord(RecordInputStream in) { _cEntries = in.readShort(); } @@ -91,9 +92,15 @@ public final class AutoFilterInfoRecord extends StandardRecord implements Clonea } @Override - public AutoFilterInfoRecord clone() - { - return (AutoFilterInfoRecord)cloneViaReserialise(); + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public AutoFilterInfoRecord clone() { + return copy(); + } + + @Override + public AutoFilterInfoRecord copy() { + return new AutoFilterInfoRecord(this); } - }
\ No newline at end of file diff --git a/src/java/org/apache/poi/hssf/record/BOFRecord.java b/src/java/org/apache/poi/hssf/record/BOFRecord.java index 992ee87220..beb8ab4ff6 100644 --- a/src/java/org/apache/poi/hssf/record/BOFRecord.java +++ b/src/java/org/apache/poi/hssf/record/BOFRecord.java @@ -19,44 +19,40 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Beginning Of File (0x0809)<P> - * Description: Somewhat of a misnomer, its used for the beginning of a set of - * records that have a particular purpose or subject. - * Used in sheets and workbooks.<P> - * REFERENCE: PG 289 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver - * @author Jason Height (jheight at chariot dot net dot au) + * Somewhat of a misnomer, its used for the beginning of a set of records that + * have a particular purpose or subject. Used in sheets and workbooks. */ -public final class BOFRecord extends StandardRecord implements Cloneable { +public final class BOFRecord extends StandardRecord { /** * for BIFF8 files the BOF is 0x809. For earlier versions see - * {@link #biff2_sid} {@link #biff3_sid} {@link #biff4_sid} + * {@link #biff2_sid} {@link #biff3_sid} {@link #biff4_sid} * {@link #biff5_sid} */ - public final static short sid = 0x809; + public static final short sid = 0x809; // SIDs from earlier BIFF versions - public final static short biff2_sid = 0x009; - public final static short biff3_sid = 0x209; - public final static short biff4_sid = 0x409; - public final static short biff5_sid = 0x809; + public static final short biff2_sid = 0x009; + public static final short biff3_sid = 0x209; + public static final short biff4_sid = 0x409; + public static final short biff5_sid = 0x809; /** suggested default (0x0600 - BIFF8) */ - public final static int VERSION = 0x0600; + public static final int VERSION = 0x0600; /** suggested default 0x10d3 */ - public final static int BUILD = 0x10d3; + public static final int BUILD = 0x10d3; /** suggested default 0x07CC (1996) */ - public final static int BUILD_YEAR = 0x07CC; // 1996 + public static final int BUILD_YEAR = 0x07CC; // 1996 /** suggested default for a normal sheet (0x41) */ - public final static int HISTORY_MASK = 0x41; + public static final int HISTORY_MASK = 0x41; - public final static int TYPE_WORKBOOK = 0x05; - public final static int TYPE_VB_MODULE = 0x06; - public final static int TYPE_WORKSHEET = 0x10; - public final static int TYPE_CHART = 0x20; - public final static int TYPE_EXCEL_4_MACRO = 0x40; - public final static int TYPE_WORKSPACE_FILE = 0x100; + public static final int TYPE_WORKBOOK = 0x05; + public static final int TYPE_VB_MODULE = 0x06; + public static final int TYPE_WORKSHEET = 0x10; + public static final int TYPE_CHART = 0x20; + public static final int TYPE_EXCEL_4_MACRO = 0x40; + public static final int TYPE_WORKSPACE_FILE = 0x100; private int field_1_version; private int field_2_type; @@ -68,9 +64,18 @@ public final class BOFRecord extends StandardRecord implements Cloneable { /** * Constructs an empty BOFRecord with no fields set. */ - public BOFRecord() { + public BOFRecord() {} + + public BOFRecord(BOFRecord other) { + super(other); + field_1_version = other.field_1_version; + field_2_type = other.field_2_type; + field_3_build = other.field_3_build; + field_4_year = other.field_4_year; + field_5_history = other.field_5_history; + field_6_rversion = other.field_6_rversion; } - + private BOFRecord(int type) { field_1_version = VERSION; field_2_type = type; @@ -79,7 +84,7 @@ public final class BOFRecord extends StandardRecord implements Cloneable { field_5_history = 0x01; field_6_rversion = VERSION; } - + public static BOFRecord createSheetBOF() { return new BOFRecord(TYPE_WORKSHEET); } @@ -269,14 +274,15 @@ public final class BOFRecord extends StandardRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public BOFRecord clone() { - BOFRecord rec = new BOFRecord(); - rec.field_1_version = field_1_version; - rec.field_2_type = field_2_type; - rec.field_3_build = field_3_build; - rec.field_4_year = field_4_year; - rec.field_5_history = field_5_history; - rec.field_6_rversion = field_6_rversion; - return rec; + return copy(); + } + + @Override + public BOFRecord copy() { + return new BOFRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/BackupRecord.java b/src/java/org/apache/poi/hssf/record/BackupRecord.java index 509d8d8dbf..5882113cb6 100644 --- a/src/java/org/apache/poi/hssf/record/BackupRecord.java +++ b/src/java/org/apache/poi/hssf/record/BackupRecord.java @@ -15,33 +15,31 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; /** - * Title: Backup Record <P> - * Description: Boolean specifying whether - * the GUI should store a backup of the file.<P> - * REFERENCE: PG 287 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) + * Boolean specifying whether the GUI should store a backup of the file. + * * @version 2.0-pre */ -public final class BackupRecord - extends StandardRecord -{ - public final static short sid = 0x40; - private short field_1_backup; // = 0; +public final class BackupRecord extends StandardRecord { + public static final short sid = 0x40; - public BackupRecord() - { + private short field_1_backup; + + public BackupRecord() {} + + public BackupRecord(BackupRecord other) { + super(other); + field_1_backup = other.field_1_backup; } - public BackupRecord(RecordInputStream in) - { + public BackupRecord(RecordInputStream in) { field_1_backup = in.readShort(); } @@ -90,4 +88,9 @@ public final class BackupRecord { return sid; } + + @Override + public BackupRecord copy() { + return new BackupRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/BlankRecord.java b/src/java/org/apache/poi/hssf/record/BlankRecord.java index 007dd86524..68e75b40c9 100644 --- a/src/java/org/apache/poi/hssf/record/BlankRecord.java +++ b/src/java/org/apache/poi/hssf/record/BlankRecord.java @@ -19,28 +19,32 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Blank cell record (0x0201) <P> - * Description: Represents a column in a row with no value but with styling.<P> - * REFERENCE: PG 287 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Jason Height (jheight at chariot dot net dot au) + * Represents a column in a row with no value but with styling. + * * @version 2.0-pre */ -public final class BlankRecord extends StandardRecord implements CellValueRecordInterface, Cloneable { - public final static short sid = 0x0201; - private int field_1_row; - private short field_2_col; - private short field_3_xf; +public final class BlankRecord extends StandardRecord implements CellValueRecordInterface { + public static final short sid = 0x0201; + + private int field_1_row; + private short field_2_col; + private short field_3_xf; /** Creates a new instance of BlankRecord */ - public BlankRecord() - { + public BlankRecord() {} + + public BlankRecord(BlankRecord other) { + super(other); + field_1_row = other.field_1_row; + field_2_col = other.field_2_col; + field_3_xf = other.field_3_xf; } - public BlankRecord(RecordInputStream in) - { + + public BlankRecord(RecordInputStream in) { field_1_row = in.readUShort(); field_2_col = in.readShort(); field_3_xf = in.readShort(); @@ -138,11 +142,15 @@ public final class BlankRecord extends StandardRecord implements CellValueRecord } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public BlankRecord clone() { - BlankRecord rec = new BlankRecord(); - rec.field_1_row = field_1_row; - rec.field_2_col = field_2_col; - rec.field_3_xf = field_3_xf; - return rec; + return copy(); + } + + @Override + public BlankRecord copy() { + return new BlankRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/BookBoolRecord.java b/src/java/org/apache/poi/hssf/record/BookBoolRecord.java index d40214523d..98c1e3e5dc 100644 --- a/src/java/org/apache/poi/hssf/record/BookBoolRecord.java +++ b/src/java/org/apache/poi/hssf/record/BookBoolRecord.java @@ -15,33 +15,31 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; /** - * Title: Save External Links record (BookBool)<P> - * Description: Contains a flag specifying whether the Gui should save externally - * linked values from other workbooks. <P> - * REFERENCE: PG 289 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) + * Contains a flag specifying whether the Gui should save externally linked values from other workbooks. + * * @version 2.0-pre */ -public final class BookBoolRecord - extends StandardRecord -{ - public final static short sid = 0xDA; - private short field_1_save_link_values; +public final class BookBoolRecord extends StandardRecord { + public static final short sid = 0xDA; - public BookBoolRecord() - { + private short field_1_save_link_values; + + public BookBoolRecord() {} + + public BookBoolRecord(BookBoolRecord other) { + super(other); + field_1_save_link_values = other.field_1_save_link_values; } - public BookBoolRecord(RecordInputStream in) - { + public BookBoolRecord(RecordInputStream in) { field_1_save_link_values = in.readShort(); } @@ -90,4 +88,9 @@ public final class BookBoolRecord { return sid; } + + @Override + public BookBoolRecord copy() { + return new BookBoolRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/BoolErrRecord.java b/src/java/org/apache/poi/hssf/record/BoolErrRecord.java index b733f2f1ff..8dd944e115 100644 --- a/src/java/org/apache/poi/hssf/record/BoolErrRecord.java +++ b/src/java/org/apache/poi/hssf/record/BoolErrRecord.java @@ -21,24 +21,27 @@ import org.apache.poi.ss.usermodel.FormulaError; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.RecordFormatException; +import org.apache.poi.util.Removal; /** - * Creates new BoolErrRecord. (0x0205) <P> - * REFERENCE: PG ??? Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Michael P. Harhen - * @author Jason Height (jheight at chariot dot net dot au) + * Creates new BoolErrRecord. (0x0205) */ -public final class BoolErrRecord extends CellRecord implements Cloneable { - public final static short sid = 0x0205; +public final class BoolErrRecord extends CellRecord { + public static final short sid = 0x0205; private int _value; /** - * If <code>true</code>, this record represents an error cell value, otherwise this record represents a boolean cell value + * If <code>true</code>, this record represents an error cell value, + * otherwise this record represents a boolean cell value */ private boolean _isError; /** Creates new BoolErrRecord */ - public BoolErrRecord() { - // fields uninitialised + public BoolErrRecord() {} + + public BoolErrRecord(BoolErrRecord other) { + super(other); + _value = other._value; + _isError = other._isError; } /** @@ -183,11 +186,15 @@ public final class BoolErrRecord extends CellRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public BoolErrRecord clone() { - BoolErrRecord rec = new BoolErrRecord(); - copyBaseFields(rec); - rec._value = _value; - rec._isError = _isError; - return rec; + return copy(); + } + + @Override + public BoolErrRecord copy() { + return new BoolErrRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/BottomMarginRecord.java b/src/java/org/apache/poi/hssf/record/BottomMarginRecord.java index 36533dab16..ff2328eab3 100644 --- a/src/java/org/apache/poi/hssf/record/BottomMarginRecord.java +++ b/src/java/org/apache/poi/hssf/record/BottomMarginRecord.java @@ -20,22 +20,24 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * Record for the bottom margin. */ -public final class BottomMarginRecord extends StandardRecord implements Margin, Cloneable { - public final static short sid = 0x29; +public final class BottomMarginRecord extends StandardRecord implements Margin { + public static final short sid = 0x29; private double field_1_margin; - public BottomMarginRecord() - { + public BottomMarginRecord() {} + public BottomMarginRecord(BottomMarginRecord other) { + super(other); + field_1_margin = other.field_1_margin; } - public BottomMarginRecord( RecordInputStream in ) - { + public BottomMarginRecord( RecordInputStream in ) { field_1_margin = in.readDouble(); } @@ -79,10 +81,15 @@ public final class BottomMarginRecord extends StandardRecord implements Margin, } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public BottomMarginRecord clone() { - BottomMarginRecord rec = new BottomMarginRecord(); - rec.field_1_margin = this.field_1_margin; - return rec; + return copy(); } -} // END OF
\ No newline at end of file + @Override + public BottomMarginRecord copy() { + return new BottomMarginRecord(this); + } +}
\ No newline at end of file diff --git a/src/java/org/apache/poi/hssf/record/BoundSheetRecord.java b/src/java/org/apache/poi/hssf/record/BoundSheetRecord.java index 33114f1a73..72131e010f 100644 --- a/src/java/org/apache/poi/hssf/record/BoundSheetRecord.java +++ b/src/java/org/apache/poi/hssf/record/BoundSheetRecord.java @@ -18,9 +18,9 @@ package org.apache.poi.hssf.record; import java.util.Arrays; -import java.util.Comparator; import java.util.List; +import org.apache.poi.ss.util.WorkbookUtil; import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; @@ -28,20 +28,16 @@ import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndianConsts; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.StringUtil; -import org.apache.poi.ss.util.WorkbookUtil; /** - * Title: Bound Sheet Record (aka BundleSheet) (0x0085)<P> - * Description: Defines a sheet within a workbook. Basically stores the sheet name - * and tells where the Beginning of file record is within the HSSF - * file. <P> - * REFERENCE: PG 291 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) + * Defines a sheet within a workbook. Basically stores the sheet name and + * tells where the Beginning of file record is within the HSSF file. */ public final class BoundSheetRecord extends StandardRecord { - public final static short sid = 0x0085; - + public static final short sid = 0x0085; private static final BitField hiddenFlag = BitFieldFactory.getInstance(0x01); private static final BitField veryHiddenFlag = BitFieldFactory.getInstance(0x02); + private int field_1_position_of_BOF; private int field_2_option_flags; private int field_4_isMultibyteUnicode; @@ -52,13 +48,21 @@ public final class BoundSheetRecord extends StandardRecord { setSheetname(sheetname); } + public BoundSheetRecord(BoundSheetRecord other) { + super(other); + field_1_position_of_BOF = other.field_1_position_of_BOF; + field_2_option_flags = other.field_2_option_flags; + field_4_isMultibyteUnicode = other.field_4_isMultibyteUnicode; + field_5_sheetname = other.field_5_sheetname; + } + /** * UTF8: sid + len + bof + flags + len(str) + unicode + str 2 + 2 + 4 + 2 + * 1 + 1 + len(str) * * UNICODE: sid + len + bof + flags + len(str) + unicode + str 2 + 2 + 4 + 2 + * 1 + 1 + 2 * len(str) - * + * * @param in the record stream to read from */ public BoundSheetRecord(RecordInputStream in) { @@ -158,7 +162,7 @@ public final class BoundSheetRecord extends StandardRecord { /** * Is the sheet hidden? Different from very hidden - * + * * @return {@code true} if hidden */ public boolean isHidden() { @@ -167,7 +171,7 @@ public final class BoundSheetRecord extends StandardRecord { /** * Is the sheet hidden? Different from very hidden - * + * * @param hidden {@code true} if hidden */ public void setHidden(boolean hidden) { @@ -176,7 +180,7 @@ public final class BoundSheetRecord extends StandardRecord { /** * Is the sheet very hidden? Different from (normal) hidden - * + * * @return {@code true} if very hidden */ public boolean isVeryHidden() { @@ -185,7 +189,7 @@ public final class BoundSheetRecord extends StandardRecord { /** * Is the sheet very hidden? Different from (normal) hidden - * + * * @param veryHidden {@code true} if very hidden */ public void setVeryHidden(boolean veryHidden) { @@ -195,22 +199,24 @@ public final class BoundSheetRecord extends StandardRecord { /** * Converts a List of {@link BoundSheetRecord}s to an array and sorts by the position of their * BOFs. - * + * * @param boundSheetRecords the boundSheetRecord list to arrayify - * + * * @return the sorted boundSheetRecords */ public static BoundSheetRecord[] orderByBofPosition(List<BoundSheetRecord> boundSheetRecords) { BoundSheetRecord[] bsrs = new BoundSheetRecord[boundSheetRecords.size()]; boundSheetRecords.toArray(bsrs); - Arrays.sort(bsrs, BOFComparator); + Arrays.sort(bsrs, BoundSheetRecord::compareRecords); return bsrs; } - - private static final Comparator<BoundSheetRecord> BOFComparator = new Comparator<BoundSheetRecord>() { - public int compare(BoundSheetRecord bsr1, BoundSheetRecord bsr2) { - return bsr1.getPositionOfBof() - bsr2.getPositionOfBof(); - } - }; + private static int compareRecords(BoundSheetRecord bsr1, BoundSheetRecord bsr2) { + return bsr1.getPositionOfBof() - bsr2.getPositionOfBof(); + } + + @Override + public BoundSheetRecord copy() { + return new BoundSheetRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/CFHeader12Record.java b/src/java/org/apache/poi/hssf/record/CFHeader12Record.java index 241faf1395..21b423632f 100644 --- a/src/java/org/apache/poi/hssf/record/CFHeader12Record.java +++ b/src/java/org/apache/poi/hssf/record/CFHeader12Record.java @@ -21,22 +21,28 @@ import org.apache.poi.hssf.record.common.FtrHeader; import org.apache.poi.hssf.record.common.FutureRecord; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * Conditional Formatting Header v12 record CFHEADER12 (0x0879), * for conditional formattings introduced in Excel 2007 and newer. */ -public final class CFHeader12Record extends CFHeaderBase implements FutureRecord, Cloneable { +public final class CFHeader12Record extends CFHeaderBase implements FutureRecord { public static final short sid = 0x0879; private FtrHeader futureHeader; - /** Creates new CFHeaderRecord */ public CFHeader12Record() { createEmpty(); futureHeader = new FtrHeader(); futureHeader.setRecordType(sid); } + + public CFHeader12Record(CFHeader12Record other) { + super(other); + futureHeader = other.futureHeader.copy(); + } + public CFHeader12Record(CellRangeAddress[] regions, int nRules) { super(regions, nRules); futureHeader = new FtrHeader(); @@ -78,12 +84,17 @@ public final class CFHeader12Record extends CFHeaderBase implements FutureRecord public CellRangeAddress getAssociatedRange() { return futureHeader.getAssociatedRange(); } - + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public CFHeader12Record clone() { - CFHeader12Record result = new CFHeader12Record(); - result.futureHeader = (FtrHeader)futureHeader.clone(); - super.copyTo(result); - return result; + return copy(); + } + + @Override + public CFHeader12Record copy() { + return new CFHeader12Record(this); } } diff --git a/src/java/org/apache/poi/hssf/record/CFHeaderBase.java b/src/java/org/apache/poi/hssf/record/CFHeaderBase.java index f4c1fbe87f..46b4c155a9 100644 --- a/src/java/org/apache/poi/hssf/record/CFHeaderBase.java +++ b/src/java/org/apache/poi/hssf/record/CFHeaderBase.java @@ -21,20 +21,28 @@ import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddressList; import org.apache.poi.ss.util.CellRangeUtil; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * Parent of Conditional Formatting Header records, * {@link CFHeaderRecord} and {@link CFHeader12Record}. */ -public abstract class CFHeaderBase extends StandardRecord implements Cloneable { +public abstract class CFHeaderBase extends StandardRecord { private int field_1_numcf; private int field_2_need_recalculation_and_id; private CellRangeAddress field_3_enclosing_cell_range; private CellRangeAddressList field_4_cell_ranges; - /** Creates new CFHeaderBase */ - protected CFHeaderBase() { + protected CFHeaderBase() {} + + protected CFHeaderBase(CFHeaderBase other) { + super(other); + field_1_numcf = other.field_1_numcf; + field_2_need_recalculation_and_id = other.field_2_need_recalculation_and_id; + field_3_enclosing_cell_range = other.field_3_enclosing_cell_range.copy(); + field_4_cell_ranges = other.field_4_cell_ranges.copy(); } + protected CFHeaderBase(CellRangeAddress[] regions, int nRules) { CellRangeAddress[] mergeCellRanges = CellRangeUtil.mergeCellRanges(regions); setCellRanges(mergeCellRanges); @@ -97,7 +105,7 @@ public abstract class CFHeaderBase extends StandardRecord implements Cloneable { } /** - * Set cell ranges list to a single cell range and + * Set cell ranges list to a single cell range and * modify the enclosing cell range accordingly. * @param cellRanges - list of CellRange objects */ @@ -151,13 +159,12 @@ public abstract class CFHeaderBase extends StandardRecord implements Cloneable { field_4_cell_ranges.serialize(out); } - protected void copyTo(CFHeaderBase result) { - result.field_1_numcf = field_1_numcf; - result.field_2_need_recalculation_and_id = field_2_need_recalculation_and_id; - result.field_3_enclosing_cell_range = field_3_enclosing_cell_range.copy(); - result.field_4_cell_ranges = field_4_cell_ranges.copy(); - } + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public abstract CFHeaderBase clone(); @Override - public abstract CFHeaderBase clone(); // NOSONAR + public abstract CFHeaderBase copy(); } diff --git a/src/java/org/apache/poi/hssf/record/CFHeaderRecord.java b/src/java/org/apache/poi/hssf/record/CFHeaderRecord.java index c3c6851fe6..1b764977b0 100644 --- a/src/java/org/apache/poi/hssf/record/CFHeaderRecord.java +++ b/src/java/org/apache/poi/hssf/record/CFHeaderRecord.java @@ -18,19 +18,24 @@ package org.apache.poi.hssf.record; import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.util.Removal; /** * Conditional Formatting Header record CFHEADER (0x01B0). * Used to describe a {@link CFRuleRecord}. * @see CFHeader12Record */ -public final class CFHeaderRecord extends CFHeaderBase implements Cloneable { +public final class CFHeaderRecord extends CFHeaderBase { public static final short sid = 0x01B0; - /** Creates new CFHeaderRecord */ public CFHeaderRecord() { createEmpty(); } + + public CFHeaderRecord(CFHeaderRecord other) { + super(other); + } + public CFHeaderRecord(CellRangeAddress[] regions, int nRules) { super(regions, nRules); } @@ -48,9 +53,15 @@ public final class CFHeaderRecord extends CFHeaderBase implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public CFHeaderRecord clone() { - CFHeaderRecord result = new CFHeaderRecord(); - super.copyTo(result); - return result; + return copy(); + } + + @Override + public CFHeaderRecord copy() { + return new CFHeaderRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/CFRule12Record.java b/src/java/org/apache/poi/hssf/record/CFRule12Record.java index 52bcf2ad24..abfb277106 100644 --- a/src/java/org/apache/poi/hssf/record/CFRule12Record.java +++ b/src/java/org/apache/poi/hssf/record/CFRule12Record.java @@ -39,18 +39,19 @@ import org.apache.poi.util.HexDump; import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.POILogger; +import org.apache.poi.util.Removal; /** - * Conditional Formatting v12 Rule Record (0x087A). - * + * Conditional Formatting v12 Rule Record (0x087A). + * * <p>This is for newer-style Excel conditional formattings, * from Excel 2007 onwards. - * + * * <p>{@link CFRuleRecord} is used where the condition type is * {@link #CONDITION_TYPE_CELL_VALUE_IS} or {@link #CONDITION_TYPE_FORMULA}, * this is only used for the other types */ -public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cloneable { +public final class CFRule12Record extends CFRuleBase implements FutureRecord { //arbitrarily selected; may need to increase private static final int MAX_RECORD_LENGTH = 100_000; @@ -66,14 +67,35 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl private int template_type; private byte template_param_length; private byte[] template_params; - + private DataBarFormatting data_bar; private IconMultiStateFormatting multistate; private ColorGradientFormatting color_gradient; // TODO Parse this, see #58150 private byte[] filter_data; - /** Creates new CFRuleRecord */ + public CFRule12Record(CFRule12Record other) { + super(other); + futureHeader = (other.futureHeader == null) ? null : other.futureHeader.copy(); + + // use min() to gracefully handle cases where the length-property and the array-length do not match + // we saw some such files in circulation + ext_formatting_length = Math.min(other.ext_formatting_length, other.ext_formatting_data.length); + ext_formatting_data = other.ext_formatting_data.clone(); + + formula_scale = other.formula_scale.copy(); + + ext_opts = other.ext_opts; + priority = other.priority; + template_type = other.template_type; + template_param_length = other.template_param_length; + template_params = (other.template_params == null) ? null : other.template_params.clone(); + color_gradient = (other.color_gradient == null) ? null : other.color_gradient.copy(); + multistate = (other.multistate == null) ? null : other.multistate.copy(); + data_bar = (other.data_bar == null) ? null : other.data_bar.copy(); + filter_data = (other.filter_data == null) ? null : other.filter_data.clone(); + } + private CFRule12Record(byte conditionType, byte comparisonOperation) { super(conditionType, comparisonOperation); setDefaults(); @@ -84,15 +106,17 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl setDefaults(); this.formula_scale = Formula.create(formulaScale); } + + private void setDefaults() { futureHeader = new FtrHeader(); futureHeader.setRecordType(sid); - + ext_formatting_length = 0; ext_formatting_data = new byte[4]; - + formula_scale = Formula.create(Ptg.EMPTY_PTG_ARRAY); - + ext_opts = 0; priority = 0; template_type = getConditionType(); @@ -102,10 +126,10 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl /** * Creates a new comparison operation rule - * + * * @param sheet the sheet * @param formulaText the first formula text - * + * * @return a new comparison operation rule */ public static CFRule12Record create(HSSFSheet sheet, String formulaText) { @@ -113,34 +137,34 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl return new CFRule12Record(CONDITION_TYPE_FORMULA, ComparisonOperator.NO_COMPARISON, formula1, null, null); } - + /** * Creates a new comparison operation rule - * + * * @param sheet the sheet * @param comparisonOperation the comparison operation * @param formulaText1 the first formula text * @param formulaText2 the second formula text - * + * * @return a new comparison operation rule */ public static CFRule12Record create(HSSFSheet sheet, byte comparisonOperation, String formulaText1, String formulaText2) { Ptg[] formula1 = parseFormula(formulaText1, sheet); Ptg[] formula2 = parseFormula(formulaText2, sheet); - return new CFRule12Record(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation, + return new CFRule12Record(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation, formula1, formula2, null); } - + /** * Creates a new comparison operation rule - * + * * @param sheet the sheet * @param comparisonOperation the comparison operation * @param formulaText1 the first formula text * @param formulaText2 the second formula text * @param formulaTextScale the scale to apply for the comparison - * + * * @return a new comparison operation rule */ public static CFRule12Record create(HSSFSheet sheet, byte comparisonOperation, @@ -148,43 +172,43 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl Ptg[] formula1 = parseFormula(formulaText1, sheet); Ptg[] formula2 = parseFormula(formulaText2, sheet); Ptg[] formula3 = parseFormula(formulaTextScale, sheet); - return new CFRule12Record(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation, + return new CFRule12Record(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation, formula1, formula2, formula3); } - + /** * Creates a new Data Bar formatting - * + * * @param sheet the sheet * @param color the data bar color - * + * * @return a new Data Bar formatting */ public static CFRule12Record create(HSSFSheet sheet, ExtendedColor color) { - CFRule12Record r = new CFRule12Record(CONDITION_TYPE_DATA_BAR, + CFRule12Record r = new CFRule12Record(CONDITION_TYPE_DATA_BAR, ComparisonOperator.NO_COMPARISON); DataBarFormatting dbf = r.createDataBarFormatting(); dbf.setColor(color); dbf.setPercentMin((byte)0); dbf.setPercentMax((byte)100); - + DataBarThreshold min = new DataBarThreshold(); min.setType(RangeType.MIN.id); dbf.setThresholdMin(min); - + DataBarThreshold max = new DataBarThreshold(); max.setType(RangeType.MAX.id); dbf.setThresholdMax(max); - + return r; } - + /** * Creates a new Icon Set / Multi-State formatting - * + * * @param sheet the sheet * @param iconSet the icon set - * + * * @return a new Icon Set / Multi-State formatting */ public static CFRule12Record create(HSSFSheet sheet, IconSet iconSet) { @@ -192,20 +216,20 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl for (int i=0; i<ts.length; i++) { ts[i] = new IconMultiStateThreshold(); } - - CFRule12Record r = new CFRule12Record(CONDITION_TYPE_ICON_SET, + + CFRule12Record r = new CFRule12Record(CONDITION_TYPE_ICON_SET, ComparisonOperator.NO_COMPARISON); IconMultiStateFormatting imf = r.createMultiStateFormatting(); imf.setIconSet(iconSet); imf.setThresholds(ts); return r; } - + /** * Creates a new Color Scale / Color Gradient formatting - * + * * @param sheet the sheet - * + * * @return a new Color Scale / Color Gradient formatting */ public static CFRule12Record createColorScale(HSSFSheet sheet) { @@ -216,8 +240,8 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl ts[i] = new ColorGradientThreshold(); colors[i] = new ExtendedColor(); } - - CFRule12Record r = new CFRule12Record(CONDITION_TYPE_COLOR_SCALE, + + CFRule12Record r = new CFRule12Record(CONDITION_TYPE_COLOR_SCALE, ComparisonOperator.NO_COMPARISON); ColorGradientFormatting cgf = r.createColorGradientFormatting(); cgf.setNumControlPoints(numPoints); @@ -232,7 +256,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl setComparisonOperation(in.readByte()); int field_3_formula1_len = in.readUShort(); int field_4_formula2_len = in.readUShort(); - + ext_formatting_length = in.readInt(); ext_formatting_data = new byte[0]; if (ext_formatting_length == 0) { @@ -245,13 +269,13 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl in.readFully(ext_formatting_data); } } - + setFormula1(Formula.read(field_3_formula1_len, in)); setFormula2(Formula.read(field_4_formula2_len, in)); - + int formula_scale_len = in.readUShort(); formula_scale = Formula.read(formula_scale_len, in); - + ext_opts = in.readByte(); priority = in.readUShort(); template_type = in.readUShort(); @@ -263,7 +287,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl logger.log(POILogger.WARN, "CF Rule v12 template params length should be 0 or 16, found " + template_param_length); in.readRemainder(); } - + byte type = getConditionType(); if (type == CONDITION_TYPE_COLOR_SCALE) { color_gradient = new ColorGradientFormatting(in); @@ -275,7 +299,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl multistate = new IconMultiStateFormatting(in); } } - + public boolean containsDataBarBlock() { return (data_bar != null); } @@ -284,7 +308,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl } public DataBarFormatting createDataBarFormatting() { if (data_bar != null) return data_bar; - + // Convert, setup and return setConditionType(CONDITION_TYPE_DATA_BAR); data_bar = new DataBarFormatting(); @@ -299,7 +323,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl } public IconMultiStateFormatting createMultiStateFormatting() { if (multistate != null) return multistate; - + // Convert, setup and return setConditionType(CONDITION_TYPE_ICON_SET); multistate = new IconMultiStateFormatting(); @@ -314,7 +338,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl } public ColorGradientFormatting createColorGradientFormatting() { if (color_gradient != null) return color_gradient; - + // Convert, setup and return setConditionType(CONDITION_TYPE_COLOR_SCALE); color_gradient = new ColorGradientFormatting(); @@ -356,7 +380,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl */ public void serialize(LittleEndianOutput out) { futureHeader.serialize(out); - + int formula1Len=getFormulaSize(getFormula1()); int formula2Len=getFormulaSize(getFormula2()); @@ -364,7 +388,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl out.writeByte(getComparisonOperation()); out.writeShort(formula1Len); out.writeShort(formula2Len); - + // TODO Update ext_formatting_length if (ext_formatting_length == 0) { out.writeInt(0); @@ -374,18 +398,18 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl serializeFormattingBlock(out); out.write(ext_formatting_data); } - + getFormula1().serializeTokens(out); getFormula2().serializeTokens(out); out.writeShort(getFormulaSize(formula_scale)); formula_scale.serializeTokens(out); - + out.writeByte(ext_opts); out.writeShort(priority); out.writeShort(template_type); out.writeByte(template_param_length); out.write(template_params); - + byte type = getConditionType(); if (type == CONDITION_TYPE_COLOR_SCALE) { color_gradient.serialize(out); @@ -409,7 +433,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl len += getFormulaSize(getFormula2()); len += 2 + getFormulaSize(formula_scale); len += 6 + template_params.length; - + byte type = getConditionType(); if (type == CONDITION_TYPE_COLOR_SCALE) { len += color_gradient.getDataLength(); @@ -461,44 +485,18 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public CFRule12Record clone() { - CFRule12Record rec = new CFRule12Record(getConditionType(), getComparisonOperation()); - rec.futureHeader.setAssociatedRange(futureHeader.getAssociatedRange().copy()); - - super.copyTo(rec); - - // use min() to gracefully handle cases where the length-property and the array-length do not match - // we saw some such files in circulation - rec.ext_formatting_length = Math.min(ext_formatting_length, ext_formatting_data.length); - rec.ext_formatting_data = IOUtils.safelyAllocate(ext_formatting_length, MAX_RECORD_LENGTH); - System.arraycopy(ext_formatting_data, 0, rec.ext_formatting_data, 0, rec.ext_formatting_length); - - rec.formula_scale = formula_scale.copy(); - - rec.ext_opts = ext_opts; - rec.priority = priority; - rec.template_type = template_type; - rec.template_param_length = template_param_length; - rec.template_params = IOUtils.safelyAllocate(template_param_length, MAX_RECORD_LENGTH); - System.arraycopy(template_params, 0, rec.template_params, 0, template_param_length); + return copy(); + } - if (color_gradient != null) { - rec.color_gradient = (ColorGradientFormatting)color_gradient.clone(); - } - if (multistate != null) { - rec.multistate = (IconMultiStateFormatting)multistate.clone(); - } - if (data_bar != null) { - rec.data_bar = (DataBarFormatting)data_bar.clone(); - } - if (filter_data != null) { - rec.filter_data = IOUtils.safelyAllocate(filter_data.length, MAX_RECORD_LENGTH); - System.arraycopy(filter_data, 0, rec.filter_data, 0, filter_data.length); - } - - return rec; + @Override + public CFRule12Record copy() { + return new CFRule12Record(this); } - + public short getFutureRecordType() { return futureHeader.getRecordType(); } diff --git a/src/java/org/apache/poi/hssf/record/CFRuleBase.java b/src/java/org/apache/poi/hssf/record/CFRuleBase.java index aae5073d75..da1fc8ba9a 100644 --- a/src/java/org/apache/poi/hssf/record/CFRuleBase.java +++ b/src/java/org/apache/poi/hssf/record/CFRuleBase.java @@ -30,32 +30,31 @@ import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; +import org.apache.poi.util.Removal; /** * Conditional Formatting Rules. This can hold old-style rules - * - * + * + * * <p>This is for the older-style Excel conditional formattings, * new-style (Excel 2007+) also make use of {@link CFRule12Record} * for their rules.</p> */ -public abstract class CFRuleBase extends StandardRecord implements Cloneable { +public abstract class CFRuleBase extends StandardRecord { // FIXME: Merge with org.apache.poi.ss.usermodel.ComparisonOperator and rewrite as an enum - public static final class ComparisonOperator { - public static final byte NO_COMPARISON = 0; - public static final byte BETWEEN = 1; - public static final byte NOT_BETWEEN = 2; - public static final byte EQUAL = 3; - public static final byte NOT_EQUAL = 4; - public static final byte GT = 5; - public static final byte LT = 6; - public static final byte GE = 7; - public static final byte LE = 8; - private static final byte max_operator = 8; + public interface ComparisonOperator { + byte NO_COMPARISON = 0; + byte BETWEEN = 1; + byte NOT_BETWEEN = 2; + byte EQUAL = 3; + byte NOT_EQUAL = 4; + byte GT = 5; + byte LT = 6; + byte GE = 7; + byte LE = 8; + byte max_operator = 8; } - protected static final POILogger logger = POILogFactory.getLogger(CFRuleBase.class); - private byte condition_type; // The only kinds that CFRuleRecord handles public static final byte CONDITION_TYPE_CELL_VALUE_IS = 1; public static final byte CONDITION_TYPE_FORMULA = 2; @@ -65,8 +64,6 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable { public static final byte CONDITION_TYPE_FILTER = 5; public static final byte CONDITION_TYPE_ICON_SET = 6; - private byte comparison_operator; - public static final int TEMPLATE_CELL_VALUE = 0x0000; public static final int TEMPLATE_FORMULA = 0x0001; public static final int TEMPLATE_COLOR_SCALE_FORMATTING = 0x0002; @@ -94,7 +91,9 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable { public static final int TEMPLATE_DUPLICATE_VALUES = 0x001B; public static final int TEMPLATE_ABOVE_OR_EQUAL_TO_AVERAGE = 0x001D; public static final int TEMPLATE_BELOW_OR_EQUAL_TO_AVERAGE = 0x001E; - + + protected static final POILogger logger = POILogFactory.getLogger(CFRuleBase.class); + static final BitField modificationBits = bf(0x003FFFFF); // Bits: font,align,bord,patt,prot static final BitField alignHor = bf(0x00000001); // 0 = Horizontal alignment modified static final BitField alignVer = bf(0x00000002); // 0 = Vertical alignment modified @@ -129,19 +128,24 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable { return BitFieldFactory.getInstance(i); } + + private byte condition_type; + private byte comparison_operator; + protected int formatting_options; - protected short formatting_not_used; // TODO Decode this properly + // TODO Decode this properly + protected short formatting_not_used; protected FontFormatting _fontFormatting; protected BorderFormatting _borderFormatting; protected PatternFormatting _patternFormatting; - + private Formula formula1; private Formula formula2; /** * Creates new CFRuleRecord - * + * * @param conditionType the condition type * @param comparisonOperation the comparison operation */ @@ -151,19 +155,34 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable { formula1 = Formula.create(Ptg.EMPTY_PTG_ARRAY); formula2 = Formula.create(Ptg.EMPTY_PTG_ARRAY); } + protected CFRuleBase(byte conditionType, byte comparisonOperation, Ptg[] formula1, Ptg[] formula2) { this(conditionType, comparisonOperation); this.formula1 = Formula.create(formula1); this.formula2 = Formula.create(formula2); } + protected CFRuleBase() {} - + + protected CFRuleBase(CFRuleBase other) { + super(other); + setConditionType(other.getConditionType()); + setComparisonOperation(other.getComparisonOperation()); + formatting_options = other.formatting_options; + formatting_not_used = other.formatting_not_used; + _fontFormatting = (!other.containsFontFormattingBlock()) ? null : other.getFontFormatting().copy(); + _borderFormatting = (!other.containsBorderFormattingBlock()) ? null : other.getBorderFormatting().copy(); + _patternFormatting = (!other.containsPatternFormattingBlock()) ? null : other.getPatternFormatting().copy(); + formula1 = other.getFormula1().copy(); + formula2 = other.getFormula2().copy(); + } + protected int readFormatOptions(RecordInputStream in) { formatting_options = in.readInt(); formatting_not_used = in.readShort(); int len = 6; - + if (containsFontFormattingBlock()) { _fontFormatting = new FontFormatting(in); len += _fontFormatting.getDataLength(); @@ -178,7 +197,7 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable { _patternFormatting = new PatternFormatting(in); len += _patternFormatting.getDataLength(); } - + return len; } @@ -187,10 +206,8 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable { } protected void setConditionType(byte condition_type) { if ((this instanceof CFRuleRecord)) { - if (condition_type == CONDITION_TYPE_CELL_VALUE_IS || - condition_type == CONDITION_TYPE_FORMULA) { - // Good, valid combination - } else { + if (!(condition_type == CONDITION_TYPE_CELL_VALUE_IS || + condition_type == CONDITION_TYPE_FORMULA)) { throw new IllegalArgumentException("CFRuleRecord only accepts Value-Is and Formula types"); } } @@ -201,7 +218,7 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable { if (operation < 0 || operation > ComparisonOperator.max_operator) throw new IllegalArgumentException( "Valid operators are only in the range 0 to " +ComparisonOperator.max_operator); - + this.comparison_operator = operation; } public byte getComparisonOperation() { @@ -351,7 +368,7 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable { private void setOptionFlag(boolean flag, BitField field) { formatting_options = field.setBoolean(formatting_options, flag); } - + protected int getFormattingBlockSize() { return 6 + (containsFontFormattingBlock()?_fontFormatting.getRawRecord().length:0)+ @@ -375,7 +392,7 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable { _patternFormatting.serialize(out); } } - + /** * get the stack of the 1st expression as a list * @@ -440,27 +457,13 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable { int sheetIndex = sheet.getWorkbook().getSheetIndex(sheet); return HSSFFormulaParser.parse(formula, sheet.getWorkbook(), FormulaType.CELL, sheetIndex); } - - protected void copyTo(CFRuleBase rec) { - rec.condition_type = condition_type; - rec.comparison_operator = comparison_operator; - - rec.formatting_options = formatting_options; - rec.formatting_not_used = formatting_not_used; - if (containsFontFormattingBlock()) { - rec._fontFormatting = _fontFormatting.clone(); - } - if (containsBorderFormattingBlock()) { - rec._borderFormatting = _borderFormatting.clone(); - } - if (containsPatternFormattingBlock()) { - rec._patternFormatting = (PatternFormatting) _patternFormatting.clone(); - } - - rec.setFormula1(getFormula1().copy()); - rec.setFormula2(getFormula2().copy()); - } - + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public abstract CFRuleBase clone(); + + @Override + public abstract CFRuleBase copy(); } diff --git a/src/java/org/apache/poi/hssf/record/CFRuleRecord.java b/src/java/org/apache/poi/hssf/record/CFRuleRecord.java index 77e6e96181..b5bd489f23 100644 --- a/src/java/org/apache/poi/hssf/record/CFRuleRecord.java +++ b/src/java/org/apache/poi/hssf/record/CFRuleRecord.java @@ -23,18 +23,22 @@ import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.ss.formula.Formula; import org.apache.poi.ss.formula.ptg.Ptg; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Conditional Formatting Rule Record (0x01B1). - * + * Conditional Formatting Rule Record (0x01B1). + * * <p>This is for the older-style Excel conditional formattings, * new-style (Excel 2007+) also make use of {@link CFRule12Record} * for their rules.</p> */ -public final class CFRuleRecord extends CFRuleBase implements Cloneable { +public final class CFRuleRecord extends CFRuleBase { public static final short sid = 0x01B1; - /** Creates new CFRuleRecord */ + public CFRuleRecord(CFRuleRecord other) { + super(other); + } + private CFRuleRecord(byte conditionType, byte comparisonOperation) { super(conditionType, comparisonOperation); setDefaults(); @@ -59,10 +63,10 @@ public final class CFRuleRecord extends CFRuleBase implements Cloneable { /** * Creates a new comparison operation rule - * + * * @param sheet the sheet * @param formulaText the formula text - * + * * @return a new comparison operation rule */ public static CFRuleRecord create(HSSFSheet sheet, String formulaText) { @@ -72,12 +76,12 @@ public final class CFRuleRecord extends CFRuleBase implements Cloneable { } /** * Creates a new comparison operation rule - * + * * @param sheet the sheet * @param comparisonOperation the comparison operation * @param formulaText1 the first formula text * @param formulaText2 the second formula text - * + * * @return a new comparison operation rule */ public static CFRuleRecord create(HSSFSheet sheet, byte comparisonOperation, @@ -120,7 +124,7 @@ public final class CFRuleRecord extends CFRuleBase implements Cloneable { out.writeByte(getComparisonOperation()); out.writeShort(formula1Len); out.writeShort(formula2Len); - + serializeFormattingBlock(out); getFormula1().serializeTokens(out); @@ -156,9 +160,15 @@ public final class CFRuleRecord extends CFRuleBase implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public CFRuleRecord clone() { - CFRuleRecord rec = new CFRuleRecord(getConditionType(), getComparisonOperation()); - super.copyTo(rec); - return rec; + return copy(); + } + + @Override + public CFRuleRecord copy() { + return new CFRuleRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/CRNCountRecord.java b/src/java/org/apache/poi/hssf/record/CRNCountRecord.java index 6037360768..4153f8d58d 100644 --- a/src/java/org/apache/poi/hssf/record/CRNCountRecord.java +++ b/src/java/org/apache/poi/hssf/record/CRNCountRecord.java @@ -19,30 +19,26 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; /** - * XCT - CRN Count <P> - * - * REFERENCE: 5.114<P> - * - * @author Josh Micich + * XCT - CRN Count */ public final class CRNCountRecord extends StandardRecord { - public final static short sid = 0x59; + public static final short sid = 0x59; private static final short DATA_SIZE = 4; + private int field_1_number_crn_records; + private int field_2_sheet_table_index; - private int field_1_number_crn_records; - private int field_2_sheet_table_index; - - public CRNCountRecord() { - throw new RuntimeException("incomplete code"); + private CRNCountRecord() { + // incomplete code } - public int getNumberOfCRNs() { - return field_1_number_crn_records; + public CRNCountRecord(CRNCountRecord other) { + super(other); + field_1_number_crn_records = other.field_1_number_crn_records; + field_2_sheet_table_index = other.field_2_sheet_table_index; } - public CRNCountRecord(RecordInputStream in) { field_1_number_crn_records = in.readShort(); if(field_1_number_crn_records < 0) { @@ -53,6 +49,9 @@ public final class CRNCountRecord extends StandardRecord { field_2_sheet_table_index = in.readShort(); } + public int getNumberOfCRNs() { + return field_1_number_crn_records; + } public String toString() { StringBuilder sb = new StringBuilder(); @@ -77,4 +76,9 @@ public final class CRNCountRecord extends StandardRecord { public short getSid() { return sid; } + + @Override + public CRNCountRecord copy() { + return new CRNCountRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/CRNRecord.java b/src/java/org/apache/poi/hssf/record/CRNRecord.java index eddd3425a9..c8086c7ba5 100644 --- a/src/java/org/apache/poi/hssf/record/CRNRecord.java +++ b/src/java/org/apache/poi/hssf/record/CRNRecord.java @@ -21,27 +21,30 @@ import org.apache.poi.ss.formula.constant.ConstantValueParser; import org.apache.poi.util.LittleEndianOutput; /** - * Title: CRN(0x005A)<p> - * Description: This record stores the contents of an external cell or cell range<p> - * REFERENCE: OOO 5.23 + * This record stores the contents of an external cell or cell range */ public final class CRNRecord extends StandardRecord { - public final static short sid = 0x005A; + public static final short sid = 0x005A; - private int field_1_last_column_index; - private int field_2_first_column_index; - private int field_3_row_index; + private int field_1_last_column_index; + private int field_2_first_column_index; + private int field_3_row_index; private Object[] field_4_constant_values; - public CRNRecord() { - throw new RuntimeException("incomplete code"); + private CRNRecord() { + // incomplete code } - public int getNumberOfCRNs() { - return field_1_last_column_index; + public CRNRecord(CRNRecord other) { + super(other); + field_1_last_column_index = other.field_1_last_column_index; + field_2_first_column_index = other.field_2_first_column_index; + field_3_row_index = other.field_3_row_index; + // field_4_constant_values are instances of Double, Boolean, String, ErrorCode, + // i.e. they are immutable and can their references can be simply cloned + field_4_constant_values = (other.field_4_constant_values == null) ? null : other.field_4_constant_values.clone(); } - public CRNRecord(RecordInputStream in) { field_1_last_column_index = in.readUByte(); field_2_first_column_index = in.readUByte(); @@ -50,6 +53,9 @@ public final class CRNRecord extends StandardRecord { field_4_constant_values = ConstantValueParser.parse(in, nValues); } + public int getNumberOfCRNs() { + return field_1_last_column_index; + } public String toString() { StringBuilder sb = new StringBuilder(); @@ -77,4 +83,9 @@ public final class CRNRecord extends StandardRecord { public short getSid() { return sid; } + + @Override + public CRNRecord copy() { + return new CRNRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/CalcCountRecord.java b/src/java/org/apache/poi/hssf/record/CalcCountRecord.java index f03791d071..94530bea12 100644 --- a/src/java/org/apache/poi/hssf/record/CalcCountRecord.java +++ b/src/java/org/apache/poi/hssf/record/CalcCountRecord.java @@ -15,34 +15,37 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Calc Count Record - * Description: Specifies the maximum times the gui should perform a formula - * recalculation. For instance: in the case a formula includes - * cells that are themselves a result of a formula and a value - * changes. This is essentially a failsafe against an infinate - * loop in the event the formulas are not independant. <P> - * REFERENCE: PG 292 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> + * Specifies the maximum times the gui should perform a formula recalculation. + * For instance: in the case a formula includes cells that are themselves a result of a formula and + * a value changes. This is essentially a failsafe against an infinite loop in the event the formulas + * are not independent. + * * @version 2.0-pre - * @see org.apache.poi.hssf.record.CalcModeRecord + * @see CalcModeRecord */ -public final class CalcCountRecord extends StandardRecord implements Cloneable { - public final static short sid = 0xC; - private short field_1_iterations; +public final class CalcCountRecord extends StandardRecord { + public static final short sid = 0xC; - public CalcCountRecord() - { + private short field_1_iterations; + + public CalcCountRecord() {} + + public CalcCountRecord(CalcCountRecord other) { + super(other); + field_1_iterations = other.field_1_iterations; } - public CalcCountRecord(RecordInputStream in) - { + + public CalcCountRecord(RecordInputStream in) { field_1_iterations = in.readShort(); } @@ -91,9 +94,15 @@ public final class CalcCountRecord extends StandardRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public CalcCountRecord clone() { - CalcCountRecord rec = new CalcCountRecord(); - rec.field_1_iterations = field_1_iterations; - return rec; + return copy(); + } + + @Override + public CalcCountRecord copy() { + return new CalcCountRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/CalcModeRecord.java b/src/java/org/apache/poi/hssf/record/CalcModeRecord.java index 6ffb84b0ff..aad2ffa9fb 100644 --- a/src/java/org/apache/poi/hssf/record/CalcModeRecord.java +++ b/src/java/org/apache/poi/hssf/record/CalcModeRecord.java @@ -15,52 +15,42 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Calc Mode Record<P> - * Description: Tells the gui whether to calculate formulas - * automatically, manually or automatically - * except for tables.<P> - * REFERENCE: PG 292 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Jason Height (jheight at chariot dot net dot au) + * Tells the gui whether to calculate formulas automatically, manually or automatically except for tables. + * * @version 2.0-pre - * @see org.apache.poi.hssf.record.CalcCountRecord + * @see CalcCountRecord */ -public final class CalcModeRecord extends StandardRecord implements Cloneable { - public final static short sid = 0xD; +public final class CalcModeRecord extends StandardRecord { + public static final short sid = 0xD; - /** - * manually calculate formulas (0) - */ + /** manually calculate formulas (0) */ + public static final short MANUAL = 0; - public final static short MANUAL = 0; + /** automatically calculate formulas (1) */ + public static final short AUTOMATIC = 1; - /** - * automatically calculate formulas (1) - */ + /** automatically calculate formulas except for tables (-1) */ + public static final short AUTOMATIC_EXCEPT_TABLES = -1; - public final static short AUTOMATIC = 1; + private short field_1_calcmode; - /** - * automatically calculate formulas except for tables (-1) - */ + public CalcModeRecord() {} - public final static short AUTOMATIC_EXCEPT_TABLES = -1; - private short field_1_calcmode; - - public CalcModeRecord() - { + public CalcModeRecord(CalcModeRecord other) { + super(other); + field_1_calcmode = other.field_1_calcmode; } - public CalcModeRecord(RecordInputStream in) - { + public CalcModeRecord(RecordInputStream in) { field_1_calcmode = in.readShort(); } @@ -119,9 +109,15 @@ public final class CalcModeRecord extends StandardRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public CalcModeRecord clone() { - CalcModeRecord rec = new CalcModeRecord(); - rec.field_1_calcmode = field_1_calcmode; - return rec; + return copy(); + } + + @Override + public CalcModeRecord copy() { + return new CalcModeRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/CellRecord.java b/src/java/org/apache/poi/hssf/record/CellRecord.java index 5ae7abebea..fd9c4d4d6a 100644 --- a/src/java/org/apache/poi/hssf/record/CellRecord.java +++ b/src/java/org/apache/poi/hssf/record/CellRecord.java @@ -29,8 +29,13 @@ public abstract class CellRecord extends StandardRecord implements CellValueReco private int _columnIndex; private int _formatIndex; - protected CellRecord() { - // fields uninitialised + protected CellRecord() {} + + protected CellRecord(CellRecord other) { + super(other); + _rowIndex = other.getRow(); + _columnIndex = other.getColumn(); + _formatIndex = other.getXFIndex(); } protected CellRecord(RecordInputStream in) { @@ -100,21 +105,21 @@ public abstract class CellRecord extends StandardRecord implements CellValueReco * 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 write to */ protected abstract void appendValueText(StringBuilder sb); /** * Gets the debug info BIFF record type name (used by {@link #toString()}. - * + * * @return the record type name */ protected abstract String getRecordName(); /** * writes out the value data for this cell record - * + * * @param out the output */ protected abstract void serializeValue(LittleEndianOutput out); @@ -137,9 +142,6 @@ public abstract class CellRecord extends StandardRecord implements CellValueReco return 6 + getValueDataSize(); } - protected final void copyBaseFields(CellRecord rec) { - rec._rowIndex = _rowIndex; - rec._columnIndex = _columnIndex; - rec._formatIndex = _formatIndex; - } + @Override + public abstract CellRecord copy(); } diff --git a/src/java/org/apache/poi/hssf/record/CodepageRecord.java b/src/java/org/apache/poi/hssf/record/CodepageRecord.java index 11d074817a..adc831af23 100644 --- a/src/java/org/apache/poi/hssf/record/CodepageRecord.java +++ b/src/java/org/apache/poi/hssf/record/CodepageRecord.java @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.hssf.record; @@ -23,33 +23,33 @@ import org.apache.poi.util.CodePageUtil; import org.apache.poi.util.LittleEndianOutput; /** - * Title: Codepage Record - * <p>Description: the default characterset. for the workbook</p> - * <p>REFERENCE: PG 293 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)</p> - * <p>Use {@link CodePageUtil} to turn these values into Java code pages - * to encode/decode strings.</p> + * The default characterset. for the workbook<p> + * + * Use {@link CodePageUtil} to turn these values into Java code pages to encode/decode strings. + * * @version 2.0-pre */ -public final class CodepageRecord - extends StandardRecord -{ - public final static short sid = 0x42; - private short field_1_codepage; // = 0; +public final class CodepageRecord extends StandardRecord { + public static final short sid = 0x42; /** * Excel 97+ (Biff 8) should always store strings as UTF-16LE or * compressed versions of that. As such, this should always be * 0x4b0 = UTF_16, except for files coming from older versions. */ - public final static short CODEPAGE = ( short ) 0x4b0; + public static final short CODEPAGE = ( short ) 0x4b0; - public CodepageRecord() - { + private short field_1_codepage; + + public CodepageRecord() {} + + public CodepageRecord(CodepageRecord other) { + super(other); + field_1_codepage = other.field_1_codepage; } - public CodepageRecord(RecordInputStream in) - { + public CodepageRecord(RecordInputStream in) { field_1_codepage = in.readShort(); } @@ -100,4 +100,9 @@ public final class CodepageRecord { return sid; } + + @Override + public CodepageRecord copy() { + return new CodepageRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/ColumnInfoRecord.java b/src/java/org/apache/poi/hssf/record/ColumnInfoRecord.java index 1f48458fde..4adbcd69be 100644 --- a/src/java/org/apache/poi/hssf/record/ColumnInfoRecord.java +++ b/src/java/org/apache/poi/hssf/record/ColumnInfoRecord.java @@ -17,27 +17,27 @@ package org.apache.poi.hssf.record; -import org.apache.poi.util.HexDump; -import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; +import org.apache.poi.util.HexDump; +import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: COLINFO Record (0x007D)<p> - * Description: Defines with width and formatting for a range of columns<p> - * REFERENCE: PG 293 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) + * Defines with width and formatting for a range of columns */ -public final class ColumnInfoRecord extends StandardRecord implements Cloneable { +public final class ColumnInfoRecord extends StandardRecord { public static final short sid = 0x007D; + private static final BitField hidden = BitFieldFactory.getInstance(0x01); + private static final BitField outlevel = BitFieldFactory.getInstance(0x0700); + private static final BitField collapsed = BitFieldFactory.getInstance(0x1000); + private int _firstCol; private int _lastCol; private int _colWidth; private int _xfIndex; private int _options; - private static final BitField hidden = BitFieldFactory.getInstance(0x01); - private static final BitField outlevel = BitFieldFactory.getInstance(0x0700); - private static final BitField collapsed = BitFieldFactory.getInstance(0x1000); // Excel seems write values 2, 10, and 260, even though spec says "must be zero" private int field_6_reserved; @@ -51,6 +51,16 @@ public final class ColumnInfoRecord extends StandardRecord implements Cloneable field_6_reserved = 2; // seems to be the most common value } + public ColumnInfoRecord(ColumnInfoRecord other) { + super(other); + _firstCol = other._firstCol; + _lastCol = other._lastCol; + _colWidth = other._colWidth; + _xfIndex = other._xfIndex; + _options = other._options; + field_6_reserved = other.field_6_reserved; + } + public ColumnInfoRecord(RecordInputStream in) { _firstCol = in.readUShort(); _lastCol = in.readUShort(); @@ -196,7 +206,7 @@ public final class ColumnInfoRecord extends StandardRecord implements Cloneable /** * @param other the format to match with - * + * * @return {@code true} if the format, options and column width match */ public boolean formatMatches(ColumnInfoRecord other) { @@ -246,14 +256,15 @@ public final class ColumnInfoRecord extends StandardRecord implements Cloneable } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public ColumnInfoRecord clone() { - ColumnInfoRecord rec = new ColumnInfoRecord(); - rec._firstCol = _firstCol; - rec._lastCol = _lastCol; - rec._colWidth = _colWidth; - rec._xfIndex = _xfIndex; - rec._options = _options; - rec.field_6_reserved = field_6_reserved; - return rec; + return copy(); + } + + @Override + public ColumnInfoRecord copy() { + return new ColumnInfoRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/CommonObjectDataSubRecord.java b/src/java/org/apache/poi/hssf/record/CommonObjectDataSubRecord.java index 6e0b86155f..5416b7e922 100644 --- a/src/java/org/apache/poi/hssf/record/CommonObjectDataSubRecord.java +++ b/src/java/org/apache/poi/hssf/record/CommonObjectDataSubRecord.java @@ -23,50 +23,51 @@ import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.RecordFormatException; +import org.apache.poi.util.Removal; /** * The common object data record is used to store all common preferences for an excel object. */ -public final class CommonObjectDataSubRecord extends SubRecord implements Cloneable { - public final static short sid = 0x0015; +public final class CommonObjectDataSubRecord extends SubRecord { + public static final short sid = 0x0015; private static final BitField locked = BitFieldFactory.getInstance(0x0001); private static final BitField printable = BitFieldFactory.getInstance(0x0010); private static final BitField autofill = BitFieldFactory.getInstance(0x2000); private static final BitField autoline = BitFieldFactory.getInstance(0x4000); - public final static short OBJECT_TYPE_GROUP = 0; - public final static short OBJECT_TYPE_LINE = 1; - public final static short OBJECT_TYPE_RECTANGLE = 2; - public final static short OBJECT_TYPE_OVAL = 3; - public final static short OBJECT_TYPE_ARC = 4; - public final static short OBJECT_TYPE_CHART = 5; - public final static short OBJECT_TYPE_TEXT = 6; - public final static short OBJECT_TYPE_BUTTON = 7; - public final static short OBJECT_TYPE_PICTURE = 8; - public final static short OBJECT_TYPE_POLYGON = 9; - public final static short OBJECT_TYPE_RESERVED1 = 10; - public final static short OBJECT_TYPE_CHECKBOX = 11; - public final static short OBJECT_TYPE_OPTION_BUTTON = 12; - public final static short OBJECT_TYPE_EDIT_BOX = 13; - public final static short OBJECT_TYPE_LABEL = 14; - public final static short OBJECT_TYPE_DIALOG_BOX = 15; - public final static short OBJECT_TYPE_SPINNER = 16; - public final static short OBJECT_TYPE_SCROLL_BAR = 17; - public final static short OBJECT_TYPE_LIST_BOX = 18; - public final static short OBJECT_TYPE_GROUP_BOX = 19; - public final static short OBJECT_TYPE_COMBO_BOX = 20; - public final static short OBJECT_TYPE_RESERVED2 = 21; - public final static short OBJECT_TYPE_RESERVED3 = 22; - public final static short OBJECT_TYPE_RESERVED4 = 23; - public final static short OBJECT_TYPE_RESERVED5 = 24; - public final static short OBJECT_TYPE_COMMENT = 25; - public final static short OBJECT_TYPE_RESERVED6 = 26; - public final static short OBJECT_TYPE_RESERVED7 = 27; - public final static short OBJECT_TYPE_RESERVED8 = 28; - public final static short OBJECT_TYPE_RESERVED9 = 29; - public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 30; - + public static final short OBJECT_TYPE_GROUP = 0; + public static final short OBJECT_TYPE_LINE = 1; + public static final short OBJECT_TYPE_RECTANGLE = 2; + public static final short OBJECT_TYPE_OVAL = 3; + public static final short OBJECT_TYPE_ARC = 4; + public static final short OBJECT_TYPE_CHART = 5; + public static final short OBJECT_TYPE_TEXT = 6; + public static final short OBJECT_TYPE_BUTTON = 7; + public static final short OBJECT_TYPE_PICTURE = 8; + public static final short OBJECT_TYPE_POLYGON = 9; + public static final short OBJECT_TYPE_RESERVED1 = 10; + public static final short OBJECT_TYPE_CHECKBOX = 11; + public static final short OBJECT_TYPE_OPTION_BUTTON = 12; + public static final short OBJECT_TYPE_EDIT_BOX = 13; + public static final short OBJECT_TYPE_LABEL = 14; + public static final short OBJECT_TYPE_DIALOG_BOX = 15; + public static final short OBJECT_TYPE_SPINNER = 16; + public static final short OBJECT_TYPE_SCROLL_BAR = 17; + public static final short OBJECT_TYPE_LIST_BOX = 18; + public static final short OBJECT_TYPE_GROUP_BOX = 19; + public static final short OBJECT_TYPE_COMBO_BOX = 20; + public static final short OBJECT_TYPE_RESERVED2 = 21; + public static final short OBJECT_TYPE_RESERVED3 = 22; + public static final short OBJECT_TYPE_RESERVED4 = 23; + public static final short OBJECT_TYPE_RESERVED5 = 24; + public static final short OBJECT_TYPE_COMMENT = 25; + public static final short OBJECT_TYPE_RESERVED6 = 26; + public static final short OBJECT_TYPE_RESERVED7 = 27; + public static final short OBJECT_TYPE_RESERVED8 = 28; + public static final short OBJECT_TYPE_RESERVED9 = 29; + public static final short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 30; + private short field_1_objectType; private int field_2_objectId; private short field_3_option; @@ -75,9 +76,16 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea private int field_6_reserved3; - public CommonObjectDataSubRecord() - { + public CommonObjectDataSubRecord() {} + public CommonObjectDataSubRecord(CommonObjectDataSubRecord other) { + super(other); + field_1_objectType = other.field_1_objectType; + field_2_objectId = other.field_2_objectId; + field_3_option = other.field_3_option; + field_4_reserved1 = other.field_4_reserved1; + field_5_reserved2 = other.field_5_reserved2; + field_6_reserved3 = other.field_6_reserved3; } public CommonObjectDataSubRecord(LittleEndianInput in, int size) { @@ -101,31 +109,31 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea buffer.append(" .objectType = ") .append("0x").append(HexDump.toHex( getObjectType ())) .append(" (").append( getObjectType() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .objectId = ") .append("0x").append(HexDump.toHex( getObjectId ())) .append(" (").append( getObjectId() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .option = ") .append("0x").append(HexDump.toHex( getOption ())) .append(" (").append( getOption() ).append(" )"); - buffer.append(System.getProperty("line.separator")); - buffer.append(" .locked = ").append(isLocked()).append('\n'); - buffer.append(" .printable = ").append(isPrintable()).append('\n'); - buffer.append(" .autofill = ").append(isAutofill()).append('\n'); - buffer.append(" .autoline = ").append(isAutoline()).append('\n'); + buffer.append(System.getProperty("line.separator")); + buffer.append(" .locked = ").append(isLocked()).append('\n'); + buffer.append(" .printable = ").append(isPrintable()).append('\n'); + buffer.append(" .autofill = ").append(isAutofill()).append('\n'); + buffer.append(" .autoline = ").append(isAutoline()).append('\n'); buffer.append(" .reserved1 = ") .append("0x").append(HexDump.toHex( getReserved1 ())) .append(" (").append( getReserved1() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .reserved2 = ") .append("0x").append(HexDump.toHex( getReserved2 ())) .append(" (").append( getReserved2() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .reserved3 = ") .append("0x").append(HexDump.toHex( getReserved3 ())) .append(" (").append( getReserved3() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append("[/ftCmo]\n"); return buffer.toString(); @@ -159,23 +167,23 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public CommonObjectDataSubRecord clone() { - CommonObjectDataSubRecord rec = new CommonObjectDataSubRecord(); - - rec.field_1_objectType = field_1_objectType; - rec.field_2_objectId = field_2_objectId; - rec.field_3_option = field_3_option; - rec.field_4_reserved1 = field_4_reserved1; - rec.field_5_reserved2 = field_5_reserved2; - rec.field_6_reserved3 = field_6_reserved3; - return rec; + return copy(); + } + + @Override + public CommonObjectDataSubRecord copy() { + return new CommonObjectDataSubRecord(this); } /** * Get the object type field for the CommonObjectData record. * - * @return One of + * @return One of * OBJECT_TYPE_GROUP * OBJECT_TYPE_LINE * OBJECT_TYPE_RECTANGLE @@ -217,7 +225,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea * Set the object type field for the CommonObjectData record. * * @param field_1_objectType - * One of + * One of * OBJECT_TYPE_GROUP * OBJECT_TYPE_LINE * OBJECT_TYPE_RECTANGLE @@ -257,7 +265,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea /** * Get the object id field for the CommonObjectData record. - * + * * @return the object id field */ public int getObjectId() @@ -267,7 +275,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea /** * Set the object id field for the CommonObjectData record. - * + * * @param field_2_objectId the object id field */ public void setObjectId(int field_2_objectId) @@ -277,7 +285,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea /** * Get the option field for the CommonObjectData record. - * + * * @return the option field */ public short getOption() @@ -287,7 +295,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea /** * Set the option field for the CommonObjectData record. - * + * * @param field_3_option the option field */ public void setOption(short field_3_option) @@ -297,7 +305,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea /** * Get the reserved1 field for the CommonObjectData record. - * + * * @return the reserved1 field */ public int getReserved1() @@ -307,7 +315,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea /** * Set the reserved1 field for the CommonObjectData record. - * + * * @param field_4_reserved1 the reserved1 field */ public void setReserved1(int field_4_reserved1) @@ -317,7 +325,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea /** * Get the reserved2 field for the CommonObjectData record. - * + * * @return the reserved2 field */ public int getReserved2() @@ -327,7 +335,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea /** * Set the reserved2 field for the CommonObjectData record. - * + * * @param field_5_reserved2 the reserved2 field */ public void setReserved2(int field_5_reserved2) @@ -337,7 +345,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea /** * Get the reserved3 field for the CommonObjectData record. - * + * * @return the reserved3 field */ public int getReserved3() @@ -347,7 +355,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea /** * Set the reserved3 field for the CommonObjectData record. - * + * * @param field_6_reserved3 the reserved3 field */ public void setReserved3(int field_6_reserved3) @@ -358,7 +366,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea /** * Sets the locked field value. * true if object is locked when sheet has been protected - * + * * @param value {@code true} if object is locked when sheet has been protected */ public void setLocked(boolean value) @@ -378,7 +386,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea /** * Sets the printable field value. * object appears when printed - * + * * @param value {@code true} if object appears when printed */ public void setPrintable(boolean value) @@ -398,7 +406,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea /** * Sets the autofill field value. * whether object uses an automatic fill style - * + * * @param value {@code true} if object uses an automatic fill style */ public void setAutofill(boolean value) @@ -418,7 +426,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea /** * Sets the autoline field value. * whether object uses an automatic line style - * + * * @param value {@code true} if object uses an automatic line style */ public void setAutoline(boolean value) diff --git a/src/java/org/apache/poi/hssf/record/ContinueRecord.java b/src/java/org/apache/poi/hssf/record/ContinueRecord.java index 0dedc62a63..09080b7f41 100644 --- a/src/java/org/apache/poi/hssf/record/ContinueRecord.java +++ b/src/java/org/apache/poi/hssf/record/ContinueRecord.java @@ -19,23 +19,26 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Continue Record(0x003C) - Helper class used primarily for SST Records <P> - * Description: handles overflow for prior record in the input - * stream; content is tailored to that prior record<P> - * @author Marc Johnson (mjohnson at apache dot org) - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Csaba Nagy (ncsaba at yahoo dot com) + * Helper class used primarily for SST Records<p> + * + * handles overflow for prior record in the input stream; content is tailored to that prior record */ -public final class ContinueRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x003C; +public final class ContinueRecord extends StandardRecord { + public static final short sid = 0x003C; private byte[] _data; public ContinueRecord(byte[] data) { _data = data; } + public ContinueRecord(ContinueRecord other) { + super(other); + _data = (other._data == null) ? null : other._data.clone(); + } + protected int getDataSize() { return _data.length; } @@ -70,7 +73,15 @@ public final class ContinueRecord extends StandardRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public ContinueRecord clone() { - return new ContinueRecord(_data); + return copy(); + } + + @Override + public ContinueRecord copy() { + return new ContinueRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/CountryRecord.java b/src/java/org/apache/poi/hssf/record/CountryRecord.java index 47020dab1e..d367d460c3 100644 --- a/src/java/org/apache/poi/hssf/record/CountryRecord.java +++ b/src/java/org/apache/poi/hssf/record/CountryRecord.java @@ -15,37 +15,36 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; /** - * Title: Country Record (aka WIN.INI country)<P> - * Description: used for localization. Currently HSSF always sets this to 1 - * and it seems to work fine even in Germany. (es geht's auch fuer Deutschland)<P> + * Country Record (aka WIN.INI country) - used for localization<p> + * + * Currently HSSF always sets this to 1 and it seems to work fine even in Germany. * - * REFERENCE: PG 298 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) * @version 2.0-pre */ -public final class CountryRecord - extends StandardRecord -{ - public final static short sid = 0x8c; +public final class CountryRecord extends StandardRecord { + public static final short sid = 0x8c; // 1 for US - private short field_1_default_country; - private short field_2_current_country; + private short field_1_default_country; + private short field_2_current_country; - public CountryRecord() - { + public CountryRecord() {} + + public CountryRecord(CountryRecord other) { + super(other); + field_1_default_country = other.field_1_default_country; + field_2_current_country = other.field_2_current_country; } - public CountryRecord(RecordInputStream in) - { + public CountryRecord(RecordInputStream in) { field_1_default_country = in.readShort(); field_2_current_country = in.readShort(); } @@ -120,4 +119,9 @@ public final class CountryRecord { return sid; } + + @Override + public CountryRecord copy() { + return new CountryRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/DBCellRecord.java b/src/java/org/apache/poi/hssf/record/DBCellRecord.java index 55db860bb8..099466a7e1 100644 --- a/src/java/org/apache/poi/hssf/record/DBCellRecord.java +++ b/src/java/org/apache/poi/hssf/record/DBCellRecord.java @@ -19,39 +19,15 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: DBCell Record (0x00D7)<p> - * Description: Used by Excel and other MS apps to quickly find rows in the sheets.<P> - * REFERENCE: PG 299/440 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) + * Used by Excel and other MS apps to quickly find rows in the sheets. */ -public final class DBCellRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x00D7; - public final static int BLOCK_SIZE = 32; - - public static final class Builder { - private short[] _cellOffsets; - private int _nCellOffsets; - public Builder() { - _cellOffsets = new short[4]; - } +public final class DBCellRecord extends StandardRecord { + public static final short sid = 0x00D7; + public static final int BLOCK_SIZE = 32; - public void addCellOffset(int cellRefOffset) { - if (_cellOffsets.length <= _nCellOffsets) { - short[] temp = new short[_nCellOffsets * 2]; - System.arraycopy(_cellOffsets, 0, temp, 0, _nCellOffsets); - _cellOffsets = temp; - } - _cellOffsets[_nCellOffsets] = (short) cellRefOffset; - _nCellOffsets++; - } - - public DBCellRecord build(int rowOffset) { - short[] cellOffsets = new short[_nCellOffsets]; - System.arraycopy(_cellOffsets, 0, cellOffsets, 0, _nCellOffsets); - return new DBCellRecord(rowOffset, cellOffsets); - } - } /** * offset from the start of this DBCellRecord to the start of the first cell in * the next DBCell block. @@ -59,23 +35,21 @@ public final class DBCellRecord extends StandardRecord implements Cloneable { private final int field_1_row_offset; private final short[] field_2_cell_offsets; - DBCellRecord(int rowOffset, short[]cellOffsets) { + public DBCellRecord(int rowOffset, short[] cellOffsets) { field_1_row_offset = rowOffset; field_2_cell_offsets = cellOffsets; } public DBCellRecord(RecordInputStream in) { field_1_row_offset = in.readUShort(); - int size = in.remaining(); + int size = in.remaining(); field_2_cell_offsets = new short[ size / 2 ]; - for (int i=0;i<field_2_cell_offsets.length;i++) - { + for (int i=0;i<field_2_cell_offsets.length;i++) { field_2_cell_offsets[ i ] = in.readShort(); } } - public String toString() { StringBuilder buffer = new StringBuilder(); @@ -91,8 +65,8 @@ public final class DBCellRecord extends StandardRecord implements Cloneable { public void serialize(LittleEndianOutput out) { out.writeInt(field_1_row_offset); - for (int k = 0; k < field_2_cell_offsets.length; k++) { - out.writeShort(field_2_cell_offsets[ k ]); + for (short field_2_cell_offset : field_2_cell_offsets) { + out.writeShort(field_2_cell_offset); } } protected int getDataSize() { @@ -104,7 +78,15 @@ public final class DBCellRecord extends StandardRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public DBCellRecord clone() { + return copy(); + } + + @Override + public DBCellRecord copy() { // safe because immutable return this; } diff --git a/src/java/org/apache/poi/hssf/record/DConRefRecord.java b/src/java/org/apache/poi/hssf/record/DConRefRecord.java index f23f7317e6..0401fe549b 100644 --- a/src/java/org/apache/poi/hssf/record/DConRefRecord.java +++ b/src/java/org/apache/poi/hssf/record/DConRefRecord.java @@ -18,10 +18,10 @@ */ package org.apache.poi.hssf.record; +import java.io.ByteArrayInputStream; import java.util.Arrays; import org.apache.poi.util.IOUtils; -import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.RecordFormatException; import org.apache.poi.util.StringUtil; @@ -67,8 +67,7 @@ import org.apache.poi.util.StringUtil; * * At the moment this class is read-only. */ -public class DConRefRecord extends StandardRecord -{ +public class DConRefRecord extends StandardRecord { //arbitrarily selected; may need to increase private static final int MAX_RECORD_LENGTH = 100_000; @@ -108,54 +107,25 @@ public class DConRefRecord extends StandardRecord */ private byte[] _unused; + public DConRefRecord(DConRefRecord other) { + super(other); + firstCol = other.firstCol; + firstRow = other.firstRow; + lastCol = other.lastCol; + lastRow = other.lastRow; + charCount = other.charCount; + charType = other.charType; + path = (other.path == null) ? null : other.path.clone(); + _unused = (other._unused == null) ? null : other._unused.clone(); + } + /** * Read constructor. * * @param data byte array containing a DConRef Record, including the header. */ - public DConRefRecord(byte[] data) - { - int offset = 0; - if (!(LittleEndian.getShort(data, offset) == DConRefRecord.sid)) - throw new RecordFormatException("incompatible sid."); - offset += LittleEndian.SHORT_SIZE; - - //length = LittleEndian.getShort(data, offset); - offset += LittleEndian.SHORT_SIZE; - - firstRow = LittleEndian.getUShort(data, offset); - offset += LittleEndian.SHORT_SIZE; - lastRow = LittleEndian.getUShort(data, offset); - offset += LittleEndian.SHORT_SIZE; - firstCol = LittleEndian.getUByte(data, offset); - offset += LittleEndian.BYTE_SIZE; - lastCol = LittleEndian.getUByte(data, offset); - offset += LittleEndian.BYTE_SIZE; - charCount = LittleEndian.getUShort(data, offset); - offset += LittleEndian.SHORT_SIZE; - if (charCount < 2) - throw new RecordFormatException("Character count must be >= 2"); - - charType = LittleEndian.getUByte(data, offset); - offset += LittleEndian.BYTE_SIZE; //7 bits reserved + 1 bit type - - /* - * bytelength is the length of the string in bytes, which depends on whether the string is - * made of single- or double-byte chars. This is given by charType, which equals 0 if - * single-byte, 1 if double-byte. - */ - int byteLength = charCount * ((charType & 1) + 1); - - path = LittleEndian.getByteArray(data, offset, byteLength, MAX_RECORD_LENGTH); - offset += byteLength; - - /* - * If it's a self reference, the last one or two bytes (depending on char type) are the - * unused field. Not sure If i need to bother with this... - */ - if (path[0] == 0x02) - _unused = LittleEndian.getByteArray(data, offset, (charType + 1), MAX_RECORD_LENGTH); - + public DConRefRecord(byte[] data) { + this(bytesToRIStream(data)); } /** @@ -163,10 +133,10 @@ public class DConRefRecord extends StandardRecord * * @param inStream RecordInputStream containing a DConRefRecord structure. */ - public DConRefRecord(RecordInputStream inStream) - { - if (inStream.getSid() != sid) + public DConRefRecord(RecordInputStream inStream) { + if (inStream.getSid() != sid) { throw new RecordFormatException("Wrong sid: " + inStream.getSid()); + } firstRow = inStream.readUShort(); lastRow = inStream.readUShort(); @@ -174,17 +144,23 @@ public class DConRefRecord extends StandardRecord lastCol = inStream.readUByte(); charCount = inStream.readUShort(); - charType = inStream.readUByte() & 0x01; //first bit only. - // byteLength depends on whether we are using single- or double-byte chars. - int byteLength = charCount * (charType + 1); + // 7 bits reserved + 1 bit type - first bit only + charType = inStream.readUByte() & 0x01; + + // bytelength is the length of the string in bytes, which depends on whether the string is + // made of single- or double-byte chars. This is given by charType, which equals 0 if + // single-byte, 1 if double-byte. + final int byteLength = charCount * (charType + 1); path = IOUtils.safelyAllocate(byteLength, MAX_RECORD_LENGTH); inStream.readFully(path); - if (path[0] == 0x02) + // If it's a self reference, the last one or two bytes (depending on char type) are the + // unused field. Not sure If i need to bother with this... + if (path[0] == 0x02) { _unused = inStream.readRemainder(); - + } } /* @@ -291,8 +267,7 @@ public class DConRefRecord extends StandardRecord //all of the path strings start with either 0x02 or 0x01 followed by zero or //more of 0x01..0x08 int offset = 1; - while (path[offset] < 0x20 && offset < path.length) - { + while (offset < path.length && path[offset] < 0x20) { offset++; } String out = new String(Arrays.copyOfRange(path, offset, path.length), StringUtil.UTF8); @@ -310,8 +285,17 @@ public class DConRefRecord extends StandardRecord */ public boolean isExternalRef() { - if (path[0] == 0x01) - return true; - return false; + return path[0] == 0x01; + } + + @Override + public DConRefRecord copy() { + return new DConRefRecord(this); + } + + private static RecordInputStream bytesToRIStream(byte[] data) { + RecordInputStream ric = new RecordInputStream(new ByteArrayInputStream(data)); + ric.nextRecord(); + return ric; } } diff --git a/src/java/org/apache/poi/hssf/record/DSFRecord.java b/src/java/org/apache/poi/hssf/record/DSFRecord.java index 8dbb534254..99101dacb2 100644 --- a/src/java/org/apache/poi/hssf/record/DSFRecord.java +++ b/src/java/org/apache/poi/hssf/record/DSFRecord.java @@ -23,21 +23,26 @@ import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; /** - * Title: Double Stream Flag Record (0x0161)<p> - * Description: tells if this is a double stream file. (always no for HSSF generated files)<p> - * Double Stream files contain both BIFF8 and BIFF7 workbooks.<p> - * REFERENCE: PG 305 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) + * Tells if this is a double stream file. (never applies to HSSF generated files)<p> + * + * Double Stream files contain both BIFF8 and BIFF7 workbooks. */ public final class DSFRecord extends StandardRecord { - public final static short sid = 0x0161; + public static final short sid = 0x0161; private static final BitField biff5BookStreamFlag = BitFieldFactory.getInstance(0x0001); private int _options; + private DSFRecord(DSFRecord other) { + super(other); + _options = other._options; + } + private DSFRecord(int options) { _options = options; } + public DSFRecord(boolean isBiff5BookStreamPresent) { this(0); _options = biff5BookStreamFlag.setBoolean(0, isBiff5BookStreamPresent); @@ -71,4 +76,9 @@ public final class DSFRecord extends StandardRecord { public short getSid() { return sid; } + + @Override + public DSFRecord copy() { + return new DSFRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/DVALRecord.java b/src/java/org/apache/poi/hssf/record/DVALRecord.java index f74dedbfea..0be6512a17 100644 --- a/src/java/org/apache/poi/hssf/record/DVALRecord.java +++ b/src/java/org/apache/poi/hssf/record/DVALRecord.java @@ -18,14 +18,13 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: DATAVALIDATIONS Record (0x01B2)<p> - * Description: used in data validation ; - * This record is the list header of all data validation records (0x01BE) in the current sheet. + * This record is the list header of all data validation records (0x01BE) in the current sheet. */ -public final class DVALRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x01B2; +public final class DVALRecord extends StandardRecord { + public static final short sid = 0x01B2; /** Options of the DVAL */ private short field_1_options; @@ -47,12 +46,21 @@ public final class DVALRecord extends StandardRecord implements Cloneable { field_5_dv_no = 0x00000000; } + public DVALRecord(DVALRecord other) { + super(other); + field_1_options = other.field_1_options; + field_2_horiz_pos = other.field_2_horiz_pos; + field_3_vert_pos = other.field_3_vert_pos; + field_cbo_id = other.field_cbo_id; + field_5_dv_no = other.field_5_dv_no; + } + public DVALRecord(RecordInputStream in) { field_1_options = in.readShort(); field_2_horiz_pos = in.readInt(); field_3_vert_pos = in.readInt(); - field_cbo_id = in.readInt(); - field_5_dv_no = in.readInt(); + field_cbo_id = in.readInt(); + field_5_dv_no = in.readInt(); } /** @@ -142,7 +150,6 @@ public final class DVALRecord extends StandardRecord implements Cloneable { } public void serialize(LittleEndianOutput out) { - out.writeShort(getOptions()); out.writeInt(getHorizontalPos()); out.writeInt(getVerticalPos()); @@ -158,14 +165,16 @@ public final class DVALRecord extends StandardRecord implements Cloneable { return sid; } - @Override - public DVALRecord clone() { - DVALRecord rec = new DVALRecord(); - rec.field_1_options = field_1_options; - rec.field_2_horiz_pos = field_2_horiz_pos; - rec.field_3_vert_pos = field_3_vert_pos; - rec.field_cbo_id = field_cbo_id; - rec.field_5_dv_no = field_5_dv_no; - return rec; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public DVALRecord clone() { + return copy(); + } + + @Override + public DVALRecord copy() { + return new DVALRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/DVRecord.java b/src/java/org/apache/poi/hssf/record/DVRecord.java index 4025794d2c..9adcc02cbe 100644 --- a/src/java/org/apache/poi/hssf/record/DVRecord.java +++ b/src/java/org/apache/poi/hssf/record/DVRecord.java @@ -25,64 +25,77 @@ import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddressList; import org.apache.poi.util.BitField; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; import org.apache.poi.util.StringUtil; /** - * Title: DATAVALIDATION Record (0x01BE)<p> - * Description: This record stores data validation settings and a list of cell ranges - * which contain these settings. The data validation settings of a sheet - * are stored in a sequential list of DV records. This list is followed by - * DVAL record(s) + * This record stores data validation settings and a list of cell ranges which contain these settings. + * The data validation settings of a sheet are stored in a sequential list of DV records. + * This list is followed by DVAL record(s) */ -public final class DVRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x01BE; - +public final class DVRecord extends StandardRecord { + public static final short sid = 0x01BE; + /** the unicode string used for error/prompt title/text when not present */ private static final UnicodeString NULL_TEXT_STRING = new UnicodeString("\0"); + /** + * Option flags field + * + * @see HSSFDataValidation utility class + */ + private static final BitField opt_data_type = new BitField(0x0000000F); + private static final BitField opt_error_style = new BitField(0x00000070); + private static final BitField opt_string_list_formula = new BitField(0x00000080); + private static final BitField opt_empty_cell_allowed = new BitField(0x00000100); + private static final BitField opt_suppress_dropdown_arrow = new BitField(0x00000200); + private static final BitField opt_show_prompt_on_cell_selected = new BitField(0x00040000); + private static final BitField opt_show_error_on_invalid_value = new BitField(0x00080000); + private static final BitField opt_condition_operator = new BitField(0x00700000); + /** Option flags */ private int _option_flags; /** Title of the prompt box, cannot be longer than 32 chars */ - private UnicodeString _promptTitle; + private final UnicodeString _promptTitle; /** Title of the error box, cannot be longer than 32 chars */ - private UnicodeString _errorTitle; + private final UnicodeString _errorTitle; /** Text of the prompt box, cannot be longer than 255 chars */ - private UnicodeString _promptText; + private final UnicodeString _promptText; /** Text of the error box, cannot be longer than 255 chars */ - private UnicodeString _errorText; + private final UnicodeString _errorText; /** Not used - Excel seems to always write 0x3FE0 */ private short _not_used_1 = 0x3FE0; /** Formula data for first condition (RPN token array without size field) */ - private Formula _formula1; + private final Formula _formula1; /** Not used - Excel seems to always write 0x0000 */ @SuppressWarnings("RedundantFieldInitialization") private short _not_used_2 = 0x0000; /** Formula data for second condition (RPN token array without size field) */ - private Formula _formula2; + private final Formula _formula2; /** Cell range address list with all affected ranges */ - private CellRangeAddressList _regions; - - /** - * Option flags field - * - * @see HSSFDataValidation utility class - */ - private static final BitField opt_data_type = new BitField(0x0000000F); - private static final BitField opt_error_style = new BitField(0x00000070); - private static final BitField opt_string_list_formula = new BitField(0x00000080); - private static final BitField opt_empty_cell_allowed = new BitField(0x00000100); - private static final BitField opt_suppress_dropdown_arrow = new BitField(0x00000200); - private static final BitField opt_show_prompt_on_cell_selected = new BitField(0x00040000); - private static final BitField opt_show_error_on_invalid_value = new BitField(0x00080000); - private static final BitField opt_condition_operator = new BitField(0x00700000); + private final CellRangeAddressList _regions; + + public DVRecord(DVRecord other) { + super(other); + _option_flags = other._option_flags; + _promptTitle = other._promptTitle.copy(); + _errorTitle = other._errorTitle.copy(); + _promptText = other._promptText.copy(); + _errorText = other._errorText.copy(); + _not_used_1 = other._not_used_1; + _formula1 = (other._formula1 == null) ? null : other._formula1.copy(); + _not_used_2 = other._not_used_2; + _formula2 = (other._formula2 == null) ? null : other._formula2.copy(); + _regions = (other._regions == null) ? null : other._regions.copy(); + } public DVRecord(int validationType, int operator, int errorStyle, boolean emptyCellAllowed, boolean suppressDropDownArrow, boolean isExplicitList, - boolean showPromptBox, String promptTitle, String promptText, + boolean showPromptBox, String promptTitle, String promptText, boolean showErrorBox, String errorTitle, String errorText, Ptg[] formula1, Ptg[] formula2, CellRangeAddressList regions) { - + // check length-limits if(promptTitle != null && promptTitle.length() > 32) { throw new IllegalStateException("Prompt-title cannot be longer than 32 characters, but had: " + promptTitle); @@ -118,7 +131,6 @@ public final class DVRecord extends StandardRecord implements Cloneable { } public DVRecord(RecordInputStream in) { - _option_flags = in.readInt(); _promptTitle = readUnicodeString(in); @@ -144,7 +156,6 @@ public final class DVRecord extends StandardRecord implements Cloneable { _regions = new CellRangeAddressList(in); } - // --> start option flags /** * @return the condition data type * @see org.apache.poi.ss.usermodel.DataValidationConstraint.ValidationType @@ -276,7 +287,7 @@ public final class DVRecord extends StandardRecord implements Cloneable { private static void appendFormula(StringBuilder sb, String label, Formula f) { sb.append(label); - + if (f == null) { sb.append("<empty>\n"); return; @@ -291,7 +302,7 @@ public final class DVRecord extends StandardRecord implements Cloneable { public void serialize(LittleEndianOutput out) { out.writeInt(_option_flags); - + serializeUnicodeString(_promptTitle, out); serializeUnicodeString(_errorTitle, out); serializeUnicodeString(_promptText, out); @@ -299,19 +310,19 @@ public final class DVRecord extends StandardRecord implements Cloneable { out.writeShort(_formula1.getEncodedTokenSize()); out.writeShort(_not_used_1); _formula1.serializeTokens(out); - + out.writeShort(_formula2.getEncodedTokenSize()); out.writeShort(_not_used_2); _formula2.serializeTokens(out); - + _regions.serialize(out); } /** * When entered via the UI, Excel translates empty string into "\0" * While it is possible to encode the title/text as empty string (Excel doesn't exactly crash), - * the resulting tool-tip text / message box looks wrong. It is best to do the same as the - * Excel UI and encode 'not present' as "\0". + * the resulting tool-tip text / message box looks wrong. It is best to do the same as the + * Excel UI and encode 'not present' as "\0". */ private static UnicodeString resolveTitleText(String str) { if (str == null || str.length() < 1) { @@ -354,13 +365,18 @@ public final class DVRecord extends StandardRecord implements Cloneable { public short getSid() { return sid; } - - /** - * Clones the object. Uses serialisation, as the - * contents are somewhat complex - */ + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public DVRecord clone() { - return (DVRecord)cloneViaReserialise(); + return copy(); + } + + /** Clones the object. */ + @Override + public DVRecord copy() { + return new DVRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/DateWindow1904Record.java b/src/java/org/apache/poi/hssf/record/DateWindow1904Record.java index 6eb2e82a6e..29338e3145 100644 --- a/src/java/org/apache/poi/hssf/record/DateWindow1904Record.java +++ b/src/java/org/apache/poi/hssf/record/DateWindow1904Record.java @@ -15,33 +15,31 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; /** - * Title: Date Window 1904 Flag record <P> - * Description: Flag specifying whether 1904 date windowing is used. - * (tick toc tick toc...BOOM!) <P> - * REFERENCE: PG 280 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) + * Flag specifying whether 1904 date windowing is used. + * * @version 2.0-pre */ -public final class DateWindow1904Record - extends StandardRecord -{ - public final static short sid = 0x22; - private short field_1_window; +public final class DateWindow1904Record extends StandardRecord { + public static final short sid = 0x22; - public DateWindow1904Record() - { + private short field_1_window; + + public DateWindow1904Record() {} + + public DateWindow1904Record(DateWindow1904Record other) { + super(other); + field_1_window = other.field_1_window; } - public DateWindow1904Record(RecordInputStream in) - { + public DateWindow1904Record(RecordInputStream in) { field_1_window = in.readShort(); } @@ -88,4 +86,9 @@ public final class DateWindow1904Record { return sid; } + + @Override + public DateWindow1904Record copy() { + return new DateWindow1904Record(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/DefaultColWidthRecord.java b/src/java/org/apache/poi/hssf/record/DefaultColWidthRecord.java index e4c416f07b..31873ed316 100644 --- a/src/java/org/apache/poi/hssf/record/DefaultColWidthRecord.java +++ b/src/java/org/apache/poi/hssf/record/DefaultColWidthRecord.java @@ -18,30 +18,32 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Default Column Width Record (0x0055) <P> - * Description: Specifies the default width for columns that have no specific - * width set.<P> - * REFERENCE: PG 302 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Jason Height (jheight at chariot dot net dot au) + * Specifies the default width for columns that have no specific width set. + * * @version 2.0-pre */ -public final class DefaultColWidthRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x0055; - private int field_1_col_width; +public final class DefaultColWidthRecord extends StandardRecord { + public static final short sid = 0x0055; /** * The default column width is 8 characters */ - public final static int DEFAULT_COLUMN_WIDTH = 0x0008; + public static final int DEFAULT_COLUMN_WIDTH = 0x0008; - public DefaultColWidthRecord() - { + private int field_1_col_width; + + public DefaultColWidthRecord() { field_1_col_width = DEFAULT_COLUMN_WIDTH; } + public DefaultColWidthRecord(DefaultColWidthRecord other) { + super(other); + field_1_col_width = other.field_1_col_width; + } + public DefaultColWidthRecord(RecordInputStream in) { field_1_col_width = in.readUShort(); @@ -92,9 +94,15 @@ public final class DefaultColWidthRecord extends StandardRecord implements Clone } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public DefaultColWidthRecord clone() { - DefaultColWidthRecord rec = new DefaultColWidthRecord(); - rec.field_1_col_width = field_1_col_width; - return rec; + return copy(); + } + + @Override + public DefaultColWidthRecord copy() { + return new DefaultColWidthRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/DefaultRowHeightRecord.java b/src/java/org/apache/poi/hssf/record/DefaultRowHeightRecord.java index 7ba2c64061..9132ca7e44 100644 --- a/src/java/org/apache/poi/hssf/record/DefaultRowHeightRecord.java +++ b/src/java/org/apache/poi/hssf/record/DefaultRowHeightRecord.java @@ -1,4 +1,3 @@ - /* ==================================================================== Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with @@ -20,35 +19,35 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Default Row Height Record - * Description: Row height for rows with undefined or not explicitly defined - * heights. - * REFERENCE: PG 301 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Jason Height (jheight at chariot dot net dot au) + * Row height for rows with undefined or not explicitly defined heights. + * * @version 2.0-pre */ -public final class DefaultRowHeightRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x225; - private short field_1_option_flags; - private short field_2_row_height; +public final class DefaultRowHeightRecord extends StandardRecord { + public static final short sid = 0x225; - /** - * The default row height for empty rows is 255 twips (255 / 20 == 12.75 points) - */ + /** The default row height for empty rows is 255 twips (255 / 20 == 12.75 points) */ public static final short DEFAULT_ROW_HEIGHT = 0xFF; - public DefaultRowHeightRecord() - { + private short field_1_option_flags; + private short field_2_row_height; + + public DefaultRowHeightRecord() { field_1_option_flags = 0x0000; field_2_row_height = DEFAULT_ROW_HEIGHT; } - public DefaultRowHeightRecord(RecordInputStream in) - { + public DefaultRowHeightRecord(DefaultRowHeightRecord other) { + super(other); + field_1_option_flags = other.field_1_option_flags; + field_2_row_height = other.field_2_row_height; + } + + public DefaultRowHeightRecord(RecordInputStream in) { field_1_option_flags = in.readShort(); field_2_row_height = in.readShort(); } @@ -121,10 +120,15 @@ public final class DefaultRowHeightRecord extends StandardRecord implements Clon } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public DefaultRowHeightRecord clone() { - DefaultRowHeightRecord rec = new DefaultRowHeightRecord(); - rec.field_1_option_flags = field_1_option_flags; - rec.field_2_row_height = field_2_row_height; - return rec; + return copy(); + } + + @Override + public DefaultRowHeightRecord copy() { + return new DefaultRowHeightRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/DeltaRecord.java b/src/java/org/apache/poi/hssf/record/DeltaRecord.java index aa3400dde5..d7dd0d508b 100644 --- a/src/java/org/apache/poi/hssf/record/DeltaRecord.java +++ b/src/java/org/apache/poi/hssf/record/DeltaRecord.java @@ -18,15 +18,12 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; -/** - * Title: Delta Record (0x0010)<p> - * Description: controls the accuracy of the calculations<p> - * REFERENCE: PG 303 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) - */ -public final class DeltaRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x0010; - public final static double DEFAULT_VALUE = 0.0010; // should be .001 +/** Controls the accuracy of the calculations */ +public final class DeltaRecord extends StandardRecord { + public static final short sid = 0x0010; + public static final double DEFAULT_VALUE = 0.0010; // a double is an IEEE 8-byte float...damn IEEE and their goofy standards an // ambiguous numeric identifiers @@ -36,6 +33,11 @@ public final class DeltaRecord extends StandardRecord implements Cloneable { field_1_max_change = maxChange; } + public DeltaRecord(DeltaRecord other) { + super(other); + field_1_max_change = other.field_1_max_change; + } + public DeltaRecord(RecordInputStream in) { field_1_max_change = in.readDouble(); } @@ -70,7 +72,15 @@ public final class DeltaRecord extends StandardRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public DeltaRecord clone() { + return copy(); + } + + @Override + public DeltaRecord copy() { // immutable return this; } diff --git a/src/java/org/apache/poi/hssf/record/DimensionsRecord.java b/src/java/org/apache/poi/hssf/record/DimensionsRecord.java index 280e3e1825..cd577f465f 100644 --- a/src/java/org/apache/poi/hssf/record/DimensionsRecord.java +++ b/src/java/org/apache/poi/hssf/record/DimensionsRecord.java @@ -15,41 +15,44 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; +import org.apache.poi.util.Removal; /** - * Title: Dimensions Record<P> - * Description: provides the minumum and maximum bounds - * of a sheet.<P> - * REFERENCE: PG 303 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Jason Height (jheight at chariot dot net dot au) + * Provides the minumum and maximum bounds of a sheet. + * * @version 2.0-pre */ -public final class DimensionsRecord extends StandardRecord implements Cloneable { +public final class DimensionsRecord extends StandardRecord { private static final POILogger logger = POILogFactory.getLogger(DimensionsRecord.class); - public final static short sid = 0x200; + public static final short sid = 0x200; private int field_1_first_row; private int field_2_last_row; // plus 1 private short field_3_first_col; private short field_4_last_col; private short field_5_zero; // must be 0 (reserved) - public DimensionsRecord() - { + public DimensionsRecord() {} + + public DimensionsRecord(DimensionsRecord other) { + super(other); + field_1_first_row = other.field_1_first_row; + field_2_last_row = other.field_2_last_row; + field_3_first_col = other.field_3_first_col; + field_4_last_col = other.field_4_last_col; + field_5_zero = other.field_5_zero; } - public DimensionsRecord(RecordInputStream in) - { + public DimensionsRecord(RecordInputStream in) { field_1_first_row = in.readInt(); field_2_last_row = in.readInt(); field_3_first_col = in.readShort(); @@ -179,13 +182,15 @@ public final class DimensionsRecord extends StandardRecord implements Cloneable } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public DimensionsRecord clone() { - DimensionsRecord rec = new DimensionsRecord(); - rec.field_1_first_row = field_1_first_row; - rec.field_2_last_row = field_2_last_row; - rec.field_3_first_col = field_3_first_col; - rec.field_4_last_col = field_4_last_col; - rec.field_5_zero = field_5_zero; - return rec; + return copy(); + } + + @Override + public DimensionsRecord copy() { + return new DimensionsRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/DrawingGroupRecord.java b/src/java/org/apache/poi/hssf/record/DrawingGroupRecord.java index 2304c04705..61c4596c02 100644 --- a/src/java/org/apache/poi/hssf/record/DrawingGroupRecord.java +++ b/src/java/org/apache/poi/hssf/record/DrawingGroupRecord.java @@ -17,13 +17,13 @@ package org.apache.poi.hssf.record; +import java.util.Iterator; +import java.util.List; + import org.apache.poi.ddf.EscherRecord; import org.apache.poi.ddf.NullEscherSerializationListener; import org.apache.poi.util.LittleEndian; -import java.util.Iterator; -import java.util.List; - public final class DrawingGroupRecord extends AbstractEscherHolderRecord { public static final short sid = 0xEB; @@ -31,12 +31,13 @@ public final class DrawingGroupRecord extends AbstractEscherHolderRecord { static final int MAX_RECORD_SIZE = 8228; private static final int MAX_DATA_SIZE = MAX_RECORD_SIZE - 4; - public DrawingGroupRecord() - { + public DrawingGroupRecord() {} + + public DrawingGroupRecord(DrawingGroupRecord other) { + super(other); } - public DrawingGroupRecord( RecordInputStream in ) - { + public DrawingGroupRecord( RecordInputStream in ) { super( in ); } @@ -136,4 +137,9 @@ public final class DrawingGroupRecord extends AbstractEscherHolderRecord { LittleEndian.putShort(data, 0 + offset, ContinueRecord.sid); LittleEndian.putShort(data, 2 + offset, (short) sizeExcludingHeader); } + + @Override + public DrawingGroupRecord copy() { + return new DrawingGroupRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/DrawingRecord.java b/src/java/org/apache/poi/hssf/record/DrawingRecord.java index a0eb3f233f..913bf33da0 100644 --- a/src/java/org/apache/poi/hssf/record/DrawingRecord.java +++ b/src/java/org/apache/poi/hssf/record/DrawingRecord.java @@ -18,10 +18,9 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; -/** - * DrawingRecord (0x00EC) - */ -public final class DrawingRecord extends StandardRecord implements Cloneable { +import org.apache.poi.util.Removal; + +public final class DrawingRecord extends StandardRecord { public static final short sid = 0x00EC; private static final byte[] EMPTY_BYTE_ARRAY = {}; @@ -33,6 +32,13 @@ public final class DrawingRecord extends StandardRecord implements Cloneable { recordData = EMPTY_BYTE_ARRAY; } + public DrawingRecord(DrawingRecord other) { + super(other); + recordData = (other.recordData == null) ? null : other.recordData.clone(); + // TODO - this code probably never copies a contd array ... + contd = (other.contd == null) ? null : other.contd.clone(); + } + public DrawingRecord(RecordInputStream in) { recordData = in.readRemainder(); } @@ -69,20 +75,21 @@ public final class DrawingRecord extends StandardRecord implements Cloneable { recordData = thedata; } + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public DrawingRecord clone() { + return copy(); + } + /** * Cloning of drawing records must be executed through HSSFPatriarch, because all id's must be changed * @return cloned drawing records */ @Override - public DrawingRecord clone() { - DrawingRecord rec = new DrawingRecord(); - rec.recordData = recordData.clone(); - if (contd != null) { - // TODO - this code probably never executes - rec.contd = contd.clone(); - } - - return rec; + public DrawingRecord copy() { + return new DrawingRecord(this); } @Override diff --git a/src/java/org/apache/poi/hssf/record/DrawingRecordForBiffViewer.java b/src/java/org/apache/poi/hssf/record/DrawingRecordForBiffViewer.java index bbbe0b3eef..905c96aaa4 100644 --- a/src/java/org/apache/poi/hssf/record/DrawingRecordForBiffViewer.java +++ b/src/java/org/apache/poi/hssf/record/DrawingRecordForBiffViewer.java @@ -26,8 +26,10 @@ import java.io.ByteArrayInputStream; public final class DrawingRecordForBiffViewer extends AbstractEscherHolderRecord { public static final short sid = 0xEC; - public DrawingRecordForBiffViewer() - { + public DrawingRecordForBiffViewer() {} + + public DrawingRecordForBiffViewer(DrawingRecordForBiffViewer other) { + super(other); } public DrawingRecordForBiffViewer( RecordInputStream in) @@ -59,4 +61,9 @@ public final class DrawingRecordForBiffViewer extends AbstractEscherHolderRecord { return sid; } + + @Override + public DrawingRecordForBiffViewer copy() { + return new DrawingRecordForBiffViewer(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/DrawingSelectionRecord.java b/src/java/org/apache/poi/hssf/record/DrawingSelectionRecord.java index 20bba6bc15..7a4b103331 100644 --- a/src/java/org/apache/poi/hssf/record/DrawingSelectionRecord.java +++ b/src/java/org/apache/poi/hssf/record/DrawingSelectionRecord.java @@ -20,13 +20,14 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * MsoDrawingSelection (0x00ED)<p> * Reference: * [MS-OGRAPH].pdf sec 2.4.69 */ -public final class DrawingSelectionRecord extends StandardRecord implements Cloneable { +public final class DrawingSelectionRecord extends StandardRecord { public static final short sid = 0x00ED; /** @@ -44,6 +45,12 @@ public final class DrawingSelectionRecord extends StandardRecord implements Clon private final int _type; private final int _length; + public OfficeArtRecordHeader(OfficeArtRecordHeader other) { + _verAndInstance = other._verAndInstance; + _type = other._type; + _length = other._length; + } + public OfficeArtRecordHeader(LittleEndianInput in) { _verAndInstance = in.readUShort(); _type = in.readUShort(); @@ -57,11 +64,10 @@ public final class DrawingSelectionRecord extends StandardRecord implements Clon } public String debugFormatAsString() { - StringBuilder sb = new StringBuilder(32); - sb.append("ver+inst=").append(HexDump.shortToHex(_verAndInstance)); - sb.append(" type=").append(HexDump.shortToHex(_type)); - sb.append(" len=").append(HexDump.intToHex(_length)); - return sb.toString(); + return + "ver+inst=" + HexDump.shortToHex(_verAndInstance) + + " type=" + HexDump.shortToHex(_type) + + " len=" + HexDump.intToHex(_length); } } @@ -93,7 +99,7 @@ public final class DrawingSelectionRecord extends StandardRecord implements Clon } protected int getDataSize() { - return OfficeArtRecordHeader.ENCODED_SIZE + return OfficeArtRecordHeader.ENCODED_SIZE + 12 // 3 int fields + _shapeIds.length * 4; } @@ -109,7 +115,15 @@ public final class DrawingSelectionRecord extends StandardRecord implements Clon } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public DrawingSelectionRecord clone() { + return copy(); + } + + @Override + public DrawingSelectionRecord copy() { // currently immutable return this; } diff --git a/src/java/org/apache/poi/hssf/record/EOFRecord.java b/src/java/org/apache/poi/hssf/record/EOFRecord.java index 9d3d6d344f..10c0d8d2a6 100644 --- a/src/java/org/apache/poi/hssf/record/EOFRecord.java +++ b/src/java/org/apache/poi/hssf/record/EOFRecord.java @@ -18,33 +18,25 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * End Of File record. - * <P> - * Description: Marks the end of records belonging to a particular object in the - * HSSF File<P> - * REFERENCE: PG 307 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Jason Height (jheight at chariot dot net dot au) + * Marks the end of records belonging to a particular object in the HSSF File + * * @version 2.0-pre */ -public final class EOFRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x0A; +public final class EOFRecord extends StandardRecord { + public static final short sid = 0x0A; public static final int ENCODED_SIZE = 4; public static final EOFRecord instance = new EOFRecord(); - - private EOFRecord() { - // no data fields - } + + private EOFRecord() {} /** * @param in unused (since this record has no data) */ - public EOFRecord(RecordInputStream in) - { - } + public EOFRecord(RecordInputStream in) {} public String toString() { @@ -68,7 +60,15 @@ public final class EOFRecord extends StandardRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public EOFRecord clone() { + return copy(); + } + + @Override + public EOFRecord copy() { return instance; } } diff --git a/src/java/org/apache/poi/hssf/record/EmbeddedObjectRefSubRecord.java b/src/java/org/apache/poi/hssf/record/EmbeddedObjectRefSubRecord.java index 43d764139a..8c2226becc 100644 --- a/src/java/org/apache/poi/hssf/record/EmbeddedObjectRefSubRecord.java +++ b/src/java/org/apache/poi/hssf/record/EmbeddedObjectRefSubRecord.java @@ -33,6 +33,7 @@ import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.apache.poi.util.RecordFormatException; +import org.apache.poi.util.Removal; import org.apache.poi.util.StringUtil; /** @@ -40,7 +41,7 @@ import org.apache.poi.util.StringUtil; * A sub-record within the OBJ record which stores a reference to an object * stored in a separate entry within the OLE2 compound file. */ -public final class EmbeddedObjectRefSubRecord extends SubRecord implements Cloneable { +public final class EmbeddedObjectRefSubRecord extends SubRecord { private static POILogger logger = POILogFactory.getLogger(EmbeddedObjectRefSubRecord.class); //arbitrarily selected; may need to increase private static final int MAX_RECORD_LENGTH = 100_000; @@ -73,8 +74,16 @@ public final class EmbeddedObjectRefSubRecord extends SubRecord implements Clone field_4_ole_classname = null; } - public short getSid() { - return sid; + public EmbeddedObjectRefSubRecord(EmbeddedObjectRefSubRecord other) { + super(other); + field_1_unknown_int = other.field_1_unknown_int; + field_2_refPtg = (other.field_2_refPtg == null) ? null : other.field_2_refPtg.copy(); + field_2_unknownFormulaData = (other.field_2_unknownFormulaData == null) ? null : other.field_2_unknownFormulaData.clone(); + field_3_unicode_flag = other.field_3_unicode_flag; + field_4_ole_classname = other.field_4_ole_classname; + field_4_unknownByte = other.field_4_unknownByte; + field_5_stream_id = other.field_5_stream_id; + field_6_unknown = (other.field_6_unknown == null) ? null : other.field_6_unknown.clone(); } public EmbeddedObjectRefSubRecord(LittleEndianInput in, int size) { @@ -158,6 +167,10 @@ public final class EmbeddedObjectRefSubRecord extends SubRecord implements Clone field_6_unknown = readRawData(in, remaining); } + public short getSid() { + return sid; + } + private static Ptg readRefPtg(byte[] formulaRawBytes) { LittleEndianInput in = new LittleEndianInputStream(new ByteArrayInputStream(formulaRawBytes)); byte ptgSid = in.readByte(); @@ -310,8 +323,16 @@ public final class EmbeddedObjectRefSubRecord extends SubRecord implements Clone } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public EmbeddedObjectRefSubRecord clone() { - return this; // TODO proper clone + return copy(); + } + + @Override + public EmbeddedObjectRefSubRecord copy() { + return new EmbeddedObjectRefSubRecord(this); } public String toString() { @@ -339,15 +360,15 @@ public final class EmbeddedObjectRefSubRecord extends SubRecord implements Clone sb.append("[/ftPictFmla]"); return sb.toString(); } - + public void setUnknownFormulaData(byte[] formularData) { field_2_unknownFormulaData = formularData; } - + public void setOleClassname(String oleClassname) { field_4_ole_classname = oleClassname; } - + public void setStorageId(int storageId) { field_5_stream_id = storageId; } diff --git a/src/java/org/apache/poi/hssf/record/EndSubRecord.java b/src/java/org/apache/poi/hssf/record/EndSubRecord.java index 4999fba6b2..9707c3d489 100644 --- a/src/java/org/apache/poi/hssf/record/EndSubRecord.java +++ b/src/java/org/apache/poi/hssf/record/EndSubRecord.java @@ -14,27 +14,25 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.RecordFormatException; +import org.apache.poi.util.Removal; /** * ftEnd (0x0000)<p> - * + * * The end data record is used to denote the end of the subrecords. */ -public final class EndSubRecord extends SubRecord implements Cloneable { +public final class EndSubRecord extends SubRecord { // Note - zero sid is somewhat unusual (compared to plain Records) - public final static short sid = 0x0000; + public static final short sid = 0x0000; private static final int ENCODED_SIZE = 0; - public EndSubRecord() - { - - } + public EndSubRecord() {} /** * @param in unused (since this record has no data) @@ -76,8 +74,15 @@ public final class EndSubRecord extends SubRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public EndSubRecord clone() { + return copy(); + } + @Override + public EndSubRecord copy() { return new EndSubRecord(); } } diff --git a/src/java/org/apache/poi/hssf/record/EscherAggregate.java b/src/java/org/apache/poi/hssf/record/EscherAggregate.java index 0eb886c2cc..309057cae1 100644 --- a/src/java/org/apache/poi/hssf/record/EscherAggregate.java +++ b/src/java/org/apache/poi/hssf/record/EscherAggregate.java @@ -85,7 +85,7 @@ import org.apache.poi.util.RecordFormatException; public final class EscherAggregate extends AbstractEscherHolderRecord { public static final short sid = 9876; // not a real sid - dummy value - private static POILogger log = POILogFactory.getLogger(EscherAggregate.class); + private static final POILogger log = POILogFactory.getLogger(EscherAggregate.class); //arbitrarily selected; may need to increase private static final int MAX_RECORD_LENGTH = 100_000_000; @@ -317,6 +317,13 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { } } + public EscherAggregate(EscherAggregate other) { + super(other); + // shallow copy, because the aggregates doesn't own the records + shapeToObj.putAll(other.shapeToObj); + tailRec.putAll(other.tailRec); + } + /** * @return Returns the current sid. */ @@ -814,4 +821,9 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { public void removeTailRecord(NoteRecord note) { tailRec.remove(note.getShapeId()); } + + @Override + public EscherAggregate copy() { + return new EscherAggregate(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/ExtSSTRecord.java b/src/java/org/apache/poi/hssf/record/ExtSSTRecord.java index b56d4ca1a0..3214fd64b1 100644 --- a/src/java/org/apache/poi/hssf/record/ExtSSTRecord.java +++ b/src/java/org/apache/poi/hssf/record/ExtSSTRecord.java @@ -17,28 +17,27 @@ package org.apache.poi.hssf.record; +import java.util.ArrayList; +import java.util.stream.Stream; + import org.apache.poi.hssf.record.cont.ContinuableRecord; import org.apache.poi.hssf.record.cont.ContinuableRecordOutput; import org.apache.poi.util.LittleEndianOutput; -import java.util.ArrayList; - /** - * Title: Extended Static String Table (0x00FF)<p> - * Description: This record is used for a quick lookup into the SST record. This - * record breaks the SST table into a set of buckets. The offsets - * to these buckets within the SST record are kept as well as the - * position relative to the start of the SST record.<p> - * REFERENCE: PG 313 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) + * Extended Static String Table (0x00FF)<p> + * This record is used for a quick lookup into the SST record. This record breaks the SST table + * into a set of buckets. The offsets to these buckets within the SST record are kept as well as + * the position relative to the start of the SST record. */ public final class ExtSSTRecord extends ContinuableRecord { - public final static short sid = 0x00FF; + public static final short sid = 0x00FF; public static final int DEFAULT_BUCKET_SIZE = 8; //Can't seem to find this documented but from the biffviewer it is clear that //Excel only records the indexes for the first 128 buckets. public static final int MAX_BUCKETS = 128; - - + + public static final class InfoSubRecord { public static final int ENCODED_SIZE = 8; private int field_1_stream_pos; // stream pointer to the SST record @@ -48,7 +47,7 @@ public final class ExtSSTRecord extends ContinuableRecord { /** * Creates new ExtSSTInfoSubRecord - * + * * @param streamPos stream pointer to the SST record * @param bucketSstOffset ... don't really understand this yet */ @@ -57,6 +56,12 @@ public final class ExtSSTRecord extends ContinuableRecord { field_2_bucket_sst_offset = bucketSstOffset; } + public InfoSubRecord(InfoSubRecord other) { + field_1_stream_pos = other.field_1_stream_pos; + field_2_bucket_sst_offset = other.field_2_bucket_sst_offset; + field_3_zero = other.field_3_zero; + } + public InfoSubRecord(RecordInputStream in) { field_1_stream_pos = in.readInt(); @@ -78,8 +83,8 @@ public final class ExtSSTRecord extends ContinuableRecord { out.writeShort(field_3_zero); } } - - + + private short _stringsPerBucket; private InfoSubRecord[] _sstInfos; @@ -89,6 +94,12 @@ public final class ExtSSTRecord extends ContinuableRecord { _sstInfos = new InfoSubRecord[0]; } + public ExtSSTRecord(ExtSSTRecord other) { + _stringsPerBucket = other._stringsPerBucket; + _sstInfos = (other._sstInfos == null) ? null + : Stream.of(other._sstInfos).map(InfoSubRecord::new).toArray(InfoSubRecord[]::new); + } + public ExtSSTRecord(RecordInputStream in) { _stringsPerBucket = in.readShort(); @@ -161,9 +172,9 @@ public final class ExtSSTRecord extends ContinuableRecord { /** * Given a number of strings (in the sst), returns the size of the extsst record - * + * * @param numStrings the number of strings - * + * * @return the size of the extsst record */ public static int getRecordSizeForStrings(int numStrings) { @@ -181,4 +192,9 @@ public final class ExtSSTRecord extends ContinuableRecord { _sstInfos[i] = new InfoSubRecord(bucketAbsoluteOffsets[i], bucketRelativeOffsets[i]); } } + + @Override + public ExtSSTRecord copy() { + return new ExtSSTRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/ExtendedFormatRecord.java b/src/java/org/apache/poi/hssf/record/ExtendedFormatRecord.java index e187540300..5c9b0f1663 100644 --- a/src/java/org/apache/poi/hssf/record/ExtendedFormatRecord.java +++ b/src/java/org/apache/poi/hssf/record/ExtendedFormatRecord.java @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.hssf.record; @@ -23,179 +23,164 @@ import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.LittleEndianOutput; /** - * Title: Extended Format Record - * Description: Probably one of the more complex records. There are two breeds: - * Style and Cell. - *<P> - * It should be noted that fields in the extended format record are - * somewhat arbitrary. Almost all of the fields are bit-level, but - * we name them as best as possible by functional group. In some - * places this is better than others. - *<P> + * Probably one of the more complex records.<p> + * There are two breeds: Style and Cell.<p> + * It should be noted that fields in the extended format record are somewhat arbitrary. + * Almost all of the fields are bit-level, but we name them as best as possible by functional group. + * In some places this is better than others. * - * REFERENCE: PG 426 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) - * @since 2.0-pre */ -public final class ExtendedFormatRecord - extends StandardRecord -{ - public static final short sid = 0xE0; +public final class ExtendedFormatRecord extends StandardRecord { + public static final short sid = 0xE0; // null constant - public static final short NULL = (short)0xfff0; + public static final short NULL = (short)0xfff0; // xf type - public static final short XF_STYLE = 1; - public static final short XF_CELL = 0; + public static final short XF_STYLE = 1; + public static final short XF_CELL = 0; // borders - public static final short NONE = 0x0; - public static final short THIN = 0x1; - public static final short MEDIUM = 0x2; - public static final short DASHED = 0x3; - public static final short DOTTED = 0x4; - public static final short THICK = 0x5; - public static final short DOUBLE = 0x6; - public static final short HAIR = 0x7; - public static final short MEDIUM_DASHED = 0x8; - public static final short DASH_DOT = 0x9; - public static final short MEDIUM_DASH_DOT = 0xA; - public static final short DASH_DOT_DOT = 0xB; - public static final short MEDIUM_DASH_DOT_DOT = 0xC; - public static final short SLANTED_DASH_DOT = 0xD; + public static final short NONE = 0x0; + public static final short THIN = 0x1; + public static final short MEDIUM = 0x2; + public static final short DASHED = 0x3; + public static final short DOTTED = 0x4; + public static final short THICK = 0x5; + public static final short DOUBLE = 0x6; + public static final short HAIR = 0x7; + public static final short MEDIUM_DASHED = 0x8; + public static final short DASH_DOT = 0x9; + public static final short MEDIUM_DASH_DOT = 0xA; + public static final short DASH_DOT_DOT = 0xB; + public static final short MEDIUM_DASH_DOT_DOT = 0xC; + public static final short SLANTED_DASH_DOT = 0xD; // alignment - public static final short GENERAL = 0x0; - public static final short LEFT = 0x1; - public static final short CENTER = 0x2; - public static final short RIGHT = 0x3; - public static final short FILL = 0x4; - public static final short JUSTIFY = 0x5; - public static final short CENTER_SELECTION = 0x6; + public static final short GENERAL = 0x0; + public static final short LEFT = 0x1; + public static final short CENTER = 0x2; + public static final short RIGHT = 0x3; + public static final short FILL = 0x4; + public static final short JUSTIFY = 0x5; + public static final short CENTER_SELECTION = 0x6; // vertical alignment - public static final short VERTICAL_TOP = 0x0; - public static final short VERTICAL_CENTER = 0x1; - public static final short VERTICAL_BOTTOM = 0x2; - public static final short VERTICAL_JUSTIFY = 0x3; + public static final short VERTICAL_TOP = 0x0; + public static final short VERTICAL_CENTER = 0x1; + public static final short VERTICAL_BOTTOM = 0x2; + public static final short VERTICAL_JUSTIFY = 0x3; // fill - public static final short NO_FILL = 0 ; - public static final short SOLID_FILL = 1 ; - public static final short FINE_DOTS = 2 ; - public static final short ALT_BARS = 3 ; - public static final short SPARSE_DOTS = 4 ; - public static final short THICK_HORZ_BANDS = 5 ; - public static final short THICK_VERT_BANDS = 6 ; - public static final short THICK_BACKWARD_DIAG = 7 ; - public static final short THICK_FORWARD_DIAG = 8 ; - public static final short BIG_SPOTS = 9 ; - public static final short BRICKS = 10 ; - public static final short THIN_HORZ_BANDS = 11 ; - public static final short THIN_VERT_BANDS = 12 ; - public static final short THIN_BACKWARD_DIAG = 13 ; - public static final short THIN_FORWARD_DIAG = 14 ; - public static final short SQUARES = 15 ; - public static final short DIAMONDS = 16 ; - - // fields in BOTH style and Cell XF records - private short field_1_font_index; // not bit-mapped - private short field_2_format_index; // not bit-mapped + public static final short NO_FILL = 0; + public static final short SOLID_FILL = 1; + public static final short FINE_DOTS = 2; + public static final short ALT_BARS = 3; + public static final short SPARSE_DOTS = 4; + public static final short THICK_HORZ_BANDS = 5; + public static final short THICK_VERT_BANDS = 6; + public static final short THICK_BACKWARD_DIAG = 7; + public static final short THICK_FORWARD_DIAG = 8; + public static final short BIG_SPOTS = 9; + public static final short BRICKS = 10; + public static final short THIN_HORZ_BANDS = 11; + public static final short THIN_VERT_BANDS = 12; + public static final short THIN_BACKWARD_DIAG = 13; + public static final short THIN_FORWARD_DIAG = 14; + public static final short SQUARES = 15; + public static final short DIAMONDS = 16; // field_3_cell_options bit map - private static final BitField _locked = BitFieldFactory.getInstance(0x0001); - private static final BitField _hidden = BitFieldFactory.getInstance(0x0002); - private static final BitField _xf_type = BitFieldFactory.getInstance(0x0004); - private static final BitField _123_prefix = BitFieldFactory.getInstance(0x0008); - private static final BitField _parent_index = BitFieldFactory.getInstance(0xFFF0); - private short field_3_cell_options; + private static final BitField _locked = bf(0x0001); + private static final BitField _hidden = bf(0x0002); + private static final BitField _xf_type = bf(0x0004); + private static final BitField _123_prefix = bf(0x0008); + private static final BitField _parent_index = bf(0xFFF0); // field_4_alignment_options bit map - private static final BitField _alignment = BitFieldFactory.getInstance(0x0007); - private static final BitField _wrap_text = BitFieldFactory.getInstance(0x0008); - private static final BitField _vertical_alignment = BitFieldFactory.getInstance(0x0070); - private static final BitField _justify_last = BitFieldFactory.getInstance(0x0080); - private static final BitField _rotation = BitFieldFactory.getInstance(0xFF00); - private short field_4_alignment_options; + private static final BitField _alignment = bf(0x0007); + private static final BitField _wrap_text = bf(0x0008); + private static final BitField _vertical_alignment = bf(0x0070); + private static final BitField _justify_last = bf(0x0080); + private static final BitField _rotation = bf(0xFF00); // field_5_indention_options - private static final BitField _indent = - BitFieldFactory.getInstance(0x000F); - private static final BitField _shrink_to_fit = - BitFieldFactory.getInstance(0x0010); - private static final BitField _merge_cells = - BitFieldFactory.getInstance(0x0020); - private static final BitField _reading_order = - BitFieldFactory.getInstance(0x00C0); + private static final BitField _indent = bf(0x000F); + private static final BitField _shrink_to_fit = bf(0x0010); + private static final BitField _merge_cells = bf(0x0020); + private static final BitField _reading_order = bf(0x00C0); // apparently bits 8 and 9 are unused - private static final BitField _indent_not_parent_format = - BitFieldFactory.getInstance(0x0400); - private static final BitField _indent_not_parent_font = - BitFieldFactory.getInstance(0x0800); - private static final BitField _indent_not_parent_alignment = - BitFieldFactory.getInstance(0x1000); - private static final BitField _indent_not_parent_border = - BitFieldFactory.getInstance(0x2000); - private static final BitField _indent_not_parent_pattern = - BitFieldFactory.getInstance(0x4000); - private static final BitField _indent_not_parent_cell_options = - BitFieldFactory.getInstance(0x8000); - private short field_5_indention_options; + private static final BitField _indent_not_parent_format = bf(0x0400); + private static final BitField _indent_not_parent_font = bf(0x0800); + private static final BitField _indent_not_parent_alignment = bf(0x1000); + private static final BitField _indent_not_parent_border = bf(0x2000); + private static final BitField _indent_not_parent_pattern = bf(0x4000); + private static final BitField _indent_not_parent_cell_options = bf(0x8000); // field_6_border_options bit map - private static final BitField _border_left = BitFieldFactory.getInstance(0x000F); - private static final BitField _border_right = BitFieldFactory.getInstance(0x00F0); - private static final BitField _border_top = BitFieldFactory.getInstance(0x0F00); - private static final BitField _border_bottom = BitFieldFactory.getInstance(0xF000); - private short field_6_border_options; + private static final BitField _border_left = bf(0x000F); + private static final BitField _border_right = bf(0x00F0); + private static final BitField _border_top = bf(0x0F00); + private static final BitField _border_bottom = bf(0xF000); // all three of the following attributes are palette options // field_7_palette_options bit map - private static final BitField _left_border_palette_idx = - BitFieldFactory.getInstance(0x007F); - private static final BitField _right_border_palette_idx = - BitFieldFactory.getInstance(0x3F80); - private static final BitField _diag = - BitFieldFactory.getInstance(0xC000); - private short field_7_palette_options; + private static final BitField _left_border_palette_idx = bf(0x007F); + private static final BitField _right_border_palette_idx = bf(0x3F80); + private static final BitField _diag = bf(0xC000); // field_8_adtl_palette_options bit map - private static final BitField _top_border_palette_idx = - BitFieldFactory.getInstance(0x0000007F); - private static final BitField _bottom_border_palette_idx = - BitFieldFactory.getInstance(0x00003F80); - private static final BitField _adtl_diag = - BitFieldFactory.getInstance(0x001fc000); - private static final BitField _adtl_diag_line_style = - BitFieldFactory.getInstance(0x01e00000); + private static final BitField _top_border_palette_idx = bf(0x0000007F); + private static final BitField _bottom_border_palette_idx = bf(0x00003F80); + private static final BitField _adtl_diag = bf(0x001fc000); + private static final BitField _adtl_diag_line_style = bf(0x01e00000); // apparently bit 25 is unused - private static final BitField _adtl_fill_pattern = - BitFieldFactory.getInstance(0xfc000000); - private int field_8_adtl_palette_options; // additional to avoid 2 + private static final BitField _adtl_fill_pattern = bf(0xfc000000); // field_9_fill_palette_options bit map - private static final BitField _fill_foreground = BitFieldFactory.getInstance(0x007F); - private static final BitField _fill_background = BitFieldFactory.getInstance(0x3f80); + private static final BitField _fill_foreground = bf(0x007F); + private static final BitField _fill_background = bf(0x3f80); + + private static BitField bf(int i) { + return BitFieldFactory.getInstance(i); + } + + + // fields in BOTH style and Cell XF records + private short field_1_font_index; // not bit-mapped + private short field_2_format_index; // not bit-mapped + + private short field_3_cell_options; + private short field_4_alignment_options; + private short field_5_indention_options; + private short field_6_border_options; + private short field_7_palette_options; + private int field_8_adtl_palette_options; // additional to avoid 2 + // apparently bits 15 and 14 are unused - private short field_9_fill_palette_options; + private short field_9_fill_palette_options; - /** - * Constructor ExtendedFormatRecord - * - * - */ + public ExtendedFormatRecord() {} - public ExtendedFormatRecord() - { + public ExtendedFormatRecord(ExtendedFormatRecord other) { + super(other); + field_1_font_index = other.field_1_font_index; + field_2_format_index = other.field_2_format_index; + field_3_cell_options = other.field_3_cell_options; + field_4_alignment_options = other.field_4_alignment_options; + field_5_indention_options = other.field_5_indention_options; + field_6_border_options = other.field_6_border_options; + field_7_palette_options = other.field_7_palette_options; + field_8_adtl_palette_options = other.field_8_adtl_palette_options; + field_9_fill_palette_options = other.field_9_fill_palette_options; } - public ExtendedFormatRecord(RecordInputStream in) - { + public ExtendedFormatRecord(RecordInputStream in) { field_1_font_index = in.readShort(); field_2_format_index = in.readShort(); field_3_cell_options = in.readShort(); @@ -560,7 +545,7 @@ public final class ExtendedFormatRecord /** * <p>Sets whether or not to use the pattern in this XF instead of the * parent XF (foreground/background).</p> - * + * * @param pattern {@code true} if this XF has a different pattern * value than its parent, {@code false} otherwise. * @see #setIndentionOptions(short) @@ -1788,16 +1773,16 @@ public final class ExtendedFormatRecord { return sid; } - + /** * Clones all the style information from another - * ExtendedFormatRecord, onto this one. This + * ExtendedFormatRecord, onto this one. This * will then hold all the same style options. - * + * * If The source ExtendedFormatRecord comes from * a different Workbook, you will need to sort * out the font and format indices yourself! - * + * * @param source the ExtendedFormatRecord to copy from */ public void cloneStyleFrom(ExtendedFormatRecord source) { @@ -1863,11 +1848,15 @@ public final class ExtendedFormatRecord } return false; } - + public int[] stateSummary() { return new int[] { field_1_font_index, field_2_format_index, field_3_cell_options, field_4_alignment_options, field_5_indention_options, field_6_border_options, field_7_palette_options, field_8_adtl_palette_options, field_9_fill_palette_options }; } - - + + + @Override + public ExtendedFormatRecord copy() { + return new ExtendedFormatRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/ExternSheetRecord.java b/src/java/org/apache/poi/hssf/record/ExternSheetRecord.java index 5c4e96b70f..ac69fcf268 100644 --- a/src/java/org/apache/poi/hssf/record/ExternSheetRecord.java +++ b/src/java/org/apache/poi/hssf/record/ExternSheetRecord.java @@ -28,9 +28,9 @@ import org.apache.poi.util.LittleEndianOutput; */ public class ExternSheetRecord extends StandardRecord { - public final static short sid = 0x0017; - private final List<RefSubRecord> _list; - + public static final short sid = 0x0017; + private final List<RefSubRecord> _list = new ArrayList<>(); + private static final class RefSubRecord { public static final int ENCODED_SIZE = 6; @@ -38,26 +38,31 @@ public class ExternSheetRecord extends StandardRecord { private final int _extBookIndex; private int _firstSheetIndex; // may be -1 (0xFFFF) private int _lastSheetIndex; // may be -1 (0xFFFF) - - public void adjustIndex(int offset) { - _firstSheetIndex += offset; - _lastSheetIndex += offset; - } - - /** a Constructor for making new sub record - */ + public RefSubRecord(int extBookIndex, int firstSheetIndex, int lastSheetIndex) { _extBookIndex = extBookIndex; _firstSheetIndex = firstSheetIndex; _lastSheetIndex = lastSheetIndex; } - + + public RefSubRecord(RefSubRecord other) { + _extBookIndex = other._extBookIndex; + _firstSheetIndex = other._firstSheetIndex; + _lastSheetIndex = other._lastSheetIndex; + } + /** * @param in the RecordInputstream to read the record from */ public RefSubRecord(RecordInputStream in) { this(in.readShort(), in.readShort(), in.readShort()); } + + public void adjustIndex(int offset) { + _firstSheetIndex += offset; + _lastSheetIndex += offset; + } + public int getExtBookIndex(){ return _extBookIndex; } @@ -67,7 +72,7 @@ public class ExternSheetRecord extends StandardRecord { public int getLastSheetIndex(){ return _lastSheetIndex; } - + @Override public String toString() { StringBuilder buffer = new StringBuilder(); @@ -76,55 +81,53 @@ public class ExternSheetRecord extends StandardRecord { buffer.append(" lastSheet=").append(_lastSheetIndex); return buffer.toString(); } - + public void serialize(LittleEndianOutput out) { out.writeShort(_extBookIndex); out.writeShort(_firstSheetIndex); out.writeShort(_lastSheetIndex); } - } - - - - public ExternSheetRecord() { - _list = new ArrayList<>(); + } + + public ExternSheetRecord() {} + + public ExternSheetRecord(ExternSheetRecord other) { + other._list.stream().map(RefSubRecord::new).forEach(_list::add); } public ExternSheetRecord(RecordInputStream in) { - _list = new ArrayList<>(); - int nItems = in.readShort(); - + for (int i = 0 ; i < nItems ; ++i) { RefSubRecord rec = new RefSubRecord(in); _list.add(rec); } } - - /** + + /** * @return number of REF structures */ public int getNumOfRefs() { return _list.size(); } - - /** + + /** * adds REF struct (ExternSheetSubRecord) * @param rec REF struct */ public void addREFRecord(RefSubRecord rec) { _list.add(rec); } - + /** returns the number of REF Records, which is in model * @return number of REF records */ public int getNumOfREFRecords() { return _list.size(); } - - + + @Override public String toString() { StringBuilder sb = new StringBuilder(); @@ -137,22 +140,22 @@ public class ExternSheetRecord extends StandardRecord { sb.append('\n'); } sb.append("[/EXTERNSHEET]\n"); - - + + return sb.toString(); } - + @Override protected int getDataSize() { return 2 + _list.size() * RefSubRecord.ENCODED_SIZE; } - + @Override public void serialize(LittleEndianOutput out) { int nItems = _list.size(); out.writeShort(nItems); - + for (int i = 0; i < nItems; i++) { getRef(i).serialize(out); } @@ -161,22 +164,22 @@ public class ExternSheetRecord extends StandardRecord { private RefSubRecord getRef(int i) { return _list.get(i); } - + public void removeSheet(int sheetIdx) { int nItems = _list.size(); for (int i = 0; i < nItems; i++) { RefSubRecord refSubRecord = _list.get(i); - if(refSubRecord.getFirstSheetIndex() == sheetIdx && + if(refSubRecord.getFirstSheetIndex() == sheetIdx && refSubRecord.getLastSheetIndex() == sheetIdx) { // removing the entry would mess up the sheet index in Formula of NameRecord _list.set(i, new RefSubRecord(refSubRecord.getExtBookIndex(), -1, -1)); - } else if (refSubRecord.getFirstSheetIndex() > sheetIdx && + } else if (refSubRecord.getFirstSheetIndex() > sheetIdx && refSubRecord.getLastSheetIndex() > sheetIdx) { _list.set(i, new RefSubRecord(refSubRecord.getExtBookIndex(), refSubRecord.getFirstSheetIndex()-1, refSubRecord.getLastSheetIndex()-1)); } } } - + /** * return the non static version of the id for this record. */ @@ -187,7 +190,7 @@ public class ExternSheetRecord extends StandardRecord { /** * @param refIndex specifies the n-th refIndex - * + * * @return the index of the SupBookRecord for this index */ public int getExtbookIndexFromRefIndex(int refIndex) { @@ -197,7 +200,7 @@ public class ExternSheetRecord extends StandardRecord { /** * @param extBookIndex external sheet reference index - * + * * @return -1 if not found */ public int findRefIndexFromExtBookIndex(int extBookIndex) { @@ -214,9 +217,9 @@ public class ExternSheetRecord extends StandardRecord { * Returns the first sheet that the reference applies to, or * -1 if the referenced sheet can't be found, or -2 if the * reference is workbook scoped. - * + * * @param extRefIndex external sheet reference index - * + * * @return the first sheet that the reference applies to, or * -1 if the referenced sheet can't be found, or -2 if the * reference is workbook scoped @@ -231,9 +234,9 @@ public class ExternSheetRecord extends StandardRecord { * reference is workbook scoped. * For a single sheet reference, the first and last should be * the same. - * + * * @param extRefIndex external sheet reference index - * + * * @return the last sheet that the reference applies to, or * -1 if the referenced sheet can't be found, or -2 if the * reference is workbook scoped. @@ -258,7 +261,7 @@ public class ExternSheetRecord extends StandardRecord { * see {@link org.apache.poi.hssf.record.SupBookRecord#getSheetNames()}. * This referenced string specifies the name of the first sheet within the external workbook that is in scope. * This sheet MUST be a worksheet or macro sheet.</p> - * + * * <p>If the supporting link type is self-referencing, then this value specifies the zero-based index of a * {@link org.apache.poi.hssf.record.BoundSheetRecord} record in the workbook stream that specifies * the first sheet within the scope of this reference. This sheet MUST be a worksheet or a macro sheet. @@ -283,7 +286,7 @@ public class ExternSheetRecord extends StandardRecord { if (ref.getExtBookIndex() != externalBookIndex) { continue; } - if (ref.getFirstSheetIndex() == firstSheetIndex && + if (ref.getFirstSheetIndex() == firstSheetIndex && ref.getLastSheetIndex() == lastSheetIndex) { return i; } @@ -301,4 +304,9 @@ public class ExternSheetRecord extends StandardRecord { } return result; } + + @Override + public ExternSheetRecord copy() { + return new ExternSheetRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/ExternalNameRecord.java b/src/java/org/apache/poi/hssf/record/ExternalNameRecord.java index ab76a43d83..a9a27c1e14 100644 --- a/src/java/org/apache/poi/hssf/record/ExternalNameRecord.java +++ b/src/java/org/apache/poi/hssf/record/ExternalNameRecord.java @@ -28,7 +28,7 @@ import org.apache.poi.util.StringUtil; */ public final class ExternalNameRecord extends StandardRecord { - public final static short sid = 0x0023; // as per BIFF8. (some old versions used 0x223) + public static final short sid = 0x0023; // as per BIFF8. (some old versions used 0x223) private static final int OPT_BUILTIN_NAME = 0x0001; private static final int OPT_AUTOMATIC_LINK = 0x0002; // m$ doc calls this fWantAdvise @@ -39,11 +39,11 @@ public final class ExternalNameRecord extends StandardRecord { private static final int OPT_ICONIFIED_PICTURE_LINK= 0x8000; - private short field_1_option_flag; - private short field_2_ixals; - private short field_3_not_used; + private short field_1_option_flag; + private short field_2_ixals; + private short field_3_not_used; private String field_4_name; - private Formula field_5_name_definition; + private Formula field_5_name_definition; /** * 'rgoper' / 'Last received results of the DDE link' @@ -60,6 +60,54 @@ public final class ExternalNameRecord extends StandardRecord { */ private int _nRows; + public ExternalNameRecord() { + field_2_ixals = 0; + } + + public ExternalNameRecord(ExternalNameRecord other) { + super(other); + field_1_option_flag = other.field_1_option_flag; + field_2_ixals = other.field_2_ixals; + field_3_not_used = other.field_3_not_used; + field_4_name = other.field_4_name; + field_5_name_definition = (other.field_5_name_definition == null) ? null : other.field_5_name_definition.copy(); + _ddeValues = (other._ddeValues == null) ? null : other._ddeValues.clone(); + _nColumns = other._nColumns; + _nRows = other._nRows; + } + + public ExternalNameRecord(RecordInputStream in) { + field_1_option_flag = in.readShort(); + field_2_ixals = in.readShort(); + field_3_not_used = in.readShort(); + + int numChars = in.readUByte(); + field_4_name = StringUtil.readUnicodeString(in, numChars); + + // the record body can take different forms. + // The form is dictated by the values of 3-th and 4-th bits in field_1_option_flag + if(!isOLELink() && !isStdDocumentNameIdentifier()){ + // another switch: the fWantAdvise bit specifies whether the body describes + // an external defined name or a DDE data item + if(isAutomaticLink()){ + if(in.available() > 0) { + //body specifies DDE data item + int nColumns = in.readUByte() + 1; + int nRows = in.readShort() + 1; + + int totalCount = nRows * nColumns; + _ddeValues = ConstantValueParser.parse(in, totalCount); + _nColumns = nColumns; + _nRows = nRows; + } + } else { + //body specifies an external defined name + int formulaLen = in.readUShort(); + field_5_name_definition = Formula.read(formulaLen, in); + } + } + } + /** * @return {@code true} if the name is a built-in name */ @@ -68,7 +116,7 @@ public final class ExternalNameRecord extends StandardRecord { } /** * For OLE and DDE, links can be either 'automatic' or 'manual' - * + * * @return {@code true} if this is a automatic link */ public boolean isAutomaticLink() { @@ -76,7 +124,7 @@ public final class ExternalNameRecord extends StandardRecord { } /** * only for OLE and DDE - * + * * @return {@code true} if this is a picture link */ public boolean isPicureLink() { @@ -84,7 +132,7 @@ public final class ExternalNameRecord extends StandardRecord { } /** * DDE links only. If <code>true</code>, this denotes the 'StdDocumentName' - * + * * @return {@code true} if this denotes the 'StdDocumentName' */ public boolean isStdDocumentNameIdentifier() { @@ -102,7 +150,7 @@ public final class ExternalNameRecord extends StandardRecord { public String getText() { return field_4_name; } - + public void setText(String str) { field_4_name = str; } @@ -112,13 +160,13 @@ public final class ExternalNameRecord extends StandardRecord { * index of the name of the Sheet this refers to, as * defined in the preceding {@link SupBookRecord}. * If it isn't a local name, then it must be zero. - * + * * @return the index of the name of the Sheet this refers to */ public short getIx() { return field_2_ixals; } - + public void setIx(short ix) { field_2_ixals = ix; } @@ -134,7 +182,7 @@ public final class ExternalNameRecord extends StandardRecord { @Override protected int getDataSize(){ int result = 2 + 4; // short and int - result += StringUtil.getEncodedSize(field_4_name) - 1; //size is byte, not short + result += StringUtil.getEncodedSize(field_4_name) - 1; //size is byte, not short if(!isOLELink() && !isStdDocumentNameIdentifier()){ if(isAutomaticLink()){ @@ -171,42 +219,6 @@ public final class ExternalNameRecord extends StandardRecord { } } - public ExternalNameRecord() { - field_2_ixals = 0; - } - - public ExternalNameRecord(RecordInputStream in) { - field_1_option_flag = in.readShort(); - field_2_ixals = in.readShort(); - field_3_not_used = in.readShort(); - - int numChars = in.readUByte(); - field_4_name = StringUtil.readUnicodeString(in, numChars); - - // the record body can take different forms. - // The form is dictated by the values of 3-th and 4-th bits in field_1_option_flag - if(!isOLELink() && !isStdDocumentNameIdentifier()){ - // another switch: the fWantAdvise bit specifies whether the body describes - // an external defined name or a DDE data item - if(isAutomaticLink()){ - if(in.available() > 0) { - //body specifies DDE data item - int nColumns = in.readUByte() + 1; - int nRows = in.readShort() + 1; - - int totalCount = nRows * nColumns; - _ddeValues = ConstantValueParser.parse(in, totalCount); - _nColumns = nColumns; - _nRows = nRows; - } - } else { - //body specifies an external defined name - int formulaLen = in.readUShort(); - field_5_name_definition = Formula.read(formulaLen, in); - } - } - } - @Override public short getSid() { return sid; @@ -228,4 +240,9 @@ public final class ExternalNameRecord extends StandardRecord { sb.append("[/EXTERNALNAME]\n"); return sb.toString(); } + + @Override + public ExternalNameRecord copy() { + return new ExternalNameRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/FeatHdrRecord.java b/src/java/org/apache/poi/hssf/record/FeatHdrRecord.java index 1acb3f05aa..4d60a85fc0 100644 --- a/src/java/org/apache/poi/hssf/record/FeatHdrRecord.java +++ b/src/java/org/apache/poi/hssf/record/FeatHdrRecord.java @@ -19,29 +19,30 @@ package org.apache.poi.hssf.record; import org.apache.poi.hssf.record.common.FtrHeader; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * Title: FeatHdr (Feature Header) Record * <P> - * This record specifies common information for Shared Features, and - * specifies the beginning of a collection of records to define them. - * The collection of data (Globals Substream ABNF, macro sheet substream + * This record specifies common information for Shared Features, and + * specifies the beginning of a collection of records to define them. + * The collection of data (Globals Substream ABNF, macro sheet substream * ABNF or worksheet substream ABNF) specifies Shared Feature data. */ -public final class FeatHdrRecord extends StandardRecord implements Cloneable { +public final class FeatHdrRecord extends StandardRecord { /** - * Specifies the enhanced protection type. Used to protect a - * shared workbook by restricting access to some areas of it + * Specifies the enhanced protection type. Used to protect a + * shared workbook by restricting access to some areas of it */ public static final int SHAREDFEATURES_ISFPROTECTION = 0x02; /** - * Specifies that formula errors should be ignored + * Specifies that formula errors should be ignored */ public static final int SHAREDFEATURES_ISFFEC2 = 0x03; /** * Specifies the smart tag type. Recognises certain * types of entries (proper names, dates/times etc) and - * flags them for action + * flags them for action */ public static final int SHAREDFEATURES_ISFFACTOID = 0x04; /** @@ -50,13 +51,13 @@ public final class FeatHdrRecord extends StandardRecord implements Cloneable { */ public static final int SHAREDFEATURES_ISFLIST = 0x05; - - public final static short sid = 0x0867; - private FtrHeader futureHeader; + public static final short sid = 0x0867; + + private final FtrHeader futureHeader; private int isf_sharedFeatureType; // See SHAREDFEATURES_ private byte reserved; // Should always be one - /** + /** * 0x00000000 = rgbHdrData not present * 0xffffffff = rgbHdrData present */ @@ -69,13 +70,18 @@ public final class FeatHdrRecord extends StandardRecord implements Cloneable { futureHeader.setRecordType(sid); } - public short getSid() { - return sid; + public FeatHdrRecord(FeatHdrRecord other) { + super(other); + futureHeader = other.futureHeader.copy(); + isf_sharedFeatureType = other.isf_sharedFeatureType; + reserved = other.reserved; + cbHdrData = other.cbHdrData; + rgbHdrData = (other.rgbHdrData == null) ? null : other.rgbHdrData.clone(); } public FeatHdrRecord(RecordInputStream in) { futureHeader = new FtrHeader(in); - + isf_sharedFeatureType = in.readShort(); reserved = in.readByte(); cbHdrData = in.readInt(); @@ -83,19 +89,23 @@ public final class FeatHdrRecord extends StandardRecord implements Cloneable { rgbHdrData = in.readRemainder(); } + public short getSid() { + return sid; + } + public String toString() { StringBuilder buffer = new StringBuilder(); buffer.append("[FEATURE HEADER]\n"); - + // TODO ... - + buffer.append("[/FEATURE HEADER]\n"); return buffer.toString(); } public void serialize(LittleEndianOutput out) { futureHeader.serialize(out); - + out.writeShort(isf_sharedFeatureType); out.writeByte(reserved); out.writeInt((int)cbHdrData); @@ -105,12 +115,20 @@ public final class FeatHdrRecord extends StandardRecord implements Cloneable { protected int getDataSize() { return 12 + 2+1+4+rgbHdrData.length; } - + + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public FeatHdrRecord clone() { + return copy(); + } + @Override - public FeatHdrRecord clone() { + public FeatHdrRecord copy() { //HACK: do a "cheat" clone, see Record.java for more information - return (FeatHdrRecord)cloneViaReserialise(); + return new FeatHdrRecord(this); } - + } diff --git a/src/java/org/apache/poi/hssf/record/FeatRecord.java b/src/java/org/apache/poi/hssf/record/FeatRecord.java index 37bb5b1f8f..673ee93bb4 100644 --- a/src/java/org/apache/poi/hssf/record/FeatRecord.java +++ b/src/java/org/apache/poi/hssf/record/FeatRecord.java @@ -17,6 +17,8 @@ package org.apache.poi.hssf.record; +import java.util.stream.Stream; + import org.apache.poi.hssf.record.common.FeatFormulaErr2; import org.apache.poi.hssf.record.common.FeatProtection; import org.apache.poi.hssf.record.common.FeatSmartTag; @@ -26,6 +28,7 @@ import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; +import org.apache.poi.util.Removal; /** * Title: Feat (Feature) Record @@ -33,19 +36,17 @@ import org.apache.poi.util.POILogger; * This record specifies Shared Features data. It is normally paired * up with a {@link FeatHdrRecord}. */ -public final class FeatRecord extends StandardRecord implements Cloneable { - private static POILogger logger = POILogFactory.getLogger(FeatRecord.class); - public final static short sid = 0x0868; +public final class FeatRecord extends StandardRecord { + private static final POILogger logger = POILogFactory.getLogger(FeatRecord.class); + public static final short sid = 0x0868; // SIDs from newer versions - public final static short v11_sid = 0x0872; - public final static short v12_sid = 0x0878; - - private FtrHeader futureHeader; - - /** - * See SHAREDFEATURES_* on {@link FeatHdrRecord} - */ - private int isf_sharedFeatureType; + public static final short v11_sid = 0x0872; + public static final short v12_sid = 0x0878; + + private final FtrHeader futureHeader; + + /** See SHAREDFEATURES_* on {@link FeatHdrRecord} */ + private int isf_sharedFeatureType; private byte reserved1; // Should always be zero private long reserved2; // Should always be zero /** Only matters if type is ISFFEC2 */ @@ -55,24 +56,33 @@ public final class FeatRecord extends StandardRecord implements Cloneable { /** * Contents depends on isf_sharedFeatureType : - * ISFPROTECTION -> FeatProtection + * ISFPROTECTION -> FeatProtection * ISFFEC2 -> FeatFormulaErr2 * ISFFACTOID -> FeatSmartTag */ - private SharedFeature sharedFeature; - + private SharedFeature sharedFeature; + public FeatRecord() { futureHeader = new FtrHeader(); futureHeader.setRecordType(sid); } - public short getSid() { - return sid; + public FeatRecord(FeatRecord other) { + super(other); + futureHeader = other.futureHeader.copy(); + isf_sharedFeatureType = other.isf_sharedFeatureType; + reserved1 = other.reserved1; + reserved2 = other.reserved2; + cbFeatData = other.cbFeatData; + reserved3 = other.reserved3; + cellRefs = (other.cellRefs == null) ? null : + Stream.of(other.cellRefs).map(CellRangeAddress::copy).toArray(CellRangeAddress[]::new); + sharedFeature = (other.sharedFeature == null) ? null : other.sharedFeature.copy(); } public FeatRecord(RecordInputStream in) { futureHeader = new FtrHeader(in); - + isf_sharedFeatureType = in.readShort(); reserved1 = in.readByte(); reserved2 = in.readInt(); @@ -84,7 +94,7 @@ public final class FeatRecord extends StandardRecord implements Cloneable { for(int i=0; i<cellRefs.length; i++) { cellRefs[i] = new CellRangeAddress(in); } - + switch(isf_sharedFeatureType) { case FeatHdrRecord.SHAREDFEATURES_ISFPROTECTION: sharedFeature = new FeatProtection(in); @@ -100,30 +110,34 @@ public final class FeatRecord extends StandardRecord implements Cloneable { } } + public short getSid() { + return sid; + } + public String toString() { StringBuilder buffer = new StringBuilder(); buffer.append("[SHARED FEATURE]\n"); - + // TODO ... - + buffer.append("[/SHARED FEATURE]\n"); return buffer.toString(); } public void serialize(LittleEndianOutput out) { futureHeader.serialize(out); - + out.writeShort(isf_sharedFeatureType); out.writeByte(reserved1); out.writeInt((int)reserved2); out.writeShort(cellRefs.length); out.writeInt((int)cbFeatData); out.writeShort(reserved3); - + for(int i=0; i<cellRefs.length; i++) { cellRefs[i].serialize(out); } - + sharedFeature.serialize(out); } @@ -156,7 +170,7 @@ public final class FeatRecord extends StandardRecord implements Cloneable { } public void setSharedFeature(SharedFeature feature) { this.sharedFeature = feature; - + if(feature instanceof FeatProtection) { isf_sharedFeatureType = FeatHdrRecord.SHAREDFEATURES_ISFPROTECTION; } @@ -166,7 +180,7 @@ public final class FeatRecord extends StandardRecord implements Cloneable { if(feature instanceof FeatSmartTag) { isf_sharedFeatureType = FeatHdrRecord.SHAREDFEATURES_ISFFACTOID; } - + if(isf_sharedFeatureType == FeatHdrRecord.SHAREDFEATURES_ISFFEC2) { cbFeatData = sharedFeature.getDataSize(); } else { @@ -174,12 +188,16 @@ public final class FeatRecord extends StandardRecord implements Cloneable { } } - @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public FeatRecord clone() { - //HACK: do a "cheat" clone, see Record.java for more information - return (FeatRecord)cloneViaReserialise(); - } + return copy(); + } - + @Override + public FeatRecord copy() { + return new FeatRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/FilePassRecord.java b/src/java/org/apache/poi/hssf/record/FilePassRecord.java index 8489447325..78a3428e93 100644 --- a/src/java/org/apache/poi/hssf/record/FilePassRecord.java +++ b/src/java/org/apache/poi/hssf/record/FilePassRecord.java @@ -33,13 +33,14 @@ import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianByteArrayOutputStream; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutputStream; +import org.apache.poi.util.Removal; /** - * Title: File Pass Record (0x002F) <p> + * File Pass Record (0x002F) <p> * - * Description: Indicates that the record after this record are encrypted. + * Indicates that the record after this record are encrypted. */ -public final class FilePassRecord extends StandardRecord implements Cloneable { +public final class FilePassRecord extends StandardRecord { public static final short sid = 0x002F; private static final int ENCRYPTION_XOR = 0; private static final int ENCRYPTION_OTHER = 1; @@ -48,12 +49,9 @@ public final class FilePassRecord extends StandardRecord implements Cloneable { private EncryptionInfo encryptionInfo; private FilePassRecord(FilePassRecord other) { + super(other); encryptionType = other.encryptionType; - try { - encryptionInfo = other.encryptionInfo.clone(); - } catch (CloneNotSupportedException e) { - throw new EncryptedDocumentException(e); - } + encryptionInfo = other.encryptionInfo.copy(); } public FilePassRecord(EncryptionMode encryptionMode) { @@ -138,8 +136,16 @@ public final class FilePassRecord extends StandardRecord implements Cloneable { return sid; } - @Override - public FilePassRecord clone() { + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public FilePassRecord clone() { + return copy(); + } + + @Override + public FilePassRecord copy() { return new FilePassRecord(this); } diff --git a/src/java/org/apache/poi/hssf/record/FileSharingRecord.java b/src/java/org/apache/poi/hssf/record/FileSharingRecord.java index bf1825730d..2eb447531d 100644 --- a/src/java/org/apache/poi/hssf/record/FileSharingRecord.java +++ b/src/java/org/apache/poi/hssf/record/FileSharingRecord.java @@ -18,17 +18,16 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; import org.apache.poi.util.StringUtil; /** - * Title: FILESHARING (0x005B) <p> - * Description: stores the encrypted readonly for a workbook (write protect) - * This functionality is accessed from the options dialog box available when performing 'Save As'.<p> - * REFERENCE: PG 314 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) + * Stores the encrypted readonly for a workbook (write protect).<p> + * This functionality is accessed from the options dialog box available when performing 'Save As'. */ -public final class FileSharingRecord extends StandardRecord implements Cloneable { +public final class FileSharingRecord extends StandardRecord { - public final static short sid = 0x005B; + public static final short sid = 0x005B; private short field_1_readonly; private short field_2_password; private byte field_3_username_unicode_options; @@ -36,14 +35,22 @@ public final class FileSharingRecord extends StandardRecord implements Cloneable public FileSharingRecord() {} + public FileSharingRecord(FileSharingRecord other) { + super(other); + field_1_readonly = other.field_1_readonly; + field_2_password = other.field_2_password; + field_3_username_unicode_options = other.field_3_username_unicode_options; + field_3_username_value = other.field_3_username_value; + } + public FileSharingRecord(RecordInputStream in) { field_1_readonly = in.readShort(); field_2_password = in.readShort(); - + int nameLen = in.readShort(); - + if(nameLen > 0) { - // TODO - Current examples(3) from junits only have zero length username. + // TODO - Current examples(3) from junits only have zero length username. field_3_username_unicode_options = in.readByte(); field_3_username_value = in.readCompressedUnicode(nameLen); } else { @@ -137,11 +144,15 @@ public final class FileSharingRecord extends StandardRecord implements Cloneable } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public FileSharingRecord clone() { - FileSharingRecord clone = new FileSharingRecord(); - clone.setReadOnly(field_1_readonly); - clone.setPassword(field_2_password); - clone.setUsername(field_3_username_value); - return clone; + return copy(); + } + + @Override + public FileSharingRecord copy() { + return new FileSharingRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/FnGroupCountRecord.java b/src/java/org/apache/poi/hssf/record/FnGroupCountRecord.java index 4258df5e1f..cdae7efe85 100644 --- a/src/java/org/apache/poi/hssf/record/FnGroupCountRecord.java +++ b/src/java/org/apache/poi/hssf/record/FnGroupCountRecord.java @@ -15,35 +15,32 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; /** - * Title: Function Group Count Record<P> - * Description: Number of built in function groups in the current version of the - * Spreadsheet (probably only used on Windoze)<P> - * REFERENCE: PG 315 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) + * umber of built in function groups in the current version of the Spreadsheet (probably only used on Windows) + * * @version 2.0-pre */ - -public final class FnGroupCountRecord - extends StandardRecord -{ - public final static short sid = 0x9c; +public final class FnGroupCountRecord extends StandardRecord { + public static final short sid = 0x9c; /** * suggested default (14 dec) */ - public final static short COUNT = 14; + public static final short COUNT = 14; private short field_1_count; - public FnGroupCountRecord() - { + public FnGroupCountRecord() {} + + public FnGroupCountRecord(FnGroupCountRecord other) { + super(other); + field_1_count = other.field_1_count; } public FnGroupCountRecord(RecordInputStream in) @@ -96,4 +93,9 @@ public final class FnGroupCountRecord { return sid; } + + @Override + public FnGroupCountRecord copy() { + return new FnGroupCountRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/FontRecord.java b/src/java/org/apache/poi/hssf/record/FontRecord.java index cf673397d6..2a3cc2f29f 100644 --- a/src/java/org/apache/poi/hssf/record/FontRecord.java +++ b/src/java/org/apache/poi/hssf/record/FontRecord.java @@ -25,50 +25,68 @@ import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.StringUtil; -/** - * Title: Font Record (0x0031) <p> - * - describes a font in the workbook (index = 0-3,5-infinity - skip 4)<P> - * Description: An element in the Font Table<p> - * REFERENCE: PG 315 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) - */ +/** Describes a font in the workbook */ public final class FontRecord extends StandardRecord { // docs are wrong (0x231 Microsoft Support site article Q184647) - public final static short sid = 0x0031; - public final static short SS_NONE = 0; - public final static short SS_SUPER = 1; - public final static short SS_SUB = 2; - public final static byte U_NONE = 0; - public final static byte U_SINGLE = 1; - public final static byte U_DOUBLE = 2; - public final static byte U_SINGLE_ACCOUNTING = 0x21; - public final static byte U_DOUBLE_ACCOUNTING = 0x22; - // in units of .05 of a point - private short field_1_font_height; - private short field_2_attributes; + public static final short sid = 0x0031; + public static final short SS_NONE = 0; + public static final short SS_SUPER = 1; + public static final short SS_SUB = 2; + public static final byte U_NONE = 0; + public static final byte U_SINGLE = 1; + public static final byte U_DOUBLE = 2; + public static final byte U_SINGLE_ACCOUNTING = 0x21; + public static final byte U_DOUBLE_ACCOUNTING = 0x22; // 0 0x01 - Reserved bit must be 0 - private static final BitField italic = BitFieldFactory.getInstance(0x02); // is this font in italics + // is this font in italics + private static final BitField italic = BitFieldFactory.getInstance(0x02); // 2 0x04 - reserved bit must be 0 - private static final BitField strikeout =BitFieldFactory.getInstance(0x08); // is this font has a line through the center - private static final BitField macoutline = BitFieldFactory.getInstance(0x10); // some weird macintosh thing....but who understands those mac people anyhow - private static final BitField macshadow = BitFieldFactory.getInstance(0x20); // some weird macintosh thing....but who understands those mac people anyhow + // is this font has a line through the center + private static final BitField strikeout = BitFieldFactory.getInstance(0x08); + // some weird macintosh thing....but who understands those mac people anyhow + private static final BitField macoutline = BitFieldFactory.getInstance(0x10); + private static final BitField macshadow = BitFieldFactory.getInstance(0x20); + + // in units of .05 of a point + private short field_1_font_height; + private short field_2_attributes; // 7-6 - reserved bits must be 0 // the rest is unused - private short field_3_color_palette_index; - private short field_4_bold_weight; - private short field_5_super_sub_script; // 00none/01super/02sub - private byte field_6_underline; // 00none/01single/02double/21singleaccounting/22doubleaccounting - private byte field_7_family; // ?? defined by windows api logfont structure? - private byte field_8_charset; // ?? defined by windows api logfont structure? - private byte field_9_zero; // must be 0 + private short field_3_color_palette_index; + private short field_4_bold_weight; + // 00none/01super/02sub + private short field_5_super_sub_script; + // 00none/01single/02double/21singleaccounting/22doubleaccounting + private byte field_6_underline; + // ?? defined by windows api logfont structure? + private byte field_7_family; + // ?? defined by windows api logfont structure? + private byte field_8_charset; + // must be 0 + private byte field_9_zero; /** possibly empty string never <code>null</code> */ - private String field_11_font_name; + private String field_11_font_name; public FontRecord() { } + public FontRecord(FontRecord other) { + super(other); + field_1_font_height = other.field_1_font_height; + field_2_attributes = other.field_2_attributes; + field_3_color_palette_index = other.field_3_color_palette_index; + field_4_bold_weight = other.field_4_bold_weight; + field_5_super_sub_script = other.field_5_super_sub_script; + field_6_underline = other.field_6_underline; + field_7_family = other.field_7_family; + field_8_charset = other.field_8_charset; + field_9_zero = other.field_9_zero; + field_11_font_name = other.field_11_font_name; + } + public FontRecord(RecordInputStream in) { field_1_font_height = in.readShort(); field_2_attributes = in.readShort(); @@ -490,4 +508,9 @@ public final class FontRecord extends StandardRecord { public boolean equals(Object o) { return (o instanceof FontRecord) && sameProperties((FontRecord) o); } + + @Override + public FontRecord copy() { + return new FontRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/FooterRecord.java b/src/java/org/apache/poi/hssf/record/FooterRecord.java index 08ba4f2f13..1c5fa0c825 100644 --- a/src/java/org/apache/poi/hssf/record/FooterRecord.java +++ b/src/java/org/apache/poi/hssf/record/FooterRecord.java @@ -17,18 +17,22 @@ package org.apache.poi.hssf.record; +import org.apache.poi.util.Removal; + /** - * Title: Footer Record (0x0015)<p> - * Description: Specifies the footer for a sheet<p> - * REFERENCE: PG 317 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) + * Specifies the footer for a sheet */ -public final class FooterRecord extends HeaderFooterBase implements Cloneable { - public final static short sid = 0x0015; +public final class FooterRecord extends HeaderFooterBase { + public static final short sid = 0x0015; public FooterRecord(String text) { super(text); } + public FooterRecord(FooterRecord other) { + super(other); + } + public FooterRecord(RecordInputStream in) { super(in); } @@ -47,7 +51,15 @@ public final class FooterRecord extends HeaderFooterBase implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public FooterRecord clone() { - return new FooterRecord(getText()); + return copy(); + } + + @Override + public FooterRecord copy() { + return new FooterRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/FormatRecord.java b/src/java/org/apache/poi/hssf/record/FormatRecord.java index 87410618c2..fc9badf9f0 100644 --- a/src/java/org/apache/poi/hssf/record/FormatRecord.java +++ b/src/java/org/apache/poi/hssf/record/FormatRecord.java @@ -22,30 +22,29 @@ import org.apache.poi.util.LittleEndianConsts; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; +import org.apache.poi.util.Removal; import org.apache.poi.util.StringUtil; /** - * Title: Format Record (0x041E)<p> - * Description: describes a number format -- those goofy strings like $(#,###)<p> - * - * REFERENCE: PG 317 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) + * Describes a number format -- those goofy strings like $(#,###) */ -public final class FormatRecord extends StandardRecord implements Cloneable { +public final class FormatRecord extends StandardRecord { private static final POILogger logger = POILogFactory.getLogger(FormatRecord.class); - public final static short sid = 0x041E; + public static final short sid = 0x041E; private final int field_1_index_code; private final boolean field_3_hasMultibyte; private final String field_4_formatstring; private FormatRecord(FormatRecord other) { + super(other); field_1_index_code = other.field_1_index_code; field_3_hasMultibyte = other.field_3_hasMultibyte; field_4_formatstring = other.field_4_formatstring; } - + public FormatRecord(int indexCode, String fs) { field_1_index_code = indexCode; field_4_formatstring = fs; @@ -114,9 +113,17 @@ public final class FormatRecord extends StandardRecord implements Cloneable { public short getSid() { return sid; } - + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public FormatRecord clone() { + return copy(); + } + + @Override + public FormatRecord copy() { return new FormatRecord(this); } diff --git a/src/java/org/apache/poi/hssf/record/FormulaRecord.java b/src/java/org/apache/poi/hssf/record/FormulaRecord.java index 662be0c630..86a382a3fb 100644 --- a/src/java/org/apache/poi/hssf/record/FormulaRecord.java +++ b/src/java/org/apache/poi/hssf/record/FormulaRecord.java @@ -18,168 +18,28 @@ package org.apache.poi.hssf.record; import org.apache.poi.ss.formula.Formula; -import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.formula.ptg.Ptg; import org.apache.poi.ss.usermodel.CellType; -import org.apache.poi.util.*; +import org.apache.poi.util.BitField; +import org.apache.poi.util.BitFieldFactory; +import org.apache.poi.util.HexDump; +import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * Formula Record (0x0006). - * REFERENCE: PG 317/444 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Jason Height (jheight at chariot dot net dot au) */ -public final class FormulaRecord extends CellRecord implements Cloneable { +public final class FormulaRecord extends CellRecord { - public static final short sid = 0x0006; // docs say 406...because of a bug Microsoft support site article #Q184647) - private static int FIXED_SIZE = 14; // double + short + int + // docs say 406...because of a bug Microsoft support site article #Q184647) + public static final short sid = 0x0006; + // double + short + int + private static final int FIXED_SIZE = 14; private static final BitField alwaysCalc = BitFieldFactory.getInstance(0x0001); private static final BitField calcOnLoad = BitFieldFactory.getInstance(0x0002); private static final BitField sharedFormula = BitFieldFactory.getInstance(0x0008); - /** - * Manages the cached formula result values of other types besides numeric. - * Excel encodes the same 8 bytes that would be field_4_value with various NaN - * values that are decoded/encoded by this class. - */ - static final class SpecialCachedValue { - /** deliberately chosen by Excel in order to encode other values within Double NaNs */ - private static final long BIT_MARKER = 0xFFFF000000000000L; - private static final int VARIABLE_DATA_LENGTH = 6; - private static final int DATA_INDEX = 2; - - // FIXME: can these be merged with {@link CellType}? - // are the numbers specific to the HSSF formula record format or just a poor-man's enum? - public static final int STRING = 0; - public static final int BOOLEAN = 1; - public static final int ERROR_CODE = 2; - public static final int EMPTY = 3; - - private final byte[] _variableData; - - private SpecialCachedValue(byte[] data) { - _variableData = data; - } - - public int getTypeCode() { - return _variableData[0]; - } - - /** - * @return <code>null</code> if the double value encoded by <tt>valueLongBits</tt> - * is a normal (non NaN) double value. - */ - public static SpecialCachedValue create(long valueLongBits) { - if ((BIT_MARKER & valueLongBits) != BIT_MARKER) { - return null; - } - - byte[] result = new byte[VARIABLE_DATA_LENGTH]; - long x = valueLongBits; - for (int i=0; i<VARIABLE_DATA_LENGTH; i++) { - result[i] = (byte) x; - x >>= 8; - } - switch (result[0]) { - case STRING: - case BOOLEAN: - case ERROR_CODE: - case EMPTY: - break; - default: - throw new org.apache.poi.util.RecordFormatException("Bad special value code (" + result[0] + ")"); - } - return new SpecialCachedValue(result); - } - - public void serialize(LittleEndianOutput out) { - out.write(_variableData); - out.writeShort(0xFFFF); - } - - public String formatDebugString() { - return formatValue() + ' ' + HexDump.toHex(_variableData); - } - - private String formatValue() { - int typeCode = getTypeCode(); - switch (typeCode) { - case STRING: - return "<string>"; - case BOOLEAN: - return getDataValue() == 0 ? "FALSE" : "TRUE"; - case ERROR_CODE: - return ErrorEval.getText(getDataValue()); - case EMPTY: - return "<empty>"; - } - return "#error(type=" + typeCode + ")#"; - } - - private int getDataValue() { - return _variableData[DATA_INDEX]; - } - - public static SpecialCachedValue createCachedEmptyValue() { - return create(EMPTY, 0); - } - - public static SpecialCachedValue createForString() { - return create(STRING, 0); - } - - public static SpecialCachedValue createCachedBoolean(boolean b) { - return create(BOOLEAN, b ? 1 : 0); - } - - public static SpecialCachedValue createCachedErrorCode(int errorCode) { - return create(ERROR_CODE, errorCode); - } - - private static SpecialCachedValue create(int code, int data) { - byte[] vd = { - (byte) code, - 0, - (byte) data, - 0, - 0, - 0, - }; - return new SpecialCachedValue(vd); - } - - @Override - public String toString() { - return getClass().getName() + '[' + formatValue() + ']'; - } - - public int getValueType() { - int typeCode = getTypeCode(); - switch (typeCode) { - case STRING: return CellType.STRING.getCode(); - case BOOLEAN: return CellType.BOOLEAN.getCode(); - case ERROR_CODE: return CellType.ERROR.getCode(); - case EMPTY: return CellType.STRING.getCode(); // is this correct? - } - throw new IllegalStateException("Unexpected type id (" + typeCode + ")"); - } - - public boolean getBooleanValue() { - if (getTypeCode() != BOOLEAN) { - throw new IllegalStateException("Not a boolean cached value - " + formatValue()); - } - return getDataValue() != 0; - } - - public int getErrorValue() { - if (getTypeCode() != ERROR_CODE) { - throw new IllegalStateException("Not an error cached value - " + formatValue()); - } - return getDataValue(); - } - } - private double field_4_value; private short field_5_options; /** @@ -193,19 +53,27 @@ public final class FormulaRecord extends CellRecord implements Cloneable { /** * Since the NaN support seems sketchy (different constants) we'll store and spit it out directly */ - private SpecialCachedValue specialCachedValue; + private FormulaSpecialCachedValue specialCachedValue; /** Creates new FormulaRecord */ - public FormulaRecord() { field_8_parsed_expr = Formula.create(Ptg.EMPTY_PTG_ARRAY); } + public FormulaRecord(FormulaRecord other) { + super(other); + field_4_value = other.field_4_value; + field_5_options = other.field_5_options; + field_6_zero = other.field_6_zero; + field_8_parsed_expr = (other.field_8_parsed_expr == null) ? null : new Formula(other.field_8_parsed_expr); + specialCachedValue = (other.specialCachedValue == null) ? null : new FormulaSpecialCachedValue(other.specialCachedValue); + } + public FormulaRecord(RecordInputStream ris) { super(ris); long valueLongBits = ris.readLong(); field_5_options = ris.readShort(); - specialCachedValue = SpecialCachedValue.create(valueLongBits); + specialCachedValue = FormulaSpecialCachedValue.create(valueLongBits); if (specialCachedValue == null) { field_4_value = Double.longBitsToDouble(valueLongBits); } @@ -228,16 +96,16 @@ public final class FormulaRecord extends CellRecord implements Cloneable { } public void setCachedResultTypeEmptyString() { - specialCachedValue = SpecialCachedValue.createCachedEmptyValue(); + specialCachedValue = FormulaSpecialCachedValue.createCachedEmptyValue(); } public void setCachedResultTypeString() { - specialCachedValue = SpecialCachedValue.createForString(); + specialCachedValue = FormulaSpecialCachedValue.createForString(); } public void setCachedResultErrorCode(int errorCode) { - specialCachedValue = SpecialCachedValue.createCachedErrorCode(errorCode); + specialCachedValue = FormulaSpecialCachedValue.createCachedErrorCode(errorCode); } public void setCachedResultBoolean(boolean value) { - specialCachedValue = SpecialCachedValue.createCachedBoolean(value); + specialCachedValue = FormulaSpecialCachedValue.createCachedBoolean(value); } /** * @return <code>true</code> if this {@link FormulaRecord} is followed by a @@ -246,7 +114,7 @@ public final class FormulaRecord extends CellRecord implements Cloneable { */ public boolean hasCachedResultString() { return specialCachedValue != null && - specialCachedValue.getTypeCode() == SpecialCachedValue.STRING; + specialCachedValue.getTypeCode() == FormulaSpecialCachedValue.STRING; } public int getCachedResultType() { @@ -353,12 +221,12 @@ public final class FormulaRecord extends CellRecord implements Cloneable { out.writeInt(field_6_zero); // may as well write original data back so as to minimise differences from original field_8_parsed_expr.serialize(out); } - + @Override protected String getRecordName() { return "FORMULA"; } - + @Override protected void appendValueText(StringBuilder sb) { sb.append(" .value = "); @@ -385,15 +253,16 @@ public final class FormulaRecord extends CellRecord implements Cloneable { } @Override - public FormulaRecord clone() { - FormulaRecord rec = new FormulaRecord(); - copyBaseFields(rec); - rec.field_4_value = field_4_value; - rec.field_5_options = field_5_options; - rec.field_6_zero = field_6_zero; - rec.field_8_parsed_expr = field_8_parsed_expr; - rec.specialCachedValue = specialCachedValue; - return rec; + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public FormulaRecord clone() { + return copy(); + } + + @Override + public FormulaRecord copy() { + return new FormulaRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/FormulaSpecialCachedValue.java b/src/java/org/apache/poi/hssf/record/FormulaSpecialCachedValue.java new file mode 100644 index 0000000000..65cf121fd1 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/FormulaSpecialCachedValue.java @@ -0,0 +1,167 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.util.HexDump; +import org.apache.poi.util.Internal; +import org.apache.poi.util.LittleEndianOutput; + +/** + * Manages the cached formula result values of other types besides numeric. + * Excel encodes the same 8 bytes that would be field_4_value with various NaN + * values that are decoded/encoded by this class. + */ +@Internal +public final class FormulaSpecialCachedValue { + /** deliberately chosen by Excel in order to encode other values within Double NaNs */ + private static final long BIT_MARKER = 0xFFFF000000000000L; + private static final int VARIABLE_DATA_LENGTH = 6; + private static final int DATA_INDEX = 2; + + // FIXME: can these be merged with {@link CellType}? + // are the numbers specific to the HSSF formula record format or just a poor-man's enum? + public static final int STRING = 0; + public static final int BOOLEAN = 1; + public static final int ERROR_CODE = 2; + public static final int EMPTY = 3; + + private final byte[] _variableData; + + FormulaSpecialCachedValue(FormulaSpecialCachedValue other) { + _variableData = (other._variableData == null) ? null : other._variableData.clone(); + } + + private FormulaSpecialCachedValue(byte[] data) { + _variableData = data; + } + + public int getTypeCode() { + return _variableData[0]; + } + + /** + * @return <code>null</code> if the double value encoded by <tt>valueLongBits</tt> + * is a normal (non NaN) double value. + */ + public static FormulaSpecialCachedValue create(long valueLongBits) { + if ((BIT_MARKER & valueLongBits) != BIT_MARKER) { + return null; + } + + byte[] result = new byte[VARIABLE_DATA_LENGTH]; + long x = valueLongBits; + for (int i=0; i<VARIABLE_DATA_LENGTH; i++) { + result[i] = (byte) x; + x >>= 8; + } + switch (result[0]) { + case STRING: + case BOOLEAN: + case ERROR_CODE: + case EMPTY: + break; + default: + throw new org.apache.poi.util.RecordFormatException("Bad special value code (" + result[0] + ")"); + } + return new FormulaSpecialCachedValue(result); + } + + public void serialize(LittleEndianOutput out) { + out.write(_variableData); + out.writeShort(0xFFFF); + } + + public String formatDebugString() { + return formatValue() + ' ' + HexDump.toHex(_variableData); + } + + private String formatValue() { + int typeCode = getTypeCode(); + switch (typeCode) { + case STRING: + return "<string>"; + case BOOLEAN: + return getDataValue() == 0 ? "FALSE" : "TRUE"; + case ERROR_CODE: + return ErrorEval.getText(getDataValue()); + case EMPTY: + return "<empty>"; + } + return "#error(type=" + typeCode + ")#"; + } + + private int getDataValue() { + return _variableData[DATA_INDEX]; + } + + public static FormulaSpecialCachedValue createCachedEmptyValue() { + return create(EMPTY, 0); + } + + public static FormulaSpecialCachedValue createForString() { + return create(STRING, 0); + } + + public static FormulaSpecialCachedValue createCachedBoolean(boolean b) { + return create(BOOLEAN, b ? 1 : 0); + } + + public static FormulaSpecialCachedValue createCachedErrorCode(int errorCode) { + return create(ERROR_CODE, errorCode); + } + + private static FormulaSpecialCachedValue create(int code, int data) { + byte[] vd = { (byte) code, 0, (byte) data, 0, 0, 0, }; + return new FormulaSpecialCachedValue(vd); + } + + @Override + public String toString() { + return getClass().getName() + '[' + formatValue() + ']'; + } + + public int getValueType() { + int typeCode = getTypeCode(); + switch (typeCode) { + case EMPTY: // is this correct? + case STRING: + return CellType.STRING.getCode(); + case BOOLEAN: + return CellType.BOOLEAN.getCode(); + case ERROR_CODE: + return CellType.ERROR.getCode(); + } + throw new IllegalStateException("Unexpected type id (" + typeCode + ")"); + } + + public boolean getBooleanValue() { + if (getTypeCode() != BOOLEAN) { + throw new IllegalStateException("Not a boolean cached value - " + formatValue()); + } + return getDataValue() != 0; + } + + public int getErrorValue() { + if (getTypeCode() != ERROR_CODE) { + throw new IllegalStateException("Not an error cached value - " + formatValue()); + } + return getDataValue(); + } +} diff --git a/src/java/org/apache/poi/hssf/record/FtCblsSubRecord.java b/src/java/org/apache/poi/hssf/record/FtCblsSubRecord.java index 50eb7bf95a..2541636a9d 100644 --- a/src/java/org/apache/poi/hssf/record/FtCblsSubRecord.java +++ b/src/java/org/apache/poi/hssf/record/FtCblsSubRecord.java @@ -22,28 +22,31 @@ import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.RecordFormatException; +import org.apache.poi.util.Removal; /** * This structure appears as part of an Obj record that represents a checkbox or radio button. - * - * @author Yegor Kozlov */ -public final class FtCblsSubRecord extends SubRecord implements Cloneable { - public final static short sid = 0x0C; +public final class FtCblsSubRecord extends SubRecord { + public static final short sid = 0x0C; private static final int ENCODED_SIZE = 20; - private byte[] reserved; + private final byte[] reserved; /** * Construct a new <code>FtCblsSubRecord</code> and * fill its data with the default values */ - public FtCblsSubRecord() - { + public FtCblsSubRecord() { reserved = new byte[ENCODED_SIZE]; } + public FtCblsSubRecord(FtCblsSubRecord other) { + super(other); + reserved = other.reserved.clone(); + } + public FtCblsSubRecord(LittleEndianInput in, int size) { if (size != ENCODED_SIZE) { throw new RecordFormatException("Unexpected size (" + size + ")"); @@ -93,12 +96,16 @@ public final class FtCblsSubRecord extends SubRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public FtCblsSubRecord clone() { - FtCblsSubRecord rec = new FtCblsSubRecord(); - byte[] recdata = new byte[reserved.length]; - System.arraycopy(reserved, 0, recdata, 0, recdata.length); - rec.reserved = recdata; - return rec; + return copy(); + } + + @Override + public FtCblsSubRecord copy() { + return new FtCblsSubRecord(this); } }
\ No newline at end of file diff --git a/src/java/org/apache/poi/hssf/record/FtCfSubRecord.java b/src/java/org/apache/poi/hssf/record/FtCfSubRecord.java index e2fd02ad7e..099dae67e8 100644 --- a/src/java/org/apache/poi/hssf/record/FtCfSubRecord.java +++ b/src/java/org/apache/poi/hssf/record/FtCfSubRecord.java @@ -21,15 +21,16 @@ import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.RecordFormatException; +import org.apache.poi.util.Removal; /** * The FtCf structure specifies the clipboard format of the picture-type Obj record containing this FtCf. */ -public final class FtCfSubRecord extends SubRecord implements Cloneable { - public final static short sid = 0x07; - public final static short length = 0x02; - +public final class FtCfSubRecord extends SubRecord { + public static final short sid = 0x07; + public static final short length = 0x02; + /** * Specifies the format of the picture is an enhanced metafile. */ @@ -39,20 +40,24 @@ public final class FtCfSubRecord extends SubRecord implements Cloneable { * Specifies the format of the picture is a bitmap. */ public static final short BITMAP_BIT = (short)0x0009; - + /** * Specifies the picture is in an unspecified format that is * neither and enhanced metafile nor a bitmap. */ public static final short UNSPECIFIED_BIT = (short)0xFFFF; - + private short flags; /** * Construct a new <code>FtPioGrbitSubRecord</code> and * fill its data with the default values */ - public FtCfSubRecord() { + public FtCfSubRecord() {} + + public FtCfSubRecord(FtCfSubRecord other) { + super(other); + flags = other.flags; } public FtCfSubRecord(LittleEndianInput in, int size) { @@ -99,10 +104,16 @@ public final class FtCfSubRecord extends SubRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public FtCfSubRecord clone() { - FtCfSubRecord rec = new FtCfSubRecord(); - rec.flags = this.flags; - return rec; + return copy(); + } + + @Override + public FtCfSubRecord copy() { + return new FtCfSubRecord(this); } public short getFlags() { diff --git a/src/java/org/apache/poi/hssf/record/FtPioGrbitSubRecord.java b/src/java/org/apache/poi/hssf/record/FtPioGrbitSubRecord.java index 2215145988..6e5845b5cd 100644 --- a/src/java/org/apache/poi/hssf/record/FtPioGrbitSubRecord.java +++ b/src/java/org/apache/poi/hssf/record/FtPioGrbitSubRecord.java @@ -21,27 +21,28 @@ import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.RecordFormatException; +import org.apache.poi.util.Removal; /** * This structure appears as part of an Obj record that represents image display properties. */ -public final class FtPioGrbitSubRecord extends SubRecord implements Cloneable { - public final static short sid = 0x08; - public final static short length = 0x02; - +public final class FtPioGrbitSubRecord extends SubRecord { + public static final short sid = 0x08; + public static final short length = 0x02; + /** - * A bit that specifies whether the picture's aspect ratio is preserved when rendered in + * A bit that specifies whether the picture's aspect ratio is preserved when rendered in * different views (Normal view, Page Break Preview view, Page Layout view and printing). */ public static final int AUTO_PICT_BIT = 1 << 0; /** - * A bit that specifies whether the pictFmla field of the Obj record that contains + * A bit that specifies whether the pictFmla field of the Obj record that contains * this FtPioGrbit specifies a DDE reference. */ public static final int DDE_BIT = 1 << 1; - + /** * A bit that specifies whether this object is expected to be updated on print to * reflect the values in the cell associated with the object. @@ -52,44 +53,48 @@ public final class FtPioGrbitSubRecord extends SubRecord implements Cloneable { * A bit that specifies whether the picture is displayed as an icon. */ public static final int ICON_BIT = 1 << 3; - + /** * A bit that specifies whether this object is an ActiveX control. * It MUST NOT be the case that both fCtl and fDde are equal to 1. */ public static final int CTL_BIT = 1 << 4; - + /** * A bit that specifies whether the object data are stored in an * embedding storage (= 0) or in the controls stream (ctls) (= 1). */ public static final int PRSTM_BIT = 1 << 5; - + /** * A bit that specifies whether this is a camera picture. */ public static final int CAMERA_BIT = 1 << 7; - + /** * A bit that specifies whether this picture's size has been explicitly set. * 0 = picture size has been explicitly set, 1 = has not been set */ public static final int DEFAULT_SIZE_BIT = 1 << 8; - + /** * A bit that specifies whether the OLE server for the object is called * to load the object's data automatically when the parent workbook is opened. */ public static final int AUTO_LOAD_BIT = 1 << 9; - + private short flags; /** * Construct a new <code>FtPioGrbitSubRecord</code> and * fill its data with the default values */ - public FtPioGrbitSubRecord() { + public FtPioGrbitSubRecord() {} + + public FtPioGrbitSubRecord(FtPioGrbitSubRecord other) { + super(other); + flags = other.flags; } public FtPioGrbitSubRecord(LittleEndianInput in, int size) { @@ -110,12 +115,12 @@ public final class FtPioGrbitSubRecord extends SubRecord implements Cloneable { } else { flags &= (0xFFFF ^ bitmask); } - } - + } + public boolean getFlagByBit(int bitmask) { return ((flags & bitmask) != 0); } - + /** * Convert this record to string. * Used by BiffViewer and other utilities. @@ -153,10 +158,16 @@ public final class FtPioGrbitSubRecord extends SubRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public FtPioGrbitSubRecord clone() { - FtPioGrbitSubRecord rec = new FtPioGrbitSubRecord(); - rec.flags = this.flags; - return rec; + return copy(); + } + + @Override + public FtPioGrbitSubRecord copy() { + return new FtPioGrbitSubRecord(this); } public short getFlags() { diff --git a/src/java/org/apache/poi/hssf/record/GridsetRecord.java b/src/java/org/apache/poi/hssf/record/GridsetRecord.java index 570ebe2867..290a8c6a75 100644 --- a/src/java/org/apache/poi/hssf/record/GridsetRecord.java +++ b/src/java/org/apache/poi/hssf/record/GridsetRecord.java @@ -18,28 +18,25 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Gridset Record.<P> - * Description: flag denoting whether the user specified that gridlines are used when - * printing.<P> - * REFERENCE: PG 320 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Glen Stampoultzis (glens at apache.org) - * @author Jason Height (jheight at chariot dot net dot au) + * Flag denoting whether the user specified that gridlines are used when printing. * * @version 2.0-pre */ -public final class GridsetRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x82; +public final class GridsetRecord extends StandardRecord { + public static final short sid = 0x82; public short field_1_gridset_flag; - public GridsetRecord() { + public GridsetRecord() {} + + public GridsetRecord(GridsetRecord other) { + super(other); + field_1_gridset_flag = other.field_1_gridset_flag; } - public GridsetRecord(RecordInputStream in) - { + public GridsetRecord(RecordInputStream in) { field_1_gridset_flag = in.readShort(); } @@ -87,9 +84,15 @@ public final class GridsetRecord extends StandardRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public GridsetRecord clone() { - GridsetRecord rec = new GridsetRecord(); - rec.field_1_gridset_flag = field_1_gridset_flag; - return rec; + return copy(); + } + + @Override + public GridsetRecord copy() { + return new GridsetRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/GroupMarkerSubRecord.java b/src/java/org/apache/poi/hssf/record/GroupMarkerSubRecord.java index 62364bc031..310324f756 100644 --- a/src/java/org/apache/poi/hssf/record/GroupMarkerSubRecord.java +++ b/src/java/org/apache/poi/hssf/record/GroupMarkerSubRecord.java @@ -21,13 +21,14 @@ import org.apache.poi.util.HexDump; import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * ftGmo (0x0006)<p> * The group marker record is used as a position holder for groups. */ -public final class GroupMarkerSubRecord extends SubRecord implements Cloneable { - public final static short sid = 0x0006; +public final class GroupMarkerSubRecord extends SubRecord { + public static final short sid = 0x0006; //arbitrarily selected; may need to increase private static final int MAX_RECORD_LENGTH = 100_000; @@ -41,6 +42,11 @@ public final class GroupMarkerSubRecord extends SubRecord implements Cloneable { reserved = EMPTY_BYTE_ARRAY; } + public GroupMarkerSubRecord(GroupMarkerSubRecord other) { + super(other); + reserved = other.reserved.clone(); + } + public GroupMarkerSubRecord(LittleEndianInput in, int size) { byte[] buf = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH); in.readFully(buf); @@ -74,10 +80,15 @@ public final class GroupMarkerSubRecord extends SubRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public GroupMarkerSubRecord clone() { - GroupMarkerSubRecord rec = new GroupMarkerSubRecord(); - rec.reserved = new byte[reserved.length]; - System.arraycopy(reserved, 0, rec.reserved, 0, reserved.length); - return rec; + return copy(); + } + + @Override + public GroupMarkerSubRecord copy() { + return new GroupMarkerSubRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/GutsRecord.java b/src/java/org/apache/poi/hssf/record/GutsRecord.java index 6f302729db..9f839df36d 100644 --- a/src/java/org/apache/poi/hssf/record/GutsRecord.java +++ b/src/java/org/apache/poi/hssf/record/GutsRecord.java @@ -15,34 +15,41 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Guts Record <P> - * Description: Row/column gutter sizes <P> - * REFERENCE: PG 320 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Jason Height (jheight at chariot dot net dot au) + * Row/column gutter sizes + * * @version 2.0-pre */ -public final class GutsRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x80; - private short field_1_left_row_gutter; // size of the row gutter to the left of the rows - private short field_2_top_col_gutter; // size of the column gutter above the columns - private short field_3_row_level_max; // maximum outline level for row gutters - private short field_4_col_level_max; // maximum outline level for column gutters - - public GutsRecord() - { +public final class GutsRecord extends StandardRecord { + public static final short sid = 0x80; + /** size of the row gutter to the left of the rows */ + private short field_1_left_row_gutter; + /** size of the column gutter above the columns */ + private short field_2_top_col_gutter; + /** maximum outline level for row gutters */ + private short field_3_row_level_max; + /** maximum outline level for column gutters */ + private short field_4_col_level_max; + + public GutsRecord() {} + + public GutsRecord(GutsRecord other) { + super(other); + field_1_left_row_gutter = other.field_1_left_row_gutter; + field_2_top_col_gutter = other.field_2_top_col_gutter; + field_3_row_level_max = other.field_3_row_level_max; + field_4_col_level_max = other.field_4_col_level_max; } - public GutsRecord(RecordInputStream in) - { + public GutsRecord(RecordInputStream in) { field_1_left_row_gutter = in.readShort(); field_2_top_col_gutter = in.readShort(); field_3_row_level_max = in.readShort(); @@ -171,12 +178,15 @@ public final class GutsRecord extends StandardRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public GutsRecord clone() { - GutsRecord rec = new GutsRecord(); - rec.field_1_left_row_gutter = field_1_left_row_gutter; - rec.field_2_top_col_gutter = field_2_top_col_gutter; - rec.field_3_row_level_max = field_3_row_level_max; - rec.field_4_col_level_max = field_4_col_level_max; - return rec; + return copy(); + } + + @Override + public GutsRecord copy() { + return new GutsRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/HCenterRecord.java b/src/java/org/apache/poi/hssf/record/HCenterRecord.java index d050823a6f..f9bd30f881 100644 --- a/src/java/org/apache/poi/hssf/record/HCenterRecord.java +++ b/src/java/org/apache/poi/hssf/record/HCenterRecord.java @@ -17,24 +17,25 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: HCenter record (0x0083)<P> - * Description: whether to center between horizontal margins<P> - * REFERENCE: PG 320 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Jason Height (jheight at chariot dot net dot au) + * Whether to center between horizontal margins + * * @version 2.0-pre */ -public final class HCenterRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x0083; - private short field_1_hcenter; +public final class HCenterRecord extends StandardRecord { + public static final short sid = 0x0083; + private short field_1_hcenter; - public HCenterRecord() { + public HCenterRecord() {} + + public HCenterRecord(HCenterRecord other) { + super(other); + field_1_hcenter = other.field_1_hcenter; } - public HCenterRecord(RecordInputStream in) - { + public HCenterRecord(RecordInputStream in) { field_1_hcenter = in.readShort(); } @@ -43,11 +44,7 @@ public final class HCenterRecord extends StandardRecord implements Cloneable { * @param hc center - t/f */ public void setHCenter(boolean hc) { - if (hc) { - field_1_hcenter = 1; - } else { - field_1_hcenter = 0; - } + field_1_hcenter = (short)(hc ? 1 : 0); } /** @@ -80,9 +77,15 @@ public final class HCenterRecord extends StandardRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public HCenterRecord clone() { - HCenterRecord rec = new HCenterRecord(); - rec.field_1_hcenter = field_1_hcenter; - return rec; + return copy(); + } + + @Override + public HCenterRecord copy() { + return new HCenterRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/HeaderFooterBase.java b/src/java/org/apache/poi/hssf/record/HeaderFooterBase.java index d0e23c73b0..2d31ec6caa 100644 --- a/src/java/org/apache/poi/hssf/record/HeaderFooterBase.java +++ b/src/java/org/apache/poi/hssf/record/HeaderFooterBase.java @@ -22,8 +22,6 @@ import org.apache.poi.util.StringUtil; /** * Common header/footer base class - * - * @author Josh Micich */ public abstract class HeaderFooterBase extends StandardRecord { private boolean field_2_hasMultibyte; @@ -33,6 +31,12 @@ public abstract class HeaderFooterBase extends StandardRecord { setText(text); } + protected HeaderFooterBase(HeaderFooterBase other) { + super(other); + field_2_hasMultibyte = other.field_2_hasMultibyte; + field_3_text = other.field_3_text; + } + protected HeaderFooterBase(RecordInputStream in) { if (in.remaining() > 0) { int field_1_footer_len = in.readShort(); @@ -107,4 +111,7 @@ public abstract class HeaderFooterBase extends StandardRecord { } return 3 + getTextLength() * (field_2_hasMultibyte ? 2 : 1); } + + @Override + public abstract HeaderFooterBase copy(); } diff --git a/src/java/org/apache/poi/hssf/record/HeaderFooterRecord.java b/src/java/org/apache/poi/hssf/record/HeaderFooterRecord.java index 92966385e1..448ae11a06 100644 --- a/src/java/org/apache/poi/hssf/record/HeaderFooterRecord.java +++ b/src/java/org/apache/poi/hssf/record/HeaderFooterRecord.java @@ -17,28 +17,31 @@ package org.apache.poi.hssf.record; -import org.apache.poi.util.HexDump; -import org.apache.poi.util.LittleEndianOutput; - import java.util.Arrays; import java.util.Locale; +import org.apache.poi.util.HexDump; +import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; + /** * The HEADERFOOTER record stores information added in Office Excel 2007 for headers/footers. - * - * @author Yegor Kozlov */ -public final class HeaderFooterRecord extends StandardRecord implements Cloneable { - +public final class HeaderFooterRecord extends StandardRecord { + public static final short sid = 0x089C; private static final byte[] BLANK_GUID = new byte[16]; - public final static short sid = 0x089C; private byte[] _rawData; public HeaderFooterRecord(byte[] data) { _rawData = data; } + public HeaderFooterRecord(HeaderFooterRecord other) { + super(other); + _rawData = (other._rawData == null) ? null : other._rawData.clone(); + } + /** * construct a HeaderFooterRecord record. No fields are interpreted and the record will * be serialized in its original form more or less @@ -58,7 +61,7 @@ public final class HeaderFooterRecord extends StandardRecord implements Cloneabl protected int getDataSize() { return _rawData.length; } - + public short getSid() { return sid; @@ -79,7 +82,7 @@ public final class HeaderFooterRecord extends StandardRecord implements Cloneabl } /** - * @return whether this record belongs to the current sheet + * @return whether this record belongs to the current sheet */ public boolean isCurrentSheet(){ return Arrays.equals(getGuid(), BLANK_GUID); @@ -96,10 +99,17 @@ public final class HeaderFooterRecord extends StandardRecord implements Cloneabl } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public HeaderFooterRecord clone() { - //HACK: do a "cheat" clone, see Record.java for more information - return (HeaderFooterRecord)cloneViaReserialise(); + return copy(); } - - + + @Override + public HeaderFooterRecord copy() { + return new HeaderFooterRecord(this); + } + + } diff --git a/src/java/org/apache/poi/hssf/record/HeaderRecord.java b/src/java/org/apache/poi/hssf/record/HeaderRecord.java index 11fd873ed6..a62f7d807d 100644 --- a/src/java/org/apache/poi/hssf/record/HeaderRecord.java +++ b/src/java/org/apache/poi/hssf/record/HeaderRecord.java @@ -17,21 +17,22 @@ package org.apache.poi.hssf.record; +import org.apache.poi.util.Removal; + /** - * Title: Header Record<P> - * Description: Specifies a header for a sheet<P> - * REFERENCE: PG 321 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Shawn Laubach (slaubach at apache dot org) Modified 3/14/02 - * @author Jason Height (jheight at chariot dot net dot au) + * Specifies a header for a sheet */ -public final class HeaderRecord extends HeaderFooterBase implements Cloneable { - public final static short sid = 0x0014; +public final class HeaderRecord extends HeaderFooterBase { + public static final short sid = 0x0014; public HeaderRecord(String text) { super(text); } + public HeaderRecord(HeaderRecord other) { + super(other); + } + public HeaderRecord(RecordInputStream in) { super(in); } @@ -50,7 +51,15 @@ public final class HeaderRecord extends HeaderFooterBase implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public HeaderRecord clone() { - return new HeaderRecord(getText()); + return copy(); + } + + @Override + public HeaderRecord copy() { + return new HeaderRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/HideObjRecord.java b/src/java/org/apache/poi/hssf/record/HideObjRecord.java index eedcf46051..a411cdb120 100644 --- a/src/java/org/apache/poi/hssf/record/HideObjRecord.java +++ b/src/java/org/apache/poi/hssf/record/HideObjRecord.java @@ -15,35 +15,33 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; /** - * Title: Hide Object Record<P> - * Description: flag defines whether to hide placeholders and object<P> - * REFERENCE: PG 321 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) + * Flag defines whether to hide placeholders and object + * * @version 2.0-pre */ +public final class HideObjRecord extends StandardRecord { + public static final short sid = 0x8d; + public static final short HIDE_ALL = 2; + public static final short SHOW_PLACEHOLDERS = 1; + public static final short SHOW_ALL = 0; -public final class HideObjRecord - extends StandardRecord -{ - public final static short sid = 0x8d; - public final static short HIDE_ALL = 2; - public final static short SHOW_PLACEHOLDERS = 1; - public final static short SHOW_ALL = 0; - private short field_1_hide_obj; + private short field_1_hide_obj; - public HideObjRecord() - { + public HideObjRecord() {} + + public HideObjRecord(HideObjRecord other) { + super(other); + field_1_hide_obj = other.field_1_hide_obj; } - public HideObjRecord(RecordInputStream in) - { + public HideObjRecord(RecordInputStream in) { field_1_hide_obj = in.readShort(); } @@ -98,4 +96,9 @@ public final class HideObjRecord { return sid; } + + @Override + public HideObjRecord copy() { + return new HideObjRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/HorizontalPageBreakRecord.java b/src/java/org/apache/poi/hssf/record/HorizontalPageBreakRecord.java index ff034ef556..bb37565c91 100644 --- a/src/java/org/apache/poi/hssf/record/HorizontalPageBreakRecord.java +++ b/src/java/org/apache/poi/hssf/record/HorizontalPageBreakRecord.java @@ -17,21 +17,24 @@ package org.apache.poi.hssf.record; -import java.util.Iterator; +import org.apache.poi.util.Removal; /** * HorizontalPageBreak (0x001B) record that stores page breaks at rows - * + * * @see PageBreakRecord */ -public final class HorizontalPageBreakRecord extends PageBreakRecord implements Cloneable { +public final class HorizontalPageBreakRecord extends PageBreakRecord { public static final short sid = 0x001B; /** * Creates an empty horizontal page break record */ - public HorizontalPageBreakRecord() { + public HorizontalPageBreakRecord() {} + + public HorizontalPageBreakRecord(HorizontalPageBreakRecord other) { + super(other); } /** @@ -46,13 +49,15 @@ public final class HorizontalPageBreakRecord extends PageBreakRecord implements } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public PageBreakRecord clone() { - PageBreakRecord result = new HorizontalPageBreakRecord(); - Iterator<Break> iterator = getBreaksIterator(); - while (iterator.hasNext()) { - Break original = iterator.next(); - result.addBreak(original.main, original.subFrom, original.subTo); - } - return result; + return copy(); + } + + @Override + public HorizontalPageBreakRecord copy() { + return new HorizontalPageBreakRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java b/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java index e7098423e3..ae6ae086a7 100644 --- a/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java +++ b/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java @@ -27,6 +27,7 @@ import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.apache.poi.util.RecordFormatException; +import org.apache.poi.util.Removal; import org.apache.poi.util.StringUtil; /** @@ -34,13 +35,14 @@ import org.apache.poi.util.StringUtil; * from the Excel-97 format. * Supports only external links for now (eg http://) */ -public final class HyperlinkRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x01B8; +public final class HyperlinkRecord extends StandardRecord { + public static final short sid = 0x01B8; private static POILogger logger = POILogFactory.getLogger(HyperlinkRecord.class); //arbitrarily selected; may need to increase private static final int MAX_RECORD_LENGTH = 100_000; + // TODO: replace with ClassID static final class GUID { /* * this class is currently only used here, but could be moved to a @@ -61,6 +63,13 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { */ private final long _d4; + public GUID(GUID other) { + _d1 = other._d1; + _d2 = other._d2; + _d3 = other._d3; + _d4 = other._d4; + } + public GUID(LittleEndianInput in) { this(in.readInt(), in.readUShort(), in.readUShort(), in.readLong()); } @@ -199,24 +208,24 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { } } - /** + /* * Link flags */ - static final int HLINK_URL = 0x01; // File link or URL. - static final int HLINK_ABS = 0x02; // Absolute path. - static final int HLINK_LABEL = 0x14; // Has label/description. + static final int HLINK_URL = 0x01; // File link or URL. + static final int HLINK_ABS = 0x02; // Absolute path. + static final int HLINK_LABEL = 0x14; // Has label/description. /** Place in worksheet. If set, the {@link #_textMark} field will be present */ - static final int HLINK_PLACE = 0x08; + static final int HLINK_PLACE = 0x08; private static final int HLINK_TARGET_FRAME = 0x80; // has 'target frame' private static final int HLINK_UNC_PATH = 0x100; // has UNC path - final static GUID STD_MONIKER = GUID.parse("79EAC9D0-BAF9-11CE-8C82-00AA004BA90B"); - final static GUID URL_MONIKER = GUID.parse("79EAC9E0-BAF9-11CE-8C82-00AA004BA90B"); - final static GUID FILE_MONIKER = GUID.parse("00000303-0000-0000-C000-000000000046"); + static final GUID STD_MONIKER = GUID.parse("79EAC9D0-BAF9-11CE-8C82-00AA004BA90B"); + static final GUID URL_MONIKER = GUID.parse("79EAC9E0-BAF9-11CE-8C82-00AA004BA90B"); + static final GUID FILE_MONIKER = GUID.parse("00000303-0000-0000-C000-000000000046"); /** expected Tail of a URL link */ - private final static byte[] URL_TAIL = HexRead.readFromString("79 58 81 F4 3B 1D 7F 48 AF 2C 82 5D C4 85 27 63 00 00 00 00 A5 AB 00 00"); + private static final byte[] URL_TAIL = HexRead.readFromString("79 58 81 F4 3B 1D 7F 48 AF 2C 82 5D C4 85 27 63 00 00 00 00 A5 AB 00 00"); /** expected Tail of a file link */ - private final static byte[] FILE_TAIL = HexRead.readFromString("FF FF AD DE 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"); + private static final byte[] FILE_TAIL = HexRead.readFromString("FF FF AD DE 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"); private static final int TAIL_SIZE = FILE_TAIL.length; @@ -246,17 +255,31 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { * This field is optional. If present, the {@link #HLINK_PLACE} must be set. */ private String _textMark; - + private byte[] _uninterpretedTail; /** * Create a new hyperlink */ - public HyperlinkRecord() - { + public HyperlinkRecord() {} + + public HyperlinkRecord(HyperlinkRecord other) { + super(other); + _range = (other._range == null) ? null : other._range.copy(); + _guid = (other._guid == null) ? null : new GUID(other._guid); + _fileOpts = other._fileOpts; + _linkOpts = other._linkOpts; + _label = other._label; + _targetFrame = other._targetFrame; + _moniker = (other._moniker == null) ? null : new GUID(other._moniker); + _shortFilename = other._shortFilename; + _address = other._address; + _textMark = other._textMark; + _uninterpretedTail = (other._uninterpretedTail == null) ? null : other._uninterpretedTail.clone(); } + /** * @return the 0-based column of the first cell that contains this hyperlink */ @@ -266,7 +289,7 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { /** * Set the first column (zero-based) of the range that contains this hyperlink - * + * * @param firstCol the first column (zero-based) */ public void setFirstColumn(int firstCol) { @@ -282,7 +305,7 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { /** * Set the last column (zero-based) of the range that contains this hyperlink - * + * * @param lastCol the last column (zero-based) */ public void setLastColumn(int lastCol) { @@ -298,7 +321,7 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { /** * Set the first row (zero-based) of the range that contains this hyperlink - * + * * @param firstRow the first row (zero-based) */ public void setFirstRow(int firstRow) { @@ -314,7 +337,7 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { /** * Set the last row (zero-based) of the range that contains this hyperlink - * + * * @param lastRow the last row (zero-based) */ public void setLastRow(int lastRow) { @@ -423,7 +446,7 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { /** * Link options. Must be a combination of HLINK_* constants. * For testing only - * + * * @return Link options */ int getLinkOptions(){ @@ -541,7 +564,7 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { } if (in.remaining() > 0) { - logger.log(POILogger.WARN, + logger.log(POILogger.WARN, "Hyperlink data remains: " + in.remaining() + " : " +HexDump.toHex(in.readRemainder()) ); @@ -699,31 +722,31 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { /** * Based on the link options, is this a url? - * + * * @return true, if this is a url link */ public boolean isUrlLink() { - return (_linkOpts & HLINK_URL) > 0 + return (_linkOpts & HLINK_URL) > 0 && (_linkOpts & HLINK_ABS) > 0; } /** * Based on the link options, is this a file? - * + * * @return true, if this is a file link */ public boolean isFileLink() { - return (_linkOpts & HLINK_URL) > 0 + return (_linkOpts & HLINK_URL) > 0 && (_linkOpts & HLINK_ABS) == 0; } /** * Based on the link options, is this a document? - * + * * @return true, if this is a docment link */ public boolean isDocumentLink() { - return (_linkOpts & HLINK_PLACE) > 0; + return (_linkOpts & HLINK_PLACE) > 0; } - + /** * Initialize a new url link */ @@ -766,19 +789,15 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public HyperlinkRecord clone() { - HyperlinkRecord rec = new HyperlinkRecord(); - rec._range = _range.copy(); - rec._guid = _guid; - rec._linkOpts = _linkOpts; - rec._fileOpts = _fileOpts; - rec._label = _label; - rec._address = _address; - rec._moniker = _moniker; - rec._shortFilename = _shortFilename; - rec._targetFrame = _targetFrame; - rec._textMark = _textMark; - rec._uninterpretedTail = _uninterpretedTail; - return rec; + return copy(); + } + + @Override + public HyperlinkRecord copy() { + return new HyperlinkRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/IndexRecord.java b/src/java/org/apache/poi/hssf/record/IndexRecord.java index 0e8997dc19..955232d44e 100644 --- a/src/java/org/apache/poi/hssf/record/IndexRecord.java +++ b/src/java/org/apache/poi/hssf/record/IndexRecord.java @@ -20,27 +20,29 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.IntList; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.RecordFormatException; +import org.apache.poi.util.Removal; /** - * Title: Index Record (0x020B)<p> - * Description: Occurs right after BOF, tells you where the DBCELL records are for a sheet - * Important for locating cells<p> - * - * REFERENCE: PG 323 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) + * Occurs right after BOF, tells you where the DBCELL records are for a sheet Important for locating cells */ -public final class IndexRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x020B; +public final class IndexRecord extends StandardRecord { + public static final short sid = 0x020B; private int field_2_first_row; // first row on the sheet private int field_3_last_row_add1; // last row private int field_4_zero; // supposed to be zero private IntList field_5_dbcells; // array of offsets to DBCELL records - public IndexRecord() - { + public IndexRecord() {} + + public IndexRecord(IndexRecord other) { + super(other); + field_2_first_row = other.field_2_first_row; + field_3_last_row_add1 = other.field_3_last_row_add1; + field_4_zero = other.field_4_zero; + field_5_dbcells = (other.field_5_dbcells == null) ? null : new IntList(other.field_5_dbcells); } - public IndexRecord(RecordInputStream in) - { + public IndexRecord(RecordInputStream in) { int field_1_zero = in.readInt(); if (field_1_zero != 0) { throw new RecordFormatException("Expected zero for field 1 but got " + field_1_zero); @@ -48,7 +50,7 @@ public final class IndexRecord extends StandardRecord implements Cloneable { field_2_first_row = in.readInt(); field_3_last_row_add1 = in.readInt(); field_4_zero = in.readInt(); - + int nCells = in.remaining() / 4; field_5_dbcells = new IntList(nCells); for(int i=0; i<nCells; i++) { @@ -139,14 +141,14 @@ public final class IndexRecord extends StandardRecord implements Cloneable { return 16 // 4 ints + getNumDbcells() * 4; } - - /** + + /** * @param blockCount the number of blocks to be indexed * @return the size of an IndexRecord when it needs to index the specified number of blocks */ public static int getRecordSizeForBlockCount(int blockCount) { return 20 + 4 * blockCount; - } + } @Override public short getSid() { @@ -154,13 +156,15 @@ public final class IndexRecord extends StandardRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public IndexRecord clone() { - IndexRecord rec = new IndexRecord(); - rec.field_2_first_row = field_2_first_row; - rec.field_3_last_row_add1 = field_3_last_row_add1; - rec.field_4_zero = field_4_zero; - rec.field_5_dbcells = new IntList(); - rec.field_5_dbcells.addAll(field_5_dbcells); - return rec; + return copy(); + } + + @Override + public IndexRecord copy() { + return new IndexRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/InterfaceEndRecord.java b/src/java/org/apache/poi/hssf/record/InterfaceEndRecord.java index 1ac28a4b7d..472f7d76df 100644 --- a/src/java/org/apache/poi/hssf/record/InterfaceEndRecord.java +++ b/src/java/org/apache/poi/hssf/record/InterfaceEndRecord.java @@ -21,11 +21,7 @@ import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.RecordFormatException; /** - * Title: Interface End Record (0x00E2)<P> - * Description: Shows where the Interface Records end (MMS) - * (has no fields)<P> - * REFERENCE: PG 324 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) + * Shows where the Interface Records ends (MMS) */ public final class InterfaceEndRecord extends StandardRecord { @@ -61,4 +57,9 @@ public final class InterfaceEndRecord extends StandardRecord { public short getSid() { return sid; } + + @Override + public InterfaceEndRecord copy() { + return instance; + } } diff --git a/src/java/org/apache/poi/hssf/record/InterfaceHdrRecord.java b/src/java/org/apache/poi/hssf/record/InterfaceHdrRecord.java index eda3cd1f0c..42b2ae3a58 100644 --- a/src/java/org/apache/poi/hssf/record/InterfaceHdrRecord.java +++ b/src/java/org/apache/poi/hssf/record/InterfaceHdrRecord.java @@ -21,19 +21,22 @@ import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; /** - * Title: Interface Header Record (0x00E1)<P> - * Description: Defines the beginning of Interface records (MMS)<P> - * REFERENCE: PG 324 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) + * Defines the beginning of Interface records (MMS) */ public final class InterfaceHdrRecord extends StandardRecord { - public final static short sid = 0x00E1; - private final int _codepage; + public static final short sid = 0x00E1; /** * suggested (and probably correct) default */ - public final static int CODEPAGE = 0x04B0; + public static final int CODEPAGE = 0x04B0; + + private final int _codepage; + + public InterfaceHdrRecord(InterfaceHdrRecord other) { + super(other); + _codepage = other._codepage; + } public InterfaceHdrRecord(int codePage) { _codepage = codePage; @@ -63,4 +66,9 @@ public final class InterfaceHdrRecord extends StandardRecord { public short getSid() { return sid; } + + @Override + public InterfaceHdrRecord copy() { + return new InterfaceHdrRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/IterationRecord.java b/src/java/org/apache/poi/hssf/record/IterationRecord.java index ca018c3e78..3636175aa2 100644 --- a/src/java/org/apache/poi/hssf/record/IterationRecord.java +++ b/src/java/org/apache/poi/hssf/record/IterationRecord.java @@ -21,28 +21,30 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Iteration Record (0x0011)<p> - * Description: Tells whether to iterate over formula calculations or not - * (if a formula is dependent upon another formula's result) - * (odd feature for something that can only have 32 elements in - * a formula!)<p> - * REFERENCE: PG 325 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) + * Tells whether to iterate over formula calculations or not. + * If a formula is dependent upon another formula's result. + * (odd feature for something that can only have 32 elements in a formula!) */ -public final class IterationRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x0011; +public final class IterationRecord extends StandardRecord { + public static final short sid = 0x0011; private static final BitField iterationOn = BitFieldFactory.getInstance(0x0001); private int _flags; + public IterationRecord(IterationRecord other) { + super(other); + _flags = other._flags; + } + public IterationRecord(boolean iterateOn) { _flags = iterationOn.setBoolean(0, iterateOn); } - public IterationRecord(RecordInputStream in) - { + public IterationRecord(RecordInputStream in) { _flags = in.readShort(); } @@ -85,7 +87,15 @@ public final class IterationRecord extends StandardRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public IterationRecord clone() { - return new IterationRecord(getIteration()); + return copy(); + } + + @Override + public IterationRecord copy() { + return new IterationRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/LabelRecord.java b/src/java/org/apache/poi/hssf/record/LabelRecord.java index 42fb7be829..b87a5fcc67 100644 --- a/src/java/org/apache/poi/hssf/record/LabelRecord.java +++ b/src/java/org/apache/poi/hssf/record/LabelRecord.java @@ -21,36 +21,43 @@ import org.apache.poi.util.HexDump; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.apache.poi.util.RecordFormatException; +import org.apache.poi.util.Removal; /** * Label Record (0x0204) - read only support for strings stored directly in the cell... - * Don't use this (except to read), use LabelSST instead <P> - * REFERENCE: PG 325 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) - * + * Don't use this (except to read), use LabelSST instead + * * @see org.apache.poi.hssf.record.LabelSSTRecord */ -public final class LabelRecord extends Record implements CellValueRecordInterface, Cloneable { - private final static POILogger logger = POILogFactory.getLogger(LabelRecord.class); +public final class LabelRecord extends Record implements CellValueRecordInterface { + private static final POILogger logger = POILogFactory.getLogger(LabelRecord.class); - public final static short sid = 0x0204; + public static final short sid = 0x0204; - private int field_1_row; - private short field_2_column; - private short field_3_xf_index; - private short field_4_string_len; - private byte field_5_unicode_flag; - private String field_6_value; + private int field_1_row; + private short field_2_column; + private short field_3_xf_index; + private short field_4_string_len; + private byte field_5_unicode_flag; + private String field_6_value; /** Creates new LabelRecord */ - public LabelRecord() - { + public LabelRecord() {} + + public LabelRecord(LabelRecord other) { + super(other); + field_1_row = other.field_1_row; + field_2_column = other.field_2_column; + field_3_xf_index = other.field_3_xf_index; + field_4_string_len = other.field_4_string_len; + field_5_unicode_flag = other.field_5_unicode_flag; + field_6_value = other.field_6_value; } /** * @param in the RecordInputstream to read the record from */ - public LabelRecord(RecordInputStream in) - { + public LabelRecord(RecordInputStream in) { field_1_row = in.readUShort(); field_2_column = in.readShort(); field_3_xf_index = in.readShort(); @@ -182,14 +189,15 @@ public final class LabelRecord extends Record implements CellValueRecordInterfac } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public LabelRecord clone() { - LabelRecord rec = new LabelRecord(); - rec.field_1_row = field_1_row; - rec.field_2_column = field_2_column; - rec.field_3_xf_index = field_3_xf_index; - rec.field_4_string_len = field_4_string_len; - rec.field_5_unicode_flag = field_5_unicode_flag; - rec.field_6_value = field_6_value; - return rec; + return copy(); + } + + @Override + public LabelRecord copy() { + return new LabelRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/LabelSSTRecord.java b/src/java/org/apache/poi/hssf/record/LabelSSTRecord.java index 80bd99cfc1..00ca0231b2 100644 --- a/src/java/org/apache/poi/hssf/record/LabelSSTRecord.java +++ b/src/java/org/apache/poi/hssf/record/LabelSSTRecord.java @@ -19,18 +19,20 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Label SST Record<P> - * Description: Refers to a string in the shared string table and is a column value.<P> - * REFERENCE: PG 325 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) + * Refers to a string in the shared string table and is a column value. */ -public final class LabelSSTRecord extends CellRecord implements Cloneable { - public final static short sid = 0xfd; +public final class LabelSSTRecord extends CellRecord { + public static final short sid = 0xfd; private int field_4_sst_index; - public LabelSSTRecord() { - // fields uninitialised + public LabelSSTRecord() {} + + public LabelSSTRecord(LabelSSTRecord other) { + super(other); + field_4_sst_index = other.field_4_sst_index; } public LabelSSTRecord(RecordInputStream in) { @@ -58,7 +60,7 @@ public final class LabelSSTRecord extends CellRecord implements Cloneable { public int getSSTIndex() { return field_4_sst_index; } - + @Override protected String getRecordName() { return "LABELSST"; @@ -85,10 +87,15 @@ public final class LabelSSTRecord extends CellRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public LabelSSTRecord clone() { - LabelSSTRecord rec = new LabelSSTRecord(); - copyBaseFields(rec); - rec.field_4_sst_index = field_4_sst_index; - return rec; + return copy(); + } + + @Override + public LabelSSTRecord copy() { + return new LabelSSTRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/LbsDataSubRecord.java b/src/java/org/apache/poi/hssf/record/LbsDataSubRecord.java index 1f564677bb..e2f7e045a8 100644 --- a/src/java/org/apache/poi/hssf/record/LbsDataSubRecord.java +++ b/src/java/org/apache/poi/hssf/record/LbsDataSubRecord.java @@ -16,11 +16,13 @@ ==================================================================== */ package org.apache.poi.hssf.record; +import org.apache.poi.common.Duplicatable; import org.apache.poi.ss.formula.ptg.Ptg; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.RecordFormatException; +import org.apache.poi.util.Removal; import org.apache.poi.util.StringUtil; /** @@ -89,6 +91,24 @@ public class LbsDataSubRecord extends SubRecord { */ private boolean[] _bsels; + LbsDataSubRecord() {} + + public LbsDataSubRecord(LbsDataSubRecord other) { + super(other); + _cbFContinued = other._cbFContinued; + _unknownPreFormulaInt = other._unknownPreFormulaInt; + _linkPtg = (other._linkPtg == null) ? null : other._linkPtg.copy(); + _unknownPostFormulaByte = other._unknownPostFormulaByte; + _cLines = other._cLines; + _iSel = other._iSel; + _flags = other._flags; + _idEdit = other._idEdit; + _dropData = (other._dropData == null) ? null : other._dropData.copy(); + _rgLines = (other._rgLines == null) ? null : other._rgLines.clone(); + _bsels = (other._bsels == null) ? null : other._bsels.clone(); + } + + /** * @param in the stream to read data from * @param cbFContinued the seconf short in the record header @@ -154,10 +174,6 @@ public class LbsDataSubRecord extends SubRecord { } - LbsDataSubRecord(){ - - } - /** * * @return a new instance of LbsDataSubRecord to construct auto-filters @@ -259,9 +275,16 @@ public class LbsDataSubRecord extends SubRecord { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public LbsDataSubRecord clone() { - // TODO: is immutable ??? - return this; + return copy(); + } + + @Override + public LbsDataSubRecord copy() { + return new LbsDataSubRecord(this); } @Override @@ -303,7 +326,7 @@ public class LbsDataSubRecord extends SubRecord { /** * This structure specifies properties of the dropdown list control */ - public static class LbsDropData { + public static class LbsDropData implements Duplicatable { /** * Combo dropdown control */ @@ -318,7 +341,7 @@ public class LbsDataSubRecord extends SubRecord { public static final int STYLE_COMBO_SIMPLE_DROPDOWN = 2; /** - * An unsigned integer that specifies the style of this dropdown. + * An unsigned integer that specifies the style of this dropdown. */ private int _wStyle; @@ -343,12 +366,20 @@ public class LbsDataSubRecord extends SubRecord { */ private Byte _unused; - public LbsDropData(){ + public LbsDropData() { _str = ""; _unused = 0; } - public LbsDropData(LittleEndianInput in){ + public LbsDropData(LbsDropData other) { + _wStyle = other._wStyle; + _cLine = other._cLine; + _dxMin = other._dxMin; + _str = other._str; + _unused = other._unused; + } + + public LbsDropData(LittleEndianInput in) { _wStyle = in.readUShort(); _cLine = in.readUShort(); _dxMin = in.readUShort(); @@ -367,7 +398,7 @@ public class LbsDataSubRecord extends SubRecord { * <li>1: Combo Edit dropdown control</li> * <li>2: Simple dropdown control (just the dropdown button)</li> * </ul> - * + * * @param style the style - see possible values */ public void setStyle(int style){ @@ -376,7 +407,7 @@ public class LbsDataSubRecord extends SubRecord { /** * Set the number of lines to be displayed in the dropdown. - * + * * @param num the number of lines to be displayed in the dropdown */ public void setNumLines(int num){ @@ -417,5 +448,10 @@ public class LbsDataSubRecord extends SubRecord { return sb.toString(); } + + @Override + public LbsDropData copy() { + return new LbsDropData(this); + } } } diff --git a/src/java/org/apache/poi/hssf/record/LeftMarginRecord.java b/src/java/org/apache/poi/hssf/record/LeftMarginRecord.java index a2c00b07d6..a3ce5754bf 100644 --- a/src/java/org/apache/poi/hssf/record/LeftMarginRecord.java +++ b/src/java/org/apache/poi/hssf/record/LeftMarginRecord.java @@ -18,18 +18,23 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * Record for the left margin. */ -public final class LeftMarginRecord extends StandardRecord implements Margin, Cloneable { - public final static short sid = 0x0026; +public final class LeftMarginRecord extends StandardRecord implements Margin { + public static final short sid = 0x0026; private double field_1_margin; - public LeftMarginRecord() { } + public LeftMarginRecord() {} - public LeftMarginRecord(RecordInputStream in) - { + public LeftMarginRecord(LeftMarginRecord other) { + super(other); + field_1_margin = other.field_1_margin; + } + + public LeftMarginRecord(RecordInputStream in) { field_1_margin = in.readDouble(); } @@ -70,9 +75,15 @@ public final class LeftMarginRecord extends StandardRecord implements Margin, Cl } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public LeftMarginRecord clone() { - LeftMarginRecord rec = new LeftMarginRecord(); - rec.field_1_margin = this.field_1_margin; - return rec; + return copy(); + } + + @Override + public LeftMarginRecord copy() { + return new LeftMarginRecord(this); } -}
\ No newline at end of file +}
\ No newline at end of file diff --git a/src/java/org/apache/poi/hssf/record/MMSRecord.java b/src/java/org/apache/poi/hssf/record/MMSRecord.java index e016ef4581..a6356ac2c5 100644 --- a/src/java/org/apache/poi/hssf/record/MMSRecord.java +++ b/src/java/org/apache/poi/hssf/record/MMSRecord.java @@ -15,38 +15,36 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; /** - * Title: MMS Record<P> - * Description: defines how many add menu and del menu options are stored - * in the file. Should always be set to 0 for HSSF workbooks<P> - * REFERENCE: PG 328 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) + * defines how many add menu and del menu options are stored in the file. + * Should always be set to 0 for HSSF workbooks. + * * @version 2.0-pre */ -public final class MMSRecord - extends StandardRecord -{ - public final static short sid = 0xC1; - private byte field_1_addMenuCount; // = 0; - private byte field_2_delMenuCount; // = 0; +public final class MMSRecord extends StandardRecord { + public static final short sid = 0xC1; + private byte field_1_addMenuCount; + private byte field_2_delMenuCount; - public MMSRecord() - { + public MMSRecord() {} + + public MMSRecord(MMSRecord other) { + field_1_addMenuCount = other.field_1_addMenuCount; + field_2_delMenuCount = other.field_2_delMenuCount; } - public MMSRecord(RecordInputStream in) - { + public MMSRecord(RecordInputStream in) { if (in.remaining()==0) { return; } - + field_1_addMenuCount = in.readByte(); field_2_delMenuCount = in.readByte(); } @@ -117,4 +115,9 @@ public final class MMSRecord { return sid; } + + @Override + public MMSRecord copy() { + return new MMSRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/MergeCellsRecord.java b/src/java/org/apache/poi/hssf/record/MergeCellsRecord.java index c71cbb2b66..1b71f9aa99 100644 --- a/src/java/org/apache/poi/hssf/record/MergeCellsRecord.java +++ b/src/java/org/apache/poi/hssf/record/MergeCellsRecord.java @@ -17,22 +17,33 @@ package org.apache.poi.hssf.record; +import java.util.stream.Stream; + import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddressList; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Merged Cells Record (0x00E5)<p> - * - * Description: Optional record defining a square area of cells to "merged" into one cell. + * Optional record defining a square area of cells to "merged" into one cell. */ -public final class MergeCellsRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x00E5; - /** sometimes the regions array is shared with other MergedCellsRecords */ +public final class MergeCellsRecord extends StandardRecord { + public static final short sid = 0x00E5; + + /** sometimes the regions array is shared with other MergedCellsRecords */ private final CellRangeAddress[] _regions; private final int _startIndex; private final int _numberOfRegions; + public MergeCellsRecord(MergeCellsRecord other) { + super(other); + _regions = (other._regions == null) ? null + : Stream.of(other._regions).map(CellRangeAddress::copy).toArray(CellRangeAddress[]::new); + _startIndex = other._startIndex; + _numberOfRegions = other._numberOfRegions; + } + + public MergeCellsRecord(CellRangeAddress[] regions, int startIndex, int numberOfRegions) { _regions = regions; _startIndex = startIndex; @@ -63,7 +74,7 @@ public final class MergeCellsRecord extends StandardRecord implements Cloneable /** * @param index the n-th MergedRegion - * + * * @return MergedRegion at the given index representing the area that is Merged (r1,c1 - r2,c2) */ public CellRangeAddress getAreaAt(int index) { @@ -107,12 +118,15 @@ public final class MergeCellsRecord extends StandardRecord implements Cloneable } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public MergeCellsRecord clone() { - int nRegions = _numberOfRegions; - CellRangeAddress[] clonedRegions = new CellRangeAddress[nRegions]; - for (int i = 0; i < clonedRegions.length; i++) { - clonedRegions[i] = _regions[_startIndex + i].copy(); - } - return new MergeCellsRecord(clonedRegions, 0, nRegions); + return copy(); + } + + @Override + public MergeCellsRecord copy() { + return new MergeCellsRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/MulBlankRecord.java b/src/java/org/apache/poi/hssf/record/MulBlankRecord.java index de5f1e1141..1c05a02e9a 100644 --- a/src/java/org/apache/poi/hssf/record/MulBlankRecord.java +++ b/src/java/org/apache/poi/hssf/record/MulBlankRecord.java @@ -18,17 +18,15 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Multiple Blank cell record(0x00BE)<p> - * Description: Represents a set of columns in a row with no value but with styling.<p> + * Represents a set of columns in a row with no value but with styling. * - * REFERENCE: PG 329 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) - * * @see BlankRecord */ public final class MulBlankRecord extends StandardRecord { - public final static short sid = 0x00BE; + public static final short sid = 0x00BE; private final int _row; private final int _firstCol; @@ -55,7 +53,7 @@ public final class MulBlankRecord extends StandardRecord { public int getFirstColumn() { return _firstCol; } - + /** * @return ending column (last cell this holds in the row). Zero based */ @@ -122,8 +120,8 @@ public final class MulBlankRecord extends StandardRecord { out.writeShort(_row); out.writeShort(_firstCol); int nItems = _xfs.length; - for (int i = 0; i < nItems; i++) { - out.writeShort(_xfs[i]); + for (short xf : _xfs) { + out.writeShort(xf); } out.writeShort(_lastCol); } @@ -134,7 +132,15 @@ public final class MulBlankRecord extends StandardRecord { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public MulBlankRecord clone() { + return copy(); + } + + @Override + public MulBlankRecord copy() { // immutable - so OK to return this return this; } diff --git a/src/java/org/apache/poi/hssf/record/MulRKRecord.java b/src/java/org/apache/poi/hssf/record/MulRKRecord.java index 30aa1e2a28..9e3e144532 100644 --- a/src/java/org/apache/poi/hssf/record/MulRKRecord.java +++ b/src/java/org/apache/poi/hssf/record/MulRKRecord.java @@ -23,18 +23,15 @@ import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.RecordFormatException; /** - * MULRK (0x00BD)<p> - * * Used to store multiple RK numbers on a row. 1 MulRk = Multiple Cell values. - * HSSF just converts this into multiple NUMBER records. READ-ONLY SUPPORT!<P> - * REFERENCE: PG 330 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) - * + * HSSF just converts this into multiple NUMBER records. READ-ONLY SUPPORT! + * * @since 2.0-pre */ public final class MulRKRecord extends StandardRecord { - public final static short sid = 0x00BD; + public static final short sid = 0x00BD; - private final int field_1_row; + private final int field_1_row; private final short field_2_first_col; private final RkRec[] field_3_rks; private final short field_4_last_col; @@ -69,9 +66,9 @@ public final class MulRKRecord extends StandardRecord { /** * returns the xf index for column (coffset = column - field_2_first_col) - * + * * @param coffset the coffset = column - field_2_first_col - * + * * @return the XF index for the column */ public short getXFAt(int coffset) { @@ -80,9 +77,9 @@ public final class MulRKRecord extends StandardRecord { /** * returns the rk number for column (coffset = column - field_2_first_col) - * + * * @param coffset the coffset = column - field_2_first_col - * + * * @return the value (decoded into a double) */ public double getRKNumberAt(int coffset) { @@ -151,4 +148,10 @@ public final class MulRKRecord extends StandardRecord { return retval; } } + + @Override + public MulRKRecord copy() { + // immutable - so OK to return this + return this; + } } diff --git a/src/java/org/apache/poi/hssf/record/NameCommentRecord.java b/src/java/org/apache/poi/hssf/record/NameCommentRecord.java index 270440f665..d9e56affb6 100644 --- a/src/java/org/apache/poi/hssf/record/NameCommentRecord.java +++ b/src/java/org/apache/poi/hssf/record/NameCommentRecord.java @@ -18,145 +18,154 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.HexDump; -import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.StringUtil; /** - * Title: NAMECMT Record (0x0894)<p> - * - * Description: Defines a comment associated with a specified name. + * Defines a comment associated with a specified name. */ public final class NameCommentRecord extends StandardRecord { - public final static short sid = 0x0894; - - private final short field_1_record_type; - private final short field_2_frt_cell_ref_flag; - private final long field_3_reserved; - //private short field_4_name_length; - //private short field_5_comment_length; - private String field_6_name_text; - private String field_7_comment_text; - - public NameCommentRecord(final String name, final String comment) { - field_1_record_type = 0; - field_2_frt_cell_ref_flag = 0; - field_3_reserved = 0; - field_6_name_text = name; - field_7_comment_text = comment; - } - - @Override - public void serialize(final LittleEndianOutput out) { - final int field_4_name_length = field_6_name_text.length(); - final int field_5_comment_length = field_7_comment_text.length(); - - out.writeShort(field_1_record_type); - out.writeShort(field_2_frt_cell_ref_flag); - out.writeLong(field_3_reserved); - out.writeShort(field_4_name_length); - out.writeShort(field_5_comment_length); - - boolean isNameMultiByte = StringUtil.hasMultibyte(field_6_name_text); - out.writeByte(isNameMultiByte ? 1 : 0); - if (isNameMultiByte) { - StringUtil.putUnicodeLE(field_6_name_text, out); - } else { - StringUtil.putCompressedUnicode(field_6_name_text, out); + public static final short sid = 0x0894; + + private final short field_1_record_type; + private final short field_2_frt_cell_ref_flag; + private final long field_3_reserved; + //private short field_4_name_length; + //private short field_5_comment_length; + private String field_6_name_text; + private String field_7_comment_text; + + public NameCommentRecord(NameCommentRecord other) { + field_1_record_type = other.field_1_record_type; + field_2_frt_cell_ref_flag = other.field_2_frt_cell_ref_flag; + field_3_reserved = other.field_3_reserved; + field_6_name_text = other.field_6_name_text; + field_7_comment_text = other.field_7_comment_text; } - boolean isCommentMultiByte = StringUtil.hasMultibyte(field_7_comment_text); - out.writeByte(isCommentMultiByte ? 1 : 0); - if (isCommentMultiByte) { - StringUtil.putUnicodeLE(field_7_comment_text, out); - } else { - StringUtil.putCompressedUnicode(field_7_comment_text, out); + + public NameCommentRecord(final String name, final String comment) { + field_1_record_type = 0; + field_2_frt_cell_ref_flag = 0; + field_3_reserved = 0; + field_6_name_text = name; + field_7_comment_text = comment; + } + + /** + * @param ris the RecordInputstream to read the record from + */ + public NameCommentRecord(final RecordInputStream ris) { + field_1_record_type = ris.readShort(); + field_2_frt_cell_ref_flag = ris.readShort(); + field_3_reserved = ris.readLong(); + final int field_4_name_length = ris.readShort(); + final int field_5_comment_length = ris.readShort(); + + if (ris.readByte() == 0) { + field_6_name_text = StringUtil.readCompressedUnicode(ris, field_4_name_length); + } else { + field_6_name_text = StringUtil.readUnicodeLE(ris, field_4_name_length); + } + if (ris.readByte() == 0) { + field_7_comment_text = StringUtil.readCompressedUnicode(ris, field_5_comment_length); + } else { + field_7_comment_text = StringUtil.readUnicodeLE(ris, field_5_comment_length); + } } - } - - @Override - protected int getDataSize() { - return 18 // 4 shorts + 1 long + 2 spurious 'nul's - + (StringUtil.hasMultibyte(field_6_name_text) ? field_6_name_text.length()*2 : field_6_name_text.length()) - + (StringUtil.hasMultibyte(field_7_comment_text) ? field_7_comment_text.length()*2 : field_7_comment_text.length()); - } - - /** - * @param ris the RecordInputstream to read the record from - */ - public NameCommentRecord(final RecordInputStream ris) { - field_1_record_type = ris.readShort(); - field_2_frt_cell_ref_flag = ris.readShort(); - field_3_reserved = ris.readLong(); - final int field_4_name_length = ris.readShort(); - final int field_5_comment_length = ris.readShort(); - - if (ris.readByte() == 0) { - field_6_name_text = StringUtil.readCompressedUnicode(ris, field_4_name_length); - } else { - field_6_name_text = StringUtil.readUnicodeLE(ris, field_4_name_length); + + @Override + public void serialize(final LittleEndianOutput out) { + final int field_4_name_length = field_6_name_text.length(); + final int field_5_comment_length = field_7_comment_text.length(); + + out.writeShort(field_1_record_type); + out.writeShort(field_2_frt_cell_ref_flag); + out.writeLong(field_3_reserved); + out.writeShort(field_4_name_length); + out.writeShort(field_5_comment_length); + + boolean isNameMultiByte = StringUtil.hasMultibyte(field_6_name_text); + out.writeByte(isNameMultiByte ? 1 : 0); + if (isNameMultiByte) { + StringUtil.putUnicodeLE(field_6_name_text, out); + } else { + StringUtil.putCompressedUnicode(field_6_name_text, out); + } + boolean isCommentMultiByte = StringUtil.hasMultibyte(field_7_comment_text); + out.writeByte(isCommentMultiByte ? 1 : 0); + if (isCommentMultiByte) { + StringUtil.putUnicodeLE(field_7_comment_text, out); + } else { + StringUtil.putCompressedUnicode(field_7_comment_text, out); + } + } + + @Override + protected int getDataSize() { + return 18 // 4 shorts + 1 long + 2 spurious 'nul's + + (StringUtil.hasMultibyte(field_6_name_text) ? field_6_name_text.length() * 2 : field_6_name_text.length()) + + (StringUtil.hasMultibyte(field_7_comment_text) ? field_7_comment_text.length() * 2 : field_7_comment_text.length()); } - if (ris.readByte() == 0) { - field_7_comment_text = StringUtil.readCompressedUnicode(ris, field_5_comment_length); - } else { - field_7_comment_text = StringUtil.readUnicodeLE(ris, field_5_comment_length); - } - } - - /** - * return the non static version of the id for this record. - */ - @Override - public short getSid() { - return sid; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - - sb.append("[NAMECMT]\n"); - sb.append(" .record type = ").append(HexDump.shortToHex(field_1_record_type)).append("\n"); - sb.append(" .frt cell ref flag = ").append(HexDump.byteToHex(field_2_frt_cell_ref_flag)).append("\n"); - sb.append(" .reserved = ").append(field_3_reserved).append("\n"); - sb.append(" .name length = ").append(field_6_name_text.length()).append("\n"); - sb.append(" .comment length = ").append(field_7_comment_text.length()).append("\n"); - sb.append(" .name = ").append(field_6_name_text).append("\n"); - sb.append(" .comment = ").append(field_7_comment_text).append("\n"); - sb.append("[/NAMECMT]\n"); - - return sb.toString(); - } - - /** - * @return the name of the NameRecord to which this comment applies. - */ - public String getNameText() { - return field_6_name_text; - } - - /** - * Updates the name we're associated with, normally used - * when renaming that Name - * - * @param newName the new name - */ - public void setNameText(String newName) { - field_6_name_text = newName; - } - - /** - * @return the text of the comment. - */ - public String getCommentText() { - return field_7_comment_text; - } - - public void setCommentText(String comment) { - field_7_comment_text = comment; - } - - public short getRecordType() { - return field_1_record_type; - } + /** + * return the non static version of the id for this record. + */ + @Override + public short getSid() { + return sid; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + + sb.append("[NAMECMT]\n"); + sb.append(" .record type = ").append(HexDump.shortToHex(field_1_record_type)).append("\n"); + sb.append(" .frt cell ref flag = ").append(HexDump.byteToHex(field_2_frt_cell_ref_flag)).append("\n"); + sb.append(" .reserved = ").append(field_3_reserved).append("\n"); + sb.append(" .name length = ").append(field_6_name_text.length()).append("\n"); + sb.append(" .comment length = ").append(field_7_comment_text.length()).append("\n"); + sb.append(" .name = ").append(field_6_name_text).append("\n"); + sb.append(" .comment = ").append(field_7_comment_text).append("\n"); + sb.append("[/NAMECMT]\n"); + + return sb.toString(); + } + + /** + * @return the name of the NameRecord to which this comment applies. + */ + public String getNameText() { + return field_6_name_text; + } + + /** + * Updates the name we're associated with, normally used + * when renaming that Name + * + * @param newName the new name + */ + public void setNameText(String newName) { + field_6_name_text = newName; + } + + /** + * @return the text of the comment. + */ + public String getCommentText() { + return field_7_comment_text; + } + + public void setCommentText(String comment) { + field_7_comment_text = comment; + } + + public short getRecordType() { + return field_1_record_type; + } + + @Override + public NameCommentRecord copy() { + return new NameCommentRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/NameRecord.java b/src/java/org/apache/poi/hssf/record/NameRecord.java index 9278ce607b..4be445956c 100644 --- a/src/java/org/apache/poi/hssf/record/NameRecord.java +++ b/src/java/org/apache/poi/hssf/record/NameRecord.java @@ -19,44 +19,46 @@ package org.apache.poi.hssf.record; import org.apache.poi.hssf.record.cont.ContinuableRecord; import org.apache.poi.hssf.record.cont.ContinuableRecordOutput; +import org.apache.poi.ss.formula.Formula; import org.apache.poi.ss.formula.ptg.Area3DPtg; import org.apache.poi.ss.formula.ptg.Ptg; import org.apache.poi.ss.formula.ptg.Ref3DPtg; -import org.apache.poi.ss.formula.Formula; -import org.apache.poi.util.*; +import org.apache.poi.util.HexDump; +import org.apache.poi.util.LittleEndianByteArrayInputStream; +import org.apache.poi.util.LittleEndianInput; +import org.apache.poi.util.StringUtil; /** - * Title: DEFINEDNAME Record (0x0018)<p> - * Description: Defines a named range within a workbook. + * Defines a named range within a workbook. */ public final class NameRecord extends ContinuableRecord { - public final static short sid = 0x0018; + public static final short sid = 0x0018; /**Included for completeness sake, not implemented */ - public final static byte BUILTIN_CONSOLIDATE_AREA = 1; + public static final byte BUILTIN_CONSOLIDATE_AREA = 1; /**Included for completeness sake, not implemented */ - public final static byte BUILTIN_AUTO_OPEN = 2; + public static final byte BUILTIN_AUTO_OPEN = 2; /**Included for completeness sake, not implemented */ - public final static byte BUILTIN_AUTO_CLOSE = 3; + public static final byte BUILTIN_AUTO_CLOSE = 3; /**Included for completeness sake, not implemented */ - public final static byte BUILTIN_DATABASE = 4; + public static final byte BUILTIN_DATABASE = 4; /**Included for completeness sake, not implemented */ - public final static byte BUILTIN_CRITERIA = 5; + public static final byte BUILTIN_CRITERIA = 5; - public final static byte BUILTIN_PRINT_AREA = 6; - public final static byte BUILTIN_PRINT_TITLE = 7; + public static final byte BUILTIN_PRINT_AREA = 6; + public static final byte BUILTIN_PRINT_TITLE = 7; /**Included for completeness sake, not implemented */ - public final static byte BUILTIN_RECORDER = 8; + public static final byte BUILTIN_RECORDER = 8; /**Included for completeness sake, not implemented */ - public final static byte BUILTIN_DATA_FORM = 9; + public static final byte BUILTIN_DATA_FORM = 9; /**Included for completeness sake, not implemented */ - public final static byte BUILTIN_AUTO_ACTIVATE = 10; + public static final byte BUILTIN_AUTO_ACTIVATE = 10; /**Included for completeness sake, not implemented */ - public final static byte BUILTIN_AUTO_DEACTIVATE = 11; + public static final byte BUILTIN_AUTO_DEACTIVATE = 11; /**Included for completeness sake, not implemented */ - public final static byte BUILTIN_SHEET_TITLE = 12; + public static final byte BUILTIN_SHEET_TITLE = 12; - public final static byte BUILTIN_FILTER_DB = 13; + public static final byte BUILTIN_FILTER_DB = 13; private static final class Option { public static final int OPT_HIDDEN_NAME = 0x0001; @@ -98,10 +100,26 @@ public final class NameRecord extends ContinuableRecord { field_17_status_bar_text = ""; } + public NameRecord(NameRecord other) { + super(other); + field_1_option_flag = other.field_1_option_flag; + field_2_keyboard_shortcut = other.field_2_keyboard_shortcut; + field_5_externSheetIndex_plus1 = other.field_5_externSheetIndex_plus1; + field_6_sheetNumber = other.field_6_sheetNumber; + field_11_nameIsMultibyte = other.field_11_nameIsMultibyte; + field_12_built_in_code = other.field_12_built_in_code; + field_12_name_text = other.field_12_name_text; + field_13_name_definition = other.field_13_name_definition; + field_14_custom_menu_text = other.field_14_custom_menu_text; + field_15_description_text = other.field_15_description_text; + field_16_help_topic_text = other.field_16_help_topic_text; + field_17_status_bar_text = other.field_17_status_bar_text; + } + /** * Constructor to create a built-in named region * @param builtin Built-in byte representation for the name record, use the public constants - * @param sheetNumber the sheet which the name applies to + * @param sheetNumber the sheet which the name applies to */ public NameRecord(byte builtin, int sheetNumber) { @@ -276,7 +294,7 @@ public final class NameRecord extends ContinuableRecord { /** * Convenience Function to determine if the name is a built-in name - * + * * @return true, if the name is a built-in name */ public boolean isBuiltInName() @@ -590,4 +608,9 @@ public final class NameRecord extends ContinuableRecord { return "Unknown"; } + + @Override + public NameRecord copy() { + return new NameRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/NoteRecord.java b/src/java/org/apache/poi/hssf/record/NoteRecord.java index 39992bbdbc..4352978141 100644 --- a/src/java/org/apache/poi/hssf/record/NoteRecord.java +++ b/src/java/org/apache/poi/hssf/record/NoteRecord.java @@ -18,27 +18,28 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; import org.apache.poi.util.StringUtil; /** * NOTE: Comment Associated with a Cell (0x001C) */ -public final class NoteRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x001C; +public final class NoteRecord extends StandardRecord { + public static final short sid = 0x001C; public static final NoteRecord[] EMPTY_ARRAY = { }; /** * Flag indicating that the comment is hidden (default) */ - public final static short NOTE_HIDDEN = 0x0; + public static final short NOTE_HIDDEN = 0x0; /** * Flag indicating that the comment is visible */ - public final static short NOTE_VISIBLE = 0x2; + public static final short NOTE_VISIBLE = 0x2; - private static final Byte DEFAULT_PADDING = Byte.valueOf((byte)0); + private static final Byte DEFAULT_PADDING = (byte) 0; private int field_1_row; private int field_2_col; @@ -46,6 +47,7 @@ public final class NoteRecord extends StandardRecord implements Cloneable { private int field_4_shapeid; private boolean field_5_hasMultibyte; private String field_6_author; + /** * Saves padding byte value to reduce delta during round-trip serialization.<br> * @@ -64,6 +66,17 @@ public final class NoteRecord extends StandardRecord implements Cloneable { field_7_padding = DEFAULT_PADDING; // seems to be always present regardless of author text } + public NoteRecord(NoteRecord other) { + super(other); + field_1_row = other.field_1_row; + field_2_col = other.field_2_col; + field_3_flags = other.field_3_flags; + field_4_shapeid = other.field_4_shapeid; + field_5_hasMultibyte = other.field_5_hasMultibyte; + field_6_author = other.field_6_author; + field_7_padding = other.field_7_padding; + } + /** * @return id of this record. */ @@ -73,7 +86,7 @@ public final class NoteRecord extends StandardRecord implements Cloneable { /** * Read the record data from the supplied <code>RecordInputStream</code> - * + * * @param in the RecordInputStream to read from */ public NoteRecord(RecordInputStream in) { @@ -194,10 +207,10 @@ public final class NoteRecord extends StandardRecord implements Cloneable { public void setFlags(short flags) { field_3_flags = flags; } - + /** * For unit testing only! - * + * * @return true, if author element uses multi byte */ protected boolean authorIsMultibyte() { @@ -206,7 +219,7 @@ public final class NoteRecord extends StandardRecord implements Cloneable { /** * Object id for OBJ record that contains the comment - * + * * @return the Object id for OBJ record that contains the comment */ public int getShapeId() { @@ -215,7 +228,7 @@ public final class NoteRecord extends StandardRecord implements Cloneable { /** * Object id for OBJ record that contains the comment - * + * * @param id the Object id for OBJ record that contains the comment */ public void setShapeId(int id) { @@ -242,13 +255,15 @@ public final class NoteRecord extends StandardRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public NoteRecord clone() { - NoteRecord rec = new NoteRecord(); - rec.field_1_row = field_1_row; - rec.field_2_col = field_2_col; - rec.field_3_flags = field_3_flags; - rec.field_4_shapeid = field_4_shapeid; - rec.field_6_author = field_6_author; - return rec; + return copy(); + } + + @Override + public NoteRecord copy() { + return new NoteRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/NoteStructureSubRecord.java b/src/java/org/apache/poi/hssf/record/NoteStructureSubRecord.java index e226b344d0..46a8f5106c 100644 --- a/src/java/org/apache/poi/hssf/record/NoteStructureSubRecord.java +++ b/src/java/org/apache/poi/hssf/record/NoteStructureSubRecord.java @@ -22,6 +22,7 @@ import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.RecordFormatException; +import org.apache.poi.util.Removal; /** * ftNts (0x000D)<p> @@ -29,25 +30,30 @@ import org.apache.poi.util.RecordFormatException; * * The docs say nothing about it. The length of this record is always 26 bytes. */ -public final class NoteStructureSubRecord extends SubRecord implements Cloneable { - public final static short sid = 0x0D; +public final class NoteStructureSubRecord extends SubRecord { + public static final short sid = 0x0D; private static final int ENCODED_SIZE = 22; - private byte[] reserved; + private final byte[] reserved; /** * Construct a new <code>NoteStructureSubRecord</code> and * fill its data with the default values */ - public NoteStructureSubRecord() - { + public NoteStructureSubRecord() { //all we know is that the the length of <code>NoteStructureSubRecord</code> is always 22 bytes reserved = new byte[ENCODED_SIZE]; } + public NoteStructureSubRecord(NoteStructureSubRecord other) { + super(other); + reserved = other.reserved.clone(); + } + + /** * Read the record data from the supplied <code>RecordInputStream</code> - * + * * @param in the input to read from * @param size the provided size - must be 22 */ @@ -103,12 +109,16 @@ public final class NoteStructureSubRecord extends SubRecord implements Cloneable } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public NoteStructureSubRecord clone() { - NoteStructureSubRecord rec = new NoteStructureSubRecord(); - byte[] recdata = new byte[reserved.length]; - System.arraycopy(reserved, 0, recdata, 0, recdata.length); - rec.reserved = recdata; - return rec; + return copy(); + } + + @Override + public NoteStructureSubRecord copy() { + return new NoteStructureSubRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/NumberRecord.java b/src/java/org/apache/poi/hssf/record/NumberRecord.java index 9d3dfd0c41..a9defdc251 100644 --- a/src/java/org/apache/poi/hssf/record/NumberRecord.java +++ b/src/java/org/apache/poi/hssf/record/NumberRecord.java @@ -19,20 +19,22 @@ package org.apache.poi.hssf.record; import org.apache.poi.ss.util.NumberToTextConverter; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * NUMBER (0x0203) Contains a numeric cell value. <P> - * REFERENCE: PG 334 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Jason Height (jheight at chariot dot net dot au) + * NUMBER (0x0203) Contains a numeric cell value. */ -public final class NumberRecord extends CellRecord implements Cloneable { +public final class NumberRecord extends CellRecord { public static final short sid = 0x0203; + private double field_4_value; /** Creates new NumberRecord */ - public NumberRecord() { - // fields uninitialised + public NumberRecord() {} + + public NumberRecord(NumberRecord other) { + super(other); + field_4_value = other.field_4_value; } /** @@ -87,10 +89,15 @@ public final class NumberRecord extends CellRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public NumberRecord clone() { - NumberRecord rec = new NumberRecord(); - copyBaseFields(rec); - rec.field_4_value = field_4_value; - return rec; + return copy(); + } + + @Override + public NumberRecord copy() { + return new NumberRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/ObjRecord.java b/src/java/org/apache/poi/hssf/record/ObjRecord.java index 2e3b49d339..c76e92848a 100644 --- a/src/java/org/apache/poi/hssf/record/ObjRecord.java +++ b/src/java/org/apache/poi/hssf/record/ObjRecord.java @@ -26,20 +26,23 @@ import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndianByteArrayInputStream; import org.apache.poi.util.LittleEndianByteArrayOutputStream; import org.apache.poi.util.RecordFormatException; +import org.apache.poi.util.Removal; /** * OBJRECORD (0x005D)<p> * * The obj record is used to hold various graphic objects and controls. */ -public final class ObjRecord extends Record implements Cloneable { - public final static short sid = 0x005D; +public final class ObjRecord extends Record { + public static final short sid = 0x005D; private static final int NORMAL_PAD_ALIGNMENT = 2; private static int MAX_PAD_ALIGNMENT = 4; - private List<SubRecord> subrecords; - /** used when POI has no idea what is going on */ + private final List<SubRecord> subrecords = new ArrayList<>(); + /** + * used when POI has no idea what is going on + */ private final byte[] _uninterpretedData; /** * Excel seems to tolerate padding to quad or double byte length @@ -51,11 +54,16 @@ public final class ObjRecord extends Record implements Cloneable { public ObjRecord() { - subrecords = new ArrayList<>(2); // TODO - ensure 2 sub-records (ftCmo 15h, and ftEnd 00h) are always created _uninterpretedData = null; } + public ObjRecord(ObjRecord other) { + other.subrecords.stream().map(SubRecord::copy).forEach(subrecords::add); + _uninterpretedData = (other._uninterpretedData == null) ? null : other._uninterpretedData.clone(); + _isPaddedToQuadByteMultiple = other._isPaddedToQuadByteMultiple; + } + public ObjRecord(RecordInputStream in) { // TODO - problems with OBJ sub-records stream // MS spec says first sub-record is always CommonObjectDataSubRecord, @@ -72,7 +80,6 @@ public final class ObjRecord extends Record implements Cloneable { // Excel tolerates the funny ObjRecord, and replaces it with a corrected version // The exact logic/reasoning is not yet understood _uninterpretedData = subRecordData; - subrecords = null; return; } @@ -84,7 +91,6 @@ public final class ObjRecord extends Record implements Cloneable { } */ - subrecords = new ArrayList<>(); LittleEndianByteArrayInputStream subRecStream = new LittleEndianByteArrayInputStream(subRecordData); CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord)SubRecord.createSubRecord(subRecStream, 0); subrecords.add(cmo); @@ -138,10 +144,8 @@ public final class ObjRecord extends Record implements Cloneable { StringBuilder sb = new StringBuilder(); sb.append("[OBJ]\n"); - if(subrecords != null) { // there are special cases where this can be, see comments in constructor above - for (final SubRecord record : subrecords) { - sb.append("SUBRECORD: ").append(record); - } + for (final SubRecord record : subrecords) { + sb.append("SUBRECORD: ").append(record); } sb.append("[/OBJ]\n"); return sb.toString(); @@ -221,12 +225,15 @@ public final class ObjRecord extends Record implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public ObjRecord clone() { - ObjRecord rec = new ObjRecord(); + return copy(); + } - for (SubRecord record : subrecords) { - rec.addSubRecord(record.clone()); - } - return rec; + @Override + public ObjRecord copy() { + return new ObjRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/ObjectProtectRecord.java b/src/java/org/apache/poi/hssf/record/ObjectProtectRecord.java index deda2f39a4..451ca35dff 100644 --- a/src/java/org/apache/poi/hssf/record/ObjectProtectRecord.java +++ b/src/java/org/apache/poi/hssf/record/ObjectProtectRecord.java @@ -15,32 +15,32 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Object Protect Record<P> - * Description: Protect embedded object with the lamest "security" ever invented. - * This record tells "I want to protect my objects" with lame security. It - * appears in conjunction with the PASSWORD and PROTECT records as well as its - * scenario protect cousin.<P> - * REFERENCE: PG 368 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) + * Protect embedded object with the lamest "security" ever invented. + * This record tells "I want to protect my objects" with lame security. + * It appears in conjunction with the PASSWORD and PROTECT records as well as its scenario protect cousin. */ -public final class ObjectProtectRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x63; - private short field_1_protect; +public final class ObjectProtectRecord extends StandardRecord { + public static final short sid = 0x63; - public ObjectProtectRecord() - { + private short field_1_protect; + + public ObjectProtectRecord() {} + + public ObjectProtectRecord(ObjectProtectRecord other) { + super(other); + field_1_protect = other.field_1_protect; } - public ObjectProtectRecord(RecordInputStream in) - { + public ObjectProtectRecord(RecordInputStream in) { field_1_protect = in.readShort(); } @@ -51,14 +51,7 @@ public final class ObjectProtectRecord extends StandardRecord implements Cloneab public void setProtect(boolean protect) { - if (protect) - { - field_1_protect = 1; - } - else - { - field_1_protect = 0; - } + field_1_protect = (short) (protect ? 1 : 0); } /** @@ -96,9 +89,15 @@ public final class ObjectProtectRecord extends StandardRecord implements Cloneab } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public ObjectProtectRecord clone() { - ObjectProtectRecord rec = new ObjectProtectRecord(); - rec.field_1_protect = field_1_protect; - return rec; + return copy(); + } + + @Override + public ObjectProtectRecord copy() { + return new ObjectProtectRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/OldFormulaRecord.java b/src/java/org/apache/poi/hssf/record/OldFormulaRecord.java index 365059f47a..f6b2914606 100644 --- a/src/java/org/apache/poi/hssf/record/OldFormulaRecord.java +++ b/src/java/org/apache/poi/hssf/record/OldFormulaRecord.java @@ -17,7 +17,6 @@ package org.apache.poi.hssf.record; -import org.apache.poi.hssf.record.FormulaRecord.SpecialCachedValue; import org.apache.poi.ss.formula.Formula; import org.apache.poi.ss.formula.ptg.Ptg; import org.apache.poi.ss.usermodel.CellType; @@ -27,12 +26,12 @@ import org.apache.poi.ss.usermodel.CellType; * encoded form, along with the value if a number */ public final class OldFormulaRecord extends OldCellRecord { - public final static short biff2_sid = 0x0006; - public final static short biff3_sid = 0x0206; - public final static short biff4_sid = 0x0406; - public final static short biff5_sid = 0x0006; + public static final short biff2_sid = 0x0006; + public static final short biff3_sid = 0x0206; + public static final short biff4_sid = 0x0406; + public static final short biff5_sid = 0x0006; - private SpecialCachedValue specialCachedValue; + private FormulaSpecialCachedValue specialCachedValue; private double field_4_value; private short field_5_options; private Formula field_6_parsed_expr; @@ -44,7 +43,7 @@ public final class OldFormulaRecord extends OldCellRecord { field_4_value = ris.readDouble(); } else { long valueLongBits = ris.readLong(); - specialCachedValue = SpecialCachedValue.create(valueLongBits); + specialCachedValue = FormulaSpecialCachedValue.create(valueLongBits); if (specialCachedValue == null) { field_4_value = Double.longBitsToDouble(valueLongBits); } @@ -67,14 +66,14 @@ public final class OldFormulaRecord extends OldCellRecord { } return specialCachedValue.getValueType(); } - + public boolean getCachedBooleanValue() { return specialCachedValue.getBooleanValue(); } public int getCachedErrorValue() { return specialCachedValue.getErrorValue(); } - + /** * get the calculated value of the formula * diff --git a/src/java/org/apache/poi/hssf/record/OldLabelRecord.java b/src/java/org/apache/poi/hssf/record/OldLabelRecord.java index 447291daa3..6dd80e911e 100644 --- a/src/java/org/apache/poi/hssf/record/OldLabelRecord.java +++ b/src/java/org/apache/poi/hssf/record/OldLabelRecord.java @@ -24,17 +24,17 @@ import org.apache.poi.util.POILogger; import org.apache.poi.util.RecordFormatException; /** - * Biff2 - Biff 4 Label Record (0x0004 / 0x0204) - read only support for + * Biff2 - Biff 4 Label Record (0x0004 / 0x0204) - read only support for * strings stored directly in the cell, from the older file formats that * didn't use {@link LabelSSTRecord} */ public final class OldLabelRecord extends OldCellRecord { - private final static POILogger logger = POILogFactory.getLogger(OldLabelRecord.class); + private static final POILogger logger = POILogFactory.getLogger(OldLabelRecord.class); //arbitrarily set, may need to increase private static final int MAX_RECORD_LENGTH = 100_000; - public final static short biff2_sid = 0x0004; - public final static short biff345_sid = 0x0204; + public static final short biff2_sid = 0x0004; + public static final short biff345_sid = 0x0204; private short field_4_string_len; private final byte[] field_5_bytes; @@ -68,7 +68,7 @@ public final class OldLabelRecord extends OldCellRecord { public void setCodePage(CodepageRecord codepage) { this.codepage = codepage; } - + /** * get the number of characters this string contains * @return number of characters @@ -80,7 +80,7 @@ public final class OldLabelRecord extends OldCellRecord { /** * Get the String of the cell - * + * * @return the String of the cell */ public String getValue() @@ -90,7 +90,7 @@ public final class OldLabelRecord extends OldCellRecord { /** * Not supported - * + * * @param offset not supported * @param data not supported * @return not supported @@ -98,7 +98,7 @@ public final class OldLabelRecord extends OldCellRecord { public int serialize(int offset, byte [] data) { throw new RecordFormatException("Old Label Records are supported READ ONLY"); } - + public int getRecordSize() { throw new RecordFormatException("Old Label Records are supported READ ONLY"); } diff --git a/src/java/org/apache/poi/hssf/record/OldSheetRecord.java b/src/java/org/apache/poi/hssf/record/OldSheetRecord.java index 195d9319cf..0672faa054 100644 --- a/src/java/org/apache/poi/hssf/record/OldSheetRecord.java +++ b/src/java/org/apache/poi/hssf/record/OldSheetRecord.java @@ -31,7 +31,7 @@ public final class OldSheetRecord { //arbitrarily selected; may need to increase private static final int MAX_RECORD_LENGTH = 100_000; - public final static short sid = 0x0085; + public static final short sid = 0x0085; private int field_1_position_of_BOF; private int field_2_visibility; diff --git a/src/java/org/apache/poi/hssf/record/OldStringRecord.java b/src/java/org/apache/poi/hssf/record/OldStringRecord.java index 2d611929f7..87140b7fc9 100644 --- a/src/java/org/apache/poi/hssf/record/OldStringRecord.java +++ b/src/java/org/apache/poi/hssf/record/OldStringRecord.java @@ -25,7 +25,7 @@ import org.apache.poi.util.IOUtils; /** - * Biff2 - Biff 4 Label Record (0x0007 / 0x0207) - read only support for + * Biff2 - Biff 4 Label Record (0x0007 / 0x0207) - read only support for * formula string results. */ public final class OldStringRecord { @@ -33,8 +33,8 @@ public final class OldStringRecord { //arbitrarily selected; may need to increase private static final int MAX_RECORD_LENGTH = 100_000; - public final static short biff2_sid = 0x0007; - public final static short biff345_sid = 0x0207; + public static final short biff2_sid = 0x0007; + public static final short biff345_sid = 0x0207; private short sid; private short field_1_string_len; @@ -46,7 +46,7 @@ public final class OldStringRecord { */ public OldStringRecord(RecordInputStream in) { sid = in.getSid(); - + if (in.getSid() == biff2_sid) { field_1_string_len = (short)in.readUByte(); } else { @@ -65,7 +65,7 @@ public final class OldStringRecord { public short getSid() { return sid; } - + public void setCodePage(CodepageRecord codepage) { this.codepage = codepage; } @@ -77,7 +77,7 @@ public final class OldStringRecord { { return getString(field_2_bytes, codepage); } - + protected static String getString(byte[] data, CodepageRecord codepage) { int cp = Property.DEFAULT_CODEPAGE; if (codepage != null) { diff --git a/src/java/org/apache/poi/hssf/record/PageBreakRecord.java b/src/java/org/apache/poi/hssf/record/PageBreakRecord.java index a1d86247dc..4b2c216a70 100644 --- a/src/java/org/apache/poi/hssf/record/PageBreakRecord.java +++ b/src/java/org/apache/poi/hssf/record/PageBreakRecord.java @@ -20,27 +20,25 @@ package org.apache.poi.hssf.record; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; -import java.util.List; import java.util.Map; import org.apache.poi.util.LittleEndianOutput; /** - * <p>Record that contains the functionality page breaks (horizontal and vertical)</p> + * Record that contains the functionality page breaks (horizontal and vertical)<p> * - * <p>The other two classes just specifically set the SIDS for record creation.</p> + * The other two classes just specifically set the SIDS for record creation.<p> * - * <p>REFERENCE: Microsoft Excel SDK page 322 and 420</p> + * REFERENCE: Microsoft Excel SDK page 322 and 420 * * @see HorizontalPageBreakRecord * @see VerticalPageBreakRecord - * @author Danny Mui (dmui at apache dot org) */ public abstract class PageBreakRecord extends StandardRecord { private static final int[] EMPTY_INT_ARRAY = { }; - private List<Break> _breaks; - private Map<Integer, Break> _breakMap; + private final ArrayList<Break> _breaks = new ArrayList<>(); + private final Map<Integer, Break> _breakMap = new HashMap<>(); /** * Since both records store 2byte integers (short), no point in @@ -56,8 +54,13 @@ public abstract class PageBreakRecord extends StandardRecord { public int subFrom; public int subTo; - public Break(int main, int subFrom, int subTo) - { + public Break(Break other) { + main = other.main; + subFrom = other.subFrom; + subTo = other.subTo; + } + + public Break(int main, int subFrom, int subTo) { this.main = main; this.subFrom = subFrom; this.subTo = subTo; @@ -76,23 +79,24 @@ public abstract class PageBreakRecord extends StandardRecord { } } - protected PageBreakRecord() { - _breaks = new ArrayList<>(); - _breakMap = new HashMap<>(); - } + protected PageBreakRecord() {} - public PageBreakRecord(RecordInputStream in) - { - int nBreaks = in.readShort(); - _breaks = new ArrayList<>(nBreaks + 2); - _breakMap = new HashMap<>(); + protected PageBreakRecord(PageBreakRecord other) { + _breaks.addAll(other._breaks); + initMap(); + } + public PageBreakRecord(RecordInputStream in) { + final int nBreaks = in.readShort(); + _breaks.ensureCapacity(nBreaks + 2); for(int k = 0; k < nBreaks; k++) { - Break br = new Break(in); - _breaks.add(br); - _breakMap.put(Integer.valueOf(br.main), br); + _breaks.add(new Break(in)); } + initMap(); + } + private void initMap() { + _breaks.forEach(br -> _breakMap.put(Integer.valueOf(br.main), br)); } public boolean isEmpty() { @@ -105,8 +109,8 @@ public abstract class PageBreakRecord extends StandardRecord { public final void serialize(LittleEndianOutput out) { int nBreaks = _breaks.size(); out.writeShort(nBreaks); - for (int i=0; i<nBreaks; i++) { - _breaks.get(i).serialize(out); + for (Break aBreak : _breaks) { + aBreak.serialize(out); } } @@ -206,4 +210,7 @@ public abstract class PageBreakRecord extends StandardRecord { } return result; } + + @Override + public abstract PageBreakRecord copy(); } diff --git a/src/java/org/apache/poi/hssf/record/PaletteRecord.java b/src/java/org/apache/poi/hssf/record/PaletteRecord.java index 72b5639581..222be3060f 100644 --- a/src/java/org/apache/poi/hssf/record/PaletteRecord.java +++ b/src/java/org/apache/poi/hssf/record/PaletteRecord.java @@ -19,34 +19,36 @@ package org.apache.poi.hssf.record; import java.util.ArrayList; import java.util.Collections; -import java.util.List; import org.apache.poi.util.LittleEndianOutput; /** - * PaletteRecord (0x0092) - Supports custom palettes. - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Brian Sanders (bsanders at risklabs dot com) - custom palette editing - * + * Supports custom palettes. */ public final class PaletteRecord extends StandardRecord { - public final static short sid = 0x0092; + public static final short sid = 0x0092; /** The standard size of an XLS palette */ - public final static byte STANDARD_PALETTE_SIZE = (byte) 56; + public static final byte STANDARD_PALETTE_SIZE = (byte) 56; /** The byte index of the first color */ - public final static short FIRST_COLOR_INDEX = (short) 0x8; + public static final short FIRST_COLOR_INDEX = (short) 0x8; - private final List<PColor> _colors; + private final ArrayList<PColor> _colors = new ArrayList<>(); public PaletteRecord() { PColor[] defaultPalette = createDefaultPalette(); - _colors = new ArrayList<>(defaultPalette.length); + _colors.ensureCapacity(defaultPalette.length); Collections.addAll(_colors, defaultPalette); } + public PaletteRecord(PaletteRecord other) { + super(other); + _colors.ensureCapacity(other._colors.size()); + other._colors.stream().map(PColor::new).forEach(_colors::add); + } + public PaletteRecord(RecordInputStream in) { int field_1_numcolors = in.readShort(); - _colors = new ArrayList<>(field_1_numcolors); + _colors.ensureCapacity(field_1_numcolors); for (int k = 0; k < field_1_numcolors; k++) { _colors.add(new PColor(in)); } @@ -71,8 +73,8 @@ public final class PaletteRecord extends StandardRecord { @Override public void serialize(LittleEndianOutput out) { out.writeShort(_colors.size()); - for (int i = 0; i < _colors.size(); i++) { - _colors.get(i).serialize(out); + for (PColor color : _colors) { + color.serialize(out); } } @@ -88,7 +90,7 @@ public final class PaletteRecord extends StandardRecord { /** * Returns the color value at a given index - * + * * @param byteIndex palette index, must be >= 0x8 * * @return the RGB triplet for the color, or <code>null</code> if the specified index @@ -129,6 +131,11 @@ public final class PaletteRecord extends StandardRecord { _colors.set(i, custColor); } + @Override + public PaletteRecord copy() { + return new PaletteRecord(this); + } + /** * Creates the default palette as PaletteRecord binary data */ @@ -213,8 +220,10 @@ public final class PaletteRecord extends StandardRecord { _blue = blue; } - public byte[] getTriplet() { - return new byte[] { (byte) _red, (byte) _green, (byte) _blue }; + public PColor(PColor other) { + _red = other._red; + _green = other._green; + _blue = other._blue; } public PColor(RecordInputStream in) { @@ -224,6 +233,10 @@ public final class PaletteRecord extends StandardRecord { in.readByte(); // unused } + public byte[] getTriplet() { + return new byte[] { (byte) _red, (byte) _green, (byte) _blue }; + } + public void serialize(LittleEndianOutput out) { out.writeByte(_red); out.writeByte(_green); diff --git a/src/java/org/apache/poi/hssf/record/PaneRecord.java b/src/java/org/apache/poi/hssf/record/PaneRecord.java index 4b0610aba7..c50e01b002 100644 --- a/src/java/org/apache/poi/hssf/record/PaneRecord.java +++ b/src/java/org/apache/poi/hssf/record/PaneRecord.java @@ -20,35 +20,41 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * Describes the frozen and unfrozen panes. */ public final class PaneRecord extends StandardRecord { - public final static short sid = 0x41; - private short field_1_x; - private short field_2_y; - private short field_3_topRow; - private short field_4_leftColumn; - private short field_5_activePane; - public final static short ACTIVE_PANE_LOWER_RIGHT = 0; - public final static short ACTIVE_PANE_UPPER_RIGHT = 1; - public final static short ACTIVE_PANE_LOWER_LEFT = 2; - public final static short ACTIVE_PANE_UPPER_LEFT = 3; - - - public PaneRecord() - { + public static final short sid = 0x41; + public static final short ACTIVE_PANE_LOWER_RIGHT = 0; + public static final short ACTIVE_PANE_UPPER_RIGHT = 1; + public static final short ACTIVE_PANE_LOWER_LEFT = 2; + public static final short ACTIVE_PANE_UPPER_LEFT = 3; + + private short field_1_x; + private short field_2_y; + private short field_3_topRow; + private short field_4_leftColumn; + private short field_5_activePane; + public PaneRecord() {} + + public PaneRecord(PaneRecord other) { + super(other); + field_1_x = other.field_1_x; + field_2_y = other.field_2_y; + field_3_topRow = other.field_3_topRow; + field_4_leftColumn = other.field_4_leftColumn; + field_5_activePane = other.field_5_activePane; } - public PaneRecord(RecordInputStream in) - { - field_1_x = in.readShort(); - field_2_y = in.readShort(); - field_3_topRow = in.readShort(); - field_4_leftColumn = in.readShort(); - field_5_activePane = in.readShort(); + public PaneRecord(RecordInputStream in) { + field_1_x = in.readShort(); + field_2_y = in.readShort(); + field_3_topRow = in.readShort(); + field_4_leftColumn = in.readShort(); + field_5_activePane = in.readShort(); } @Override @@ -60,23 +66,23 @@ public final class PaneRecord extends StandardRecord { buffer.append(" .x = ") .append("0x").append(HexDump.toHex( getX ())) .append(" (").append( getX() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .y = ") .append("0x").append(HexDump.toHex( getY ())) .append(" (").append( getY() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .topRow = ") .append("0x").append(HexDump.toHex( getTopRow ())) .append(" (").append( getTopRow() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .leftColumn = ") .append("0x").append(HexDump.toHex( getLeftColumn ())) .append(" (").append( getLeftColumn() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .activePane = ") .append("0x").append(HexDump.toHex( getActivePane ())) .append(" (").append( getActivePane() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append("[/PANE]\n"); return buffer.toString(); @@ -103,20 +109,21 @@ public final class PaneRecord extends StandardRecord { } @Override - public Object clone() { - PaneRecord rec = new PaneRecord(); - - rec.field_1_x = field_1_x; - rec.field_2_y = field_2_y; - rec.field_3_topRow = field_3_topRow; - rec.field_4_leftColumn = field_4_leftColumn; - rec.field_5_activePane = field_5_activePane; - return rec; + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public PaneRecord clone() { + return copy(); + } + + @Override + public PaneRecord copy() { + return new PaneRecord(this); } /** * Get the x field for the Pane record. - * + * * @return the x value */ public short getX() @@ -126,7 +133,7 @@ public final class PaneRecord extends StandardRecord { /** * Set the x field for the Pane record. - * + * * @param field_1_x the x value */ public void setX(short field_1_x) @@ -136,7 +143,7 @@ public final class PaneRecord extends StandardRecord { /** * Get the y field for the Pane record. - * + * * @return the y value */ public short getY() @@ -146,7 +153,7 @@ public final class PaneRecord extends StandardRecord { /** * Set the y field for the Pane record. - * + * * @param field_2_y the y value */ public void setY(short field_2_y) @@ -156,7 +163,7 @@ public final class PaneRecord extends StandardRecord { /** * Get the top row field for the Pane record. - * + * * @return the top row */ public short getTopRow() @@ -166,7 +173,7 @@ public final class PaneRecord extends StandardRecord { /** * Set the top row field for the Pane record. - * + * * @param field_3_topRow the top row */ public void setTopRow(short field_3_topRow) @@ -176,7 +183,7 @@ public final class PaneRecord extends StandardRecord { /** * Get the left column field for the Pane record. - * + * * @return the left column */ public short getLeftColumn() @@ -186,7 +193,7 @@ public final class PaneRecord extends StandardRecord { /** * Set the left column field for the Pane record. - * + * * @param field_4_leftColumn the left column */ public void setLeftColumn(short field_4_leftColumn) @@ -197,7 +204,7 @@ public final class PaneRecord extends StandardRecord { /** * Get the active pane field for the Pane record. * - * @return One of + * @return One of * ACTIVE_PANE_LOWER_RIGHT * ACTIVE_PANE_UPPER_RIGHT * ACTIVE_PANE_LOWER_LEFT @@ -212,7 +219,7 @@ public final class PaneRecord extends StandardRecord { * Set the active pane field for the Pane record. * * @param field_5_activePane - * One of + * One of * ACTIVE_PANE_LOWER_RIGHT * ACTIVE_PANE_UPPER_RIGHT * ACTIVE_PANE_LOWER_LEFT diff --git a/src/java/org/apache/poi/hssf/record/PasswordRecord.java b/src/java/org/apache/poi/hssf/record/PasswordRecord.java index 211ddcbe58..c177949b3e 100644 --- a/src/java/org/apache/poi/hssf/record/PasswordRecord.java +++ b/src/java/org/apache/poi/hssf/record/PasswordRecord.java @@ -19,20 +19,26 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Password Record (0x0013)<p> - * Description: stores the encrypted password for a sheet or workbook (HSSF doesn't support encryption) - * REFERENCE: PG 371 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) + * Stores the encrypted password for a sheet or workbook (HSSF doesn't support encryption) */ public final class PasswordRecord extends StandardRecord { - public final static short sid = 0x0013; - private int field_1_password; // not sure why this is only 2 bytes, but it is... go figure + public static final short sid = 0x0013; + + // not sure why this is only 2 bytes, but it is... go figure + private int field_1_password; public PasswordRecord(int password) { field_1_password = password; } + public PasswordRecord(PasswordRecord other) { + super(other); + field_1_password = other.field_1_password; + } + public PasswordRecord(RecordInputStream in) { field_1_password = in.readShort(); } @@ -77,10 +83,18 @@ public final class PasswordRecord extends StandardRecord { return sid; } + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public PasswordRecord clone() { + return copy(); + } + /** * Clone this record. */ - public Object clone() { - return new PasswordRecord(field_1_password); + public PasswordRecord copy() { + return new PasswordRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/PasswordRev4Record.java b/src/java/org/apache/poi/hssf/record/PasswordRev4Record.java index ed8f4ff970..997b721e83 100644 --- a/src/java/org/apache/poi/hssf/record/PasswordRev4Record.java +++ b/src/java/org/apache/poi/hssf/record/PasswordRev4Record.java @@ -21,18 +21,22 @@ import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; /** - * Title: Protection Revision 4 password Record (0x01BC)<p> - * Description: Stores the (2 byte??!!) encrypted password for a shared workbook<p> - * REFERENCE: PG 374 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) + * Protection Revision 4 password Record (0x01BC)<p> + * Stores the (2 byte??!!) encrypted password for a shared workbook */ public final class PasswordRev4Record extends StandardRecord { - public final static short sid = 0x01BC; + public static final short sid = 0x01BC; private int field_1_password; public PasswordRev4Record(int pw) { field_1_password = pw; } + public PasswordRev4Record(PasswordRev4Record other) { + super(other); + field_1_password = other.field_1_password; + } + public PasswordRev4Record(RecordInputStream in) { field_1_password = in.readShort(); } @@ -66,4 +70,9 @@ public final class PasswordRev4Record extends StandardRecord { public short getSid() { return sid; } + + @Override + public PasswordRev4Record copy() { + return new PasswordRev4Record(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/PrecisionRecord.java b/src/java/org/apache/poi/hssf/record/PrecisionRecord.java index 74bf8cf916..13d0c0a41f 100644 --- a/src/java/org/apache/poi/hssf/record/PrecisionRecord.java +++ b/src/java/org/apache/poi/hssf/record/PrecisionRecord.java @@ -20,21 +20,24 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; /** - * Title: Precision Record<P> - * Description: defines whether to store with full precision or what's displayed by the gui - * (meaning have really screwed up and skewed figures or only think you do!)<P> - * REFERENCE: PG 372 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> + * Defines whether to store with full precision or what's displayed by the gui + * (meaning have really screwed up and skewed figures or only think you do!) + * * @version 2.0-pre */ public final class PrecisionRecord extends StandardRecord { - public final static short sid = 0xE; - public short field_1_precision; + public static final short sid = 0xE; - public PrecisionRecord() { + public short field_1_precision; + + public PrecisionRecord() {} + + public PrecisionRecord(PrecisionRecord other) { + super(other); + field_1_precision = other.field_1_precision; } - public PrecisionRecord(RecordInputStream in) - { + public PrecisionRecord(RecordInputStream in) { field_1_precision = in.readShort(); } @@ -44,11 +47,7 @@ public final class PrecisionRecord extends StandardRecord { * @param fullprecision - or not */ public void setFullPrecision(boolean fullprecision) { - if (fullprecision) { - field_1_precision = 1; - } else { - field_1_precision = 0; - } + field_1_precision = (short) (fullprecision ? 1 : 0); } /** @@ -80,4 +79,9 @@ public final class PrecisionRecord extends StandardRecord { { return sid; } + + @Override + public PrecisionRecord copy() { + return new PrecisionRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/PrintGridlinesRecord.java b/src/java/org/apache/poi/hssf/record/PrintGridlinesRecord.java index 2563f34326..2e84590aa2 100644 --- a/src/java/org/apache/poi/hssf/record/PrintGridlinesRecord.java +++ b/src/java/org/apache/poi/hssf/record/PrintGridlinesRecord.java @@ -17,24 +17,25 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Print Gridlines Record<P> - * Description: whether to print the gridlines when you enjoy you spreadsheet on paper.<P> - * REFERENCE: PG 373 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Jason Height (jheight at chariot dot net dot au) + * Whether to print the gridlines when you enjoy the spreadsheet on paper. + * * @version 2.0-pre */ public final class PrintGridlinesRecord extends StandardRecord { - public final static short sid = 0x2b; - private short field_1_print_gridlines; + public static final short sid = 0x2b; + private short field_1_print_gridlines; - public PrintGridlinesRecord() { + public PrintGridlinesRecord() {} + + public PrintGridlinesRecord(PrintGridlinesRecord other) { + super(other); + field_1_print_gridlines = other.field_1_print_gridlines; } - public PrintGridlinesRecord(RecordInputStream in) - { + public PrintGridlinesRecord(RecordInputStream in) { field_1_print_gridlines = in.readShort(); } @@ -44,11 +45,7 @@ public final class PrintGridlinesRecord extends StandardRecord { * @param pg make spreadsheet ugly - Y/N */ public void setPrintGridlines(boolean pg) { - if (pg) { - field_1_print_gridlines = 1; - } else { - field_1_print_gridlines = 0; - } + field_1_print_gridlines = (short) (pg ? 1 : 0); } /** @@ -81,9 +78,15 @@ public final class PrintGridlinesRecord extends StandardRecord { return sid; } - public Object clone() { - PrintGridlinesRecord rec = new PrintGridlinesRecord(); - rec.field_1_print_gridlines = field_1_print_gridlines; - return rec; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public PrintGridlinesRecord clone() { + return copy(); + } + + public PrintGridlinesRecord copy() { + return new PrintGridlinesRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/PrintHeadersRecord.java b/src/java/org/apache/poi/hssf/record/PrintHeadersRecord.java index 607c4a8b7c..4ab1568351 100644 --- a/src/java/org/apache/poi/hssf/record/PrintHeadersRecord.java +++ b/src/java/org/apache/poi/hssf/record/PrintHeadersRecord.java @@ -18,25 +18,26 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Print Headers Record<P> - * Description: Whether or not to print the row/column headers when you - * enjoy your spreadsheet in the physical form.<P> - * REFERENCE: PG 373 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Jason Height (jheight at chariot dot net dot au) + * Whether or not to print the row/column headers when you enjoy your spreadsheet in the physical form. + * * @version 2.0-pre */ public final class PrintHeadersRecord extends StandardRecord { - public final static short sid = 0x2a; - private short field_1_print_headers; + public static final short sid = 0x2a; + private short field_1_print_headers; - public PrintHeadersRecord() { + public PrintHeadersRecord() {} + + public PrintHeadersRecord(PrintHeadersRecord other) { + super(other); + field_1_print_headers = other.field_1_print_headers; } - public PrintHeadersRecord(RecordInputStream in) - { + + public PrintHeadersRecord(RecordInputStream in) { field_1_print_headers = in.readShort(); } @@ -81,9 +82,15 @@ public final class PrintHeadersRecord extends StandardRecord { return sid; } - public Object clone() { - PrintHeadersRecord rec = new PrintHeadersRecord(); - rec.field_1_print_headers = field_1_print_headers; - return rec; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public PrintHeadersRecord clone() { + return copy(); + } + + public PrintHeadersRecord copy() { + return new PrintHeadersRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/PrintSetupRecord.java b/src/java/org/apache/poi/hssf/record/PrintSetupRecord.java index 6ab28c2369..7868185f0d 100644 --- a/src/java/org/apache/poi/hssf/record/PrintSetupRecord.java +++ b/src/java/org/apache/poi/hssf/record/PrintSetupRecord.java @@ -18,20 +18,36 @@ package org.apache.poi.hssf.record; import org.apache.poi.ss.usermodel.PrintSetup; -import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; +import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: PAGESETUP (0x00A1)<p> - * Description: Stores print setup options -- bogus for HSSF (and marked as such)<p> - * REFERENCE: PG 385 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<p> - * REFERENCE: PG 412 Microsoft Excel Binary File Format Structure v20091214 - * + * Stores print setup options -- bogus for HSSF (and marked as such) + * * @since 2.0-pre */ public final class PrintSetupRecord extends StandardRecord { - public final static short sid = 0x00A1; + public static final short sid = 0x00A1; + // print over then down + private static final BitField lefttoright = BitFieldFactory.getInstance(0x01); + // landscape mode + private static final BitField landscape = BitFieldFactory.getInstance(0x02); + // if papersize, scale, resolution, copies, landscape + private static final BitField validsettings = BitFieldFactory.getInstance(0x04); + // print mono/b&w, colorless + private static final BitField nocolor = BitFieldFactory.getInstance(0x08); + // print draft quality + private static final BitField draft = BitFieldFactory.getInstance(0x10); + // print the notes + private static final BitField notes = BitFieldFactory.getInstance(0x20); + // the orientation is not set + private static final BitField noOrientation = BitFieldFactory.getInstance(0x40); + // use a user set page no, instead of auto + private static final BitField usepage = BitFieldFactory.getInstance(0x80); + + /** Constants for this are held in {@link PrintSetup} */ private short field_1_paper_size; private short field_2_scale; @@ -39,37 +55,30 @@ public final class PrintSetupRecord extends StandardRecord { private short field_4_fit_width; private short field_5_fit_height; private short field_6_options; - static final private BitField lefttoright = - BitFieldFactory.getInstance(0x01); // print over then down - static final private BitField landscape = - BitFieldFactory.getInstance(0x02); // landscape mode - static final private BitField validsettings = BitFieldFactory.getInstance( - 0x04); // if papersize, scale, resolution, copies, landscape - - // weren't obtained from the print consider them - // mere bunk - static final private BitField nocolor = - BitFieldFactory.getInstance(0x08); // print mono/b&w, colorless - static final private BitField draft = - BitFieldFactory.getInstance(0x10); // print draft quality - static final private BitField notes = - BitFieldFactory.getInstance(0x20); // print the notes - static final private BitField noOrientation = - BitFieldFactory.getInstance(0x40); // the orientation is not set - static final private BitField usepage = - BitFieldFactory.getInstance(0x80); // use a user set page no, instead of auto private short field_7_hresolution; private short field_8_vresolution; private double field_9_headermargin; private double field_10_footermargin; private short field_11_copies; - public PrintSetupRecord() - { + public PrintSetupRecord() {} + + public PrintSetupRecord(PrintSetupRecord other) { + super(other); + field_1_paper_size = other.field_1_paper_size; + field_2_scale = other.field_2_scale; + field_3_page_start = other.field_3_page_start; + field_4_fit_width = other.field_4_fit_width; + field_5_fit_height = other.field_5_fit_height; + field_6_options = other.field_6_options; + field_7_hresolution = other.field_7_hresolution; + field_8_vresolution = other.field_8_vresolution; + field_9_headermargin = other.field_9_headermargin; + field_10_footermargin = other.field_10_footermargin; + field_11_copies = other.field_11_copies; } - public PrintSetupRecord(RecordInputStream in) - { + public PrintSetupRecord(RecordInputStream in) { field_1_paper_size = in.readShort(); field_2_scale = in.readShort(); field_3_page_start = in.readShort(); @@ -347,19 +356,16 @@ public final class PrintSetupRecord extends StandardRecord { return sid; } - public Object clone() { - PrintSetupRecord rec = new PrintSetupRecord(); - rec.field_1_paper_size = field_1_paper_size; - rec.field_2_scale = field_2_scale; - rec.field_3_page_start = field_3_page_start; - rec.field_4_fit_width = field_4_fit_width; - rec.field_5_fit_height = field_5_fit_height; - rec.field_6_options = field_6_options; - rec.field_7_hresolution = field_7_hresolution; - rec.field_8_vresolution = field_8_vresolution; - rec.field_9_headermargin = field_9_headermargin; - rec.field_10_footermargin = field_10_footermargin; - rec.field_11_copies = field_11_copies; - return rec; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public PrintSetupRecord clone() { + return copy(); + } + + @Override + public PrintSetupRecord copy() { + return new PrintSetupRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/ProtectRecord.java b/src/java/org/apache/poi/hssf/record/ProtectRecord.java index 9058026ad9..867c15c398 100644 --- a/src/java/org/apache/poi/hssf/record/ProtectRecord.java +++ b/src/java/org/apache/poi/hssf/record/ProtectRecord.java @@ -21,16 +21,15 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Protect Record (0x0012)<p> - * Description: defines whether a sheet or workbook is protected (HSSF DOES NOT SUPPORT ENCRYPTION)<p> + * Defines whether a sheet or workbook is protected (HSSF DOES NOT SUPPORT ENCRYPTION)<p> * HSSF now supports the simple "protected" sheets (where they are not encrypted and open office et al * ignore the password record entirely). - * REFERENCE: PG 373 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) */ public final class ProtectRecord extends StandardRecord { - public final static short sid = 0x0012; + public static final short sid = 0x0012; private static final BitField protectFlag = BitFieldFactory.getInstance(0x0001); @@ -40,6 +39,11 @@ public final class ProtectRecord extends StandardRecord { _options = options; } + private ProtectRecord(ProtectRecord other) { + super(other); + _options = other._options; + } + public ProtectRecord(boolean isProtected) { this(0); setProtect(isProtected); @@ -86,7 +90,16 @@ public final class ProtectRecord extends StandardRecord { return sid; } - public Object clone() { - return new ProtectRecord(_options); + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public ProtectRecord clone() { + return copy(); + } + + @Override + public ProtectRecord copy() { + return new ProtectRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/ProtectionRev4Record.java b/src/java/org/apache/poi/hssf/record/ProtectionRev4Record.java index ba51b6df38..0b6ab783b1 100644 --- a/src/java/org/apache/poi/hssf/record/ProtectionRev4Record.java +++ b/src/java/org/apache/poi/hssf/record/ProtectionRev4Record.java @@ -23,12 +23,10 @@ import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; /** - * Title: Protection Revision 4 Record (0x01AF)<p> - * Description: describes whether this is a protected shared/tracked workbook<p> - * REFERENCE: PG 373 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) + * Describes whether this is a protected shared/tracked workbook<p> */ public final class ProtectionRev4Record extends StandardRecord { - public final static short sid = 0x01AF; + public static final short sid = 0x01AF; private static final BitField protectedFlag = BitFieldFactory.getInstance(0x0001); @@ -38,6 +36,11 @@ public final class ProtectionRev4Record extends StandardRecord { _options = options; } + private ProtectionRev4Record(ProtectionRev4Record other) { + super(other); + _options = other._options; + } + public ProtectionRev4Record(boolean protect) { this(0); setProtect(protect); @@ -83,4 +86,9 @@ public final class ProtectionRev4Record extends StandardRecord { public short getSid() { return sid; } + + @Override + public ProtectionRev4Record copy() { + return new ProtectionRev4Record(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/RKRecord.java b/src/java/org/apache/poi/hssf/record/RKRecord.java index 3aac08d69f..b8846e127d 100644 --- a/src/java/org/apache/poi/hssf/record/RKRecord.java +++ b/src/java/org/apache/poi/hssf/record/RKRecord.java @@ -19,30 +19,31 @@ package org.apache.poi.hssf.record; import org.apache.poi.hssf.util.RKUtil; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: RK Record (0x027E)<p> - * Description: An internal 32 bit number with the two most significant bits - * storing the type. This is part of a bizarre scheme to save disk - * space and memory (gee look at all the other whole records that - * are in the file just "cause"..,far better to waste processor - * cycles on this then leave on of those "valuable" records out).<p> + * An internal 32 bit number with the two most significant bits storing the type. + * This is part of a bizarre scheme to save disk space and memory (gee look at all the other whole + * records that are in the file just "cause".., far better to waste processor cycles on this then + * leave on of those "valuable" records out). * We support this in READ-ONLY mode. HSSF converts these to NUMBER records<p> * - * REFERENCE: PG 376 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) - * * @see org.apache.poi.hssf.record.NumberRecord */ public final class RKRecord extends CellRecord { - public final static short sid = 0x027E; - public final static short RK_IEEE_NUMBER = 0; - public final static short RK_IEEE_NUMBER_TIMES_100 = 1; - public final static short RK_INTEGER = 2; - public final static short RK_INTEGER_TIMES_100 = 3; + public static final short sid = 0x027E; + public static final short RK_IEEE_NUMBER = 0; + public static final short RK_IEEE_NUMBER_TIMES_100 = 1; + public static final short RK_INTEGER = 2; + public static final short RK_INTEGER_TIMES_100 = 3; + private int field_4_rk_number; - private RKRecord() { - // fields uninitialised + private RKRecord() {} + + public RKRecord(RKRecord other) { + super(other); + field_4_rk_number = other.field_4_rk_number; } public RKRecord(RecordInputStream in) { @@ -97,10 +98,15 @@ public final class RKRecord extends CellRecord { } @Override - public Object clone() { - RKRecord rec = new RKRecord(); - copyBaseFields(rec); - rec.field_4_rk_number = field_4_rk_number; - return rec; + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public RKRecord clone() { + return copy(); + } + + @Override + public RKRecord copy() { + return new RKRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/RecalcIdRecord.java b/src/java/org/apache/poi/hssf/record/RecalcIdRecord.java index 933c5a9698..c86622077f 100644 --- a/src/java/org/apache/poi/hssf/record/RecalcIdRecord.java +++ b/src/java/org/apache/poi/hssf/record/RecalcIdRecord.java @@ -21,18 +21,16 @@ import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; /** - * Title: Recalc Id Record (0x01C1)<p> - * Description: This record contains an ID that marks when a worksheet was last - * recalculated. It's an optimization Excel uses to determine if it - * needs to recalculate the spreadsheet when it's opened. So far, only - * the two engine ids {@code 0x80 0x38 0x01 0x00} - * and {@code 0x60 0x69 0x01 0x00} have been seen. - * A value of {@code 0x00} will cause Excel to recalculate - * all formulas on the next load.<p> - * REFERENCE: http://chicago.sourceforge.net/devel/docs/excel/biff8.html + * This record contains an ID that marks when a worksheet was last recalculated. + * It's an optimization Excel uses to determine if it needs to recalculate the spreadsheet + * when it's opened. So far, only the two engine ids {@code 0x80 0x38 0x01 0x00} and + * {@code 0x60 0x69 0x01 0x00} have been seen. A value of {@code 0x00} will cause Excel + * to recalculate all formulas on the next load. + * + * @see <a href="http://chicago.sourceforge.net/devel/docs/excel/biff8.html">Chicago biff8 docs</a> */ public final class RecalcIdRecord extends StandardRecord { - public final static short sid = 0x01C1; + public static final short sid = 0x01C1; private final int _reserved0; /** @@ -49,6 +47,11 @@ public final class RecalcIdRecord extends StandardRecord { _engineId = 0; } + public RecalcIdRecord(RecalcIdRecord other) { + _reserved0 = other._reserved0; + _engineId = other._engineId; + } + public RecalcIdRecord(RecordInputStream in) { in.readUShort(); // field 'rt' should have value 0x01C1, but Excel doesn't care during reading _reserved0 = in.readUShort(); @@ -90,4 +93,9 @@ public final class RecalcIdRecord extends StandardRecord { public short getSid() { return sid; } + + @Override + public RecalcIdRecord copy() { + return new RecalcIdRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/Record.java b/src/java/org/apache/poi/hssf/record/Record.java index 60ba7cd5df..86c4f7c03e 100644 --- a/src/java/org/apache/poi/hssf/record/Record.java +++ b/src/java/org/apache/poi/hssf/record/Record.java @@ -19,14 +19,16 @@ package org.apache.poi.hssf.record; import java.io.ByteArrayInputStream; +import org.apache.poi.common.Duplicatable; + /** * All HSSF Records inherit from this class. */ -public abstract class Record extends RecordBase { +public abstract class Record extends RecordBase implements Duplicatable { - protected Record() { - // no fields to initialise - } + protected Record() {} + + protected Record(Record other) {} /** * called by the class that is responsible for writing this sucker. @@ -52,16 +54,11 @@ public abstract class Record extends RecordBase { /** * return the non static version of the id for this record. - * + * * @return he id for this record */ public abstract short getSid(); - @Override - public Object clone() throws CloneNotSupportedException { - throw new CloneNotSupportedException("The class "+getClass().getName()+" needs to define a clone method"); - } - /** * Clone the current record, via a call to serialize * it, and another to create a new record from the @@ -70,7 +67,7 @@ public abstract class Record extends RecordBase { * internal counts / ids in them. For those which * do, a full model-aware cloning is needed, which * allocates new ids / counts as needed. - * + * * @return the cloned current record */ public Record cloneViaReserialise() { @@ -86,4 +83,6 @@ public abstract class Record extends RecordBase { } return r[0]; } + + public abstract Record copy(); } diff --git a/src/java/org/apache/poi/hssf/record/RecordBase.java b/src/java/org/apache/poi/hssf/record/RecordBase.java index d19d2718d1..40907ec7e7 100644 --- a/src/java/org/apache/poi/hssf/record/RecordBase.java +++ b/src/java/org/apache/poi/hssf/record/RecordBase.java @@ -25,7 +25,7 @@ public abstract class RecordBase { * called by the class that is responsible for writing this sucker. * Subclasses should implement this so that their data is passed back in a * byte array. - * + * * @param offset to begin writing at * @param data byte array containing instance data * @return number of bytes written @@ -35,7 +35,7 @@ public abstract class RecordBase { /** * gives the current serialized size of the record. Should include the sid * and reclength (4 bytes). - * + * * @return the record size */ public abstract int getRecordSize(); diff --git a/src/java/org/apache/poi/hssf/record/RecordInputStream.java b/src/java/org/apache/poi/hssf/record/RecordInputStream.java index 400553721e..a8af77c2e1 100644 --- a/src/java/org/apache/poi/hssf/record/RecordInputStream.java +++ b/src/java/org/apache/poi/hssf/record/RecordInputStream.java @@ -41,7 +41,7 @@ public final class RecordInputStream implements LittleEndianInput { /** Maximum size of a single record (minus the 4 byte header) without a continue*/ - public final static short MAX_RECORD_DATA_SIZE = 8224; + public static final short MAX_RECORD_DATA_SIZE = 8224; private static final int INVALID_SID_VALUE = -1; //arbitrarily selected; may need to increase private static final int MAX_RECORD_LENGTH = 100_000; @@ -60,7 +60,7 @@ public final class RecordInputStream implements LittleEndianInput { public static final class LeftoverDataException extends RuntimeException { public LeftoverDataException(int sid, int remainingByteCount) { super("Initialisation of record 0x" + Integer.toHexString(sid).toUpperCase(Locale.ROOT) - + "(" + getRecordName(sid) + ") left " + remainingByteCount + + "(" + getRecordName(sid) + ") left " + remainingByteCount + " bytes remaining still to be read."); } @@ -177,9 +177,9 @@ public final class RecordInputStream implements LittleEndianInput { /** * Note - this method is expected to be called only when completed reading the current BIFF * record. - * + * * @return true, if there's another record in the stream - * + * * @throws LeftoverDataException if this method is called before reaching the end of the * current record. */ @@ -268,7 +268,7 @@ public final class RecordInputStream implements LittleEndianInput { } /** - * Reads a 32 bit, signed value + * Reads a 32 bit, signed value */ @Override public int readInt() { @@ -310,11 +310,11 @@ public final class RecordInputStream implements LittleEndianInput { // YK: Excel doesn't write NaN but instead converts the cell type into {@link CellType#ERROR}. return Double.longBitsToDouble(readLong()); } - + public void readPlain(byte[] buf, int off, int len) { readFully(buf, 0, buf.length, true); } - + @Override public void readFully(byte[] buf) { readFully(buf, 0, buf.length, false); @@ -324,7 +324,7 @@ public final class RecordInputStream implements LittleEndianInput { public void readFully(byte[] buf, int off, int len) { readFully(buf, off, len, false); } - + private void readFully(byte[] buf, int off, int len, boolean isPlain) { int origLen = len; if (buf == null) { @@ -332,7 +332,7 @@ public final class RecordInputStream implements LittleEndianInput { } else if (off < 0 || len < 0 || len > buf.length - off) { throw new IndexOutOfBoundsException(); } - + while (len > 0) { int nextChunk = Math.min(available(),len); if (nextChunk == 0) { @@ -452,7 +452,7 @@ public final class RecordInputStream implements LittleEndianInput { * into any following continue records. * * @return all byte data for the current record - * + * * @deprecated POI 2.0 Best to write a input stream that wraps this one * where there is special sub record that may overlap continue * records. @@ -511,10 +511,10 @@ public final class RecordInputStream implements LittleEndianInput { } /** - * Mark the stream position - experimental function + * Mark the stream position - experimental function * * @param readlimit the read ahead limit - * + * * @see InputStream#mark(int) */ @Internal @@ -522,13 +522,13 @@ public final class RecordInputStream implements LittleEndianInput { ((InputStream)_dataInput).mark(readlimit); _markedDataOffset = _currentDataOffset; } - + /** * Resets the stream position to the previously marked position. * Experimental function - this only works, when nextRecord() wasn't called in the meantime. * * @throws IOException if marking is not supported - * + * * @see InputStream#reset() */ @Internal diff --git a/src/java/org/apache/poi/hssf/record/RefModeRecord.java b/src/java/org/apache/poi/hssf/record/RefModeRecord.java index 987da8f768..5ad1635e9b 100644 --- a/src/java/org/apache/poi/hssf/record/RefModeRecord.java +++ b/src/java/org/apache/poi/hssf/record/RefModeRecord.java @@ -15,35 +15,32 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: RefMode Record<P> - * Description: Describes which reference mode to use<P> - * REFERENCE: PG 376 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Jason Height (jheight at chariot dot net dot au) + * Describes which reference mode to use + * * @version 2.0-pre */ -public final class RefModeRecord - extends StandardRecord -{ - public final static short sid = 0xf; - public final static short USE_A1_MODE = 1; - public final static short USE_R1C1_MODE = 0; +public final class RefModeRecord extends StandardRecord { + public static final short sid = 0xf; + public static final short USE_A1_MODE = 1; + public static final short USE_R1C1_MODE = 0; private short field_1_mode; - public RefModeRecord() - { + public RefModeRecord() {} + + public RefModeRecord(RefModeRecord other) { + field_1_mode = other.field_1_mode; } - public RefModeRecord(RecordInputStream in) - { + public RefModeRecord(RecordInputStream in) { field_1_mode = in.readShort(); } @@ -96,9 +93,16 @@ public final class RefModeRecord return sid; } - public Object clone() { - RefModeRecord rec = new RefModeRecord(); - rec.field_1_mode = field_1_mode; - return rec; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public RefModeRecord clone() { + return copy(); + } + + @Override + public RefModeRecord copy() { + return new RefModeRecord(); } } diff --git a/src/java/org/apache/poi/hssf/record/RefreshAllRecord.java b/src/java/org/apache/poi/hssf/record/RefreshAllRecord.java index ebe1c7ea3e..26c121401a 100644 --- a/src/java/org/apache/poi/hssf/record/RefreshAllRecord.java +++ b/src/java/org/apache/poi/hssf/record/RefreshAllRecord.java @@ -21,15 +21,14 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Refresh All Record (0x01B7)<p> - * Description: Flag whether to refresh all external data when loading a sheet. - * (which hssf doesn't support anyhow so who really cares?)<p> - * REFERENCE: PG 376 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) + * Flag whether to refresh all external data when loading a sheet. + * (which hssf doesn't support anyhow so who really cares?) */ public final class RefreshAllRecord extends StandardRecord { - public final static short sid = 0x01B7; + public static final short sid = 0x01B7; private static final BitField refreshFlag = BitFieldFactory.getInstance(0x0001); @@ -39,6 +38,11 @@ public final class RefreshAllRecord extends StandardRecord { _options = options; } + private RefreshAllRecord(RefreshAllRecord other) { + super(other); + _options = other._options; + } + public RefreshAllRecord(RecordInputStream in) { this(in.readUShort()); } @@ -84,8 +88,17 @@ public final class RefreshAllRecord extends StandardRecord { public short getSid() { return sid; } + + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public RefreshAllRecord clone() { + return copy(); + } + @Override - public Object clone() { - return new RefreshAllRecord(_options); + public RefreshAllRecord copy() { + return new RefreshAllRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/RightMarginRecord.java b/src/java/org/apache/poi/hssf/record/RightMarginRecord.java index 4a8f1b33f2..87458f5d8e 100644 --- a/src/java/org/apache/poi/hssf/record/RightMarginRecord.java +++ b/src/java/org/apache/poi/hssf/record/RightMarginRecord.java @@ -18,18 +18,23 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * Record for the right margin. */ public final class RightMarginRecord extends StandardRecord implements Margin { - public final static short sid = 0x27; + public static final short sid = 0x27; private double field_1_margin; - public RightMarginRecord() { } + public RightMarginRecord() {} - public RightMarginRecord( RecordInputStream in ) - { + public RightMarginRecord(RightMarginRecord other) { + super(other); + field_1_margin = other.field_1_margin; + } + + public RightMarginRecord( RecordInputStream in ) { field_1_margin = in.readDouble(); } @@ -63,10 +68,15 @@ public final class RightMarginRecord extends StandardRecord implements Margin { public void setMargin( double field_1_margin ) { this.field_1_margin = field_1_margin; } - public Object clone() - { - RightMarginRecord rec = new RightMarginRecord(); - rec.field_1_margin = this.field_1_margin; - return rec; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public RightMarginRecord clone() { + return copy(); + } + + public RightMarginRecord copy() { + return new RightMarginRecord(this); } -} // END OF
\ No newline at end of file +}
\ No newline at end of file diff --git a/src/java/org/apache/poi/hssf/record/RowRecord.java b/src/java/org/apache/poi/hssf/record/RowRecord.java index 2987e042ed..c04776d849 100644 --- a/src/java/org/apache/poi/hssf/record/RowRecord.java +++ b/src/java/org/apache/poi/hssf/record/RowRecord.java @@ -21,22 +21,34 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Row Record (0x0208)<p> - * Description: stores the row information for the sheet.<p> - * REFERENCE: PG 379 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) - * + * Stores the row information for the sheet. + * * @since 2.0-pre */ public final class RowRecord extends StandardRecord { - public final static short sid = 0x0208; + public static final short sid = 0x0208; public static final int ENCODED_SIZE = 20; - + private static final int OPTION_BITS_ALWAYS_SET = 0x0100; //private static final int DEFAULT_HEIGHT_BIT = 0x8000; + private static final BitField outlineLevel = BitFieldFactory.getInstance(0x07); + // bit 3 reserved + private static final BitField colapsed = BitFieldFactory.getInstance(0x10); + private static final BitField zeroHeight = BitFieldFactory.getInstance(0x20); + private static final BitField badFontHeight = BitFieldFactory.getInstance(0x40); + private static final BitField formatted = BitFieldFactory.getInstance(0x80); + + private static final BitField xfIndex = BitFieldFactory.getInstance(0xFFF); + private static final BitField topBorder = BitFieldFactory.getInstance(0x1000); + private static final BitField bottomBorder = BitFieldFactory.getInstance(0x2000); + private static final BitField phoeneticGuide = BitFieldFactory.getInstance(0x4000); + // bit 15 is unused + private int field_1_row_number; private int field_2_first_col; private int field_3_last_col; // plus 1 @@ -47,20 +59,21 @@ public final class RowRecord extends StandardRecord { private short field_6_reserved; /** 16 bit options flags */ private int field_7_option_flags; - private static final BitField outlineLevel = BitFieldFactory.getInstance(0x07); - // bit 3 reserved - private static final BitField colapsed = BitFieldFactory.getInstance(0x10); - private static final BitField zeroHeight = BitFieldFactory.getInstance(0x20); - private static final BitField badFontHeight = BitFieldFactory.getInstance(0x40); - private static final BitField formatted = BitFieldFactory.getInstance(0x80); - /** 16 bit options flags */ private int field_8_option_flags; // only if isFormatted - private static final BitField xfIndex = BitFieldFactory.getInstance(0xFFF); - private static final BitField topBorder = BitFieldFactory.getInstance(0x1000); - private static final BitField bottomBorder = BitFieldFactory.getInstance(0x2000); - private static final BitField phoeneticGuide = BitFieldFactory.getInstance(0x4000); - // bit 15 is unused + + public RowRecord(RowRecord other) { + super(other); + field_1_row_number = other.field_1_row_number; + field_2_first_col = other.field_2_first_col; + field_3_last_col = other.field_3_last_col; + field_4_height = other.field_4_height; + field_5_optimize = other.field_5_optimize; + field_6_reserved = other.field_6_reserved; + field_7_option_flags = other.field_7_option_flags; + field_8_option_flags = other.field_8_option_flags; + } + public RowRecord(int rowNumber) { if(rowNumber < 0) { @@ -91,7 +104,7 @@ public final class RowRecord extends StandardRecord { } /** - * Updates the firstCol and lastCol fields to the reserved value (-1) + * Updates the firstCol and lastCol fields to the reserved value (-1) * to signify that this row is empty */ public void setEmpty() { @@ -101,7 +114,7 @@ public final class RowRecord extends StandardRecord { public boolean isEmpty() { return (field_2_first_col | field_3_last_col) == 0; } - + /** * set the logical row number for this row (0 based index) * @param row - the row number @@ -202,7 +215,7 @@ public final class RowRecord extends StandardRecord { public void setTopBorder(boolean f) { field_8_option_flags = topBorder.setBoolean(field_8_option_flags, f); } - + /** * A bit that specifies whether any cell in the row has a medium or thick * bottom border, or any cell in the row directly below the current row has @@ -212,7 +225,7 @@ public final class RowRecord extends StandardRecord { public void setBottomBorder(boolean f) { field_8_option_flags = bottomBorder.setBoolean(field_8_option_flags, f); } - + /** * A bit that specifies whether the phonetic guide feature is enabled for * any cell in this row. @@ -221,7 +234,7 @@ public final class RowRecord extends StandardRecord { public void setPhoeneticGuide(boolean f) { field_8_option_flags = phoeneticGuide.setBoolean(field_8_option_flags, f); } - + /** * get the logical row number for this row (0 based index) * @return row - the row number @@ -239,7 +252,7 @@ public final class RowRecord extends StandardRecord { } /** - * get the logical col number for the last cell this row (0 based index), plus one + * get the logical col number for the last cell this row (0 based index), plus one * @return col - the last col index + 1 */ public int getLastCol() { @@ -328,7 +341,7 @@ public final class RowRecord extends StandardRecord { public short getOptionFlags2() { return (short)field_8_option_flags; } - + /** * if the row is formatted then this is the index to the extended format record * @see org.apache.poi.hssf.record.ExtendedFormatRecord @@ -364,7 +377,7 @@ public final class RowRecord extends StandardRecord { public boolean getPhoeneticGuide() { return phoeneticGuide.isSet(field_8_option_flags); } - + public String toString() { StringBuilder sb = new StringBuilder(); @@ -410,15 +423,16 @@ public final class RowRecord extends StandardRecord { return sid; } - public Object clone() { - RowRecord rec = new RowRecord(field_1_row_number); - rec.field_2_first_col = field_2_first_col; - rec.field_3_last_col = field_3_last_col; - rec.field_4_height = field_4_height; - rec.field_5_optimize = field_5_optimize; - rec.field_6_reserved = field_6_reserved; - rec.field_7_option_flags = field_7_option_flags; - rec.field_8_option_flags = field_8_option_flags; - return rec; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public RowRecord clone() { + return copy(); + } + + @Override + public RowRecord copy() { + return new RowRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/SCLRecord.java b/src/java/org/apache/poi/hssf/record/SCLRecord.java index c4dbfb0a53..73757a4bce 100644 --- a/src/java/org/apache/poi/hssf/record/SCLRecord.java +++ b/src/java/org/apache/poi/hssf/record/SCLRecord.java @@ -19,24 +19,27 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * Specifies the window's zoom magnification.<p> * If this record isn't present then the windows zoom is 100%. see p384 Excel Dev Kit */ public final class SCLRecord extends StandardRecord { - public final static short sid = 0x00A0; - private short field_1_numerator; - private short field_2_denominator; + public static final short sid = 0x00A0; + private short field_1_numerator; + private short field_2_denominator; - public SCLRecord() - { + public SCLRecord() {} + public SCLRecord(SCLRecord other) { + super(other); + field_1_numerator = other.field_1_numerator; + field_2_denominator = other.field_2_denominator; } - public SCLRecord(RecordInputStream in) - { + public SCLRecord(RecordInputStream in) { field_1_numerator = in.readShort(); field_2_denominator = in.readShort(); } @@ -50,11 +53,11 @@ public final class SCLRecord extends StandardRecord { buffer.append(" .numerator = ") .append("0x").append(HexDump.toHex( getNumerator ())) .append(" (").append( getNumerator() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .denominator = ") .append("0x").append(HexDump.toHex( getDenominator ())) .append(" (").append( getDenominator() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append("[/SCL]\n"); return buffer.toString(); @@ -78,17 +81,21 @@ public final class SCLRecord extends StandardRecord { } @Override - public Object clone() { - SCLRecord rec = new SCLRecord(); - - rec.field_1_numerator = field_1_numerator; - rec.field_2_denominator = field_2_denominator; - return rec; + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public SCLRecord clone() { + return copy(); + } + + @Override + public SCLRecord copy() { + return new SCLRecord(this); } /** * Get the numerator field for the SCL record. - * + * * @return the numerator */ public short getNumerator() @@ -98,7 +105,7 @@ public final class SCLRecord extends StandardRecord { /** * Set the numerator field for the SCL record. - * + * * @param field_1_numerator the numerator */ public void setNumerator(short field_1_numerator) @@ -108,7 +115,7 @@ public final class SCLRecord extends StandardRecord { /** * Get the denominator field for the SCL record. - * + * * @return the denominator */ public short getDenominator() @@ -118,7 +125,7 @@ public final class SCLRecord extends StandardRecord { /** * Set the denominator field for the SCL record. - * + * * @param field_2_denominator the denominator */ public void setDenominator(short field_2_denominator) diff --git a/src/java/org/apache/poi/hssf/record/SSTRecord.java b/src/java/org/apache/poi/hssf/record/SSTRecord.java index f7f1365d0e..aa79678f2c 100644 --- a/src/java/org/apache/poi/hssf/record/SSTRecord.java +++ b/src/java/org/apache/poi/hssf/record/SSTRecord.java @@ -23,14 +23,11 @@ import org.apache.poi.hssf.record.common.UnicodeString; import org.apache.poi.hssf.record.cont.ContinuableRecord; import org.apache.poi.hssf.record.cont.ContinuableRecordOutput; import org.apache.poi.util.IntMapper; -import org.apache.poi.util.LittleEndianConsts; /** - * Title: Static String Table Record (0x00FC)<p> + * Static String Table Record (0x00FC)<p> * - * Description: This holds all the strings for LabelSSTRecords.<p> - * - * REFERENCE: PG 389 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) + * This holds all the strings for LabelSSTRecords. * * @see org.apache.poi.hssf.record.LabelSSTRecord * @see org.apache.poi.hssf.record.ContinueRecord @@ -40,38 +37,45 @@ public final class SSTRecord extends ContinuableRecord { private static final UnicodeString EMPTY_STRING = new UnicodeString(""); - // TODO - move these constants to test class (the only consumer) - /** standard record overhead: two shorts (record id plus data space size)*/ - static final int STD_RECORD_OVERHEAD = 2 * LittleEndianConsts.SHORT_SIZE; - - /** SST overhead: the standard record overhead, plus the number of strings and the number of unique strings -- two ints */ - static final int SST_RECORD_OVERHEAD = STD_RECORD_OVERHEAD + 2 * LittleEndianConsts.INT_SIZE; - - /** how much data can we stuff into an SST record? That would be _max minus the standard SST record overhead */ - static final int MAX_DATA_SPACE = RecordInputStream.MAX_RECORD_DATA_SIZE - 8; - - /** union of strings in the SST and EXTSST */ + /** + * union of strings in the SST and EXTSST + */ private int field_1_num_strings; - /** according to docs ONLY SST */ + /** + * according to docs ONLY SST + */ private int field_2_num_unique_strings; private IntMapper<UnicodeString> field_3_strings; private SSTDeserializer deserializer; - /** Offsets from the beginning of the SST record (even across continuations) */ - int[] bucketAbsoluteOffsets; - /** Offsets relative the start of the current SST or continue record */ - int[] bucketRelativeOffsets; + /** + * Offsets from the beginning of the SST record (even across continuations) + */ + private int[] bucketAbsoluteOffsets; + /** + * Offsets relative the start of the current SST or continue record + */ + private int[] bucketRelativeOffsets; - public SSTRecord() - { + public SSTRecord() { field_1_num_strings = 0; field_2_num_unique_strings = 0; field_3_strings = new IntMapper<>(); deserializer = new SSTDeserializer(field_3_strings); } + public SSTRecord(SSTRecord other) { + super(other); + field_1_num_strings = other.field_1_num_strings; + field_2_num_unique_strings = other.field_2_num_unique_strings; + field_3_strings = other.field_3_strings.copy(); + deserializer = new SSTDeserializer(field_3_strings); + bucketAbsoluteOffsets = (other.bucketAbsoluteOffsets == null) ? null : other.bucketAbsoluteOffsets.clone(); + bucketRelativeOffsets = (other.bucketRelativeOffsets == null) ? null : other.bucketRelativeOffsets.clone(); + } + /** * Add a string. * @@ -242,7 +246,7 @@ public final class SSTRecord extends ContinuableRecord { field_1_num_strings = in.readInt(); field_2_num_unique_strings = in.readInt(); field_3_strings = new IntMapper<>(); - + deserializer = new SSTDeserializer(field_3_strings); // Bug 57456: some Excel Sheets send 0 as field=1, but have some random number in field_2, // we should not try to read the strings in this case. @@ -319,4 +323,9 @@ public final class SSTRecord extends ContinuableRecord { public int calcExtSSTRecordSize() { return ExtSSTRecord.getRecordSizeForStrings(field_3_strings.size()); } + + @Override + public SSTRecord copy() { + return new SSTRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/SaveRecalcRecord.java b/src/java/org/apache/poi/hssf/record/SaveRecalcRecord.java index 05c66f78f0..8945d8035d 100644 --- a/src/java/org/apache/poi/hssf/record/SaveRecalcRecord.java +++ b/src/java/org/apache/poi/hssf/record/SaveRecalcRecord.java @@ -18,43 +18,44 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Save Recalc Record <P> - * Description: defines whether to recalculate before saving (set to true)<P> - * REFERENCE: PG 381 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Jason Height (jheight at chariot dot net dot au) + * Defines whether to recalculate before saving (set to true) + * * @version 2.0-pre */ -public final class SaveRecalcRecord - extends StandardRecord -{ - public final static short sid = 0x5f; - private short field_1_recalc; +public final class SaveRecalcRecord extends StandardRecord { + public static final short sid = 0x5f; + private short field_1_recalc; public SaveRecalcRecord() { } - public SaveRecalcRecord(RecordInputStream in) - { + public SaveRecalcRecord(SaveRecalcRecord other) { + super(other); + field_1_recalc = other.field_1_recalc; + } + + public SaveRecalcRecord(RecordInputStream in) { field_1_recalc = in.readShort(); } /** * set whether to recalculate formulas/etc before saving or not + * * @param recalc - whether to recalculate or not */ public void setRecalc(boolean recalc) { - field_1_recalc = ( short ) (recalc ? 1 : 0); + field_1_recalc = (short) (recalc ? 1 : 0); } /** * get whether to recalculate formulas/etc before saving or not + * * @return recalc - whether to recalculate or not */ - public boolean getRecalc() - { + public boolean getRecalc() { return (field_1_recalc == 1); } @@ -73,14 +74,20 @@ public final class SaveRecalcRecord return 2; } - public short getSid() - { + public short getSid() { return sid; } - public Object clone() { - SaveRecalcRecord rec = new SaveRecalcRecord(); - rec.field_1_recalc = field_1_recalc; - return rec; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public SaveRecalcRecord clone() { + return copy(); + } + + @Override + public SaveRecalcRecord copy() { + return new SaveRecalcRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/ScenarioProtectRecord.java b/src/java/org/apache/poi/hssf/record/ScenarioProtectRecord.java index 20e10945c0..400caf68a8 100644 --- a/src/java/org/apache/poi/hssf/record/ScenarioProtectRecord.java +++ b/src/java/org/apache/poi/hssf/record/ScenarioProtectRecord.java @@ -15,35 +15,30 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Scenario Protect Record<P> - * Description: I have no idea what a Scenario is or why on would want to - * protect it with the lamest "security" ever invented. However this record tells - * excel "I want to protect my scenarios" (0xAF) with lame security. It appears - * in conjunction with the PASSWORD and PROTECT records as well as its object - * protect cousin.<P> - * REFERENCE: PG 383 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) + * I have no idea what a Scenario is or why on would want to protect it with the lamest "security" ever invented. + * However this record tells excel "I want to protect my scenarios" (0xAF) with lame security. + * It appears in conjunction with the PASSWORD and PROTECT records as well as its object protect cousin. */ +public final class ScenarioProtectRecord extends StandardRecord { + public static final short sid = 0xdd; + private short field_1_protect; -public final class ScenarioProtectRecord - extends StandardRecord -{ - public final static short sid = 0xdd; - private short field_1_protect; + public ScenarioProtectRecord() {} - public ScenarioProtectRecord() - { + public ScenarioProtectRecord(ScenarioProtectRecord other) { + super(other); + field_1_protect = other.field_1_protect; } - public ScenarioProtectRecord(RecordInputStream in) - { + public ScenarioProtectRecord(RecordInputStream in) { field_1_protect = in.readShort(); } @@ -98,9 +93,15 @@ public final class ScenarioProtectRecord return sid; } - public Object clone() { - ScenarioProtectRecord rec = new ScenarioProtectRecord(); - rec.field_1_protect = field_1_protect; - return rec; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public ScenarioProtectRecord clone() { + return copy(); + } + + public ScenarioProtectRecord copy() { + return new ScenarioProtectRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/SelectionRecord.java b/src/java/org/apache/poi/hssf/record/SelectionRecord.java index 904fe04109..08d14bae0c 100644 --- a/src/java/org/apache/poi/hssf/record/SelectionRecord.java +++ b/src/java/org/apache/poi/hssf/record/SelectionRecord.java @@ -17,28 +17,39 @@ package org.apache.poi.hssf.record; +import java.util.stream.Stream; + import org.apache.poi.hssf.util.CellRangeAddress8Bit; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Selection Record (0x001D)<P> - * Description: shows the user's selection on the sheet - * for write set num refs to 0<P> - * - * REFERENCE: PG 291 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) + * Shows the user's selection on the sheet for write set num refs to 0 */ public final class SelectionRecord extends StandardRecord { - public final static short sid = 0x001D; - private byte field_1_pane; - private int field_2_row_active_cell; - private int field_3_col_active_cell; - private int field_4_active_cell_ref_index; + public static final short sid = 0x001D; + + + private byte field_1_pane; + private int field_2_row_active_cell; + private int field_3_col_active_cell; + private int field_4_active_cell_ref_index; private CellRangeAddress8Bit[] field_6_refs; + public SelectionRecord(SelectionRecord other) { + super(other); + field_1_pane = other.field_1_pane; + field_2_row_active_cell = other.field_2_row_active_cell; + field_3_col_active_cell = other.field_3_col_active_cell; + field_4_active_cell_ref_index = other.field_4_active_cell_ref_index; + field_6_refs = (other.field_6_refs == null) ? null + : Stream.of(other.field_6_refs).map(CellRangeAddress8Bit::copy).toArray(CellRangeAddress8Bit[]::new); + } + /** * Creates a default selection record (cell A1, in pane ID 3) - * + * * @param activeCellRow the active cells row index * @param activeCellCol the active cells column index */ @@ -172,11 +183,15 @@ public final class SelectionRecord extends StandardRecord { } @Override - public Object clone() { - SelectionRecord rec = new SelectionRecord(field_2_row_active_cell, field_3_col_active_cell); - rec.field_1_pane = field_1_pane; - rec.field_4_active_cell_ref_index = field_4_active_cell_ref_index; - rec.field_6_refs = field_6_refs; - return rec; + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public SelectionRecord clone() { + return copy(); + } + + @Override + public SelectionRecord copy() { + return new SelectionRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java b/src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java index 328402db80..a54ba8fbb4 100644 --- a/src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java +++ b/src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java @@ -17,27 +17,26 @@ package org.apache.poi.hssf.record; -import org.apache.poi.ss.formula.ptg.*; import org.apache.poi.hssf.util.CellRangeAddress8Bit; -import org.apache.poi.ss.formula.Formula; import org.apache.poi.ss.SpreadsheetVersion; +import org.apache.poi.ss.formula.Formula; import org.apache.poi.ss.formula.SharedFormula; +import org.apache.poi.ss.formula.ptg.Ptg; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: SHAREDFMLA (0x04BC) SharedFormulaRecord - * Description: Primarily used as an excel optimization so that multiple similar formulas - * are not written out too many times. We should recognize this record and - * serialize as is since this is used when reading templates. + * Primarily used as an excel optimization so that multiple similar formulas are not + * written out too many times. We should recognize this record and serialize as is + * since this is used when reading templates. * <p> * Note: the documentation says that the SID is BC where biffviewer reports 4BC. The hex dump shows * that the two byte sid representation to be 'BC 04' that is consistent with the other high byte * record types. - * @author Danny Mui at apache dot org */ public final class SharedFormulaRecord extends SharedValueRecordBase { - public final static short sid = 0x04BC; + public static final short sid = 0x04BC; private int field_5_reserved; private Formula field_7_parsed_expr; @@ -46,6 +45,13 @@ public final class SharedFormulaRecord extends SharedValueRecordBase { public SharedFormulaRecord() { this(new CellRangeAddress8Bit(0,0,0,0)); } + + public SharedFormulaRecord(SharedFormulaRecord other) { + super(other); + field_5_reserved = other.field_5_reserved; + field_7_parsed_expr = (other.field_7_parsed_expr == null) ? null : other.field_7_parsed_expr.copy(); + } + private SharedFormulaRecord(CellRangeAddress8Bit range) { super(range); field_7_parsed_expr = Formula.create(Ptg.EMPTY_PTG_ARRAY); @@ -117,11 +123,17 @@ public final class SharedFormulaRecord extends SharedValueRecordBase { return sf.convertSharedFormulas(field_7_parsed_expr.getTokens(), formulaRow, formulaColumn); } - public Object clone() { - SharedFormulaRecord result = new SharedFormulaRecord(getRange()); - result.field_5_reserved = field_5_reserved; - result.field_7_parsed_expr = field_7_parsed_expr.copy(); - return result; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public SharedFormulaRecord clone() { + return copy(); + } + + @Override + public SharedFormulaRecord copy() { + return new SharedFormulaRecord(this); } public boolean isFormulaSame(SharedFormulaRecord other) { return field_7_parsed_expr.isSame(other.field_7_parsed_expr); diff --git a/src/java/org/apache/poi/hssf/record/SharedValueRecordBase.java b/src/java/org/apache/poi/hssf/record/SharedValueRecordBase.java index 51fe091808..3f23037d2a 100644 --- a/src/java/org/apache/poi/hssf/record/SharedValueRecordBase.java +++ b/src/java/org/apache/poi/hssf/record/SharedValueRecordBase.java @@ -29,6 +29,11 @@ public abstract class SharedValueRecordBase extends StandardRecord { private CellRangeAddress8Bit _range; + protected SharedValueRecordBase(SharedValueRecordBase other) { + super(other); + _range = (other._range == null) ? null : other._range.copy(); + } + protected SharedValueRecordBase(CellRangeAddress8Bit range) { if (range == null) { throw new IllegalArgumentException("range must be supplied."); @@ -88,9 +93,9 @@ public abstract class SharedValueRecordBase extends StandardRecord { /** * @param rowIx the row index * @param colIx the column index - * + * * @return {@code true} if (rowIx, colIx) is within the range of this shared value object. - * + * * @see #getRange() */ public final boolean isInRange(int rowIx, int colIx) { diff --git a/src/java/org/apache/poi/hssf/record/StandardRecord.java b/src/java/org/apache/poi/hssf/record/StandardRecord.java index 610c57b835..ac7637672b 100644 --- a/src/java/org/apache/poi/hssf/record/StandardRecord.java +++ b/src/java/org/apache/poi/hssf/record/StandardRecord.java @@ -29,6 +29,10 @@ import org.apache.poi.util.LittleEndianOutput; public abstract class StandardRecord extends Record { protected abstract int getDataSize(); + protected StandardRecord() {} + + protected StandardRecord(StandardRecord other) {} + @Override public final int getRecordSize() { return 4 + getDataSize(); @@ -75,4 +79,6 @@ public abstract class StandardRecord extends Record { * the output object */ protected abstract void serialize(LittleEndianOutput out); + + public abstract StandardRecord copy(); } diff --git a/src/java/org/apache/poi/hssf/record/StringRecord.java b/src/java/org/apache/poi/hssf/record/StringRecord.java index d672588614..106331bb1a 100644 --- a/src/java/org/apache/poi/hssf/record/StringRecord.java +++ b/src/java/org/apache/poi/hssf/record/StringRecord.java @@ -19,20 +19,25 @@ package org.apache.poi.hssf.record; import org.apache.poi.hssf.record.cont.ContinuableRecord; import org.apache.poi.hssf.record.cont.ContinuableRecordOutput; +import org.apache.poi.util.Removal; import org.apache.poi.util.StringUtil; /** * STRING (0x0207)<p> - * + * * Stores the cached result of a text formula */ public final class StringRecord extends ContinuableRecord { - public final static short sid = 0x0207; + public static final short sid = 0x0207; private boolean _is16bitUnicode; private String _text; - public StringRecord() { + public StringRecord() {} + + public StringRecord(StringRecord other) { + _is16bitUnicode = other._is16bitUnicode; + _text = other._text; } /** @@ -41,7 +46,7 @@ public final class StringRecord extends ContinuableRecord { public StringRecord( RecordInputStream in) { int field_1_string_length = in.readUShort(); _is16bitUnicode = in.readByte() != 0x00; - + if (_is16bitUnicode){ _text = in.readUnicodeLEString(field_1_string_length); } else { @@ -74,7 +79,7 @@ public final class StringRecord extends ContinuableRecord { */ public void setString(String string) { _text = string; - _is16bitUnicode = StringUtil.hasMultibyte(string); + _is16bitUnicode = StringUtil.hasMultibyte(string); } public String toString() { @@ -82,11 +87,16 @@ public final class StringRecord extends ContinuableRecord { " .string = " + _text + "\n" + "[/STRING]\n"; } - - public Object clone() { - StringRecord rec = new StringRecord(); - rec._is16bitUnicode= _is16bitUnicode; - rec._text = _text; - return rec; + + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public StringRecord clone() { + return copy(); + } + + public StringRecord copy() { + return new StringRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/StyleRecord.java b/src/java/org/apache/poi/hssf/record/StyleRecord.java index c5b7db7562..8acb8d0d6d 100644 --- a/src/java/org/apache/poi/hssf/record/StyleRecord.java +++ b/src/java/org/apache/poi/hssf/record/StyleRecord.java @@ -25,12 +25,10 @@ import org.apache.poi.util.RecordFormatException; import org.apache.poi.util.StringUtil; /** - * Title: Style Record (0x0293)<p> - * Description: Describes a builtin to the gui or user defined style<p> - * REFERENCE: PG 390 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) + * Describes a builtin to the gui or user defined style */ public final class StyleRecord extends StandardRecord { - public final static short sid = 0x0293; + public static final short sid = 0x0293; private static final BitField styleIndexMask = BitFieldFactory.getInstance(0x0FFF); private static final BitField isBuiltinFlag = BitFieldFactory.getInstance(0x8000); @@ -53,6 +51,15 @@ public final class StyleRecord extends StandardRecord { field_1_xf_index = isBuiltinFlag.set(0); } + public StyleRecord(StyleRecord other) { + super(other); + field_1_xf_index = other.field_1_xf_index; + field_2_builtin_style = other.field_2_builtin_style; + field_3_outline_style_level = other.field_3_outline_style_level; + field_3_stringHasMultibyte = other.field_3_stringHasMultibyte; + field_4_name = other.field_4_name; + } + public StyleRecord(RecordInputStream in) { field_1_xf_index = in.readShort(); if (isBuiltin()) { @@ -189,4 +196,9 @@ public final class StyleRecord extends StandardRecord { public short getSid() { return sid; } + + @Override + public StyleRecord copy() { + return new StyleRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/SubRecord.java b/src/java/org/apache/poi/hssf/record/SubRecord.java index 9e24213519..aaab95881f 100644 --- a/src/java/org/apache/poi/hssf/record/SubRecord.java +++ b/src/java/org/apache/poi/hssf/record/SubRecord.java @@ -17,27 +17,29 @@ package org.apache.poi.hssf.record; +import java.io.ByteArrayOutputStream; + +import org.apache.poi.common.Duplicatable; import org.apache.poi.util.HexDump; import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutputStream; - -import java.io.ByteArrayOutputStream; +import org.apache.poi.util.Removal; /** * Subrecords are part of the OBJ class. */ -public abstract class SubRecord { +public abstract class SubRecord implements Duplicatable { //arbitrarily selected; may need to increase private static final int MAX_RECORD_LENGTH = 1_000_000; - protected SubRecord() { - // no fields to initialise - } + protected SubRecord() {} - /** + protected SubRecord(SubRecord other) {} + + /** * read a sub-record from the supplied stream * * @param in the stream to read from @@ -90,8 +92,6 @@ public abstract class SubRecord { public abstract void serialize(LittleEndianOutput out); - @Override - public abstract SubRecord clone(); /** * Whether this record terminates the sub-record stream. @@ -126,8 +126,17 @@ public abstract class SubRecord { out.writeShort(_data.length); out.write(_data); } + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public UnknownSubRecord clone() { + return copy(); + } + + @Override + public UnknownSubRecord copy() { return this; } @Override @@ -141,4 +150,13 @@ public abstract class SubRecord { return sb.toString(); } } + + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public abstract SubRecord clone(); + + @Override + public abstract SubRecord copy(); } diff --git a/src/java/org/apache/poi/hssf/record/SupBookRecord.java b/src/java/org/apache/poi/hssf/record/SupBookRecord.java index 32046669a6..212cc63360 100644 --- a/src/java/org/apache/poi/hssf/record/SupBookRecord.java +++ b/src/java/org/apache/poi/hssf/record/SupBookRecord.java @@ -23,45 +23,42 @@ import org.apache.poi.util.POILogger; import org.apache.poi.util.StringUtil; /** - * Title: Sup Book - EXTERNALBOOK (0x01AE)<p> - * Description: A External Workbook Description (Supplemental Book) - * Its only a dummy record for making new ExternSheet Record<p> - * REFERENCE: 5.38 + * A External Workbook Description (Supplemental Book). + * Its only a dummy record for making new ExternSheet Record */ public final class SupBookRecord extends StandardRecord { - private final static POILogger logger = POILogFactory.getLogger(SupBookRecord.class); - - public final static short sid = 0x01AE; + private static final POILogger logger = POILogFactory.getLogger(SupBookRecord.class); + + public static final short sid = 0x01AE; private static final short SMALL_RECORD_SIZE = 4; private static final short TAG_INTERNAL_REFERENCES = 0x0401; private static final short TAG_ADD_IN_FUNCTIONS = 0x3A01; + static final char CH_VOLUME = 1; + static final char CH_SAME_VOLUME = 2; + static final char CH_DOWN_DIR = 3; + static final char CH_UP_DIR = 4; + static final char CH_LONG_VOLUME = 5; + static final char CH_STARTUP_DIR = 6; + static final char CH_ALT_STARTUP_DIR = 7; + static final char CH_LIB_DIR = 8; + static final String PATH_SEPERATOR = System.getProperty("file.separator"); + private short field_1_number_of_sheets; private String field_2_encoded_url; private String[] field_3_sheet_names; private boolean _isAddInFunctions; - protected static final char CH_VOLUME = 1; - protected static final char CH_SAME_VOLUME = 2; - protected static final char CH_DOWN_DIR = 3; - protected static final char CH_UP_DIR = 4; - protected static final char CH_LONG_VOLUME = 5; - protected static final char CH_STARTUP_DIR = 6; - protected static final char CH_ALT_STARTUP_DIR = 7; - protected static final char CH_LIB_DIR = 8; - protected static final String PATH_SEPERATOR = System.getProperty("file.separator"); - - public static SupBookRecord createInternalReferences(short numberOfSheets) { - return new SupBookRecord(false, numberOfSheets); - } - public static SupBookRecord createAddInFunctions() { - return new SupBookRecord(true, (short)1 /* this field MUST be 0x0001 for add-in referencing */); - } - public static SupBookRecord createExternalReferences(String url, String[] sheetNames) { - return new SupBookRecord(url, sheetNames); + public SupBookRecord(SupBookRecord other) { + super(other); + field_1_number_of_sheets = other.field_1_number_of_sheets; + field_2_encoded_url = other.field_2_encoded_url; + field_3_sheet_names = other.field_3_sheet_names; + _isAddInFunctions = other._isAddInFunctions; } + private SupBookRecord(boolean isAddInFuncs, short numberOfSheets) { // else not 'External References' field_1_number_of_sheets = numberOfSheets; @@ -69,6 +66,7 @@ public final class SupBookRecord extends StandardRecord { field_3_sheet_names = null; _isAddInFunctions = isAddInFuncs; } + public SupBookRecord(String url, String[] sheetNames) { field_1_number_of_sheets = (short) sheetNames.length; field_2_encoded_url = url; @@ -76,6 +74,16 @@ public final class SupBookRecord extends StandardRecord { _isAddInFunctions = false; } + public static SupBookRecord createInternalReferences(short numberOfSheets) { + return new SupBookRecord(false, numberOfSheets); + } + public static SupBookRecord createAddInFunctions() { + return new SupBookRecord(true, (short)1 /* this field MUST be 0x0001 for add-in referencing */); + } + public static SupBookRecord createExternalReferences(String url, String[] sheetNames) { + return new SupBookRecord(url, sheetNames); + } + public boolean isExternalReferences() { return field_3_sheet_names != null; } @@ -248,9 +256,14 @@ public final class SupBookRecord extends StandardRecord { public String[] getSheetNames() { return field_3_sheet_names.clone(); } - + public void setURL(String pUrl) { //Keep the first marker character! - field_2_encoded_url = field_2_encoded_url.substring(0, 1) + pUrl; + field_2_encoded_url = field_2_encoded_url.substring(0, 1) + pUrl; + } + + @Override + public SupBookRecord copy() { + return new SupBookRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/TabIdRecord.java b/src/java/org/apache/poi/hssf/record/TabIdRecord.java index 833357029e..f1bfd672b1 100644 --- a/src/java/org/apache/poi/hssf/record/TabIdRecord.java +++ b/src/java/org/apache/poi/hssf/record/TabIdRecord.java @@ -20,13 +20,10 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; /** - * Title: Sheet Tab Index Array Record (0x013D)<p> - * Description: Contains an array of sheet id's. Sheets always keep their ID - * regardless of what their name is.<p> - * REFERENCE: PG 412 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) + * Contains an array of sheet id's. Sheets always keep their ID regardless of what their name is. */ public final class TabIdRecord extends StandardRecord { - public final static short sid = 0x013D; + public static final short sid = 0x013D; private static final short[] EMPTY_SHORT_ARRAY = { }; public short[] _tabids; @@ -35,6 +32,11 @@ public final class TabIdRecord extends StandardRecord { _tabids = EMPTY_SHORT_ARRAY; } + public TabIdRecord(TabIdRecord other) { + super(other); + _tabids = (other._tabids == null) ? null : other._tabids.clone(); + } + public TabIdRecord(RecordInputStream in) { int nTabs = in.remaining() / 2; _tabids = new short[nTabs]; @@ -64,10 +66,8 @@ public final class TabIdRecord extends StandardRecord { } public void serialize(LittleEndianOutput out) { - short[] tabids = _tabids; - - for (int i = 0; i < tabids.length; i++) { - out.writeShort(tabids[i]); + for (short tabid : _tabids) { + out.writeShort(tabid); } } @@ -78,4 +78,9 @@ public final class TabIdRecord extends StandardRecord { public short getSid() { return sid; } + + @Override + public TabIdRecord copy() { + return new TabIdRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/TableRecord.java b/src/java/org/apache/poi/hssf/record/TableRecord.java index 2dd1d0ee01..571b58f59e 100644 --- a/src/java/org/apache/poi/hssf/record/TableRecord.java +++ b/src/java/org/apache/poi/hssf/record/TableRecord.java @@ -17,22 +17,17 @@ package org.apache.poi.hssf.record; -import org.apache.poi.ss.formula.ptg.TblPtg; import org.apache.poi.hssf.util.CellRangeAddress8Bit; +import org.apache.poi.ss.formula.ptg.TblPtg; import org.apache.poi.ss.util.CellReference; import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; /** - * DATATABLE (0x0236)<p> - * - * TableRecord - The record specifies a data table. - * This record is preceded by a single Formula record that - * defines the first cell in the data table, which should - * only contain a single Ptg, {@link TblPtg}. - * - * See p536 of the June 08 binary docs + * The record specifies a data table.<p> + * This record is preceded by a single Formula record that defines the first cell in the data table, + * which should only contain a single {@link TblPtg Ptg}. */ public final class TableRecord extends SharedValueRecordBase { public static final short sid = 0x0236; @@ -51,6 +46,16 @@ public final class TableRecord extends SharedValueRecordBase { private int field_9_rowInputCol; private int field_10_colInputCol; + public TableRecord(TableRecord other) { + super(other); + field_5_flags = other.field_5_flags; + field_6_res = other.field_6_res; + field_7_rowInputRow = other.field_7_rowInputRow; + field_8_colInputRow = other.field_8_colInputRow; + field_9_rowInputCol = other.field_9_rowInputCol; + field_10_colInputCol = other.field_10_colInputCol; + } + public TableRecord(RecordInputStream in) { super(in); field_5_flags = in.readByte(); @@ -142,7 +147,7 @@ public final class TableRecord extends SharedValueRecordBase { return sid; } protected int getExtraDataSize() { - return + return 2 // 2 byte fields + 8; // 4 short fields } @@ -170,6 +175,11 @@ public final class TableRecord extends SharedValueRecordBase { return buffer.toString(); } + @Override + public TableRecord copy() { + return new TableRecord(this); + } + private static CellReference cr(int rowIx, int colIxAndFlags) { int colIx = colIxAndFlags & 0x00FF; boolean isRowAbs = (colIxAndFlags & 0x8000) == 0; diff --git a/src/java/org/apache/poi/hssf/record/TableStylesRecord.java b/src/java/org/apache/poi/hssf/record/TableStylesRecord.java index df15ac2355..6a9ed63a54 100644 --- a/src/java/org/apache/poi/hssf/record/TableStylesRecord.java +++ b/src/java/org/apache/poi/hssf/record/TableStylesRecord.java @@ -26,16 +26,26 @@ import org.apache.poi.util.StringUtil; */ public final class TableStylesRecord extends StandardRecord { public static final short sid = 0x088E; - + private int rt; private int grbitFrt; - private byte[] unused = new byte[8]; + private final byte[] unused = new byte[8]; private int cts; - + private String rgchDefListStyle; private String rgchDefPivotStyle; - - + + + public TableStylesRecord(TableStylesRecord other) { + super(other); + rt = other.rt; + grbitFrt = other.grbitFrt; + System.arraycopy(other.unused, 0, unused, 0, unused.length); + cts = other.cts; + rgchDefListStyle = other.rgchDefListStyle; + rgchDefPivotStyle = other.rgchDefPivotStyle; + } + public TableStylesRecord(RecordInputStream in) { rt = in.readUShort(); grbitFrt = in.readUShort(); @@ -43,21 +53,21 @@ public final class TableStylesRecord extends StandardRecord { cts = in.readInt(); int cchDefListStyle = in.readUShort(); int cchDefPivotStyle = in.readUShort(); - + rgchDefListStyle = in.readUnicodeLEString(cchDefListStyle); rgchDefPivotStyle = in.readUnicodeLEString(cchDefPivotStyle); } - + @Override protected void serialize(LittleEndianOutput out) { out.writeShort(rt); out.writeShort(grbitFrt); out.write(unused); out.writeInt(cts); - + out.writeShort(rgchDefListStyle.length()); out.writeShort(rgchDefPivotStyle.length()); - + StringUtil.putUnicodeLE(rgchDefListStyle, out); StringUtil.putUnicodeLE(rgchDefPivotStyle, out); } @@ -89,4 +99,9 @@ public final class TableStylesRecord extends StandardRecord { buffer.append("[/TABLESTYLES]\n"); return buffer.toString(); } + + @Override + public TableStylesRecord copy() { + return new TableStylesRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/TextObjectRecord.java b/src/java/org/apache/poi/hssf/record/TextObjectRecord.java index d5c9e3f425..1116282ac8 100644 --- a/src/java/org/apache/poi/hssf/record/TextObjectRecord.java +++ b/src/java/org/apache/poi/hssf/record/TextObjectRecord.java @@ -26,6 +26,7 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; import org.apache.poi.util.RecordFormatException; +import org.apache.poi.util.Removal; /** * The TXO record (0x01B6) is used to define the properties of a text box. It is @@ -34,7 +35,7 @@ import org.apache.poi.util.RecordFormatException; * contains the formatting runs. */ public final class TextObjectRecord extends ContinuableRecord { - public final static short sid = 0x01B6; + public static final short sid = 0x01B6; private static final int FORMAT_RUN_ENCODED_SIZE = 8; // 2 shorts and 4 bytes reserved @@ -42,19 +43,19 @@ public final class TextObjectRecord extends ContinuableRecord { private static final BitField VerticalTextAlignment = BitFieldFactory.getInstance(0x0070); private static final BitField textLocked = BitFieldFactory.getInstance(0x0200); - public final static short HORIZONTAL_TEXT_ALIGNMENT_LEFT_ALIGNED = 1; - public final static short HORIZONTAL_TEXT_ALIGNMENT_CENTERED = 2; - public final static short HORIZONTAL_TEXT_ALIGNMENT_RIGHT_ALIGNED = 3; - public final static short HORIZONTAL_TEXT_ALIGNMENT_JUSTIFIED = 4; - public final static short VERTICAL_TEXT_ALIGNMENT_TOP = 1; - public final static short VERTICAL_TEXT_ALIGNMENT_CENTER = 2; - public final static short VERTICAL_TEXT_ALIGNMENT_BOTTOM = 3; - public final static short VERTICAL_TEXT_ALIGNMENT_JUSTIFY = 4; + public static final short HORIZONTAL_TEXT_ALIGNMENT_LEFT_ALIGNED = 1; + public static final short HORIZONTAL_TEXT_ALIGNMENT_CENTERED = 2; + public static final short HORIZONTAL_TEXT_ALIGNMENT_RIGHT_ALIGNED = 3; + public static final short HORIZONTAL_TEXT_ALIGNMENT_JUSTIFIED = 4; + public static final short VERTICAL_TEXT_ALIGNMENT_TOP = 1; + public static final short VERTICAL_TEXT_ALIGNMENT_CENTER = 2; + public static final short VERTICAL_TEXT_ALIGNMENT_BOTTOM = 3; + public static final short VERTICAL_TEXT_ALIGNMENT_JUSTIFY = 4; - public final static short TEXT_ORIENTATION_NONE = 0; - public final static short TEXT_ORIENTATION_TOP_TO_BOTTOM = 1; - public final static short TEXT_ORIENTATION_ROT_RIGHT = 2; - public final static short TEXT_ORIENTATION_ROT_LEFT = 3; + public static final short TEXT_ORIENTATION_NONE = 0; + public static final short TEXT_ORIENTATION_TOP_TO_BOTTOM = 1; + public static final short TEXT_ORIENTATION_ROT_RIGHT = 2; + public static final short TEXT_ORIENTATION_ROT_LEFT = 3; private int field_1_options; private int field_2_textOrientation; @@ -80,8 +81,24 @@ public final class TextObjectRecord extends ContinuableRecord { * Value is often the same as the earlier firstColumn byte. */ private Byte _unknownPostFormulaByte; - public TextObjectRecord() { - // + public TextObjectRecord() {} + + public TextObjectRecord(TextObjectRecord other) { + super(other); + field_1_options = other.field_1_options; + field_2_textOrientation = other.field_2_textOrientation; + field_3_reserved4 = other.field_3_reserved4; + field_4_reserved5 = other.field_4_reserved5; + field_5_reserved6 = other.field_5_reserved6; + field_8_reserved7 = other.field_8_reserved7; + + _text = other._text; + + if (other._linkRefPtg != null) { + _unknownPreFormulaInt = other._unknownPreFormulaInt; + _linkRefPtg = other._linkRefPtg.copy(); + _unknownPostFormulaByte = other._unknownPostFormulaByte; + } } public TextObjectRecord(RecordInputStream in) { @@ -325,24 +342,16 @@ public final class TextObjectRecord extends ContinuableRecord { return sb.toString(); } - public Object clone() { - - TextObjectRecord rec = new TextObjectRecord(); - - rec.field_1_options = field_1_options; - rec.field_2_textOrientation = field_2_textOrientation; - rec.field_3_reserved4 = field_3_reserved4; - rec.field_4_reserved5 = field_4_reserved5; - rec.field_5_reserved6 = field_5_reserved6; - rec.field_8_reserved7 = field_8_reserved7; - - rec._text = _text; // clone needed? + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public TextObjectRecord clone() { + return copy(); + } - if (_linkRefPtg != null) { - rec._unknownPreFormulaInt = _unknownPreFormulaInt; - rec._linkRefPtg = _linkRefPtg.copy(); - rec._unknownPostFormulaByte = _unknownPostFormulaByte; - } - return rec; + @Override + public TextObjectRecord copy() { + return new TextObjectRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/TopMarginRecord.java b/src/java/org/apache/poi/hssf/record/TopMarginRecord.java index 99d7d49021..11cee8ad20 100644 --- a/src/java/org/apache/poi/hssf/record/TopMarginRecord.java +++ b/src/java/org/apache/poi/hssf/record/TopMarginRecord.java @@ -17,22 +17,28 @@ package org.apache.poi.hssf.record; -import org.apache.poi.util.*; +import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * Record for the top margin. */ public final class TopMarginRecord extends StandardRecord implements Margin { - public final static short sid = 0x28; + public static final short sid = 0x28; + private double field_1_margin; - public TopMarginRecord() { } + public TopMarginRecord() {} + + public TopMarginRecord(TopMarginRecord other) { + super(other); + field_1_margin = other.field_1_margin; + } /** * @param in the RecordInputstream to read the record from */ - public TopMarginRecord( RecordInputStream in ) - { + public TopMarginRecord( RecordInputStream in ) { field_1_margin = in.readDouble(); } @@ -66,10 +72,16 @@ public final class TopMarginRecord extends StandardRecord implements Margin { public void setMargin( double field_1_margin ) { this.field_1_margin = field_1_margin; } - public Object clone() - { - TopMarginRecord rec = new TopMarginRecord(); - rec.field_1_margin = this.field_1_margin; - return rec; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public TopMarginRecord clone() { + return copy(); + } + + @Override + public TopMarginRecord copy() { + return new TopMarginRecord(this); } -} // END OF
\ No newline at end of file +}
\ No newline at end of file diff --git a/src/java/org/apache/poi/hssf/record/UncalcedRecord.java b/src/java/org/apache/poi/hssf/record/UncalcedRecord.java index 9310766aac..22e8ddb0a6 100644 --- a/src/java/org/apache/poi/hssf/record/UncalcedRecord.java +++ b/src/java/org/apache/poi/hssf/record/UncalcedRecord.java @@ -20,15 +20,11 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; /** - * Title: Uncalced Record - * <P> - * If this record occurs in the Worksheet Substream, it indicates that the formulas have not + * If this record occurs in the Worksheet Substream, it indicates that the formulas have not * been recalculated before the document was saved. - * - * @author Olivier Leprince */ -public final class UncalcedRecord extends StandardRecord { - public final static short sid = 0x005E; +public final class UncalcedRecord extends StandardRecord { + public static final short sid = 0x005E; private short _reserved; @@ -36,6 +32,11 @@ public final class UncalcedRecord extends StandardRecord { _reserved = 0; } + public UncalcedRecord(UncalcedRecord other) { + super(other); + _reserved = other._reserved; + } + public short getSid() { return sid; } @@ -63,4 +64,9 @@ public final class UncalcedRecord extends StandardRecord { public static int getStaticRecordSize() { return 6; } + + @Override + public UncalcedRecord copy() { + return new UncalcedRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/UnknownRecord.java b/src/java/org/apache/poi/hssf/record/UnknownRecord.java index 9b4dc55c84..f71da5b0a3 100644 --- a/src/java/org/apache/poi/hssf/record/UnknownRecord.java +++ b/src/java/org/apache/poi/hssf/record/UnknownRecord.java @@ -22,13 +22,12 @@ import java.util.Locale; import org.apache.poi.hssf.record.aggregates.PageSettingsBlock; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Unknown Record (for debugging)<p> - * Description: Unknown record just tells you the sid so you can figure out - * what records you are missing. Also helps us read/modify sheets we - * don't know all the records to. (HSSF leaves these alone!)<p> - * Company: SuperLink Software, Inc. + * Unknown record just tells you the sid so you can figure out what records you are missing. + * Also helps us read/modify sheets we don't know all the records to. + * (HSSF leaves these alone!) */ public final class UnknownRecord extends StandardRecord { @@ -206,7 +205,7 @@ public final class UnknownRecord extends StandardRecord { case 0x08A7: return "CRTLAYOUT12A"; case 0x08C8: return "PLV{Mac Excel}"; - + case 0x1001: return "UNITS"; case 0x1006: return "CHARTDATAFORMAT"; case 0x1007: return "CHARTLINEFORMAT"; @@ -286,7 +285,15 @@ public final class UnknownRecord extends StandardRecord { } @Override - public Object clone() { + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public UnknownRecord clone() { + return copy(); + } + + @Override + public UnknownRecord copy() { // immutable - OK to return this return this; } diff --git a/src/java/org/apache/poi/hssf/record/UseSelFSRecord.java b/src/java/org/apache/poi/hssf/record/UseSelFSRecord.java index c8d6691300..1095c7a0a3 100644 --- a/src/java/org/apache/poi/hssf/record/UseSelFSRecord.java +++ b/src/java/org/apache/poi/hssf/record/UseSelFSRecord.java @@ -21,20 +21,23 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: USESELFS (0x0160) - Use Natural Language Formulas Flag <p> - * Description: Tells the GUI if this was written by something that can use - * "natural language" formulas. HSSF can't.<p> - * REFERENCE: PG 420 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) + * Tells the GUI if this was written by something that can use "natural language" formulas. HSSF can't. */ public final class UseSelFSRecord extends StandardRecord { - public final static short sid = 0x0160; + public static final short sid = 0x0160; private static final BitField useNaturalLanguageFormulasFlag = BitFieldFactory.getInstance(0x0001); private int _options; + private UseSelFSRecord(UseSelFSRecord other) { + super(other); + _options = other._options; + } + private UseSelFSRecord(int options) { _options = options; } @@ -70,7 +73,15 @@ public final class UseSelFSRecord extends StandardRecord { } @Override - public Object clone() { - return new UseSelFSRecord(_options); + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public UseSelFSRecord clone() { + return copy(); + } + + @Override + public UseSelFSRecord copy() { + return new UseSelFSRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/UserSViewBegin.java b/src/java/org/apache/poi/hssf/record/UserSViewBegin.java index c32cffbb2b..ccbb2b6261 100644 --- a/src/java/org/apache/poi/hssf/record/UserSViewBegin.java +++ b/src/java/org/apache/poi/hssf/record/UserSViewBegin.java @@ -21,19 +21,24 @@ import java.util.Locale; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * The UserSViewBegin record specifies settings for a custom view associated with the sheet. * This record also marks the start of custom view records, which save custom view settings. * Records between {@link UserSViewBegin} and {@link UserSViewEnd} contain settings for the custom view, * not settings for the sheet itself. - * - * @author Yegor Kozlov */ public final class UserSViewBegin extends StandardRecord { - public final static short sid = 0x01AA; - private byte[] _rawData; + public static final short sid = 0x01AA; + + private byte[] _rawData; + + public UserSViewBegin(UserSViewBegin other) { + super(other); + _rawData = (other._rawData == null) ? null : other._rawData.clone(); + } public UserSViewBegin(byte[] data) { _rawData = data; @@ -83,9 +88,17 @@ public final class UserSViewBegin extends StandardRecord { return sb.toString(); } - //HACK: do a "cheat" clone, see Record.java for more information - public Object clone() { - return cloneViaReserialise(); + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public UserSViewBegin clone() { + return copy(); } - + + @Override + public UserSViewBegin copy() { + return new UserSViewBegin(this); + } + } diff --git a/src/java/org/apache/poi/hssf/record/UserSViewEnd.java b/src/java/org/apache/poi/hssf/record/UserSViewEnd.java index b3410ebc3e..09c8c3b40b 100644 --- a/src/java/org/apache/poi/hssf/record/UserSViewEnd.java +++ b/src/java/org/apache/poi/hssf/record/UserSViewEnd.java @@ -21,15 +21,21 @@ import java.util.Locale; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * The UserSViewEnd record marks the end of the settings for a custom view associated with the sheet */ public final class UserSViewEnd extends StandardRecord { - public final static short sid = 0x01AB; + public static final short sid = 0x01AB; private byte[] _rawData; + public UserSViewEnd(UserSViewEnd other) { + super(other); + _rawData = (other._rawData == null) ? null : other._rawData.clone(); + } + public UserSViewEnd(byte[] data) { _rawData = data; } @@ -69,10 +75,16 @@ public final class UserSViewEnd extends StandardRecord { return sb.toString(); } - //HACK: do a "cheat" clone, see Record.java for more information - public Object clone() { - return cloneViaReserialise(); + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public UserSViewEnd clone() { + return copy(); } - + @Override + public UserSViewEnd copy() { + return new UserSViewEnd(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/VCenterRecord.java b/src/java/org/apache/poi/hssf/record/VCenterRecord.java index 2439a9a42d..601be847df 100644 --- a/src/java/org/apache/poi/hssf/record/VCenterRecord.java +++ b/src/java/org/apache/poi/hssf/record/VCenterRecord.java @@ -18,26 +18,26 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: VCenter record<P> - * Description: tells whether to center the sheet between vertical margins<P> - * REFERENCE: PG 420 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Jason Height (jheight at chariot dot net dot au) + * Tells whether to center the sheet between vertical margins + * * @version 2.0-pre */ public final class VCenterRecord extends StandardRecord { - public final static short sid = 0x84; + public static final short sid = 0x84; private int field_1_vcenter; - public VCenterRecord() - { + public VCenterRecord() {} + + public VCenterRecord(VCenterRecord other) { + super(other); + field_1_vcenter = other.field_1_vcenter; } - public VCenterRecord(RecordInputStream in) - { + public VCenterRecord(RecordInputStream in) { field_1_vcenter = in.readShort(); } @@ -85,9 +85,16 @@ public final class VCenterRecord extends StandardRecord { return sid; } - public Object clone() { - VCenterRecord rec = new VCenterRecord(); - rec.field_1_vcenter = field_1_vcenter; - return rec; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public VCenterRecord clone() { + return copy(); + } + + @Override + public VCenterRecord copy() { + return new VCenterRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/VerticalPageBreakRecord.java b/src/java/org/apache/poi/hssf/record/VerticalPageBreakRecord.java index f15baf6ffb..d8e8a9a459 100644 --- a/src/java/org/apache/poi/hssf/record/VerticalPageBreakRecord.java +++ b/src/java/org/apache/poi/hssf/record/VerticalPageBreakRecord.java @@ -17,11 +17,11 @@ package org.apache.poi.hssf.record; -import java.util.Iterator; +import org.apache.poi.util.Removal; /** * VerticalPageBreak (0x001A) record that stores page breaks at columns - * + * * @see PageBreakRecord */ public final class VerticalPageBreakRecord extends PageBreakRecord { @@ -31,8 +31,10 @@ public final class VerticalPageBreakRecord extends PageBreakRecord { /** * Creates an empty vertical page break record */ - public VerticalPageBreakRecord() { + public VerticalPageBreakRecord() {} + public VerticalPageBreakRecord(VerticalPageBreakRecord other) { + super(other); } /** @@ -46,13 +48,16 @@ public final class VerticalPageBreakRecord extends PageBreakRecord { return sid; } - public Object clone() { - PageBreakRecord result = new VerticalPageBreakRecord(); - Iterator<Break> iterator = getBreaksIterator(); - while (iterator.hasNext()) { - Break original = iterator.next(); - result.addBreak(original.main, original.subFrom, original.subTo); - } - return result; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public VerticalPageBreakRecord clone() { + return copy(); + } + + @Override + public VerticalPageBreakRecord copy() { + return new VerticalPageBreakRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/WSBoolRecord.java b/src/java/org/apache/poi/hssf/record/WSBoolRecord.java index 5995eda6da..27824f79b8 100644 --- a/src/java/org/apache/poi/hssf/record/WSBoolRecord.java +++ b/src/java/org/apache/poi/hssf/record/WSBoolRecord.java @@ -20,36 +20,50 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: WSBOOL (0x0081) (called SHEETPR in OOO doc)<p> - * Description: stores workbook settings (aka its a big "everything we didn't - * put somewhere else")<p> - * REFERENCE: PG 425 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) + * Stores workbook settings (aka its a big "everything we didn't put somewhere else") */ public final class WSBoolRecord extends StandardRecord { - public final static short sid = 0x0081; - private byte field_1_wsbool; // crappy names are because this is really one big short field (2byte) - private byte field_2_wsbool; // but the docs inconsistently use it as 2 separate bytes - - // I decided to be consistent in this way. - private static final BitField autobreaks = BitFieldFactory.getInstance(0x01); // are automatic page breaks visible + public static final short sid = 0x0081; + // are automatic page breaks visible + private static final BitField autobreaks = BitFieldFactory.getInstance(0x01); // bits 1 to 3 unused - private static final BitField dialog = BitFieldFactory.getInstance(0x10); // is sheet dialog sheet - private static final BitField applystyles = BitFieldFactory.getInstance(0x20); // whether to apply automatic styles to outlines - private static final BitField rowsumsbelow = BitFieldFactory.getInstance(0x40); // whether summary rows will appear below detail in outlines - private static final BitField rowsumsright = BitFieldFactory.getInstance(0x80); // whether summary rows will appear right of the detail in outlines - private static final BitField fittopage = BitFieldFactory.getInstance(0x01); // whether to fit stuff to the page + // is sheet dialog sheet + private static final BitField dialog = BitFieldFactory.getInstance(0x10); + // whether to apply automatic styles to outlines + private static final BitField applystyles = BitFieldFactory.getInstance(0x20); + // whether summary rows will appear below detail in outlines + private static final BitField rowsumsbelow = BitFieldFactory.getInstance(0x40); + // whether summary rows will appear right of the detail in outlines + private static final BitField rowsumsright = BitFieldFactory.getInstance(0x80); + // whether to fit stuff to the page + private static final BitField fittopage = BitFieldFactory.getInstance(0x01); // bit 2 reserved - private static final BitField displayguts = BitFieldFactory.getInstance(0x06); // whether to display outline symbols (in the gutters) + // whether to display outline symbols (in the gutters) + private static final BitField displayguts = BitFieldFactory.getInstance(0x06); // bits 4-5 reserved - private static final BitField alternateexpression = BitFieldFactory.getInstance(0x40); // whether to use alternate expression eval - private static final BitField alternateformula = BitFieldFactory.getInstance(0x80); // whether to use alternate formula entry + // whether to use alternate expression eval + private static final BitField alternateexpression = BitFieldFactory.getInstance(0x40); + // whether to use alternate formula entry + private static final BitField alternateformula = BitFieldFactory.getInstance(0x80); + + // crappy names are because this is really one big short field (2byte) + private byte field_1_wsbool; + // but the docs inconsistently use it as 2 separate bytes + private byte field_2_wsbool; + - public WSBoolRecord() { + public WSBoolRecord() {} + + public WSBoolRecord(WSBoolRecord other) { + super(other); + field_1_wsbool = other.field_1_wsbool; + field_2_wsbool = other.field_2_wsbool; } public WSBoolRecord(RecordInputStream in) { @@ -292,10 +306,16 @@ public final class WSBoolRecord extends StandardRecord { return sid; } - public Object clone() { - WSBoolRecord rec = new WSBoolRecord(); - rec.field_1_wsbool = field_1_wsbool; - rec.field_2_wsbool = field_2_wsbool; - return rec; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public WSBoolRecord clone() { + return copy(); + } + + @Override + public WSBoolRecord copy() { + return new WSBoolRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/WindowOneRecord.java b/src/java/org/apache/poi/hssf/record/WindowOneRecord.java index 440348e37a..8aa8f60933 100644 --- a/src/java/org/apache/poi/hssf/record/WindowOneRecord.java +++ b/src/java/org/apache/poi/hssf/record/WindowOneRecord.java @@ -22,55 +22,64 @@ import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.LittleEndianOutput; /** - * Title: Window1 Record<P> - * Description: Stores the attributes of the workbook window. This is basically - * so the gui knows how big to make the window holding the spreadsheet - * document.<P> - * REFERENCE: PG 421 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) + * Stores the attributes of the workbook window. + * This is basically so the gui knows how big to make the window holding the spreadsheet document. + * * @version 2.0-pre */ public final class WindowOneRecord extends StandardRecord { - public final static short sid = 0x3d; - - // our variable names stolen from old TV sets. - private short field_1_h_hold; // horizontal position - private short field_2_v_hold; // vertical position - private short field_3_width; - private short field_4_height; - private short field_5_options; - static final private BitField hidden = - BitFieldFactory.getInstance(0x01); // is this window is hidden - static final private BitField iconic = - BitFieldFactory.getInstance(0x02); // is this window is an icon + public static final short sid = 0x3d; + + // horizontal position + private short field_1_h_hold; + // vertical position + private short field_2_v_hold; + private short field_3_width; + private short field_4_height; + private short field_5_options; + // is this window is hidden + static final private BitField hidden = BitFieldFactory.getInstance(0x01); + // is this window is an icon + static final private BitField iconic = BitFieldFactory.getInstance(0x02); + // reserved @SuppressWarnings("unused") - static final private BitField reserved = BitFieldFactory.getInstance(0x04); // reserved - static final private BitField hscroll = - BitFieldFactory.getInstance(0x08); // display horizontal scrollbar - static final private BitField vscroll = - BitFieldFactory.getInstance(0x10); // display vertical scrollbar - static final private BitField tabs = - BitFieldFactory.getInstance(0x20); // display tabs at the bottom + static final private BitField reserved = BitFieldFactory.getInstance(0x04); + // display horizontal scrollbar + static final private BitField hscroll = BitFieldFactory.getInstance(0x08); + // display vertical scrollbar + static final private BitField vscroll = BitFieldFactory.getInstance(0x10); + // display tabs at the bottom + static final private BitField tabs = BitFieldFactory.getInstance(0x20); // all the rest are "reserved" - private int field_6_active_sheet; - private int field_7_first_visible_tab; - private short field_8_num_selected_tabs; - private short field_9_tab_width_ratio; - - public WindowOneRecord() - { - } - - public WindowOneRecord(RecordInputStream in) - { + private int field_6_active_sheet; + private int field_7_first_visible_tab; + private short field_8_num_selected_tabs; + private short field_9_tab_width_ratio; + + public WindowOneRecord() {} + + public WindowOneRecord(WindowOneRecord other) { + super(other); + field_1_h_hold = other.field_1_h_hold; + field_2_v_hold = other.field_2_v_hold; + field_3_width = other.field_3_width; + field_4_height = other.field_4_height; + field_5_options = other.field_5_options; + field_6_active_sheet = other.field_6_active_sheet; + field_7_first_visible_tab = other.field_7_first_visible_tab; + field_8_num_selected_tabs = other.field_8_num_selected_tabs; + field_9_tab_width_ratio = other.field_9_tab_width_ratio; + } + + public WindowOneRecord(RecordInputStream in) { field_1_h_hold = in.readShort(); field_2_v_hold = in.readShort(); field_3_width = in.readShort(); field_4_height = in.readShort(); field_5_options = in.readShort(); field_6_active_sheet = in.readShort(); - field_7_first_visible_tab = in.readShort(); + field_7_first_visible_tab = in.readShort(); field_8_num_selected_tabs = in.readShort(); field_9_tab_width_ratio = in.readShort(); } @@ -318,16 +327,16 @@ public final class WindowOneRecord extends StandardRecord { // end options bitfields - + /** - * @return the index of the currently displayed sheet + * @return the index of the currently displayed sheet */ public int getActiveSheetIndex() { return field_6_active_sheet; } /** - * @return the first visible sheet in the worksheet tab-bar. + * @return the first visible sheet in the worksheet tab-bar. * I.E. the scroll position of the tab-bar. */ public int getFirstVisibleTab() { @@ -407,4 +416,9 @@ public final class WindowOneRecord extends StandardRecord { { return sid; } + + @Override + public WindowOneRecord copy() { + return new WindowOneRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/WindowProtectRecord.java b/src/java/org/apache/poi/hssf/record/WindowProtectRecord.java index 12d471c385..c5b26235ce 100644 --- a/src/java/org/apache/poi/hssf/record/WindowProtectRecord.java +++ b/src/java/org/apache/poi/hssf/record/WindowProtectRecord.java @@ -21,14 +21,13 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Window Protect Record (0x0019)<p> - * Description: flags whether workbook windows are protected<p> - * REFERENCE: PG 424 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) + * Flags whether workbook windows are protected */ public final class WindowProtectRecord extends StandardRecord { - public final static short sid = 0x0019; + public static final short sid = 0x0019; private static final BitField settingsProtectedFlag = BitFieldFactory.getInstance(0x0001); @@ -38,6 +37,11 @@ public final class WindowProtectRecord extends StandardRecord { _options = options; } + public WindowProtectRecord(WindowProtectRecord other) { + super(other); + _options = other._options; + } + public WindowProtectRecord(RecordInputStream in) { this(in.readUShort()); } @@ -85,8 +89,17 @@ public final class WindowProtectRecord extends StandardRecord { { return sid; } + + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public WindowProtectRecord clone() { + return copy(); + } + @Override - public Object clone() { - return new WindowProtectRecord(_options); + public WindowProtectRecord copy() { + return new WindowProtectRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/WindowTwoRecord.java b/src/java/org/apache/poi/hssf/record/WindowTwoRecord.java index d58f2ee3eb..d9aea08cce 100644 --- a/src/java/org/apache/poi/hssf/record/WindowTwoRecord.java +++ b/src/java/org/apache/poi/hssf/record/WindowTwoRecord.java @@ -20,17 +20,15 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Title: Window Two Record<P> - * Description: sheet window settings<P> - * REFERENCE: PG 422 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Jason Height (jheight at chariot dot net dot au) + * Sheet window settings + * * @version 2.0-pre */ public final class WindowTwoRecord extends StandardRecord { - public final static short sid = 0x023E; + public static final short sid = 0x023E; // bitfields private static final BitField displayFormulas = BitFieldFactory.getInstance(0x01); @@ -39,7 +37,7 @@ public final class WindowTwoRecord extends StandardRecord { private static final BitField freezePanes = BitFieldFactory.getInstance(0x08); private static final BitField displayZeros = BitFieldFactory.getInstance(0x10); /** if false use color in field 4 if true use default foreground for headers */ - private static final BitField defaultHeader = BitFieldFactory.getInstance(0x20); + private static final BitField defaultHeader = BitFieldFactory.getInstance(0x20); private static final BitField arabic = BitFieldFactory.getInstance(0x040); private static final BitField displayGuts = BitFieldFactory.getInstance(0x080); private static final BitField freezePanesNoSplit = BitFieldFactory.getInstance(0x100); @@ -49,20 +47,28 @@ public final class WindowTwoRecord extends StandardRecord { // 4-7 reserved // end bitfields - private short field_1_options; - private short field_2_top_row; - private short field_3_left_col; - private int field_4_header_color; - private short field_5_page_break_zoom; - private short field_6_normal_zoom; - private int field_7_reserved; + private short field_1_options; + private short field_2_top_row; + private short field_3_left_col; + private int field_4_header_color; + private short field_5_page_break_zoom; + private short field_6_normal_zoom; + private int field_7_reserved; - public WindowTwoRecord() - { + public WindowTwoRecord() {} + + public WindowTwoRecord(WindowTwoRecord other) { + super(other); + field_1_options = other.field_1_options; + field_2_top_row = other.field_2_top_row; + field_3_left_col = other.field_3_left_col; + field_4_header_color = other.field_4_header_color; + field_5_page_break_zoom = other.field_5_page_break_zoom; + field_6_normal_zoom = other.field_6_normal_zoom; + field_7_reserved = other.field_7_reserved; } - public WindowTwoRecord(RecordInputStream in) - { + public WindowTwoRecord(RecordInputStream in) { int size = in.remaining(); field_1_options = in.readShort(); field_2_top_row = in.readShort(); @@ -475,15 +481,16 @@ public final class WindowTwoRecord extends StandardRecord { return sid; } - public Object clone() { - WindowTwoRecord rec = new WindowTwoRecord(); - rec.field_1_options = field_1_options; - rec.field_2_top_row = field_2_top_row; - rec.field_3_left_col = field_3_left_col; - rec.field_4_header_color = field_4_header_color; - rec.field_5_page_break_zoom = field_5_page_break_zoom; - rec.field_6_normal_zoom = field_6_normal_zoom; - rec.field_7_reserved = field_7_reserved; - return rec; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public WindowTwoRecord clone() { + return copy(); + } + + @Override + public WindowTwoRecord copy() { + return new WindowTwoRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/WriteAccessRecord.java b/src/java/org/apache/poi/hssf/record/WriteAccessRecord.java index e6d62ca4ff..65773251c1 100644 --- a/src/java/org/apache/poi/hssf/record/WriteAccessRecord.java +++ b/src/java/org/apache/poi/hssf/record/WriteAccessRecord.java @@ -26,28 +26,33 @@ import org.apache.poi.util.StringUtil; /** * Title: Write Access Record (0x005C)<p> - * - * Description: Stores the username of that who owns the spreadsheet generator (on unix the user's + * + * Description: Stores the username of that who owns the spreadsheet generator (on unix the user's * login, on Windoze its the name you typed when you installed the thing)<p> - * - * REFERENCE: PG 424 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) */ public final class WriteAccessRecord extends StandardRecord { - public final static short sid = 0x005C; + public static final short sid = 0x005C; private static final byte PAD_CHAR = (byte) ' '; private static final int DATA_SIZE = 112; - private String field_1_username; /** this record is always padded to a constant length */ private static final byte[] PADDING = new byte[DATA_SIZE]; static { Arrays.fill(PADDING, PAD_CHAR); } + private String field_1_username; + + public WriteAccessRecord() { setUsername(""); } + public WriteAccessRecord(WriteAccessRecord other) { + super(other); + field_1_username = other.field_1_username; + } + public WriteAccessRecord(RecordInputStream in) { if (in.remaining() > DATA_SIZE) { throw new RecordFormatException("Expected data size (" + DATA_SIZE + ") but got (" @@ -91,7 +96,7 @@ public final class WriteAccessRecord extends StandardRecord { /** * set the username for the user that created the report. HSSF uses the * logged in user. - * + * * @param username of the user who is logged in (probably "tomcat" or "apache") */ public void setUsername(String username) { @@ -109,7 +114,7 @@ public final class WriteAccessRecord extends StandardRecord { * get the username for the user that created the report. HSSF uses the * logged in user. On natively created M$ Excel sheet this would be the name * you typed in when you installed it in most cases. - * + * * @return username of the user who is logged in (probably "tomcat" or "apache") */ public String getUsername() { @@ -148,4 +153,9 @@ public final class WriteAccessRecord extends StandardRecord { public short getSid() { return sid; } + + @Override + public WriteAccessRecord copy() { + return new WriteAccessRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/WriteProtectRecord.java b/src/java/org/apache/poi/hssf/record/WriteProtectRecord.java index edd4962569..41e3e2d988 100644 --- a/src/java/org/apache/poi/hssf/record/WriteProtectRecord.java +++ b/src/java/org/apache/poi/hssf/record/WriteProtectRecord.java @@ -20,17 +20,14 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; /** - * Title: Write Protect Record<P> - * Description: Indicated that the sheet/workbook is write protected. - * REFERENCE: PG 425 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> + * Indicated that the sheet/workbook is write protected. + * * @version 3.0-pre */ public final class WriteProtectRecord extends StandardRecord { - public final static short sid = 0x86; + public static final short sid = 0x86; - public WriteProtectRecord() - { - } + public WriteProtectRecord() {} /** * @param in unused (since this record has no data) @@ -62,4 +59,9 @@ public final class WriteProtectRecord extends StandardRecord { { return sid; } + + @Override + public WriteProtectRecord copy() { + return new WriteProtectRecord(); + } } 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 8c9e0be763..87c5798df8 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java @@ -37,7 +37,7 @@ import org.apache.poi.util.POILogger; import org.apache.poi.util.RecordFormatException; /** - * <p>CFRecordsAggregate - aggregates Conditional Formatting records CFHeaderRecord + * <p>CFRecordsAggregate - aggregates Conditional Formatting records CFHeaderRecord * and number of up CFRuleRecord records together to simplify access to them.</p> * <p>Note that Excel versions before 2007 can only cope with a maximum of 3 * Conditional Formatting rules per sheet. Excel 2007 or newer can cope with @@ -52,7 +52,12 @@ public final class CFRecordsAggregate extends RecordAggregate { private final CFHeaderBase header; /** List of CFRuleRecord objects */ - private final List<CFRuleBase> rules; + private final List<CFRuleBase> rules = new ArrayList<>(); + + public CFRecordsAggregate(CFRecordsAggregate other) { + header = other.header.copy(); + other.rules.stream().map(t -> t.copy()).forEach(rules::add); + } private CFRecordsAggregate(CFHeaderBase pHeader, CFRuleBase[] pRules) { if(pHeader == null) { @@ -63,7 +68,7 @@ public final class CFRecordsAggregate extends RecordAggregate { } if(pRules.length > MAX_97_2003_CONDTIONAL_FORMAT_RULES) { logger.log(POILogger.WARN, "Excel versions before 2007 require that " - + "No more than " + MAX_97_2003_CONDTIONAL_FORMAT_RULES + + "No more than " + MAX_97_2003_CONDTIONAL_FORMAT_RULES + " rules may be specified, " + pRules.length + " were found," + " this file will cause problems with old Excel versions"); } @@ -71,7 +76,6 @@ public final class CFRecordsAggregate extends RecordAggregate { throw new RecordFormatException("Mismatch number of rules"); } header = pHeader; - rules = new ArrayList<>(pRules.length); for (CFRuleBase pRule : pRules) { checkRuleType(pRule); rules.add(pRule); @@ -105,7 +109,7 @@ public final class CFRecordsAggregate extends RecordAggregate { Record rec = rs.getNext(); if (rec.getSid() != CFHeaderRecord.sid && rec.getSid() != CFHeader12Record.sid) { - throw new IllegalStateException("next record sid was " + rec.getSid() + throw new IllegalStateException("next record sid was " + rec.getSid() + " instead of " + CFHeaderRecord.sid + " or " + CFHeader12Record.sid + " as expected"); } @@ -127,11 +131,7 @@ public final class CFRecordsAggregate extends RecordAggregate { * @return A new object with the same values as this record */ public CFRecordsAggregate cloneCFAggregate() { - CFRuleBase[] newRecs = new CFRuleBase[rules.size()]; - for (int i = 0; i < newRecs.length; i++) { - newRecs[i] = getRule(i).clone(); - } - return new CFRecordsAggregate(header.clone(), newRecs); + return new CFRecordsAggregate(this); } /** @@ -143,7 +143,7 @@ public final class CFRecordsAggregate extends RecordAggregate { private void checkRuleIndex(int idx) { if(idx < 0 || idx >= rules.size()) { - throw new IllegalArgumentException("Bad rule record index (" + idx + throw new IllegalArgumentException("Bad rule record index (" + idx + ") nRules=" + rules.size()); } } @@ -176,8 +176,8 @@ public final class CFRecordsAggregate extends RecordAggregate { throw new IllegalArgumentException("r must not be null"); } if(rules.size() >= MAX_97_2003_CONDTIONAL_FORMAT_RULES) { - logger.log(POILogger.WARN, "Excel versions before 2007 cannot cope with" - + " any more than " + MAX_97_2003_CONDTIONAL_FORMAT_RULES + logger.log(POILogger.WARN, "Excel versions before 2007 cannot cope with" + + " any more than " + MAX_97_2003_CONDTIONAL_FORMAT_RULES + " - this file will cause problems with old Excel versions"); } checkRuleType(r); diff --git a/src/java/org/apache/poi/hssf/record/aggregates/ColumnInfoRecordsAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/ColumnInfoRecordsAggregate.java index 5debe7361c..4b43327918 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/ColumnInfoRecordsAggregate.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/ColumnInfoRecordsAggregate.java @@ -18,50 +18,37 @@ package org.apache.poi.hssf.record.aggregates; import java.util.ArrayList; -import java.util.Comparator; import java.util.List; +import org.apache.poi.common.Duplicatable; import org.apache.poi.hssf.model.RecordStream; import org.apache.poi.hssf.record.ColumnInfoRecord; +import org.apache.poi.util.Removal; -/** - * @author Glen Stampoultzis - */ -public final class ColumnInfoRecordsAggregate extends RecordAggregate implements Cloneable { +public final class ColumnInfoRecordsAggregate extends RecordAggregate implements Duplicatable { /** * List of {@link ColumnInfoRecord}s assumed to be in order */ - private final List<ColumnInfoRecord> records; - - - private static final class CIRComparator implements Comparator<ColumnInfoRecord> { - public static final Comparator<ColumnInfoRecord> instance = new CIRComparator(); - private CIRComparator() { - // enforce singleton - } - public int compare(ColumnInfoRecord a, ColumnInfoRecord b) { - return compareColInfos(a, b); - } - public static int compareColInfos(ColumnInfoRecord a, ColumnInfoRecord b) { - return a.getFirstColumn()-b.getFirstColumn(); - } - } + private final List<ColumnInfoRecord> records = new ArrayList<>(); /** * Creates an empty aggregate */ - public ColumnInfoRecordsAggregate() { - records = new ArrayList<>(); + public ColumnInfoRecordsAggregate() {} + + public ColumnInfoRecordsAggregate(ColumnInfoRecordsAggregate other) { + other.records.stream().map(ColumnInfoRecord::copy).forEach(records::add); } + public ColumnInfoRecordsAggregate(RecordStream rs) { this(); boolean isInOrder = true; ColumnInfoRecord cirPrev = null; - while(rs.peekNextClass() == ColumnInfoRecord.class) { + while (rs.peekNextClass() == ColumnInfoRecord.class) { ColumnInfoRecord cir = (ColumnInfoRecord) rs.getNext(); records.add(cir); - if (cirPrev != null && CIRComparator.compareColInfos(cirPrev, cir) > 0) { + if (cirPrev != null && compareColInfos(cirPrev, cir) > 0) { isInOrder = false; } cirPrev = cir; @@ -70,17 +57,21 @@ public final class ColumnInfoRecordsAggregate extends RecordAggregate implements throw new RuntimeException("No column info records found"); } if (!isInOrder) { - records.sort(CIRComparator.instance); + records.sort(ColumnInfoRecordsAggregate::compareColInfos); } } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public ColumnInfoRecordsAggregate clone() { - ColumnInfoRecordsAggregate rec = new ColumnInfoRecordsAggregate(); - for (ColumnInfoRecord ci : records) { - rec.records.add(ci.clone()); - } - return rec; + return copy(); + } + + @Override + public ColumnInfoRecordsAggregate copy() { + return new ColumnInfoRecordsAggregate(this); } /** @@ -88,7 +79,7 @@ public final class ColumnInfoRecordsAggregate extends RecordAggregate implements */ public void insertColumn(ColumnInfoRecord col) { records.add(col); - records.sort(CIRComparator.instance); + records.sort(ColumnInfoRecordsAggregate::compareColInfos); } /** @@ -111,7 +102,7 @@ public final class ColumnInfoRecordsAggregate extends RecordAggregate implements ColumnInfoRecord cirPrev = null; for (ColumnInfoRecord cir : records) { rv.visitRecord(cir); - if (cirPrev != null && CIRComparator.compareColInfos(cirPrev, cir) > 0) { + if (cirPrev != null && compareColInfos(cirPrev, cir) > 0) { // Excel probably wouldn't mind, but there is much logic in this class // that assumes the column info records are kept in order throw new RuntimeException("Column info records are out of order"); @@ -290,7 +281,7 @@ public final class ColumnInfoRecordsAggregate extends RecordAggregate implements } private static ColumnInfoRecord copyColInfo(ColumnInfoRecord ci) { - return ci.clone(); + return ci.copy(); } @@ -554,4 +545,8 @@ public final class ColumnInfoRecordsAggregate extends RecordAggregate implements return maxIndex; } + + private static int compareColInfos(ColumnInfoRecord a, ColumnInfoRecord b) { + return a.getFirstColumn()-b.getFirstColumn(); + } } diff --git a/src/java/org/apache/poi/hssf/record/aggregates/ConditionalFormattingTable.java b/src/java/org/apache/poi/hssf/record/aggregates/ConditionalFormattingTable.java index 625cc9a6ac..2afbb3813d 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/ConditionalFormattingTable.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/ConditionalFormattingTable.java @@ -21,33 +21,26 @@ import java.util.ArrayList; import java.util.List; import org.apache.poi.hssf.model.RecordStream; -import org.apache.poi.hssf.record.CFHeader12Record; -import org.apache.poi.hssf.record.CFHeaderRecord; +import org.apache.poi.hssf.record.CFHeaderBase; import org.apache.poi.ss.formula.FormulaShifter; /** * Holds all the conditional formatting for a workbook sheet.<p> - * + * * See OOO exelfileformat.pdf sec 4.12 'Conditional Formatting Table' */ public final class ConditionalFormattingTable extends RecordAggregate { - private final List<CFRecordsAggregate> _cfHeaders; + private final List<CFRecordsAggregate> _cfHeaders = new ArrayList<>(); /** * Creates an empty ConditionalFormattingTable */ - public ConditionalFormattingTable() { - _cfHeaders = new ArrayList<>(); - } + public ConditionalFormattingTable() {} public ConditionalFormattingTable(RecordStream rs) { - - List<CFRecordsAggregate> temp = new ArrayList<>(); - while (rs.peekNextClass() == CFHeaderRecord.class || - rs.peekNextClass() == CFHeader12Record.class) { - temp.add(CFRecordsAggregate.createCFAggregate(rs)); + while (rs.peekNextRecord() instanceof CFHeaderBase) { + _cfHeaders.add(CFRecordsAggregate.createCFAggregate(rs)); } - _cfHeaders = temp; } public void visitContainedRecords(RecordVisitor rv) { diff --git a/src/java/org/apache/poi/hssf/record/aggregates/DataValidityTable.java b/src/java/org/apache/poi/hssf/record/aggregates/DataValidityTable.java index 654abaf41f..e6ad8bb29d 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/DataValidityTable.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/DataValidityTable.java @@ -56,9 +56,7 @@ public final class DataValidityTable extends RecordAggregate { return; } rv.visitRecord(_headerRec); - for (int i = 0; i < _validationList.size(); i++) { - rv.visitRecord(_validationList.get(i)); - } + _validationList.forEach(rv::visitRecord); } public void addDataValidation(DVRecord dvRecord) { diff --git a/src/java/org/apache/poi/hssf/record/aggregates/FormulaRecordAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/FormulaRecordAggregate.java index ff442f4e60..62c3df3a05 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/FormulaRecordAggregate.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/FormulaRecordAggregate.java @@ -35,9 +35,6 @@ import org.apache.poi.util.RecordFormatException; /** * The formula record aggregate is used to join together the formula record and it's * (optional) string record and (optional) Shared Formula Record (template reads, excel optimization). - * - * @author Glen Stampoultzis (glens at apache.org) - * @author Vladimirs Abramovs(Vladimirs.Abramovs at exigenservices.com) - Array Formula support */ public final class FormulaRecordAggregate extends RecordAggregate implements CellValueRecordInterface { @@ -79,6 +76,7 @@ public final class FormulaRecordAggregate extends RecordAggregate implements Cel } } } + /** * Sometimes the shared formula flag "seems" to be erroneously set (because the corresponding * {@link SharedFormulaRecord} does not exist). Normally this would leave no way of determining diff --git a/src/java/org/apache/poi/hssf/record/aggregates/MergedCellsTable.java b/src/java/org/apache/poi/hssf/record/aggregates/MergedCellsTable.java index f85b3375a3..c698cb0d27 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/MergedCellsTable.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/MergedCellsTable.java @@ -25,12 +25,9 @@ import org.apache.poi.hssf.record.MergeCellsRecord; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddressList; -/** - * - * @author Josh Micich - */ public final class MergedCellsTable extends RecordAggregate { - private static int MAX_MERGED_REGIONS = 1027; // enforced by the 8224 byte limit + // enforced by the 8224 byte limit + private static final int MAX_MERGED_REGIONS = 1027; private final List<CellRangeAddress> _mergedRegions; diff --git a/src/java/org/apache/poi/hssf/record/aggregates/RecordAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/RecordAggregate.java index c56d114695..8336dcaefe 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/RecordAggregate.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/RecordAggregate.java @@ -24,8 +24,6 @@ import org.apache.poi.hssf.record.RecordBase; * <tt>RecordAggregate</tt>s are groups of of BIFF <tt>Record</tt>s that are typically stored * together and/or updated together. Workbook / Sheet records are typically stored in a sequential * list, which does not provide much structure to coordinate updates. - * - * @author Josh Micich */ public abstract class RecordAggregate extends RecordBase { diff --git a/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java index dc238a9625..21c9ad8436 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java @@ -24,7 +24,21 @@ import java.util.Map; import java.util.TreeMap; import org.apache.poi.hssf.model.RecordStream; -import org.apache.poi.hssf.record.*; +import org.apache.poi.hssf.record.ArrayRecord; +import org.apache.poi.hssf.record.CellValueRecordInterface; +import org.apache.poi.hssf.record.ContinueRecord; +import org.apache.poi.hssf.record.DBCellRecord; +import org.apache.poi.hssf.record.DConRefRecord; +import org.apache.poi.hssf.record.DimensionsRecord; +import org.apache.poi.hssf.record.FormulaRecord; +import org.apache.poi.hssf.record.IndexRecord; +import org.apache.poi.hssf.record.MergeCellsRecord; +import org.apache.poi.hssf.record.MulBlankRecord; +import org.apache.poi.hssf.record.Record; +import org.apache.poi.hssf.record.RowRecord; +import org.apache.poi.hssf.record.SharedFormulaRecord; +import org.apache.poi.hssf.record.TableRecord; +import org.apache.poi.hssf.record.UnknownRecord; import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.formula.FormulaShifter; @@ -116,7 +130,7 @@ public final class RowRecordsAggregate extends RecordAggregate { // Integer integer = Integer.valueOf(row.getRowNumber()); _rowRecords.put(Integer.valueOf(row.getRowNumber()), row); // Clear the cached values - _rowRecordValues = null; + _rowRecordValues = null; if ((row.getRowNumber() < _firstrow) || (_firstrow == -1)) { _firstrow = row.getRowNumber(); } @@ -137,7 +151,7 @@ public final class RowRecordsAggregate extends RecordAggregate { _rowRecords.put(key, rr); throw new RuntimeException("Attempt to remove row that does not belong to this sheet"); } - + // Clear the cached values _rowRecordValues = null; } @@ -260,7 +274,9 @@ public final class RowRecordsAggregate extends RecordAggregate { // Serialize a block of cells for those rows final int startRowNumber = getStartRowNumberForBlock(blockIndex); final int endRowNumber = getEndRowNumberForBlock(blockIndex); - DBCellRecord.Builder dbcrBuilder = new DBCellRecord.Builder(); + + final List<Short> cellOffsets = new ArrayList<>(); + // Note: Cell references start from the second row... int cellRefOffset = (rowBlockSize - RowRecord.ENCODED_SIZE); for (int row = startRowNumber; row <= endRowNumber; row++) { @@ -271,17 +287,25 @@ public final class RowRecordsAggregate extends RecordAggregate { pos += rowCellSize; // Add the offset to the first cell for the row into the // DBCellRecord. - dbcrBuilder.addCellOffset(cellRefOffset); + cellOffsets.add((short)cellRefOffset); cellRefOffset = rowCellSize; } } // Calculate Offset from the start of a DBCellRecord to the first Row - rv.visitRecord(dbcrBuilder.build(pos)); + rv.visitRecord(new DBCellRecord(pos, shortListToArray(cellOffsets))); } - for (Record _unknownRecord : _unknownRecords) { - // Potentially breaking the file here since we don't know exactly where to write these records - rv.visitRecord(_unknownRecord); + + // Potentially breaking the file here since we don't know exactly where to write these records + _unknownRecords.forEach(rv::visitRecord); + } + + private static short[] shortListToArray(List<Short> list) { + final short[] arr = new short[list.size()]; + int idx = 0; + for (Short s : list) { + arr[idx++] = s; } + return arr; } public Iterator<RowRecord> getIterator() { @@ -434,7 +458,7 @@ public final class RowRecordsAggregate extends RecordAggregate { return startHidden; } - + /** * Returns an iterator for the cell values */ 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 b612a5ee3e..a87a24a81b 100644 --- a/src/java/org/apache/poi/hssf/record/cf/BorderFormatting.java +++ b/src/java/org/apache/poi/hssf/record/cf/BorderFormatting.java @@ -17,48 +17,49 @@ package org.apache.poi.hssf.record.cf; +import org.apache.poi.common.Duplicatable; import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * Border Formatting Block of the Conditional Formatting Rule Record. */ -public final class BorderFormatting implements Cloneable { +public final class BorderFormatting implements Duplicatable { /** No border */ - public final static short BORDER_NONE = 0x0; + public static final short BORDER_NONE = 0x0; /** Thin border */ - public final static short BORDER_THIN = 0x1; + public static final short BORDER_THIN = 0x1; /** Medium border */ - public final static short BORDER_MEDIUM = 0x2; + public static final short BORDER_MEDIUM = 0x2; /** dash border */ - public final static short BORDER_DASHED = 0x3; + public static final short BORDER_DASHED = 0x3; /** dot border */ - public final static short BORDER_HAIR = 0x4; + public static final short BORDER_HAIR = 0x4; /** Thick border */ - public final static short BORDER_THICK = 0x5; + public static final short BORDER_THICK = 0x5; /** double-line border */ - public final static short BORDER_DOUBLE = 0x6; + public static final short BORDER_DOUBLE = 0x6; /** hair-line border */ - public final static short BORDER_DOTTED = 0x7; + public static final short BORDER_DOTTED = 0x7; /** Medium dashed border */ - public final static short BORDER_MEDIUM_DASHED = 0x8; + public static final short BORDER_MEDIUM_DASHED = 0x8; /** dash-dot border */ - public final static short BORDER_DASH_DOT = 0x9; + public static final short BORDER_DASH_DOT = 0x9; /** medium dash-dot border */ - public final static short BORDER_MEDIUM_DASH_DOT = 0xA; + public static final short BORDER_MEDIUM_DASH_DOT = 0xA; /** dash-dot-dot border */ - public final static short BORDER_DASH_DOT_DOT = 0xB; + public static final short BORDER_DASH_DOT_DOT = 0xB; /** medium dash-dot-dot border */ - public final static short BORDER_MEDIUM_DASH_DOT_DOT = 0xC; + public static final short BORDER_MEDIUM_DASH_DOT_DOT = 0xC; /** slanted dash-dot border */ - public final static short BORDER_SLANTED_DASH_DOT = 0xD; + public static final short BORDER_SLANTED_DASH_DOT = 0xD; // BORDER FORMATTING BLOCK // For Border Line Style codes see HSSFCellStyle.BORDER_XXXXXX - private int field_13_border_styles1; private static final BitField bordLeftLineStyle = BitFieldFactory.getInstance(0x0000000F); private static final BitField bordRightLineStyle = BitFieldFactory.getInstance(0x000000F0); private static final BitField bordTopLineStyle = BitFieldFactory.getInstance(0x00000F00); @@ -68,19 +69,26 @@ public final class BorderFormatting implements Cloneable { private static final BitField bordTlBrLineOnOff = BitFieldFactory.getInstance(0x40000000); private static final BitField bordBlTrtLineOnOff = BitFieldFactory.getInstance(0x80000000); - private int field_14_border_styles2; private static final BitField bordTopLineColor = BitFieldFactory.getInstance(0x0000007F); private static final BitField bordBottomLineColor= BitFieldFactory.getInstance(0x00003f80); private static final BitField bordDiagLineColor = BitFieldFactory.getInstance(0x001FC000); private static final BitField bordDiagLineStyle = BitFieldFactory.getInstance(0x01E00000); + private int field_13_border_styles1; + private int field_14_border_styles2; + public BorderFormatting() { field_13_border_styles1 = 0; field_14_border_styles2 = 0; } - /** Creates new FontFormatting */ + public BorderFormatting(BorderFormatting other) { + field_13_border_styles1 = other.field_13_border_styles1; + field_14_border_styles2 = other.field_14_border_styles2; + } + + /** Creates new FontFormatting */ public BorderFormatting(LittleEndianInput in) { field_13_border_styles1 = in.readInt(); field_14_border_styles2 = in.readInt(); @@ -447,11 +455,15 @@ public final class BorderFormatting implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public BorderFormatting clone() { - BorderFormatting rec = new BorderFormatting(); - rec.field_13_border_styles1 = field_13_border_styles1; - rec.field_14_border_styles2 = field_14_border_styles2; - return rec; + return copy(); + } + + public BorderFormatting copy() { + return new BorderFormatting(this); } public int serialize(int offset, byte [] data) { 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 ea781a8062..830d24fd73 100644 --- a/src/java/org/apache/poi/hssf/record/cf/ColorGradientFormatting.java +++ b/src/java/org/apache/poi/hssf/record/cf/ColorGradientFormatting.java @@ -17,6 +17,9 @@ package org.apache.poi.hssf.record.cf; +import java.util.stream.Stream; + +import org.apache.poi.common.Duplicatable; import org.apache.poi.hssf.record.common.ExtendedColor; import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; @@ -24,27 +27,39 @@ import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; +import org.apache.poi.util.Removal; /** * Color Gradient / Color Scale Conditional Formatting Rule Record. * (Called Color Gradient in the file format docs, but more commonly * Color Scale in the UI) */ -public final class ColorGradientFormatting implements Cloneable { - private static POILogger log = POILogFactory.getLogger(ColorGradientFormatting.class); +public final class ColorGradientFormatting implements Duplicatable { + 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 ColorGradientThreshold[] thresholds; private ExtendedColor[] colors; - - private static BitField clamp = BitFieldFactory.getInstance(0x01); - private static BitField background = BitFieldFactory.getInstance(0x02); - + public ColorGradientFormatting() { options = 3; thresholds = new ColorGradientThreshold[3]; - colors = new ExtendedColor[3]; + colors = new ExtendedColor[3]; + } + + public ColorGradientFormatting(ColorGradientFormatting other) { + options = other.options; + if (other.thresholds != null) { + thresholds = Stream.of(other.thresholds).map(ColorGradientThreshold::copy).toArray(ColorGradientThreshold[]::new); + } + if (other.colors != null) { + colors = Stream.of(other.colors).map(ExtendedColor::copy).toArray(ExtendedColor[]::new); + } } + public ColorGradientFormatting(LittleEndianInput in) { in.readShort(); // Ignored in.readByte(); // Reserved @@ -54,7 +69,7 @@ public final class ColorGradientFormatting implements Cloneable { log.log(POILogger.WARN, "Inconsistent Color Gradient defintion, found " + numI + " vs " + numG + " entries"); } options = in.readByte(); - + thresholds = new ColorGradientThreshold[numI]; for (int i=0; i<thresholds.length; i++) { thresholds[i] = new ColorGradientThreshold(in); @@ -65,7 +80,7 @@ public final class ColorGradientFormatting implements Cloneable { colors[i] = new ExtendedColor(in); } } - + public int getNumControlPoints() { return thresholds.length; } @@ -73,18 +88,18 @@ public final class ColorGradientFormatting implements Cloneable { if (num != thresholds.length) { ColorGradientThreshold[] nt = new ColorGradientThreshold[num]; ExtendedColor[] nc = new ExtendedColor[num]; - + int copy = Math.min(thresholds.length, num); System.arraycopy(thresholds, 0, nt, 0, copy); System.arraycopy(colors, 0, nc, 0, copy); - + this.thresholds = nt; this.colors = nc; - + updateThresholdPositions(); } } - + public ColorGradientThreshold[] getThresholds() { return thresholds; } @@ -99,7 +114,7 @@ public final class ColorGradientFormatting implements Cloneable { public void setColors(ExtendedColor[] colors) { this.colors = (colors == null) ? null : colors.clone(); } - + public boolean isClampToCurve() { return getOptionFlag(clamp); } @@ -107,8 +122,7 @@ public final class ColorGradientFormatting implements Cloneable { return getOptionFlag(background); } private boolean getOptionFlag(BitField field) { - int value = field.getValue(options); - return value==0 ? false : true; + return field.isSet(options); } private void updateThresholdPositions() { @@ -116,8 +130,8 @@ public final class ColorGradientFormatting implements Cloneable { for (int i=0; i<thresholds.length; i++) { thresholds[i].setPosition(step*i); } - } - + } + public String toString() { StringBuilder buffer = new StringBuilder(); buffer.append(" [Color Gradient Formatting]\n"); @@ -132,17 +146,19 @@ public final class ColorGradientFormatting implements Cloneable { buffer.append(" [/Color Gradient Formatting]\n"); return buffer.toString(); } - - public Object clone() { - ColorGradientFormatting rec = new ColorGradientFormatting(); - rec.options = options; - rec.thresholds = new ColorGradientThreshold[thresholds.length]; - rec.colors = new ExtendedColor[colors.length]; - System.arraycopy(thresholds, 0, rec.thresholds, 0, thresholds.length); - System.arraycopy(colors, 0, rec.colors, 0, colors.length); - return rec; - } - + + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public ColorGradientFormatting clone() { + return copy(); + } + + public ColorGradientFormatting copy() { + return new ColorGradientFormatting(this); + } + public int getDataLength() { int len = 6; for (Threshold t : thresholds) { @@ -161,15 +177,15 @@ public final class ColorGradientFormatting implements Cloneable { out.writeByte(thresholds.length); out.writeByte(thresholds.length); out.writeByte(options); - + for (ColorGradientThreshold t : thresholds) { t.serialize(out); } - + double step = 1d / (colors.length-1); for (int i=0; i<colors.length; i++) { out.writeDouble(i*step); - + ExtendedColor c = colors[i]; c.serialize(out); } 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 e7bea75a5a..9c41995dbd 100644 --- a/src/java/org/apache/poi/hssf/record/cf/ColorGradientThreshold.java +++ b/src/java/org/apache/poi/hssf/record/cf/ColorGradientThreshold.java @@ -17,21 +17,27 @@ package org.apache.poi.hssf.record.cf; +import org.apache.poi.common.Duplicatable; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; +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 Cloneable { +public final class ColorGradientThreshold extends Threshold implements Duplicatable { private double position; public ColorGradientThreshold() { - super(); position = 0d; } + public ColorGradientThreshold(ColorGradientThreshold other) { + super(other); + position = other.position; + } + /** Creates new Color Gradient Threshold */ public ColorGradientThreshold(LittleEndianInput in) { super(in); @@ -50,11 +56,16 @@ public final class ColorGradientThreshold extends Threshold implements Cloneable } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public ColorGradientThreshold clone() { - ColorGradientThreshold rec = new ColorGradientThreshold(); - super.copyTo(rec); - rec.position = position; - return rec; + return copy(); + } + + @Override + public ColorGradientThreshold copy() { + return new ColorGradientThreshold(this); } public void serialize(LittleEndianOutput out) { 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 2e5cb7252b..466fad4990 100644 --- a/src/java/org/apache/poi/hssf/record/cf/DataBarFormatting.java +++ b/src/java/org/apache/poi/hssf/record/cf/DataBarFormatting.java @@ -17,6 +17,7 @@ package org.apache.poi.hssf.record.cf; +import org.apache.poi.common.Duplicatable; import org.apache.poi.hssf.record.common.ExtendedColor; import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; @@ -24,57 +25,68 @@ import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; +import org.apache.poi.util.Removal; /** * Data Bar Conditional Formatting Rule Record. */ -public final class DataBarFormatting implements Cloneable { +public final class DataBarFormatting implements Duplicatable { private static POILogger log = POILogFactory.getLogger(DataBarFormatting.class); + private static final BitField iconOnly = BitFieldFactory.getInstance(0x01); + private static final BitField reversed = BitFieldFactory.getInstance(0x04); + private byte options; private byte percentMin; private byte percentMax; private ExtendedColor color; private DataBarThreshold thresholdMin; private DataBarThreshold thresholdMax; - - private static BitField iconOnly = BitFieldFactory.getInstance(0x01); - private static BitField reversed = BitFieldFactory.getInstance(0x04); - + public DataBarFormatting() { options = 2; } + + public DataBarFormatting(DataBarFormatting other) { + options = other.options; + percentMin = other.percentMin; + percentMax = other.percentMax; + color = (other.color == null) ? null : other.color.copy(); + thresholdMin = (other.thresholdMin == null) ? null : other.thresholdMin.copy(); + thresholdMax = (other.thresholdMax == null) ? null : other.thresholdMax.copy(); + } + public DataBarFormatting(LittleEndianInput in) { in.readShort(); // Ignored in.readByte(); // Reserved options = in.readByte(); - + percentMin = in.readByte(); percentMax = in.readByte(); if (percentMin < 0 || percentMin > 100) log.log(POILogger.WARN, "Inconsistent Minimum Percentage found " + percentMin); if (percentMax < 0 || percentMax > 100) log.log(POILogger.WARN, "Inconsistent Minimum Percentage found " + percentMin); - + color = new ExtendedColor(in); thresholdMin = new DataBarThreshold(in); thresholdMax = new DataBarThreshold(in); } - + public boolean isIconOnly() { return getOptionFlag(iconOnly); } public void setIconOnly(boolean only) { setOptionFlag(only, iconOnly); } - + public boolean isReversed() { return getOptionFlag(reversed); } public void setReversed(boolean rev) { setOptionFlag(rev, reversed); } - + private boolean getOptionFlag(BitField field) { int value = field.getValue(options); return value==0 ? false : true; @@ -89,35 +101,35 @@ public final class DataBarFormatting implements Cloneable { public void setPercentMin(byte percentMin) { this.percentMin = percentMin; } - + public byte getPercentMax() { return percentMax; } public void setPercentMax(byte percentMax) { this.percentMax = percentMax; } - + public ExtendedColor getColor() { return color; } public void setColor(ExtendedColor color) { this.color = color; } - + public DataBarThreshold getThresholdMin() { return thresholdMin; } public void setThresholdMin(DataBarThreshold thresholdMin) { this.thresholdMin = thresholdMin; } - + public DataBarThreshold getThresholdMax() { return thresholdMax; } public void setThresholdMax(DataBarThreshold thresholdMax) { this.thresholdMax = thresholdMax; } - + public String toString() { StringBuilder buffer = new StringBuilder(); buffer.append(" [Data Bar Formatting]\n"); @@ -129,21 +141,22 @@ public final class DataBarFormatting implements Cloneable { buffer.append(" [/Data Bar Formatting]\n"); return buffer.toString(); } - - public Object clone() { - DataBarFormatting rec = new DataBarFormatting(); - rec.options = options; - rec.percentMin = percentMin; - rec.percentMax = percentMax; - rec.color = color.clone(); - rec.thresholdMin = thresholdMin.clone(); - rec.thresholdMax = thresholdMax.clone(); - return rec; - } - + + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public DataBarFormatting clone() { + return copy(); + } + + public DataBarFormatting copy() { + return new DataBarFormatting(this); + } + public int getDataLength() { return 6 + color.getDataLength() + - thresholdMin.getDataLength() + + thresholdMin.getDataLength() + thresholdMax.getDataLength(); } diff --git a/src/java/org/apache/poi/hssf/record/cf/DataBarThreshold.java b/src/java/org/apache/poi/hssf/record/cf/DataBarThreshold.java index 63c7f6b363..8d88a6ab23 100644 --- a/src/java/org/apache/poi/hssf/record/cf/DataBarThreshold.java +++ b/src/java/org/apache/poi/hssf/record/cf/DataBarThreshold.java @@ -17,26 +17,38 @@ package org.apache.poi.hssf.record.cf; +import org.apache.poi.common.Duplicatable; import org.apache.poi.util.LittleEndianInput; +import org.apache.poi.util.Removal; /** * Data Bar specific Threshold / value (CFVO), * for changes in Conditional Formatting */ -public final class DataBarThreshold extends Threshold implements Cloneable { +public final class DataBarThreshold extends Threshold implements Duplicatable { public DataBarThreshold() { super(); } + public DataBarThreshold(DataBarThreshold other) { + super(other); + } + /** Creates new Data Bar Threshold */ public DataBarThreshold(LittleEndianInput in) { super(in); } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public DataBarThreshold clone() { - DataBarThreshold rec = new DataBarThreshold(); - super.copyTo(rec); - return rec; + return copy(); + } + + @Override + public DataBarThreshold copy() { + return new DataBarThreshold(this); } } 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 e6ea05de23..22a4aed29e 100644 --- a/src/java/org/apache/poi/hssf/record/cf/FontFormatting.java +++ b/src/java/org/apache/poi/hssf/record/cf/FontFormatting.java @@ -20,17 +20,17 @@ package org.apache.poi.hssf.record.cf; import java.util.Locale; +import org.apache.poi.common.Duplicatable; import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; 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 Cloneable { - private final byte[] _rawData = new byte[RAW_DATA_SIZE]; - +public final class FontFormatting implements Duplicatable { private static final int OFFSET_FONT_NAME = 0; private static final int OFFSET_FONT_HEIGHT = 64; private static final int OFFSET_FONT_OPTIONS = 68; @@ -49,7 +49,7 @@ public final class FontFormatting implements Cloneable { private static final int RAW_DATA_SIZE = 118; - public final static int FONT_CELL_HEIGHT_PRESERVED = 0xFFFFFFFF; + public static final int FONT_CELL_HEIGHT_PRESERVED = 0xFFFFFFFF; // FONT OPTIONS MASKS private static final BitField posture = BitFieldFactory.getInstance(0x00000002); @@ -88,6 +88,8 @@ public final class FontFormatting implements Cloneable { */ private static final short FONT_WEIGHT_BOLD = 0x2bc; + private final byte[] _rawData = new byte[RAW_DATA_SIZE]; + public FontFormatting() { setFontHeight(-1); setItalic(false); @@ -114,11 +116,12 @@ public final class FontFormatting implements Cloneable { setShort(OFFSET_FONT_FORMATING_END, 0x0001); } - /** Creates new FontFormatting */ + public FontFormatting(FontFormatting other) { + System.arraycopy(other._rawData, 0, _rawData, 0, _rawData.length); + } + public FontFormatting(RecordInputStream in) { - for (int i = 0; i < _rawData.length; i++) { - _rawData[i] = in.readByte(); - } + in.readFully(_rawData); } private short getShort(int offset) { @@ -499,7 +502,7 @@ public final class FontFormatting implements Cloneable { append(getFontWeight()). append( getFontWeight() == FONT_WEIGHT_NORMAL ? "(Normal)" - : getFontWeight() == FONT_WEIGHT_BOLD ? "(Bold)" + : getFontWeight() == FONT_WEIGHT_BOLD ? "(Bold)" : "0x"+Integer.toHexString(getFontWeight())). append("\n"); } @@ -533,9 +536,15 @@ public final class FontFormatting implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public FontFormatting clone() { - FontFormatting other = new FontFormatting(); - System.arraycopy(_rawData, 0, other._rawData, 0, _rawData.length); - return other; + return copy(); + } + + @Override + public FontFormatting copy() { + return new FontFormatting(this); } } 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 b388296180..08d3ea04f6 100644 --- a/src/java/org/apache/poi/hssf/record/cf/IconMultiStateFormatting.java +++ b/src/java/org/apache/poi/hssf/record/cf/IconMultiStateFormatting.java @@ -17,6 +17,9 @@ package org.apache.poi.hssf.record.cf; +import java.util.stream.Stream; + +import org.apache.poi.common.Duplicatable; import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet; import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; @@ -24,17 +27,18 @@ import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; +import org.apache.poi.util.Removal; /** * Icon / Multi-State Conditional Formatting Rule Record. */ -public final class IconMultiStateFormatting implements Cloneable { - private static POILogger log = POILogFactory.getLogger(IconMultiStateFormatting.class); - +public final class IconMultiStateFormatting implements Duplicatable { + private static final POILogger log = POILogFactory.getLogger(IconMultiStateFormatting.class); + private IconSet iconSet; private byte options; private Threshold[] thresholds; - + private static BitField iconOnly = BitFieldFactory.getInstance(0x01); private static BitField reversed = BitFieldFactory.getInstance(0x04); @@ -43,6 +47,15 @@ public final class IconMultiStateFormatting implements Cloneable { options = 0; thresholds = new Threshold[iconSet.num]; } + + public IconMultiStateFormatting(IconMultiStateFormatting other) { + iconSet = other.iconSet; + options = other.options; + if (other.thresholds != null) { + thresholds = Stream.of(other.thresholds).map(Threshold::copy).toArray(Threshold[]::new); + } + } + public IconMultiStateFormatting(LittleEndianInput in) { in.readShort(); // Ignored in.readByte(); // Reserved @@ -53,13 +66,13 @@ public final class IconMultiStateFormatting implements Cloneable { log.log(POILogger.WARN, "Inconsistent Icon Set defintion, found " + iconSet + " but defined as " + num + " entries"); } options = in.readByte(); - + thresholds = new Threshold[iconSet.num]; for (int i=0; i<thresholds.length; i++) { thresholds[i] = new IconMultiStateThreshold(in); } } - + public IconSet getIconSet() { return iconSet; } @@ -73,21 +86,21 @@ public final class IconMultiStateFormatting implements Cloneable { public void setThresholds(Threshold[] thresholds) { this.thresholds = (thresholds == null) ? null : thresholds.clone(); } - + public boolean isIconOnly() { return getOptionFlag(iconOnly); } public void setIconOnly(boolean only) { setOptionFlag(only, iconOnly); } - + public boolean isReversed() { return getOptionFlag(reversed); } public void setReversed(boolean rev) { setOptionFlag(rev, reversed); } - + private boolean getOptionFlag(BitField field) { int value = field.getValue(options); return value==0 ? false : true; @@ -95,7 +108,7 @@ public final class IconMultiStateFormatting implements Cloneable { private void setOptionFlag(boolean option, BitField field) { options = field.setByteBoolean(options, option); } - + public String toString() { StringBuilder buffer = new StringBuilder(); buffer.append(" [Icon Formatting]\n"); @@ -108,16 +121,20 @@ public final class IconMultiStateFormatting implements Cloneable { buffer.append(" [/Icon Formatting]\n"); return buffer.toString(); } - - public Object clone() { - IconMultiStateFormatting rec = new IconMultiStateFormatting(); - rec.iconSet = iconSet; - rec.options = options; - rec.thresholds = new Threshold[thresholds.length]; - System.arraycopy(thresholds, 0, rec.thresholds, 0, thresholds.length); - return rec; + + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public IconMultiStateFormatting clone() { + return copy(); + } + + @Override + public IconMultiStateFormatting copy() { + return new IconMultiStateFormatting(this); } - + public int getDataLength() { int len = 6; for (Threshold t : thresholds) { diff --git a/src/java/org/apache/poi/hssf/record/cf/IconMultiStateThreshold.java b/src/java/org/apache/poi/hssf/record/cf/IconMultiStateThreshold.java index 03d95caf33..a8c9e807cd 100644 --- a/src/java/org/apache/poi/hssf/record/cf/IconMultiStateThreshold.java +++ b/src/java/org/apache/poi/hssf/record/cf/IconMultiStateThreshold.java @@ -17,14 +17,16 @@ package org.apache.poi.hssf.record.cf; +import org.apache.poi.common.Duplicatable; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * Icon / Multi-State specific Threshold / value (CFVO), * for changes in Conditional Formatting */ -public final class IconMultiStateThreshold extends Threshold implements Cloneable { +public final class IconMultiStateThreshold extends Threshold implements Duplicatable { /** * Cell values that are equal to the threshold value do not pass the threshold */ @@ -33,15 +35,18 @@ public final class IconMultiStateThreshold extends Threshold implements Cloneabl * Cell values that are equal to the threshold value pass the threshold. */ public static final byte EQUALS_INCLUDE = 1; - + private byte equals; public IconMultiStateThreshold() { - super(); equals = EQUALS_INCLUDE; } - /** Creates new Ico Multi-State Threshold */ + public IconMultiStateThreshold(IconMultiStateThreshold other) { + super(other); + equals = other.equals; + } + public IconMultiStateThreshold(LittleEndianInput in) { super(in); equals = in.readByte(); @@ -61,11 +66,16 @@ public final class IconMultiStateThreshold extends Threshold implements Cloneabl } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public IconMultiStateThreshold clone() { - IconMultiStateThreshold rec = new IconMultiStateThreshold(); - super.copyTo(rec); - rec.equals = equals; - return rec; + return copy(); + } + + @Override + public IconMultiStateThreshold copy() { + return new IconMultiStateThreshold(this); } public void serialize(LittleEndianOutput out) { 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 1294e43d16..e03e652698 100644 --- a/src/java/org/apache/poi/hssf/record/cf/PatternFormatting.java +++ b/src/java/org/apache/poi/hssf/record/cf/PatternFormatting.java @@ -17,80 +17,87 @@ package org.apache.poi.hssf.record.cf; +import org.apache.poi.common.Duplicatable; import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * Pattern Formatting Block of the Conditional Formatting Rule Record. */ -public final class PatternFormatting implements Cloneable { +public final class PatternFormatting implements Duplicatable { /** No background */ - public final static short NO_FILL = 0 ; + public static final short NO_FILL = 0 ; /** Solidly filled */ - public final static short SOLID_FOREGROUND = 1 ; + public static final short SOLID_FOREGROUND = 1 ; /** Small fine dots */ - public final static short FINE_DOTS = 2 ; + public static final short FINE_DOTS = 2 ; /** Wide dots */ - public final static short ALT_BARS = 3 ; + public static final short ALT_BARS = 3 ; /** Sparse dots */ - public final static short SPARSE_DOTS = 4 ; + public static final short SPARSE_DOTS = 4 ; /** Thick horizontal bands */ - public final static short THICK_HORZ_BANDS = 5 ; + public static final short THICK_HORZ_BANDS = 5 ; /** Thick vertical bands */ - public final static short THICK_VERT_BANDS = 6 ; + public static final short THICK_VERT_BANDS = 6 ; /** Thick backward facing diagonals */ - public final static short THICK_BACKWARD_DIAG = 7 ; + public static final short THICK_BACKWARD_DIAG = 7 ; /** Thick forward facing diagonals */ - public final static short THICK_FORWARD_DIAG = 8 ; + public static final short THICK_FORWARD_DIAG = 8 ; /** Large spots */ - public final static short BIG_SPOTS = 9 ; + public static final short BIG_SPOTS = 9 ; /** Brick-like layout */ - public final static short BRICKS = 10 ; + public static final short BRICKS = 10 ; /** Thin horizontal bands */ - public final static short THIN_HORZ_BANDS = 11 ; + public static final short THIN_HORZ_BANDS = 11 ; /** Thin vertical bands */ - public final static short THIN_VERT_BANDS = 12 ; + public static final short THIN_VERT_BANDS = 12 ; /** Thin backward diagonal */ - public final static short THIN_BACKWARD_DIAG = 13 ; + public static final short THIN_BACKWARD_DIAG = 13 ; /** Thin forward diagonal */ - public final static short THIN_FORWARD_DIAG = 14 ; + public static final short THIN_FORWARD_DIAG = 14 ; /** Squares */ - public final static short SQUARES = 15 ; + public static final short SQUARES = 15 ; /** Diamonds */ - public final static short DIAMONDS = 16 ; + public static final short DIAMONDS = 16 ; /** Less Dots */ - public final static short LESS_DOTS = 17 ; + public static final short LESS_DOTS = 17 ; /** Least Dots */ - public final static short LEAST_DOTS = 18 ; - - + public static final short LEAST_DOTS = 18 ; + + // PATTERN FORMATING BLOCK // For Pattern Styles see constants at HSSFCellStyle (from NO_FILL to LEAST_DOTS) - private int field_15_pattern_style; private static final BitField fillPatternStyle = BitFieldFactory.getInstance(0xFC00); - - private int field_16_pattern_color_indexes; - private static final BitField patternColorIndex = BitFieldFactory.getInstance(0x007F); - private static final BitField patternBackgroundColorIndex = BitFieldFactory.getInstance(0x3F80); - + private static final BitField patternColorIndex = BitFieldFactory.getInstance(0x007F); + private static final BitField patternBackgroundColorIndex = BitFieldFactory.getInstance(0x3F80); + + private int field_15_pattern_style; + private int field_16_pattern_color_indexes; + + public PatternFormatting() { - field_15_pattern_style = 0; - field_16_pattern_color_indexes = 0; + field_15_pattern_style = 0; + field_16_pattern_color_indexes = 0; + } + + public PatternFormatting(PatternFormatting other) { + field_15_pattern_style = other.field_15_pattern_style; + field_16_pattern_color_indexes = other.field_16_pattern_color_indexes; } - - /** Creates new FontFormatting */ + public PatternFormatting(LittleEndianInput in) { field_15_pattern_style = in.readUShort(); field_16_pattern_color_indexes = in.readUShort(); } - + public int getDataLength() { return 4; } - + /** * setting fill pattern * @@ -112,7 +119,7 @@ public final class PatternFormatting implements Cloneable { * @see #SQUARES * @see #DIAMONDS * - * @param fp fill pattern + * @param fp fill pattern */ public void setFillPattern(int fp) { field_15_pattern_style = fillPatternStyle.setValue(field_15_pattern_style, fp); @@ -124,11 +131,11 @@ public final class PatternFormatting implements Cloneable { public int getFillPattern() { return fillPatternStyle.getValue(field_15_pattern_style); } - + /** * set the background fill color. */ - public void setFillBackgroundColor(int bg) { + public void setFillBackgroundColor(int bg) { field_16_pattern_color_indexes = patternBackgroundColorIndex.setValue(field_16_pattern_color_indexes,bg); } @@ -154,7 +161,7 @@ public final class PatternFormatting implements Cloneable { public int getFillForegroundColor() { return patternColorIndex.getValue(field_16_pattern_color_indexes); } - + public String toString() { StringBuilder buffer = new StringBuilder(); buffer.append(" [Pattern Formatting]\n"); @@ -164,12 +171,17 @@ public final class PatternFormatting implements Cloneable { buffer.append(" [/Pattern Formatting]\n"); return buffer.toString(); } - - public Object clone() { - PatternFormatting rec = new PatternFormatting(); - rec.field_15_pattern_style = field_15_pattern_style; - rec.field_16_pattern_color_indexes = field_16_pattern_color_indexes; - return rec; + + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public PatternFormatting clone() { + return copy(); + } + + public PatternFormatting copy() { + return new PatternFormatting(this); } public void serialize(LittleEndianOutput out) { 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 71df40b9c0..4ce6a1e107 100644 --- a/src/java/org/apache/poi/hssf/record/cf/Threshold.java +++ b/src/java/org/apache/poi/hssf/record/cf/Threshold.java @@ -39,6 +39,12 @@ public abstract class Threshold { value = 0d; } + protected Threshold(Threshold other) { + type = other.type; + formula = other.formula.copy(); + value = other.value; + } + /** Creates new Threshold */ protected Threshold(LittleEndianInput in) { type = in.readByte(); @@ -92,7 +98,7 @@ public abstract class Threshold { public void setValue(Double value) { this.value = value; } - + public int getDataLength() { int len = 1 + formula.getEncodedSize(); if (value != null) { @@ -111,12 +117,6 @@ public abstract class Threshold { return buffer.toString(); } - public void copyTo(Threshold rec) { - rec.type = type; - rec.formula = formula; - rec.value = value; - } - public void serialize(LittleEndianOutput out) { out.writeByte(type); if (formula.getTokens().length == 0) { @@ -128,4 +128,6 @@ public abstract class Threshold { out.writeDouble(value); } } + + public abstract Threshold copy(); } diff --git a/src/java/org/apache/poi/hssf/record/chart/AreaFormatRecord.java b/src/java/org/apache/poi/hssf/record/chart/AreaFormatRecord.java index afda4669a6..61b19fd5df 100644 --- a/src/java/org/apache/poi/hssf/record/chart/AreaFormatRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/AreaFormatRecord.java @@ -23,18 +23,17 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * The area format record is used to define the colours and patterns for an area.<p> - * - * @author Glen Stampoultzis (glens at apache.org) + * The area format record is used to define the colours and patterns for an area. */ -public final class AreaFormatRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x100A; - +public final class AreaFormatRecord extends StandardRecord { + public static final short sid = 0x100A; + private static final BitField automatic = BitFieldFactory.getInstance(0x1); private static final BitField invert = BitFieldFactory.getInstance(0x2); - + private int field_1_foregroundColor; private int field_2_backgroundColor; private short field_3_pattern; @@ -43,20 +42,25 @@ public final class AreaFormatRecord extends StandardRecord implements Cloneable private short field_6_backcolorIndex; - public AreaFormatRecord() - { + public AreaFormatRecord() {} - } - - public AreaFormatRecord(RecordInputStream in) - { + public AreaFormatRecord(RecordInputStream in) { field_1_foregroundColor = in.readInt(); field_2_backgroundColor = in.readInt(); field_3_pattern = in.readShort(); field_4_formatFlags = in.readShort(); field_5_forecolorIndex = in.readShort(); field_6_backcolorIndex = in.readShort(); + } + public AreaFormatRecord(AreaFormatRecord other) { + super(other); + field_1_foregroundColor = other.field_1_foregroundColor; + field_2_backgroundColor = other.field_2_backgroundColor; + field_3_pattern = other.field_3_pattern; + field_4_formatFlags = other.field_4_formatFlags; + field_5_forecolorIndex = other.field_5_forecolorIndex; + field_6_backcolorIndex = other.field_6_backcolorIndex; } public String toString() @@ -67,29 +71,29 @@ public final class AreaFormatRecord extends StandardRecord implements Cloneable buffer.append(" .foregroundColor = ") .append("0x").append(HexDump.toHex( getForegroundColor ())) .append(" (").append( getForegroundColor() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .backgroundColor = ") .append("0x").append(HexDump.toHex( getBackgroundColor ())) .append(" (").append( getBackgroundColor() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .pattern = ") .append("0x").append(HexDump.toHex( getPattern ())) .append(" (").append( getPattern() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .formatFlags = ") .append("0x").append(HexDump.toHex( getFormatFlags ())) .append(" (").append( getFormatFlags() ).append(" )"); - buffer.append(System.getProperty("line.separator")); - buffer.append(" .automatic = ").append(isAutomatic()).append('\n'); - buffer.append(" .invert = ").append(isInvert()).append('\n'); + buffer.append(System.getProperty("line.separator")); + buffer.append(" .automatic = ").append(isAutomatic()).append('\n'); + buffer.append(" .invert = ").append(isInvert()).append('\n'); buffer.append(" .forecolorIndex = ") .append("0x").append(HexDump.toHex( getForecolorIndex ())) .append(" (").append( getForecolorIndex() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .backcolorIndex = ") .append("0x").append(HexDump.toHex( getBackcolorIndex ())) .append(" (").append( getBackcolorIndex() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append("[/AREAFORMAT]\n"); return buffer.toString(); @@ -114,21 +118,13 @@ public final class AreaFormatRecord extends StandardRecord implements Cloneable } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public AreaFormatRecord clone() { - AreaFormatRecord rec = new AreaFormatRecord(); - - rec.field_1_foregroundColor = field_1_foregroundColor; - rec.field_2_backgroundColor = field_2_backgroundColor; - rec.field_3_pattern = field_3_pattern; - rec.field_4_formatFlags = field_4_formatFlags; - rec.field_5_forecolorIndex = field_5_forecolorIndex; - rec.field_6_backcolorIndex = field_6_backcolorIndex; - return rec; + return copy(); } - - - /** * Get the foreground color field for the AreaFormat record. */ @@ -260,4 +256,9 @@ public final class AreaFormatRecord extends StandardRecord implements Cloneable { return invert.isSet(field_4_formatFlags); } + + @Override + public AreaFormatRecord copy() { + return new AreaFormatRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/chart/AreaRecord.java b/src/java/org/apache/poi/hssf/record/chart/AreaRecord.java index 77746d40a1..98431b7e18 100644 --- a/src/java/org/apache/poi/hssf/record/chart/AreaRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/AreaRecord.java @@ -23,28 +23,28 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * The area record is used to define a area chart.<p> - * - * @author Glen Stampoultzis (glens at apache.org) + * The area record is used to define a area chart. */ -public final class AreaRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x101A; - private short field_1_formatFlags; +public final class AreaRecord extends StandardRecord { + public static final short sid = 0x101A; private static final BitField stacked = BitFieldFactory.getInstance(0x1); private static final BitField displayAsPercentage = BitFieldFactory.getInstance(0x2); private static final BitField shadow = BitFieldFactory.getInstance(0x4); + private short field_1_formatFlags; - public AreaRecord() - { - } + public AreaRecord() {} - public AreaRecord(RecordInputStream in) - { + public AreaRecord(AreaRecord other) { + super(other); + field_1_formatFlags = other.field_1_formatFlags; + } + public AreaRecord(RecordInputStream in) { field_1_formatFlags = in.readShort(); } @@ -56,10 +56,10 @@ public final class AreaRecord extends StandardRecord implements Cloneable { buffer.append(" .formatFlags = ") .append("0x").append(HexDump.toHex( getFormatFlags ())) .append(" (").append( getFormatFlags() ).append(" )"); - buffer.append(System.getProperty("line.separator")); - buffer.append(" .stacked = ").append(isStacked()).append('\n'); - buffer.append(" .displayAsPercentage = ").append(isDisplayAsPercentage()).append('\n'); - buffer.append(" .shadow = ").append(isShadow()).append('\n'); + buffer.append(System.getProperty("line.separator")); + buffer.append(" .stacked = ").append(isStacked()).append('\n'); + buffer.append(" .displayAsPercentage = ").append(isDisplayAsPercentage()).append('\n'); + buffer.append(" .shadow = ").append(isShadow()).append('\n'); buffer.append("[/AREA]\n"); return buffer.toString(); @@ -79,16 +79,13 @@ public final class AreaRecord extends StandardRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public AreaRecord clone() { - AreaRecord rec = new AreaRecord(); - - rec.field_1_formatFlags = field_1_formatFlags; - return rec; + return copy(); } - - - /** * Get the format flags field for the Area record. */ @@ -158,4 +155,9 @@ public final class AreaRecord extends StandardRecord implements Cloneable { { return shadow.isSet(field_1_formatFlags); } + + @Override + public AreaRecord copy() { + return new AreaRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/chart/AxisLineFormatRecord.java b/src/java/org/apache/poi/hssf/record/chart/AxisLineFormatRecord.java index 7996aa99c7..8ae0b7ffea 100644 --- a/src/java/org/apache/poi/hssf/record/chart/AxisLineFormatRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/AxisLineFormatRecord.java @@ -21,29 +21,29 @@ import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * The axis line format record defines the axis type details.<p> - * - * @author Glen Stampoultzis (glens at apache.org) + * The axis line format record defines the axis type details. */ -public final class AxisLineFormatRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x1021; - private short field_1_axisType; - public final static short AXIS_TYPE_AXIS_LINE = 0; - public final static short AXIS_TYPE_MAJOR_GRID_LINE = 1; - public final static short AXIS_TYPE_MINOR_GRID_LINE = 2; - public final static short AXIS_TYPE_WALLS_OR_FLOOR = 3; +public final class AxisLineFormatRecord extends StandardRecord { + public static final short sid = 0x1021; + public static final short AXIS_TYPE_AXIS_LINE = 0; + public static final short AXIS_TYPE_MAJOR_GRID_LINE = 1; + public static final short AXIS_TYPE_MINOR_GRID_LINE = 2; + public static final short AXIS_TYPE_WALLS_OR_FLOOR = 3; + private short field_1_axisType; - public AxisLineFormatRecord() - { + public AxisLineFormatRecord() {} + public AxisLineFormatRecord(AxisLineFormatRecord other) { + super(other); + field_1_axisType = other.field_1_axisType; } - public AxisLineFormatRecord(RecordInputStream in) - { - field_1_axisType = in.readShort(); + public AxisLineFormatRecord(RecordInputStream in) { + field_1_axisType = in.readShort(); } public String toString() @@ -54,7 +54,7 @@ public final class AxisLineFormatRecord extends StandardRecord implements Clonea buffer.append(" .axisType = ") .append("0x").append(HexDump.toHex( getAxisType ())) .append(" (").append( getAxisType() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append("[/AXISLINEFORMAT]\n"); return buffer.toString(); @@ -74,20 +74,17 @@ public final class AxisLineFormatRecord extends StandardRecord implements Clonea } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public AxisLineFormatRecord clone() { - AxisLineFormatRecord rec = new AxisLineFormatRecord(); - - rec.field_1_axisType = field_1_axisType; - return rec; + return copy(); } - - - /** * Get the axis type field for the AxisLineFormat record. * - * @return One of + * @return One of * AXIS_TYPE_AXIS_LINE * AXIS_TYPE_MAJOR_GRID_LINE * AXIS_TYPE_MINOR_GRID_LINE @@ -102,7 +99,7 @@ public final class AxisLineFormatRecord extends StandardRecord implements Clonea * Set the axis type field for the AxisLineFormat record. * * @param field_1_axisType - * One of + * One of * AXIS_TYPE_AXIS_LINE * AXIS_TYPE_MAJOR_GRID_LINE * AXIS_TYPE_MINOR_GRID_LINE @@ -112,4 +109,9 @@ public final class AxisLineFormatRecord extends StandardRecord implements Clonea { this.field_1_axisType = field_1_axisType; } + + @Override + public AxisLineFormatRecord copy() { + return new AxisLineFormatRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/chart/AxisOptionsRecord.java b/src/java/org/apache/poi/hssf/record/chart/AxisOptionsRecord.java index b08fdb29e6..158284f21c 100644 --- a/src/java/org/apache/poi/hssf/record/chart/AxisOptionsRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/AxisOptionsRecord.java @@ -23,14 +23,13 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * The axis options record provides unit information and other various tidbits about the axis.<p> - * - * @author Andrew C. Oliver(acoliver at apache.org) + * The axis options record provides unit information and other various tidbits about the axis. */ -public final class AxisOptionsRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x1062; +public final class AxisOptionsRecord extends StandardRecord { + public static final short sid = 0x1062; private static final BitField defaultMinimum = BitFieldFactory.getInstance(0x01); private static final BitField defaultMaximum = BitFieldFactory.getInstance(0x02); @@ -52,22 +51,32 @@ public final class AxisOptionsRecord extends StandardRecord implements Cloneable private short field_9_options; - public AxisOptionsRecord() - { + public AxisOptionsRecord() {} + public AxisOptionsRecord(AxisOptionsRecord other) { + super(other); + field_1_minimumCategory = other.field_1_minimumCategory; + field_2_maximumCategory = other.field_2_maximumCategory; + field_3_majorUnitValue = other.field_3_majorUnitValue; + field_4_majorUnit = other.field_4_majorUnit; + field_5_minorUnitValue = other.field_5_minorUnitValue; + field_6_minorUnit = other.field_6_minorUnit; + field_7_baseUnit = other.field_7_baseUnit; + field_8_crossingPoint = other.field_8_crossingPoint; + field_9_options = other.field_9_options; } - public AxisOptionsRecord(RecordInputStream in) - { - field_1_minimumCategory = in.readShort(); - field_2_maximumCategory = in.readShort(); - field_3_majorUnitValue = in.readShort(); - field_4_majorUnit = in.readShort(); - field_5_minorUnitValue = in.readShort(); - field_6_minorUnit = in.readShort(); - field_7_baseUnit = in.readShort(); - field_8_crossingPoint = in.readShort(); - field_9_options = in.readShort(); + + public AxisOptionsRecord(RecordInputStream in) { + field_1_minimumCategory = in.readShort(); + field_2_maximumCategory = in.readShort(); + field_3_majorUnitValue = in.readShort(); + field_4_majorUnit = in.readShort(); + field_5_minorUnitValue = in.readShort(); + field_6_minorUnit = in.readShort(); + field_7_baseUnit = in.readShort(); + field_8_crossingPoint = in.readShort(); + field_9_options = in.readShort(); } public String toString() @@ -78,47 +87,47 @@ public final class AxisOptionsRecord extends StandardRecord implements Cloneable buffer.append(" .minimumCategory = ") .append("0x").append(HexDump.toHex( getMinimumCategory ())) .append(" (").append( getMinimumCategory() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .maximumCategory = ") .append("0x").append(HexDump.toHex( getMaximumCategory ())) .append(" (").append( getMaximumCategory() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .majorUnitValue = ") .append("0x").append(HexDump.toHex( getMajorUnitValue ())) .append(" (").append( getMajorUnitValue() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .majorUnit = ") .append("0x").append(HexDump.toHex( getMajorUnit ())) .append(" (").append( getMajorUnit() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .minorUnitValue = ") .append("0x").append(HexDump.toHex( getMinorUnitValue ())) .append(" (").append( getMinorUnitValue() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .minorUnit = ") .append("0x").append(HexDump.toHex( getMinorUnit ())) .append(" (").append( getMinorUnit() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .baseUnit = ") .append("0x").append(HexDump.toHex( getBaseUnit ())) .append(" (").append( getBaseUnit() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .crossingPoint = ") .append("0x").append(HexDump.toHex( getCrossingPoint ())) .append(" (").append( getCrossingPoint() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .options = ") .append("0x").append(HexDump.toHex( getOptions ())) .append(" (").append( getOptions() ).append(" )"); - buffer.append(System.getProperty("line.separator")); - buffer.append(" .defaultMinimum = ").append(isDefaultMinimum()).append('\n'); - buffer.append(" .defaultMaximum = ").append(isDefaultMaximum()).append('\n'); - buffer.append(" .defaultMajor = ").append(isDefaultMajor()).append('\n'); - buffer.append(" .defaultMinorUnit = ").append(isDefaultMinorUnit()).append('\n'); - buffer.append(" .isDate = ").append(isIsDate()).append('\n'); - buffer.append(" .defaultBase = ").append(isDefaultBase()).append('\n'); - buffer.append(" .defaultCross = ").append(isDefaultCross()).append('\n'); - buffer.append(" .defaultDateSettings = ").append(isDefaultDateSettings()).append('\n'); + buffer.append(System.getProperty("line.separator")); + buffer.append(" .defaultMinimum = ").append(isDefaultMinimum()).append('\n'); + buffer.append(" .defaultMaximum = ").append(isDefaultMaximum()).append('\n'); + buffer.append(" .defaultMajor = ").append(isDefaultMajor()).append('\n'); + buffer.append(" .defaultMinorUnit = ").append(isDefaultMinorUnit()).append('\n'); + buffer.append(" .isDate = ").append(isIsDate()).append('\n'); + buffer.append(" .defaultBase = ").append(isDefaultBase()).append('\n'); + buffer.append(" .defaultCross = ").append(isDefaultCross()).append('\n'); + buffer.append(" .defaultDateSettings = ").append(isDefaultDateSettings()).append('\n'); buffer.append("[/AXCEXT]\n"); return buffer.toString(); @@ -146,24 +155,13 @@ public final class AxisOptionsRecord extends StandardRecord implements Cloneable } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public AxisOptionsRecord clone() { - AxisOptionsRecord rec = new AxisOptionsRecord(); - - rec.field_1_minimumCategory = field_1_minimumCategory; - rec.field_2_maximumCategory = field_2_maximumCategory; - rec.field_3_majorUnitValue = field_3_majorUnitValue; - rec.field_4_majorUnit = field_4_majorUnit; - rec.field_5_minorUnitValue = field_5_minorUnitValue; - rec.field_6_minorUnit = field_6_minorUnit; - rec.field_7_baseUnit = field_7_baseUnit; - rec.field_8_crossingPoint = field_8_crossingPoint; - rec.field_9_options = field_9_options; - return rec; + return copy(); } - - - /** * Get the minimum category field for the AxisOptions record. */ @@ -451,4 +449,9 @@ public final class AxisOptionsRecord extends StandardRecord implements Cloneable { return defaultDateSettings.isSet(field_9_options); } + + @Override + public AxisOptionsRecord copy() { + return new AxisOptionsRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/chart/AxisParentRecord.java b/src/java/org/apache/poi/hssf/record/chart/AxisParentRecord.java index 8eda4ba2d2..bb61c8d940 100644 --- a/src/java/org/apache/poi/hssf/record/chart/AxisParentRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/AxisParentRecord.java @@ -21,35 +21,41 @@ import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * The axis size and location<p> - * - * @author Glen Stampoultzis (glens at apache.org) + * The axis size and location */ -public final class AxisParentRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x1041; - private short field_1_axisType; - public final static short AXIS_TYPE_MAIN = 0; - public final static short AXIS_TYPE_SECONDARY = 1; - private int field_2_x; - private int field_3_y; - private int field_4_width; - private int field_5_height; - - - public AxisParentRecord() - { +public final class AxisParentRecord extends StandardRecord { + public static final short sid = 0x1041; + public static final short AXIS_TYPE_MAIN = 0; + public static final short AXIS_TYPE_SECONDARY = 1; + + private short field_1_axisType; + private int field_2_x; + private int field_3_y; + private int field_4_width; + private int field_5_height; + + public AxisParentRecord() {} + + public AxisParentRecord(AxisParentRecord other) { + super(other); + field_1_axisType = other.field_1_axisType; + field_2_x = other.field_2_x; + field_3_y = other.field_3_y; + field_4_width = other.field_4_width; + field_5_height = other.field_5_height; } - public AxisParentRecord(RecordInputStream in) - { - field_1_axisType = in.readShort(); - field_2_x = in.readInt(); - field_3_y = in.readInt(); - field_4_width = in.readInt(); - field_5_height = in.readInt(); + + public AxisParentRecord(RecordInputStream in) { + field_1_axisType = in.readShort(); + field_2_x = in.readInt(); + field_3_y = in.readInt(); + field_4_width = in.readInt(); + field_5_height = in.readInt(); } public String toString() @@ -60,23 +66,23 @@ public final class AxisParentRecord extends StandardRecord implements Cloneable buffer.append(" .axisType = ") .append("0x").append(HexDump.toHex( getAxisType ())) .append(" (").append( getAxisType() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .x = ") .append("0x").append(HexDump.toHex( getX ())) .append(" (").append( getX() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .y = ") .append("0x").append(HexDump.toHex( getY ())) .append(" (").append( getY() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .width = ") .append("0x").append(HexDump.toHex( getWidth ())) .append(" (").append( getWidth() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .height = ") .append("0x").append(HexDump.toHex( getHeight ())) .append(" (").append( getHeight() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append("[/AXISPARENT]\n"); return buffer.toString(); @@ -100,24 +106,17 @@ public final class AxisParentRecord extends StandardRecord implements Cloneable } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public AxisParentRecord clone() { - AxisParentRecord rec = new AxisParentRecord(); - - rec.field_1_axisType = field_1_axisType; - rec.field_2_x = field_2_x; - rec.field_3_y = field_3_y; - rec.field_4_width = field_4_width; - rec.field_5_height = field_5_height; - return rec; + return copy(); } - - - /** * Get the axis type field for the AxisParent record. * - * @return One of + * @return One of * AXIS_TYPE_MAIN * AXIS_TYPE_SECONDARY */ @@ -130,7 +129,7 @@ public final class AxisParentRecord extends StandardRecord implements Cloneable * Set the axis type field for the AxisParent record. * * @param field_1_axisType - * One of + * One of * AXIS_TYPE_MAIN * AXIS_TYPE_SECONDARY */ @@ -202,4 +201,9 @@ public final class AxisParentRecord extends StandardRecord implements Cloneable { this.field_5_height = field_5_height; } + + @Override + public AxisParentRecord copy() { + return new AxisParentRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/chart/AxisRecord.java b/src/java/org/apache/poi/hssf/record/chart/AxisRecord.java index e418119b19..75cb72e78e 100644 --- a/src/java/org/apache/poi/hssf/record/chart/AxisRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/AxisRecord.java @@ -21,36 +21,40 @@ import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * The axis record defines the type of an axis.<p> - * - * @author Glen Stampoultzis (glens at apache.org) + * The axis record defines the type of an axis. */ -public final class AxisRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x101d; - private short field_1_axisType; - public final static short AXIS_TYPE_CATEGORY_OR_X_AXIS = 0; - public final static short AXIS_TYPE_VALUE_AXIS = 1; - public final static short AXIS_TYPE_SERIES_AXIS = 2; - private int field_2_reserved1; - private int field_3_reserved2; - private int field_4_reserved3; - private int field_5_reserved4; - - - public AxisRecord() - { +public final class AxisRecord extends StandardRecord { + public static final short sid = 0x101d; + public static final short AXIS_TYPE_CATEGORY_OR_X_AXIS = 0; + public static final short AXIS_TYPE_VALUE_AXIS = 1; + public static final short AXIS_TYPE_SERIES_AXIS = 2; + + private short field_1_axisType; + private int field_2_reserved1; + private int field_3_reserved2; + private int field_4_reserved3; + private int field_5_reserved4; + + public AxisRecord() {} + public AxisRecord(AxisRecord other) { + super(other); + field_1_axisType = other.field_1_axisType; + field_2_reserved1 = other.field_2_reserved1; + field_3_reserved2 = other.field_3_reserved2; + field_4_reserved3 = other.field_4_reserved3; + field_5_reserved4 = other.field_5_reserved4; } - public AxisRecord(RecordInputStream in) - { - field_1_axisType = in.readShort(); - field_2_reserved1 = in.readInt(); - field_3_reserved2 = in.readInt(); - field_4_reserved3 = in.readInt(); - field_5_reserved4 = in.readInt(); + public AxisRecord(RecordInputStream in) { + field_1_axisType = in.readShort(); + field_2_reserved1 = in.readInt(); + field_3_reserved2 = in.readInt(); + field_4_reserved3 = in.readInt(); + field_5_reserved4 = in.readInt(); } public String toString() @@ -61,23 +65,23 @@ public final class AxisRecord extends StandardRecord implements Cloneable { buffer.append(" .axisType = ") .append("0x").append(HexDump.toHex( getAxisType ())) .append(" (").append( getAxisType() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .reserved1 = ") .append("0x").append(HexDump.toHex( getReserved1 ())) .append(" (").append( getReserved1() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .reserved2 = ") .append("0x").append(HexDump.toHex( getReserved2 ())) .append(" (").append( getReserved2() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .reserved3 = ") .append("0x").append(HexDump.toHex( getReserved3 ())) .append(" (").append( getReserved3() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .reserved4 = ") .append("0x").append(HexDump.toHex( getReserved4 ())) .append(" (").append( getReserved4() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append("[/AXIS]\n"); return buffer.toString(); @@ -101,24 +105,17 @@ public final class AxisRecord extends StandardRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public AxisRecord clone() { - AxisRecord rec = new AxisRecord(); - - rec.field_1_axisType = field_1_axisType; - rec.field_2_reserved1 = field_2_reserved1; - rec.field_3_reserved2 = field_3_reserved2; - rec.field_4_reserved3 = field_4_reserved3; - rec.field_5_reserved4 = field_5_reserved4; - return rec; + return copy(); } - - - /** * Get the axis type field for the Axis record. * - * @return One of + * @return One of * AXIS_TYPE_CATEGORY_OR_X_AXIS * AXIS_TYPE_VALUE_AXIS * AXIS_TYPE_SERIES_AXIS @@ -132,7 +129,7 @@ public final class AxisRecord extends StandardRecord implements Cloneable { * Set the axis type field for the Axis record. * * @param field_1_axisType - * One of + * One of * AXIS_TYPE_CATEGORY_OR_X_AXIS * AXIS_TYPE_VALUE_AXIS * AXIS_TYPE_SERIES_AXIS @@ -205,4 +202,9 @@ public final class AxisRecord extends StandardRecord implements Cloneable { { this.field_5_reserved4 = field_5_reserved4; } + + @Override + public AxisRecord copy() { + return new AxisRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/chart/AxisUsedRecord.java b/src/java/org/apache/poi/hssf/record/chart/AxisUsedRecord.java index 1c4f4eeb43..df1c0482c6 100644 --- a/src/java/org/apache/poi/hssf/record/chart/AxisUsedRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/AxisUsedRecord.java @@ -21,25 +21,25 @@ import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * The number of axes used on a chart.<p> - * - * @author Glen Stampoultzis (glens at apache.org) + * The number of axes used on a chart. */ -public final class AxisUsedRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x1046; - private short field_1_numAxis; +public final class AxisUsedRecord extends StandardRecord { + public static final short sid = 0x1046; + private short field_1_numAxis; - public AxisUsedRecord() - { + public AxisUsedRecord() {} + public AxisUsedRecord(AxisUsedRecord other) { + super(other); + field_1_numAxis = other.field_1_numAxis; } - public AxisUsedRecord(RecordInputStream in) - { - field_1_numAxis = in.readShort(); + public AxisUsedRecord(RecordInputStream in) { + field_1_numAxis = in.readShort(); } public String toString() @@ -50,7 +50,7 @@ public final class AxisUsedRecord extends StandardRecord implements Cloneable { buffer.append(" .numAxis = ") .append("0x").append(HexDump.toHex( getNumAxis ())) .append(" (").append( getNumAxis() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append("[/AXISUSED]\n"); return buffer.toString(); @@ -70,16 +70,13 @@ public final class AxisUsedRecord extends StandardRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public AxisUsedRecord clone() { - AxisUsedRecord rec = new AxisUsedRecord(); - - rec.field_1_numAxis = field_1_numAxis; - return rec; + return copy(); } - - - /** * Get the num axis field for the AxisUsed record. */ @@ -95,4 +92,9 @@ public final class AxisUsedRecord extends StandardRecord implements Cloneable { { this.field_1_numAxis = field_1_numAxis; } + + @Override + public AxisUsedRecord copy() { + return new AxisUsedRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/chart/BarRecord.java b/src/java/org/apache/poi/hssf/record/chart/BarRecord.java index 58c3af30e3..2cc62b8271 100644 --- a/src/java/org/apache/poi/hssf/record/chart/BarRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/BarRecord.java @@ -23,35 +23,37 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * The bar record is used to define a bar chart.<p> - * - * @author Glen Stampoultzis (glens at apache.org) + * The bar record is used to define a bar chart. */ -public final class BarRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x1017; +public final class BarRecord extends StandardRecord { + public static final short sid = 0x1017; - private static final BitField horizontal = BitFieldFactory.getInstance(0x1); - private static final BitField stacked = BitFieldFactory.getInstance(0x2); - private static final BitField displayAsPercentage = BitFieldFactory.getInstance(0x4); - private static final BitField shadow = BitFieldFactory.getInstance(0x8); + private static final BitField horizontal = BitFieldFactory.getInstance(0x1); + private static final BitField stacked = BitFieldFactory.getInstance(0x2); + private static final BitField displayAsPercentage = BitFieldFactory.getInstance(0x4); + private static final BitField shadow = BitFieldFactory.getInstance(0x8); - private short field_1_barSpace; - private short field_2_categorySpace; - private short field_3_formatFlags; + private short field_1_barSpace; + private short field_2_categorySpace; + private short field_3_formatFlags; - public BarRecord() - { + public BarRecord() {} + public BarRecord(BarRecord other) { + super(other); + field_1_barSpace = other.field_1_barSpace; + field_2_categorySpace = other.field_2_categorySpace; + field_3_formatFlags = other.field_3_formatFlags; } - public BarRecord(RecordInputStream in) - { - field_1_barSpace = in.readShort(); - field_2_categorySpace = in.readShort(); - field_3_formatFlags = in.readShort(); + public BarRecord(RecordInputStream in) { + field_1_barSpace = in.readShort(); + field_2_categorySpace = in.readShort(); + field_3_formatFlags = in.readShort(); } public String toString() @@ -62,19 +64,19 @@ public final class BarRecord extends StandardRecord implements Cloneable { buffer.append(" .barSpace = ") .append("0x").append(HexDump.toHex( getBarSpace ())) .append(" (").append( getBarSpace() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .categorySpace = ") .append("0x").append(HexDump.toHex( getCategorySpace ())) .append(" (").append( getCategorySpace() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .formatFlags = ") .append("0x").append(HexDump.toHex( getFormatFlags ())) .append(" (").append( getFormatFlags() ).append(" )"); - buffer.append(System.getProperty("line.separator")); - buffer.append(" .horizontal = ").append(isHorizontal()).append('\n'); - buffer.append(" .stacked = ").append(isStacked()).append('\n'); - buffer.append(" .displayAsPercentage = ").append(isDisplayAsPercentage()).append('\n'); - buffer.append(" .shadow = ").append(isShadow()).append('\n'); + buffer.append(System.getProperty("line.separator")); + buffer.append(" .horizontal = ").append(isHorizontal()).append('\n'); + buffer.append(" .stacked = ").append(isStacked()).append('\n'); + buffer.append(" .displayAsPercentage = ").append(isDisplayAsPercentage()).append('\n'); + buffer.append(" .shadow = ").append(isShadow()).append('\n'); buffer.append("[/BAR]\n"); return buffer.toString(); @@ -96,18 +98,13 @@ public final class BarRecord extends StandardRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public BarRecord clone() { - BarRecord rec = new BarRecord(); - - rec.field_1_barSpace = field_1_barSpace; - rec.field_2_categorySpace = field_2_categorySpace; - rec.field_3_formatFlags = field_3_formatFlags; - return rec; + return copy(); } - - - /** * Get the bar space field for the Bar record. */ @@ -227,4 +224,9 @@ public final class BarRecord extends StandardRecord implements Cloneable { { return shadow.isSet(field_3_formatFlags); } + + @Override + public BarRecord copy() { + return new BarRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/chart/BeginRecord.java b/src/java/org/apache/poi/hssf/record/chart/BeginRecord.java index e50db00367..128d621c89 100644 --- a/src/java/org/apache/poi/hssf/record/chart/BeginRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/BeginRecord.java @@ -20,28 +20,27 @@ package org.apache.poi.hssf.record.chart; import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * The begin record defines the start of a block of records for a (grpahing + * The begin record defines the start of a block of records for a (graphing * data object. This record is matched with a corresponding EndRecord. * * @see EndRecord - * - * @author Glen Stampoultzis (glens at apache.org) */ -public final class BeginRecord extends StandardRecord implements Cloneable { +public final class BeginRecord extends StandardRecord { public static final short sid = 0x1033; - public BeginRecord() - { + public BeginRecord() {} + + public BeginRecord(BeginRecord other) { + super(other); } /** * @param in unused (since this record has no data) */ - public BeginRecord(RecordInputStream in) - { - } + public BeginRecord(RecordInputStream in) {} public String toString() { @@ -63,10 +62,17 @@ public final class BeginRecord extends StandardRecord implements Cloneable { { return sid; } - + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public BeginRecord clone() { - // No data so nothing to copy - return new BeginRecord(); + return copy(); + } + + @Override + public BeginRecord copy() { + return new BeginRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/chart/CatLabRecord.java b/src/java/org/apache/poi/hssf/record/chart/CatLabRecord.java index 5404d8e371..f0264f4b7b 100644 --- a/src/java/org/apache/poi/hssf/record/chart/CatLabRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/CatLabRecord.java @@ -23,27 +23,35 @@ import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; /** - * CATLAB - Category Labels (0x0856)<br> - * - * @author Patrick Cheng + * CATLAB - Category Labels (0x0856) */ public final class CatLabRecord extends StandardRecord { public static final short sid = 0x0856; - + private short rt; private short grbitFrt; private short wOffset; private short at; private short grbit; private Short unused; - + + public CatLabRecord(CatLabRecord other) { + super(other); + rt = other.rt; + grbitFrt = other.grbitFrt; + wOffset = other.wOffset; + at = other.at; + grbit = other.grbit; + unused = other.unused; + } + public CatLabRecord(RecordInputStream in) { rt = in.readShort(); grbitFrt = in.readShort(); wOffset = in.readShort(); at = in.readShort(); grbit = in.readShort(); - + // Often, but not always has an unused short at the end if(in.available() == 0) { unused = null; @@ -51,7 +59,7 @@ public final class CatLabRecord extends StandardRecord { unused = in.readShort(); } } - + @Override protected int getDataSize() { return 2 + 2 + 2 + 2 + 2 + (unused==null? 0:2); @@ -89,4 +97,9 @@ public final class CatLabRecord extends StandardRecord { buffer.append("[/CATLAB]\n"); return buffer.toString(); } + + @Override + public CatLabRecord copy() { + return new CatLabRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/chart/CategorySeriesAxisRecord.java b/src/java/org/apache/poi/hssf/record/chart/CategorySeriesAxisRecord.java index 79574286d8..60f45ae9bf 100644 --- a/src/java/org/apache/poi/hssf/record/chart/CategorySeriesAxisRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/CategorySeriesAxisRecord.java @@ -23,36 +23,39 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * This record refers to a category or series axis and is used to specify label/tickmark frequency.<p> - * - * @author Glen Stampoultzis (glens at apache.org) + * This record refers to a category or series axis and is used to specify label/tickmark frequency. */ -public final class CategorySeriesAxisRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x1020; +public final class CategorySeriesAxisRecord extends StandardRecord { + public static final short sid = 0x1020; private static final BitField valueAxisCrossing = BitFieldFactory.getInstance(0x1); private static final BitField crossesFarRight = BitFieldFactory.getInstance(0x2); private static final BitField reversed = BitFieldFactory.getInstance(0x4); - - private short field_1_crossingPoint; - private short field_2_labelFrequency; - private short field_3_tickMarkFrequency; - private short field_4_options; + private short field_1_crossingPoint; + private short field_2_labelFrequency; + private short field_3_tickMarkFrequency; + private short field_4_options; - public CategorySeriesAxisRecord() - { + public CategorySeriesAxisRecord() {} + + public CategorySeriesAxisRecord(CategorySeriesAxisRecord other) { + super(other); + field_1_crossingPoint = other.field_1_crossingPoint; + field_2_labelFrequency = other.field_2_labelFrequency; + field_3_tickMarkFrequency = other.field_3_tickMarkFrequency; + field_4_options = other.field_4_options; } - public CategorySeriesAxisRecord(RecordInputStream in) - { - field_1_crossingPoint = in.readShort(); - field_2_labelFrequency = in.readShort(); - field_3_tickMarkFrequency = in.readShort(); - field_4_options = in.readShort(); + public CategorySeriesAxisRecord(RecordInputStream in) { + field_1_crossingPoint = in.readShort(); + field_2_labelFrequency = in.readShort(); + field_3_tickMarkFrequency = in.readShort(); + field_4_options = in.readShort(); } public String toString() @@ -63,22 +66,22 @@ public final class CategorySeriesAxisRecord extends StandardRecord implements Cl buffer.append(" .crossingPoint = ") .append("0x").append(HexDump.toHex( getCrossingPoint ())) .append(" (").append( getCrossingPoint() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .labelFrequency = ") .append("0x").append(HexDump.toHex( getLabelFrequency ())) .append(" (").append( getLabelFrequency() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .tickMarkFrequency = ") .append("0x").append(HexDump.toHex( getTickMarkFrequency ())) .append(" (").append( getTickMarkFrequency() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .options = ") .append("0x").append(HexDump.toHex( getOptions ())) .append(" (").append( getOptions() ).append(" )"); - buffer.append(System.getProperty("line.separator")); - buffer.append(" .valueAxisCrossing = ").append(isValueAxisCrossing()).append('\n'); - buffer.append(" .crossesFarRight = ").append(isCrossesFarRight()).append('\n'); - buffer.append(" .reversed = ").append(isReversed()).append('\n'); + buffer.append(System.getProperty("line.separator")); + buffer.append(" .valueAxisCrossing = ").append(isValueAxisCrossing()).append('\n'); + buffer.append(" .crossesFarRight = ").append(isCrossesFarRight()).append('\n'); + buffer.append(" .reversed = ").append(isReversed()).append('\n'); buffer.append("[/CATSERRANGE]\n"); return buffer.toString(); @@ -101,19 +104,13 @@ public final class CategorySeriesAxisRecord extends StandardRecord implements Cl } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public CategorySeriesAxisRecord clone() { - CategorySeriesAxisRecord rec = new CategorySeriesAxisRecord(); - - rec.field_1_crossingPoint = field_1_crossingPoint; - rec.field_2_labelFrequency = field_2_labelFrequency; - rec.field_3_tickMarkFrequency = field_3_tickMarkFrequency; - rec.field_4_options = field_4_options; - return rec; + return copy(); } - - - /** * Get the crossing point field for the CategorySeriesAxis record. */ @@ -231,4 +228,9 @@ public final class CategorySeriesAxisRecord extends StandardRecord implements Cl { return reversed.isSet(field_4_options); } + + @Override + public CategorySeriesAxisRecord copy() { + return new CategorySeriesAxisRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/chart/ChartEndBlockRecord.java b/src/java/org/apache/poi/hssf/record/chart/ChartEndBlockRecord.java index cbb092c4f8..4e821b7af7 100644 --- a/src/java/org/apache/poi/hssf/record/chart/ChartEndBlockRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/ChartEndBlockRecord.java @@ -21,13 +21,12 @@ import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * ENDBLOCK - Chart Future Record Type End Block (0x0853)<br> - * - * @author Patrick Cheng + * ENDBLOCK - Chart Future Record Type End Block (0x0853) */ -public final class ChartEndBlockRecord extends StandardRecord implements Cloneable { +public final class ChartEndBlockRecord extends StandardRecord { public static final short sid = 0x0853; private short rt; @@ -35,9 +34,16 @@ public final class ChartEndBlockRecord extends StandardRecord implements Cloneab private short iObjectKind; private byte[] unused; - public ChartEndBlockRecord() { + public ChartEndBlockRecord() {} + + public ChartEndBlockRecord(ChartEndBlockRecord other) { + super(other); + rt = other.rt; + grbitFrt = other.grbitFrt; + iObjectKind = other.iObjectKind; + unused = (other.unused == null) ? null : other.unused.clone(); } - + public ChartEndBlockRecord(RecordInputStream in) { rt = in.readShort(); grbitFrt = in.readShort(); @@ -83,16 +89,17 @@ public final class ChartEndBlockRecord extends StandardRecord implements Cloneab buffer.append("[/ENDBLOCK]\n"); return buffer.toString(); } - + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public ChartEndBlockRecord clone() { - ChartEndBlockRecord record = new ChartEndBlockRecord(); - - record.rt = rt ; - record.grbitFrt = grbitFrt ; - record.iObjectKind = iObjectKind ; - record.unused = unused.clone() ; - - return record; + return copy(); + } + + @Override + public ChartEndBlockRecord copy() { + return new ChartEndBlockRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/chart/ChartEndObjectRecord.java b/src/java/org/apache/poi/hssf/record/chart/ChartEndObjectRecord.java index e097ce0ad9..124e40519b 100644 --- a/src/java/org/apache/poi/hssf/record/chart/ChartEndObjectRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/ChartEndObjectRecord.java @@ -33,6 +33,14 @@ public final class ChartEndObjectRecord extends StandardRecord { private short iObjectKind; private byte[] reserved; + public ChartEndObjectRecord(ChartEndObjectRecord other) { + super(other); + rt = other.rt; + grbitFrt = other.grbitFrt; + iObjectKind = other.iObjectKind; + reserved = (other.reserved == null) ? null : other.reserved.clone(); + } + public ChartEndObjectRecord(RecordInputStream in) { rt = in.readShort(); grbitFrt = in.readShort(); @@ -45,7 +53,7 @@ public final class ChartEndObjectRecord extends StandardRecord { if(in.available() == 0) { // They've gone missing... } else { - // Read the reserved bytes + // Read the reserved bytes in.readFully(reserved); } } @@ -81,4 +89,9 @@ public final class ChartEndObjectRecord extends StandardRecord { buffer.append("[/ENDOBJECT]\n"); return buffer.toString(); } + + @Override + public ChartEndObjectRecord copy() { + return new ChartEndObjectRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/chart/ChartFRTInfoRecord.java b/src/java/org/apache/poi/hssf/record/chart/ChartFRTInfoRecord.java index f3680f3bfb..d5237d0bfd 100644 --- a/src/java/org/apache/poi/hssf/record/chart/ChartFRTInfoRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/ChartFRTInfoRecord.java @@ -17,6 +17,8 @@ package org.apache.poi.hssf.record.chart; +import java.util.stream.Stream; + import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.HexDump; @@ -40,6 +42,11 @@ public final class ChartFRTInfoRecord extends StandardRecord { private int rtFirst; private int rtLast; + public CFRTID(CFRTID other) { + rtFirst = other.rtFirst; + rtLast = other.rtLast; + } + public CFRTID(LittleEndianInput in) { rtFirst = in.readShort(); rtLast = in.readShort(); @@ -51,6 +58,17 @@ public final class ChartFRTInfoRecord extends StandardRecord { } } + public ChartFRTInfoRecord(ChartFRTInfoRecord other) { + super(other); + rt = other.rt; + grbitFrt = other.grbitFrt; + verOriginator = other.verOriginator; + verWriter = other.verWriter; + if (other.rgCFRTID != null) { + rgCFRTID = Stream.of(other.rgCFRTID).map(CFRTID::new).toArray(CFRTID[]::new); + } + } + public ChartFRTInfoRecord(RecordInputStream in) { rt = in.readShort(); grbitFrt = in.readShort(); @@ -81,11 +99,10 @@ public final class ChartFRTInfoRecord extends StandardRecord { out.writeShort(grbitFrt); out.writeByte(verOriginator); out.writeByte(verWriter); - int nCFRTIDs = rgCFRTID.length; - out.writeShort(nCFRTIDs); + out.writeShort(rgCFRTID.length); - for (int i = 0; i < nCFRTIDs; i++) { - rgCFRTID[i].serialize(out); + for (CFRTID cfrtid : rgCFRTID) { + cfrtid.serialize(out); } } @@ -102,4 +119,9 @@ public final class ChartFRTInfoRecord extends StandardRecord { buffer.append("[/CHARTFRTINFO]\n"); return buffer.toString(); } + + @Override + public ChartFRTInfoRecord copy() { + return new ChartFRTInfoRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/chart/ChartFormatRecord.java b/src/java/org/apache/poi/hssf/record/chart/ChartFormatRecord.java index 5599f63697..0d5fe11815 100644 --- a/src/java/org/apache/poi/hssf/record/chart/ChartFormatRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/ChartFormatRecord.java @@ -43,10 +43,19 @@ public final class ChartFormatRecord extends StandardRecord { private int field5_grbit; private int field6_unknown; - public ChartFormatRecord() { - // fields uninitialised + public ChartFormatRecord() {} + + public ChartFormatRecord(ChartFormatRecord other) { + super(other); + field1_x_position = other.field1_x_position; + field2_y_position = other.field2_y_position; + field3_width = other.field3_width; + field4_height = other.field4_height; + field5_grbit = other.field5_grbit; + field6_unknown = other.field6_unknown; } + public ChartFormatRecord(RecordInputStream in) { field1_x_position = in.readInt(); field2_y_position = in.readInt(); @@ -125,4 +134,9 @@ public final class ChartFormatRecord extends StandardRecord { public void setVaryDisplayPattern(boolean value) { field5_grbit = varyDisplayPattern.setBoolean(field5_grbit, value); } + + @Override + public ChartFormatRecord copy() { + return new ChartFormatRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/chart/ChartRecord.java b/src/java/org/apache/poi/hssf/record/chart/ChartRecord.java index 33590ece50..ae17a05d96 100644 --- a/src/java/org/apache/poi/hssf/record/chart/ChartRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/ChartRecord.java @@ -20,34 +20,40 @@ package org.apache.poi.hssf.record.chart; import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * CHART (0x1002)<p> - * + * * The chart record is used to define the location and size of a chart.<p> - * - * Chart related records don't seem to be covered in either the - * <A HREF="http://sc.openoffice.org/excelfileformat.pdf">OOO</A> - * or the - * <A HREF="http://download.microsoft.com/download/0/B/E/0BE8BDD7-E5E8-422A-ABFD-4342ED7AD886/Excel97-2007BinaryFileFormat(xls)Specification.pdf">MS</A> - * documentation. - * + * + * Chart related records don't seem to be covered in either the + * <A HREF="http://sc.openoffice.org/excelfileformat.pdf">OOO</A> + * or the + * <A HREF="http://download.microsoft.com/download/0/B/E/0BE8BDD7-E5E8-422A-ABFD-4342ED7AD886/Excel97-2007BinaryFileFormat(xls)Specification.pdf">MS</A> + * documentation. + * * The book "Microsoft Excel 97 Developer's Kit" ISBN: (1-57231-498-2) seems to have an entire - * chapter (10) devoted to Chart records. One + * chapter (10) devoted to Chart records. One * <A HREF="http://ooxmlisdefectivebydesign.blogspot.com/2008/03/bad-surprise-in-microsoft-office-binary.html">blog</A> * suggests that some documentation for these records is available in "MSDN Library, Feb 1998", * but no later. */ -public final class ChartRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x1002; +public final class ChartRecord extends StandardRecord { + public static final short sid = 0x1002; private int field_1_x; private int field_2_y; private int field_3_width; private int field_4_height; + public ChartRecord() {} - public ChartRecord() { - // fields uninitialised + public ChartRecord(ChartRecord other) { + super(other); + field_1_x = other.field_1_x; + field_2_y = other.field_2_y; + field_3_width = other.field_3_width; + field_4_height = other.field_4_height; } public ChartRecord(RecordInputStream in) { @@ -86,18 +92,17 @@ public final class ChartRecord extends StandardRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public ChartRecord clone() { - ChartRecord rec = new ChartRecord(); - - rec.field_1_x = field_1_x; - rec.field_2_y = field_2_y; - rec.field_3_width = field_3_width; - rec.field_4_height = field_4_height; - return rec; + return copy(); } - - + @Override + public ChartRecord copy() { + return new ChartRecord(this); + } /** * Get the x field for the Chart record. diff --git a/src/java/org/apache/poi/hssf/record/chart/ChartStartBlockRecord.java b/src/java/org/apache/poi/hssf/record/chart/ChartStartBlockRecord.java index fb98a7cf82..7403706a76 100644 --- a/src/java/org/apache/poi/hssf/record/chart/ChartStartBlockRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/ChartStartBlockRecord.java @@ -21,11 +21,12 @@ import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * STARTBLOCK - Chart Future Record Type Start Block (0x0852) */ -public final class ChartStartBlockRecord extends StandardRecord implements Cloneable { +public final class ChartStartBlockRecord extends StandardRecord { public static final short sid = 0x0852; private short rt; @@ -35,9 +36,18 @@ public final class ChartStartBlockRecord extends StandardRecord implements Clone private short iObjectInstance1; private short iObjectInstance2; - public ChartStartBlockRecord() { + public ChartStartBlockRecord() {} + + public ChartStartBlockRecord(ChartStartBlockRecord other) { + super(other); + rt = other.rt; + grbitFrt = other.grbitFrt; + iObjectKind = other.iObjectKind; + iObjectContext = other.iObjectContext; + iObjectInstance1 = other.iObjectInstance1; + iObjectInstance2 = other.iObjectInstance2; } - + public ChartStartBlockRecord(RecordInputStream in) { rt = in.readShort(); grbitFrt = in.readShort(); @@ -81,18 +91,17 @@ public final class ChartStartBlockRecord extends StandardRecord implements Clone buffer.append("[/STARTBLOCK]\n"); return buffer.toString(); } - + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public ChartStartBlockRecord clone() { - ChartStartBlockRecord record = new ChartStartBlockRecord(); - - record.rt = rt; - record.grbitFrt = grbitFrt; - record.iObjectKind = iObjectKind; - record.iObjectContext = iObjectContext; - record.iObjectInstance1 = iObjectInstance1; - record.iObjectInstance2 = iObjectInstance2; - - return record; + return copy(); + } + + @Override + public ChartStartBlockRecord copy() { + return new ChartStartBlockRecord(this); } } diff --git a/src/java/org/apache/poi/hssf/record/chart/ChartStartObjectRecord.java b/src/java/org/apache/poi/hssf/record/chart/ChartStartObjectRecord.java index 5ddaecc117..f7d82b3fdd 100644 --- a/src/java/org/apache/poi/hssf/record/chart/ChartStartObjectRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/ChartStartObjectRecord.java @@ -35,6 +35,16 @@ public final class ChartStartObjectRecord extends StandardRecord { private short iObjectInstance1; private short iObjectInstance2; + public ChartStartObjectRecord(ChartStartObjectRecord other) { + super(other); + rt = other.rt; + grbitFrt = other.grbitFrt; + iObjectKind = other.iObjectKind; + iObjectContext = other.iObjectContext; + iObjectInstance1 = other.iObjectInstance1; + iObjectInstance2 = other.iObjectInstance2; + } + public ChartStartObjectRecord(RecordInputStream in) { rt = in.readShort(); grbitFrt = in.readShort(); @@ -78,4 +88,9 @@ public final class ChartStartObjectRecord extends StandardRecord { buffer.append("[/STARTOBJECT]\n"); return buffer.toString(); } + + @Override + public ChartStartObjectRecord copy() { + return new ChartStartObjectRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/chart/ChartTitleFormatRecord.java b/src/java/org/apache/poi/hssf/record/chart/ChartTitleFormatRecord.java index 09229072da..49a2a8d4af 100644 --- a/src/java/org/apache/poi/hssf/record/chart/ChartTitleFormatRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/ChartTitleFormatRecord.java @@ -20,6 +20,8 @@ */ package org.apache.poi.hssf.record.chart; +import java.util.stream.Stream; + import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.LittleEndianOutput; @@ -30,14 +32,19 @@ import org.apache.poi.util.LittleEndianOutput; */ public class ChartTitleFormatRecord extends StandardRecord { public static final short sid = 0x1050; - - private CTFormat[] _formats; - + + private final CTFormat[] _formats; + private static final class CTFormat { public static final int ENCODED_SIZE=4; private int _offset; private int _fontIndex; - + + public CTFormat(CTFormat other) { + _offset = other._offset; + _fontIndex = other._fontIndex; + } + public CTFormat(RecordInputStream in) { _offset = in.readShort(); _fontIndex = in.readShort(); @@ -59,6 +66,10 @@ public class ChartTitleFormatRecord extends StandardRecord { } } + public ChartTitleFormatRecord(ChartTitleFormatRecord other) { + super(other); + _formats = Stream.of(other._formats).map(CTFormat::new).toArray(CTFormat[]::new); + } public ChartTitleFormatRecord(RecordInputStream in) { int nRecs = in.readUShort(); @@ -79,15 +90,15 @@ public class ChartTitleFormatRecord extends StandardRecord { protected int getDataSize() { return 2 + CTFormat.ENCODED_SIZE * _formats.length; } - + public short getSid() { return sid; } - + public int getFormatCount() { return _formats.length; } - + public void modifyFormatRun(short oldPos, short newLen) { int shift = 0; for(int i=0; i < _formats.length; i++) { @@ -97,10 +108,10 @@ public class ChartTitleFormatRecord extends StandardRecord { } else if (oldPos == ctf.getOffset() && i < _formats.length - 1){ CTFormat nextCTF = _formats[i + 1]; shift = newLen - (nextCTF.getOffset() - ctf.getOffset()); - } + } } } - + public String toString() { StringBuilder buffer = new StringBuilder(); @@ -115,4 +126,9 @@ public class ChartTitleFormatRecord extends StandardRecord { buffer.append("[/CHARTTITLEFORMAT]\n"); return buffer.toString(); } + + @Override + public ChartTitleFormatRecord copy() { + return new ChartTitleFormatRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/chart/DatRecord.java b/src/java/org/apache/poi/hssf/record/chart/DatRecord.java index 4d7d29f328..25b80d3d00 100644 --- a/src/java/org/apache/poi/hssf/record/chart/DatRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/DatRecord.java @@ -23,29 +23,30 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * The dat record is used to store options for the chart. */ -public final class DatRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x1063; +public final class DatRecord extends StandardRecord { + public static final short sid = 0x1063; private static final BitField horizontalBorder = BitFieldFactory.getInstance(0x1); private static final BitField verticalBorder = BitFieldFactory.getInstance(0x2); private static final BitField border = BitFieldFactory.getInstance(0x4); private static final BitField showSeriesKey = BitFieldFactory.getInstance(0x8); - private short field_1_options; + private short field_1_options; + public DatRecord() {} - public DatRecord() - { - + public DatRecord(DatRecord other) { + super(other); + field_1_options = other.field_1_options; } - public DatRecord(RecordInputStream in) - { - field_1_options = in.readShort(); + public DatRecord(RecordInputStream in) { + field_1_options = in.readShort(); } public String toString() @@ -56,11 +57,11 @@ public final class DatRecord extends StandardRecord implements Cloneable { buffer.append(" .options = ") .append("0x").append(HexDump.toHex( getOptions ())) .append(" (").append( getOptions() ).append(" )"); - buffer.append(System.getProperty("line.separator")); - buffer.append(" .horizontalBorder = ").append(isHorizontalBorder()).append('\n'); - buffer.append(" .verticalBorder = ").append(isVerticalBorder()).append('\n'); - buffer.append(" .border = ").append(isBorder()).append('\n'); - buffer.append(" .showSeriesKey = ").append(isShowSeriesKey()).append('\n'); + buffer.append(System.getProperty("line.separator")); + buffer.append(" .horizontalBorder = ").append(isHorizontalBorder()).append('\n'); + buffer.append(" .verticalBorder = ").append(isVerticalBorder()).append('\n'); + buffer.append(" .border = ").append(isBorder()).append('\n'); + buffer.append(" .showSeriesKey = ").append(isShowSeriesKey()).append('\n'); buffer.append("[/DAT]\n"); return buffer.toString(); @@ -80,14 +81,17 @@ public final class DatRecord extends StandardRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public DatRecord clone() { - DatRecord rec = new DatRecord(); - rec.field_1_options = field_1_options; - return rec; + return copy(); } - - + @Override + public DatRecord copy() { + return new DatRecord(this); + } /** * Get the options field for the Dat record. diff --git a/src/java/org/apache/poi/hssf/record/chart/DataFormatRecord.java b/src/java/org/apache/poi/hssf/record/chart/DataFormatRecord.java index 2c7d5c23b2..072f9ef72f 100644 --- a/src/java/org/apache/poi/hssf/record/chart/DataFormatRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/DataFormatRecord.java @@ -23,12 +23,13 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * The data format record is used to index into a series. */ -public final class DataFormatRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x1006; +public final class DataFormatRecord extends StandardRecord { + public static final short sid = 0x1006; private static final BitField useExcel4Colors = BitFieldFactory.getInstance(0x1); @@ -37,18 +38,21 @@ public final class DataFormatRecord extends StandardRecord implements Cloneable private short field_3_seriesNumber; private short field_4_formatFlags; + public DataFormatRecord() {} - public DataFormatRecord() - { - + public DataFormatRecord(DataFormatRecord other) { + super(other); + field_1_pointNumber = other.field_1_pointNumber; + field_2_seriesIndex = other.field_2_seriesIndex; + field_3_seriesNumber = other.field_3_seriesNumber; + field_4_formatFlags = other.field_4_formatFlags; } - public DataFormatRecord(RecordInputStream in) - { - field_1_pointNumber = in.readShort(); - field_2_seriesIndex = in.readShort(); - field_3_seriesNumber = in.readShort(); - field_4_formatFlags = in.readShort(); + public DataFormatRecord(RecordInputStream in) { + field_1_pointNumber = in.readShort(); + field_2_seriesIndex = in.readShort(); + field_3_seriesNumber = in.readShort(); + field_4_formatFlags = in.readShort(); } public String toString() @@ -59,20 +63,20 @@ public final class DataFormatRecord extends StandardRecord implements Cloneable buffer.append(" .pointNumber = ") .append("0x").append(HexDump.toHex( getPointNumber ())) .append(" (").append( getPointNumber() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .seriesIndex = ") .append("0x").append(HexDump.toHex( getSeriesIndex ())) .append(" (").append( getSeriesIndex() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .seriesNumber = ") .append("0x").append(HexDump.toHex( getSeriesNumber ())) .append(" (").append( getSeriesNumber() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .formatFlags = ") .append("0x").append(HexDump.toHex( getFormatFlags ())) .append(" (").append( getFormatFlags() ).append(" )"); - buffer.append(System.getProperty("line.separator")); - buffer.append(" .useExcel4Colors = ").append(isUseExcel4Colors()).append('\n'); + buffer.append(System.getProperty("line.separator")); + buffer.append(" .useExcel4Colors = ").append(isUseExcel4Colors()).append('\n'); buffer.append("[/DATAFORMAT]\n"); return buffer.toString(); @@ -95,18 +99,17 @@ public final class DataFormatRecord extends StandardRecord implements Cloneable } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public DataFormatRecord clone() { - DataFormatRecord rec = new DataFormatRecord(); - - rec.field_1_pointNumber = field_1_pointNumber; - rec.field_2_seriesIndex = field_2_seriesIndex; - rec.field_3_seriesNumber = field_3_seriesNumber; - rec.field_4_formatFlags = field_4_formatFlags; - return rec; + return copy(); } - - + @Override + public DataFormatRecord copy() { + return new DataFormatRecord(this); + } /** * Get the point number field for the DataFormat record. diff --git a/src/java/org/apache/poi/hssf/record/chart/DataLabelExtensionRecord.java b/src/java/org/apache/poi/hssf/record/chart/DataLabelExtensionRecord.java index 64f29efc44..acad498488 100644 --- a/src/java/org/apache/poi/hssf/record/chart/DataLabelExtensionRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/DataLabelExtensionRecord.java @@ -27,17 +27,24 @@ import org.apache.poi.util.LittleEndianOutput; */ public final class DataLabelExtensionRecord extends StandardRecord { public static final short sid = 0x086A; - + private int rt; private int grbitFrt; - private byte[] unused = new byte[8]; - + private final byte[] unused = new byte[8]; + + public DataLabelExtensionRecord(DataLabelExtensionRecord other) { + super(other); + rt = other.rt; + grbitFrt = other.grbitFrt; + System.arraycopy(other.unused, 0, unused, 0, unused.length); + } + public DataLabelExtensionRecord(RecordInputStream in) { rt = in.readShort(); grbitFrt = in.readShort(); in.readFully(unused); } - + @Override protected int getDataSize() { return 2 + 2 + 8; @@ -67,4 +74,9 @@ public final class DataLabelExtensionRecord extends StandardRecord { buffer.append("[/DATALABEXT]\n"); return buffer.toString(); } + + @Override + public DataLabelExtensionRecord copy() { + return new DataLabelExtensionRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/chart/DefaultDataLabelTextPropertiesRecord.java b/src/java/org/apache/poi/hssf/record/chart/DefaultDataLabelTextPropertiesRecord.java index b26f39b1e2..545edc4841 100644 --- a/src/java/org/apache/poi/hssf/record/chart/DefaultDataLabelTextPropertiesRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/DefaultDataLabelTextPropertiesRecord.java @@ -21,26 +21,28 @@ import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * The default data label text properties record identifies the text characteristics of the preceding text record. */ -public final class DefaultDataLabelTextPropertiesRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x1024; - private short field_1_categoryDataType; - public final static short CATEGORY_DATA_TYPE_SHOW_LABELS_CHARACTERISTIC = 0; - public final static short CATEGORY_DATA_TYPE_VALUE_AND_PERCENTAGE_CHARACTERISTIC = 1; - public final static short CATEGORY_DATA_TYPE_ALL_TEXT_CHARACTERISTIC = 2; +public final class DefaultDataLabelTextPropertiesRecord extends StandardRecord { + public static final short sid = 0x1024; + public static final short CATEGORY_DATA_TYPE_SHOW_LABELS_CHARACTERISTIC = 0; + public static final short CATEGORY_DATA_TYPE_VALUE_AND_PERCENTAGE_CHARACTERISTIC = 1; + public static final short CATEGORY_DATA_TYPE_ALL_TEXT_CHARACTERISTIC = 2; + private short field_1_categoryDataType; - public DefaultDataLabelTextPropertiesRecord() - { + public DefaultDataLabelTextPropertiesRecord() {} + public DefaultDataLabelTextPropertiesRecord(DefaultDataLabelTextPropertiesRecord other) { + super(other); + field_1_categoryDataType = other.field_1_categoryDataType; } - public DefaultDataLabelTextPropertiesRecord(RecordInputStream in) - { - field_1_categoryDataType = in.readShort(); + public DefaultDataLabelTextPropertiesRecord(RecordInputStream in) { + field_1_categoryDataType = in.readShort(); } public String toString() @@ -51,7 +53,7 @@ public final class DefaultDataLabelTextPropertiesRecord extends StandardRecord i buffer.append(" .categoryDataType = ") .append("0x").append(HexDump.toHex( getCategoryDataType ())) .append(" (").append( getCategoryDataType() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append("[/DEFAULTTEXT]\n"); return buffer.toString(); @@ -71,20 +73,22 @@ public final class DefaultDataLabelTextPropertiesRecord extends StandardRecord i } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public DefaultDataLabelTextPropertiesRecord clone() { - DefaultDataLabelTextPropertiesRecord rec = new DefaultDataLabelTextPropertiesRecord(); - - rec.field_1_categoryDataType = field_1_categoryDataType; - return rec; + return copy(); } - - + @Override + public DefaultDataLabelTextPropertiesRecord copy() { + return new DefaultDataLabelTextPropertiesRecord(this); + } /** * Get the category data type field for the DefaultDataLabelTextProperties record. * - * @return One of + * @return One of * CATEGORY_DATA_TYPE_SHOW_LABELS_CHARACTERISTIC * CATEGORY_DATA_TYPE_VALUE_AND_PERCENTAGE_CHARACTERISTIC * CATEGORY_DATA_TYPE_ALL_TEXT_CHARACTERISTIC @@ -98,7 +102,7 @@ public final class DefaultDataLabelTextPropertiesRecord extends StandardRecord i * Set the category data type field for the DefaultDataLabelTextProperties record. * * @param field_1_categoryDataType - * One of + * One of * CATEGORY_DATA_TYPE_SHOW_LABELS_CHARACTERISTIC * CATEGORY_DATA_TYPE_VALUE_AND_PERCENTAGE_CHARACTERISTIC * CATEGORY_DATA_TYPE_ALL_TEXT_CHARACTERISTIC diff --git a/src/java/org/apache/poi/hssf/record/chart/EndRecord.java b/src/java/org/apache/poi/hssf/record/chart/EndRecord.java index bb539c21d8..3651101eac 100644 --- a/src/java/org/apache/poi/hssf/record/chart/EndRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/EndRecord.java @@ -20,28 +20,24 @@ package org.apache.poi.hssf.record.chart; import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * The end record defines the end of a block of records for a (Graphing) * data object. This record is matched with a corresponding BeginRecord. * * @see BeginRecord - * - * @author Glen Stampoultzis (glens at apache.org) */ -public final class EndRecord extends StandardRecord implements Cloneable { +public final class EndRecord extends StandardRecord { public static final short sid = 0x1034; - public EndRecord() - { - } + public EndRecord() {} /** * @param in unused (since this record has no data) */ - public EndRecord(RecordInputStream in) - { + public EndRecord(RecordInputStream in) { } public String toString() @@ -64,9 +60,17 @@ public final class EndRecord extends StandardRecord implements Cloneable { { return sid; } - + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public EndRecord clone() { + return copy(); + } + + @Override + public EndRecord copy() { // No data so nothing to copy return new EndRecord(); } diff --git a/src/java/org/apache/poi/hssf/record/chart/FontBasisRecord.java b/src/java/org/apache/poi/hssf/record/chart/FontBasisRecord.java index 6b24869bfe..2cbd5b03a8 100644 --- a/src/java/org/apache/poi/hssf/record/chart/FontBasisRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/FontBasisRecord.java @@ -21,22 +21,27 @@ import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; -/** - * The font basis record stores various font metrics. - */ -public final class FontBasisRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x1060; - private short field_1_xBasis; - private short field_2_yBasis; - private short field_3_heightBasis; - private short field_4_scale; - private short field_5_indexToFontTable; +/** The font basis record stores various font metrics. */ +public final class FontBasisRecord extends StandardRecord { + public static final short sid = 0x1060; + private short field_1_xBasis; + private short field_2_yBasis; + private short field_3_heightBasis; + private short field_4_scale; + private short field_5_indexToFontTable; - public FontBasisRecord() - { + public FontBasisRecord() {} + public FontBasisRecord(FontBasisRecord other) { + super(other); + field_1_xBasis = other.field_1_xBasis; + field_2_yBasis = other.field_2_yBasis; + field_3_heightBasis = other.field_3_heightBasis; + field_4_scale = other.field_4_scale; + field_5_indexToFontTable = other.field_5_indexToFontTable; } public FontBasisRecord(RecordInputStream in) @@ -56,23 +61,23 @@ public final class FontBasisRecord extends StandardRecord implements Cloneable { buffer.append(" .xBasis = ") .append("0x").append(HexDump.toHex( getXBasis ())) .append(" (").append( getXBasis() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .yBasis = ") .append("0x").append(HexDump.toHex( getYBasis ())) .append(" (").append( getYBasis() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .heightBasis = ") .append("0x").append(HexDump.toHex( getHeightBasis ())) .append(" (").append( getHeightBasis() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .scale = ") .append("0x").append(HexDump.toHex( getScale ())) .append(" (").append( getScale() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .indexToFontTable = ") .append("0x").append(HexDump.toHex( getIndexToFontTable ())) .append(" (").append( getIndexToFontTable() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append("[/FBI]\n"); return buffer.toString(); @@ -96,19 +101,17 @@ public final class FontBasisRecord extends StandardRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public FontBasisRecord clone() { - FontBasisRecord rec = new FontBasisRecord(); - - rec.field_1_xBasis = field_1_xBasis; - rec.field_2_yBasis = field_2_yBasis; - rec.field_3_heightBasis = field_3_heightBasis; - rec.field_4_scale = field_4_scale; - rec.field_5_indexToFontTable = field_5_indexToFontTable; - return rec; + return copy(); } - - + @Override + public FontBasisRecord copy() { + return new FontBasisRecord(this); + } /** * Get the x Basis field for the FontBasis record. diff --git a/src/java/org/apache/poi/hssf/record/chart/FontIndexRecord.java b/src/java/org/apache/poi/hssf/record/chart/FontIndexRecord.java index cd3f08ffc2..1d79da8ddf 100644 --- a/src/java/org/apache/poi/hssf/record/chart/FontIndexRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/FontIndexRecord.java @@ -21,25 +21,22 @@ import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; -/** - * The font index record indexes into the font table for the text record.<p> - * - * @author Glen Stampoultzis (glens at apache.org) - */ -public final class FontIndexRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x1026; - private short field_1_fontIndex; +/** The font index record indexes into the font table for the text record. */ +public final class FontIndexRecord extends StandardRecord { + public static final short sid = 0x1026; + private short field_1_fontIndex; + public FontIndexRecord() {} - public FontIndexRecord() - { - + public FontIndexRecord(FontIndexRecord other) { + super(other); + field_1_fontIndex = other.field_1_fontIndex; } - public FontIndexRecord(RecordInputStream in) - { - field_1_fontIndex = in.readShort(); + public FontIndexRecord(RecordInputStream in) { + field_1_fontIndex = in.readShort(); } public String toString() @@ -50,7 +47,7 @@ public final class FontIndexRecord extends StandardRecord implements Cloneable { buffer.append(" .fontIndex = ") .append("0x").append(HexDump.toHex( getFontIndex ())) .append(" (").append( getFontIndex() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append("[/FONTX]\n"); return buffer.toString(); @@ -70,11 +67,16 @@ public final class FontIndexRecord extends StandardRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public FontIndexRecord clone() { - FontIndexRecord rec = new FontIndexRecord(); - - rec.field_1_fontIndex = field_1_fontIndex; - return rec; + return copy(); + } + + @Override + public FontIndexRecord copy() { + return new FontIndexRecord(this); } diff --git a/src/java/org/apache/poi/hssf/record/chart/FrameRecord.java b/src/java/org/apache/poi/hssf/record/chart/FrameRecord.java index f78574a674..1ced6abe94 100644 --- a/src/java/org/apache/poi/hssf/record/chart/FrameRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/FrameRecord.java @@ -23,31 +23,34 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * The frame record indicates whether there is a border around the displayed text of a chart. */ -public final class FrameRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x1032; +public final class FrameRecord extends StandardRecord { + public static final short sid = 0x1032; + public static final short BORDER_TYPE_REGULAR = 0; + public static final short BORDER_TYPE_SHADOW = 1; private static final BitField autoSize = BitFieldFactory.getInstance(0x1); private static final BitField autoPosition = BitFieldFactory.getInstance(0x2); - private short field_1_borderType; - public final static short BORDER_TYPE_REGULAR = 0; - public final static short BORDER_TYPE_SHADOW = 1; - private short field_2_options; + private short field_1_borderType; + private short field_2_options; - public FrameRecord() - { + public FrameRecord() {} + public FrameRecord(FrameRecord other) { + super(other); + field_1_borderType = other.field_1_borderType; + field_2_options = other.field_2_options; } - public FrameRecord(RecordInputStream in) - { - field_1_borderType = in.readShort(); - field_2_options = in.readShort(); + public FrameRecord(RecordInputStream in) { + field_1_borderType = in.readShort(); + field_2_options = in.readShort(); } public String toString() @@ -58,13 +61,13 @@ public final class FrameRecord extends StandardRecord implements Cloneable { buffer.append(" .borderType = ") .append("0x").append(HexDump.toHex( getBorderType ())) .append(" (").append( getBorderType() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .options = ") .append("0x").append(HexDump.toHex( getOptions ())) .append(" (").append( getOptions() ).append(" )"); - buffer.append(System.getProperty("line.separator")); - buffer.append(" .autoSize = ").append(isAutoSize()).append('\n'); - buffer.append(" .autoPosition = ").append(isAutoPosition()).append('\n'); + buffer.append(System.getProperty("line.separator")); + buffer.append(" .autoSize = ").append(isAutoSize()).append('\n'); + buffer.append(" .autoPosition = ").append(isAutoPosition()).append('\n'); buffer.append("[/FRAME]\n"); return buffer.toString(); @@ -85,21 +88,22 @@ public final class FrameRecord extends StandardRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public FrameRecord clone() { - FrameRecord rec = new FrameRecord(); - - rec.field_1_borderType = field_1_borderType; - rec.field_2_options = field_2_options; - return rec; + return copy(); } - - + @Override + public FrameRecord copy() { + return new FrameRecord(this); + } /** * Get the border type field for the Frame record. * - * @return One of + * @return One of * BORDER_TYPE_REGULAR * BORDER_TYPE_SHADOW */ @@ -112,7 +116,7 @@ public final class FrameRecord extends StandardRecord implements Cloneable { * Set the border type field for the Frame record. * * @param field_1_borderType - * One of + * One of * BORDER_TYPE_REGULAR * BORDER_TYPE_SHADOW */ diff --git a/src/java/org/apache/poi/hssf/record/chart/LegendRecord.java b/src/java/org/apache/poi/hssf/record/chart/LegendRecord.java index 2a4a3ba98b..17aa2fce88 100644 --- a/src/java/org/apache/poi/hssf/record/chart/LegendRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/LegendRecord.java @@ -23,12 +23,13 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * Defines a legend for a chart. */ -public final class LegendRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x1015; +public final class LegendRecord extends StandardRecord { + public static final short sid = 0x1015; private static final BitField autoPosition = BitFieldFactory.getInstance(0x01); private static final BitField autoSeries = BitFieldFactory.getInstance(0x02); @@ -37,38 +38,46 @@ public final class LegendRecord extends StandardRecord implements Cloneable { private static final BitField vertical = BitFieldFactory.getInstance(0x10); private static final BitField dataTable = BitFieldFactory.getInstance(0x20); - private int field_1_xAxisUpperLeft; - private int field_2_yAxisUpperLeft; - private int field_3_xSize; - private int field_4_ySize; - private byte field_5_type; - public final static byte TYPE_BOTTOM = 0; - public final static byte TYPE_CORNER = 1; - public final static byte TYPE_TOP = 2; - public final static byte TYPE_RIGHT = 3; - public final static byte TYPE_LEFT = 4; - public final static byte TYPE_UNDOCKED = 7; - private byte field_6_spacing; - public final static byte SPACING_CLOSE = 0; - public final static byte SPACING_MEDIUM = 1; - public final static byte SPACING_OPEN = 2; - private short field_7_options; - - - public LegendRecord() - { - - } - - public LegendRecord(RecordInputStream in) - { - field_1_xAxisUpperLeft = in.readInt(); - field_2_yAxisUpperLeft = in.readInt(); - field_3_xSize = in.readInt(); - field_4_ySize = in.readInt(); - field_5_type = in.readByte(); - field_6_spacing = in.readByte(); - field_7_options = in.readShort(); + public static final byte TYPE_BOTTOM = 0; + public static final byte TYPE_CORNER = 1; + public static final byte TYPE_TOP = 2; + public static final byte TYPE_RIGHT = 3; + public static final byte TYPE_LEFT = 4; + public static final byte TYPE_UNDOCKED = 7; + public static final byte SPACING_CLOSE = 0; + public static final byte SPACING_MEDIUM = 1; + public static final byte SPACING_OPEN = 2; + + + private int field_1_xAxisUpperLeft; + private int field_2_yAxisUpperLeft; + private int field_3_xSize; + private int field_4_ySize; + private byte field_5_type; + private byte field_6_spacing; + private short field_7_options; + + public LegendRecord() {} + + public LegendRecord(LegendRecord other) { + super(other); + field_1_xAxisUpperLeft = other.field_1_xAxisUpperLeft; + field_2_yAxisUpperLeft = other.field_2_yAxisUpperLeft; + field_3_xSize = other.field_3_xSize; + field_4_ySize = other.field_4_ySize; + field_5_type = other.field_5_type; + field_6_spacing = other.field_6_spacing; + field_7_options = other.field_7_options; + } + + public LegendRecord(RecordInputStream in) { + field_1_xAxisUpperLeft = in.readInt(); + field_2_yAxisUpperLeft = in.readInt(); + field_3_xSize = in.readInt(); + field_4_ySize = in.readInt(); + field_5_type = in.readByte(); + field_6_spacing = in.readByte(); + field_7_options = in.readShort(); } public String toString() @@ -79,37 +88,37 @@ public final class LegendRecord extends StandardRecord implements Cloneable { buffer.append(" .xAxisUpperLeft = ") .append("0x").append(HexDump.toHex( getXAxisUpperLeft ())) .append(" (").append( getXAxisUpperLeft() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .yAxisUpperLeft = ") .append("0x").append(HexDump.toHex( getYAxisUpperLeft ())) .append(" (").append( getYAxisUpperLeft() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .xSize = ") .append("0x").append(HexDump.toHex( getXSize ())) .append(" (").append( getXSize() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .ySize = ") .append("0x").append(HexDump.toHex( getYSize ())) .append(" (").append( getYSize() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .type = ") .append("0x").append(HexDump.toHex( getType ())) .append(" (").append( getType() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .spacing = ") .append("0x").append(HexDump.toHex( getSpacing ())) .append(" (").append( getSpacing() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .options = ") .append("0x").append(HexDump.toHex( getOptions ())) .append(" (").append( getOptions() ).append(" )"); - buffer.append(System.getProperty("line.separator")); - buffer.append(" .autoPosition = ").append(isAutoPosition()).append('\n'); - buffer.append(" .autoSeries = ").append(isAutoSeries()).append('\n'); - buffer.append(" .autoXPositioning = ").append(isAutoXPositioning()).append('\n'); - buffer.append(" .autoYPositioning = ").append(isAutoYPositioning()).append('\n'); - buffer.append(" .vertical = ").append(isVertical()).append('\n'); - buffer.append(" .dataTable = ").append(isDataTable()).append('\n'); + buffer.append(System.getProperty("line.separator")); + buffer.append(" .autoPosition = ").append(isAutoPosition()).append('\n'); + buffer.append(" .autoSeries = ").append(isAutoSeries()).append('\n'); + buffer.append(" .autoXPositioning = ").append(isAutoXPositioning()).append('\n'); + buffer.append(" .autoYPositioning = ").append(isAutoYPositioning()).append('\n'); + buffer.append(" .vertical = ").append(isVertical()).append('\n'); + buffer.append(" .dataTable = ").append(isDataTable()).append('\n'); buffer.append("[/LEGEND]\n"); return buffer.toString(); @@ -135,17 +144,16 @@ public final class LegendRecord extends StandardRecord implements Cloneable { } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public LegendRecord clone() { - LegendRecord rec = new LegendRecord(); - - rec.field_1_xAxisUpperLeft = field_1_xAxisUpperLeft; - rec.field_2_yAxisUpperLeft = field_2_yAxisUpperLeft; - rec.field_3_xSize = field_3_xSize; - rec.field_4_ySize = field_4_ySize; - rec.field_5_type = field_5_type; - rec.field_6_spacing = field_6_spacing; - rec.field_7_options = field_7_options; - return rec; + return copy(); + } + + @Override + public LegendRecord copy() { + return new LegendRecord(this); } @@ -218,7 +226,7 @@ public final class LegendRecord extends StandardRecord implements Cloneable { /** * Get the type field for the Legend record. * - * @return One of + * @return One of * TYPE_BOTTOM * TYPE_CORNER * TYPE_TOP @@ -235,7 +243,7 @@ public final class LegendRecord extends StandardRecord implements Cloneable { * Set the type field for the Legend record. * * @param field_5_type - * One of + * One of * TYPE_BOTTOM * TYPE_CORNER * TYPE_TOP @@ -251,7 +259,7 @@ public final class LegendRecord extends StandardRecord implements Cloneable { /** * Get the spacing field for the Legend record. * - * @return One of + * @return One of * SPACING_CLOSE * SPACING_MEDIUM * SPACING_OPEN @@ -265,7 +273,7 @@ public final class LegendRecord extends StandardRecord implements Cloneable { * Set the spacing field for the Legend record. * * @param field_6_spacing - * One of + * One of * SPACING_CLOSE * SPACING_MEDIUM * SPACING_OPEN diff --git a/src/java/org/apache/poi/hssf/record/chart/LineFormatRecord.java b/src/java/org/apache/poi/hssf/record/chart/LineFormatRecord.java index e0acece3ba..21eef9d26f 100644 --- a/src/java/org/apache/poi/hssf/record/chart/LineFormatRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/LineFormatRecord.java @@ -23,50 +23,58 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * Describes a line format record. The line format record controls how a line on a chart appears. */ -public final class LineFormatRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x1007; +public final class LineFormatRecord extends StandardRecord { + public static final short sid = 0x1007; private static final BitField auto = BitFieldFactory.getInstance(0x1); private static final BitField drawTicks = BitFieldFactory.getInstance(0x4); private static final BitField unknown = BitFieldFactory.getInstance(0x4); - private int field_1_lineColor; - private short field_2_linePattern; - public final static short LINE_PATTERN_SOLID = 0; - public final static short LINE_PATTERN_DASH = 1; - public final static short LINE_PATTERN_DOT = 2; - public final static short LINE_PATTERN_DASH_DOT = 3; - public final static short LINE_PATTERN_DASH_DOT_DOT = 4; - public final static short LINE_PATTERN_NONE = 5; - public final static short LINE_PATTERN_DARK_GRAY_PATTERN = 6; - public final static short LINE_PATTERN_MEDIUM_GRAY_PATTERN = 7; - public final static short LINE_PATTERN_LIGHT_GRAY_PATTERN = 8; - private short field_3_weight; - public final static short WEIGHT_HAIRLINE = -1; - public final static short WEIGHT_NARROW = 0; - public final static short WEIGHT_MEDIUM = 1; - public final static short WEIGHT_WIDE = 2; - private short field_4_format; - private short field_5_colourPaletteIndex; - - - public LineFormatRecord() - { - + public static final short LINE_PATTERN_SOLID = 0; + public static final short LINE_PATTERN_DASH = 1; + public static final short LINE_PATTERN_DOT = 2; + public static final short LINE_PATTERN_DASH_DOT = 3; + public static final short LINE_PATTERN_DASH_DOT_DOT = 4; + public static final short LINE_PATTERN_NONE = 5; + public static final short LINE_PATTERN_DARK_GRAY_PATTERN = 6; + public static final short LINE_PATTERN_MEDIUM_GRAY_PATTERN = 7; + public static final short LINE_PATTERN_LIGHT_GRAY_PATTERN = 8; + + public static final short WEIGHT_HAIRLINE = -1; + public static final short WEIGHT_NARROW = 0; + public static final short WEIGHT_MEDIUM = 1; + public static final short WEIGHT_WIDE = 2; + + + private int field_1_lineColor; + private short field_2_linePattern; + private short field_3_weight; + private short field_4_format; + private short field_5_colourPaletteIndex; + + + public LineFormatRecord() {} + + public LineFormatRecord(LineFormatRecord other) { + super(other); + field_1_lineColor = other.field_1_lineColor; + field_2_linePattern = other.field_2_linePattern; + field_3_weight = other.field_3_weight; + field_4_format = other.field_4_format; + field_5_colourPaletteIndex = other.field_5_colourPaletteIndex; } - public LineFormatRecord(RecordInputStream in) - { - field_1_lineColor = in.readInt(); - field_2_linePattern = in.readShort(); - field_3_weight = in.readShort(); - field_4_format = in.readShort(); - field_5_colourPaletteIndex = in.readShort(); - + public LineFormatRecord(RecordInputStream in) { + field_1_lineColor = in.readInt(); + field_2_linePattern = in.readShort(); + field_3_weight = in.readShort(); + field_4_format = in.readShort(); + field_5_colourPaletteIndex = in.readShort(); } public String toString() @@ -77,26 +85,26 @@ public final class LineFormatRecord extends StandardRecord implements Cloneable buffer.append(" .lineColor = ") .append("0x").append(HexDump.toHex( getLineColor ())) .append(" (").append( getLineColor() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .linePattern = ") .append("0x").append(HexDump.toHex( getLinePattern ())) .append(" (").append( getLinePattern() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .weight = ") .append("0x").append(HexDump.toHex( getWeight ())) .append(" (").append( getWeight() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .format = ") .append("0x").append(HexDump.toHex( getFormat ())) .append(" (").append( getFormat() ).append(" )"); - buffer.append(System.getProperty("line.separator")); - buffer.append(" .auto = ").append(isAuto()).append('\n'); - buffer.append(" .drawTicks = ").append(isDrawTicks()).append('\n'); - buffer.append(" .unknown = ").append(isUnknown()).append('\n'); + buffer.append(System.getProperty("line.separator")); + buffer.append(" .auto = ").append(isAuto()).append('\n'); + buffer.append(" .drawTicks = ").append(isDrawTicks()).append('\n'); + buffer.append(" .unknown = ").append(isUnknown()).append('\n'); buffer.append(" .colourPaletteIndex = ") .append("0x").append(HexDump.toHex( getColourPaletteIndex ())) .append(" (").append( getColourPaletteIndex() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append("[/LINEFORMAT]\n"); return buffer.toString(); @@ -120,19 +128,17 @@ public final class LineFormatRecord extends StandardRecord implements Cloneable } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public LineFormatRecord clone() { - LineFormatRecord rec = new LineFormatRecord(); - - rec.field_1_lineColor = field_1_lineColor; - rec.field_2_linePattern = field_2_linePattern; - rec.field_3_weight = field_3_weight; - rec.field_4_format = field_4_format; - rec.field_5_colourPaletteIndex = field_5_colourPaletteIndex; - return rec; + return copy(); } - - + @Override + public LineFormatRecord copy() { + return new LineFormatRecord(this); + } /** * Get the line color field for the LineFormat record. @@ -153,7 +159,7 @@ public final class LineFormatRecord extends StandardRecord implements Cloneable /** * Get the line pattern field for the LineFormat record. * - * @return One of + * @return One of * LINE_PATTERN_SOLID * LINE_PATTERN_DASH * LINE_PATTERN_DOT @@ -173,7 +179,7 @@ public final class LineFormatRecord extends StandardRecord implements Cloneable * Set the line pattern field for the LineFormat record. * * @param field_2_linePattern - * One of + * One of * LINE_PATTERN_SOLID * LINE_PATTERN_DASH * LINE_PATTERN_DOT @@ -192,7 +198,7 @@ public final class LineFormatRecord extends StandardRecord implements Cloneable /** * Get the weight field for the LineFormat record. * - * @return One of + * @return One of * WEIGHT_HAIRLINE * WEIGHT_NARROW * WEIGHT_MEDIUM @@ -207,7 +213,7 @@ public final class LineFormatRecord extends StandardRecord implements Cloneable * Set the weight field for the LineFormat record. * * @param field_3_weight - * One of + * One of * WEIGHT_HAIRLINE * WEIGHT_NARROW * WEIGHT_MEDIUM diff --git a/src/java/org/apache/poi/hssf/record/chart/LinkedDataRecord.java b/src/java/org/apache/poi/hssf/record/chart/LinkedDataRecord.java index 96c8501d33..49d0afc7a0 100644 --- a/src/java/org/apache/poi/hssf/record/chart/LinkedDataRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/LinkedDataRecord.java @@ -19,44 +19,52 @@ package org.apache.poi.hssf.record.chart; import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; -import org.apache.poi.ss.formula.ptg.Ptg; import org.apache.poi.ss.formula.Formula; +import org.apache.poi.ss.formula.ptg.Ptg; import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * Describes a linked data record. This record refers to the series data or text. */ -public final class LinkedDataRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x1051; +public final class LinkedDataRecord extends StandardRecord { + public static final short sid = 0x1051; + + public static final byte LINK_TYPE_TITLE_OR_TEXT = 0; + public static final byte LINK_TYPE_VALUES = 1; + public static final byte LINK_TYPE_CATEGORIES = 2; + public static final byte LINK_TYPE_SECONDARY_CATEGORIES = 3; + + public static final byte REFERENCE_TYPE_DEFAULT_CATEGORIES = 0; + public static final byte REFERENCE_TYPE_DIRECT = 1; + public static final byte REFERENCE_TYPE_WORKSHEET = 2; + public static final byte REFERENCE_TYPE_NOT_USED = 3; + public static final byte REFERENCE_TYPE_ERROR_REPORTED = 4; private static final BitField customNumberFormat= BitFieldFactory.getInstance(0x1); private byte field_1_linkType; - public final static byte LINK_TYPE_TITLE_OR_TEXT = 0; - public final static byte LINK_TYPE_VALUES = 1; - public final static byte LINK_TYPE_CATEGORIES = 2; - public final static byte LINK_TYPE_SECONDARY_CATEGORIES = 3; private byte field_2_referenceType; - public final static byte REFERENCE_TYPE_DEFAULT_CATEGORIES = 0; - public final static byte REFERENCE_TYPE_DIRECT = 1; - public final static byte REFERENCE_TYPE_WORKSHEET = 2; - public final static byte REFERENCE_TYPE_NOT_USED = 3; - public final static byte REFERENCE_TYPE_ERROR_REPORTED = 4; private short field_3_options; private short field_4_indexNumberFmtRecord; private Formula field_5_formulaOfLink; - public LinkedDataRecord() - { + public LinkedDataRecord() {} + public LinkedDataRecord(LinkedDataRecord other) { + super(other); + field_1_linkType = other.field_1_linkType; + field_2_referenceType = other.field_2_referenceType; + field_3_options = other.field_3_options; + field_4_indexNumberFmtRecord = other.field_4_indexNumberFmtRecord; + field_5_formulaOfLink = (other.field_5_formulaOfLink == null) ? null : other.field_5_formulaOfLink.copy(); } - public LinkedDataRecord(RecordInputStream in) - { + public LinkedDataRecord(RecordInputStream in) { field_1_linkType = in.readByte(); field_2_referenceType = in.readByte(); field_3_options = in.readShort(); @@ -102,26 +110,24 @@ public final class LinkedDataRecord extends StandardRecord implements Cloneable } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public LinkedDataRecord clone() { - LinkedDataRecord rec = new LinkedDataRecord(); - - rec.field_1_linkType = field_1_linkType; - rec.field_2_referenceType = field_2_referenceType; - rec.field_3_options = field_3_options; - rec.field_4_indexNumberFmtRecord = field_4_indexNumberFmtRecord; - rec.field_5_formulaOfLink = field_5_formulaOfLink.copy(); - return rec; + return copy(); } - - + @Override + public LinkedDataRecord copy() { + return new LinkedDataRecord(this); + } /** * Get the link type field for the LinkedData record. * * @return One of * {@link #LINK_TYPE_TITLE_OR_TEXT}, - * {@link #LINK_TYPE_VALUES}, + * {@link #LINK_TYPE_VALUES}, * {@link #LINK_TYPE_CATEGORIES}, or * {@link #LINK_TYPE_SECONDARY_CATEGORIES} */ diff --git a/src/java/org/apache/poi/hssf/record/chart/NumberFormatIndexRecord.java b/src/java/org/apache/poi/hssf/record/chart/NumberFormatIndexRecord.java index 9ba2a27b16..2c04258800 100644 --- a/src/java/org/apache/poi/hssf/record/chart/NumberFormatIndexRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/NumberFormatIndexRecord.java @@ -21,23 +21,25 @@ import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * The number format index record indexes format table. This applies to an axis. */ -public final class NumberFormatIndexRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x104E; - private short field_1_formatIndex; +public final class NumberFormatIndexRecord extends StandardRecord { + public static final short sid = 0x104E; + private short field_1_formatIndex; - public NumberFormatIndexRecord() - { + public NumberFormatIndexRecord() { } + public NumberFormatIndexRecord(NumberFormatIndexRecord other) { + super(other); + field_1_formatIndex = other.field_1_formatIndex; } - public NumberFormatIndexRecord(RecordInputStream in) - { - field_1_formatIndex = in.readShort(); + public NumberFormatIndexRecord(RecordInputStream in) { + field_1_formatIndex = in.readShort(); } public String toString() @@ -48,7 +50,7 @@ public final class NumberFormatIndexRecord extends StandardRecord implements Clo buffer.append(" .formatIndex = ") .append("0x").append(HexDump.toHex( getFormatIndex ())) .append(" (").append( getFormatIndex() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append("[/IFMT]\n"); return buffer.toString(); @@ -68,15 +70,17 @@ public final class NumberFormatIndexRecord extends StandardRecord implements Clo } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public NumberFormatIndexRecord clone() { - NumberFormatIndexRecord rec = new NumberFormatIndexRecord(); - - rec.field_1_formatIndex = field_1_formatIndex; - return rec; + return copy(); } - - + @Override + public NumberFormatIndexRecord copy() { + return new NumberFormatIndexRecord(this); + } /** * Get the format index field for the NumberFormatIndex record. diff --git a/src/java/org/apache/poi/hssf/record/chart/ObjectLinkRecord.java b/src/java/org/apache/poi/hssf/record/chart/ObjectLinkRecord.java index c179f2603f..d52bfbe937 100644 --- a/src/java/org/apache/poi/hssf/record/chart/ObjectLinkRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/ObjectLinkRecord.java @@ -21,33 +21,37 @@ import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * Links text to an object on the chart or identifies it as the title. */ -public final class ObjectLinkRecord extends StandardRecord implements Cloneable { - public final static short sid = 0x1027; - private short field_1_anchorId; - public final static short ANCHOR_ID_CHART_TITLE = 1; - public final static short ANCHOR_ID_Y_AXIS = 2; - public final static short ANCHOR_ID_X_AXIS = 3; - public final static short ANCHOR_ID_SERIES_OR_POINT = 4; - public final static short ANCHOR_ID_Z_AXIS = 7; - private short field_2_link1; - private short field_3_link2; - - - public ObjectLinkRecord() - { - +public final class ObjectLinkRecord extends StandardRecord { + public static final short sid = 0x1027; + + public static final short ANCHOR_ID_CHART_TITLE = 1; + public static final short ANCHOR_ID_Y_AXIS = 2; + public static final short ANCHOR_ID_X_AXIS = 3; + public static final short ANCHOR_ID_SERIES_OR_POINT = 4; + public static final short ANCHOR_ID_Z_AXIS = 7; + + private short field_1_anchorId; + private short field_2_link1; + private short field_3_link2; + + public ObjectLinkRecord() {} + + public ObjectLinkRecord(ObjectLinkRecord other) { + super(other); + field_1_anchorId = other.field_1_anchorId; + field_2_link1 = other.field_2_link1; + field_3_link2 = other.field_3_link2; } - public ObjectLinkRecord(RecordInputStream in) - { - field_1_anchorId = in.readShort(); - field_2_link1 = in.readShort(); - field_3_link2 = in.readShort(); - + public ObjectLinkRecord(RecordInputStream in) { + field_1_anchorId = in.readShort(); + field_2_link1 = in.readShort(); + field_3_link2 = in.readShort(); } public String toString() @@ -58,15 +62,15 @@ public final class ObjectLinkRecord extends StandardRecord implements Cloneable buffer.append(" .anchorId = ") .append("0x").append(HexDump.toHex( getAnchorId ())) .append(" (").append( getAnchorId() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .link1 = ") .append("0x").append(HexDump.toHex( getLink1 ())) .append(" (").append( getLink1() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .link2 = ") .append("0x").append(HexDump.toHex( getLink2 ())) .append(" (").append( getLink2() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append("[/OBJECTLINK]\n"); return buffer.toString(); @@ -88,22 +92,22 @@ public final class ObjectLinkRecord extends StandardRecord implements Cloneable } @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") public ObjectLinkRecord clone() { - ObjectLinkRecord rec = new ObjectLinkRecord(); - - rec.field_1_anchorId = field_1_anchorId; - rec.field_2_link1 = field_2_link1; - rec.field_3_link2 = field_3_link2; - return rec; + return copy(); } - - + @Override + public ObjectLinkRecord copy() { + return new ObjectLinkRecord(this); + } /** * Get the anchor id field for the ObjectLink record. * - * @return One of + * @return One of * ANCHOR_ID_CHART_TITLE * ANCHOR_ID_Y_AXIS * ANCHOR_ID_X_AXIS @@ -119,7 +123,7 @@ public final class ObjectLinkRecord extends StandardRecord implements Cloneable * Set the anchor id field for the ObjectLink record. * * @param field_1_anchorId - * One of + * One of * ANCHOR_ID_CHART_TITLE * ANCHOR_ID_Y_AXIS * ANCHOR_ID_X_AXIS diff --git a/src/java/org/apache/poi/hssf/record/chart/PlotAreaRecord.java b/src/java/org/apache/poi/hssf/record/chart/PlotAreaRecord.java index 920fbc2e66..332808d785 100644 --- a/src/java/org/apache/poi/hssf/record/chart/PlotAreaRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/PlotAreaRecord.java @@ -20,26 +20,20 @@ package org.apache.poi.hssf.record.chart; import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * preceeds and identifies a frame as belonging to the plot area. */ public final class PlotAreaRecord extends StandardRecord { - public final static short sid = 0x1035; + public static final short sid = 0x1035; - - public PlotAreaRecord() - { - - } + public PlotAreaRecord() {} /** * @param in unused (since this record has no data) */ - public PlotAreaRecord(RecordInputStream in) - { - - } + public PlotAreaRecord(RecordInputStream in) {} public String toString() { @@ -63,7 +57,16 @@ public final class PlotAreaRecord extends StandardRecord { return sid; } - public Object clone() { + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public PlotAreaRecord clone() { + return copy(); + } + + @Override + public PlotAreaRecord copy() { return new PlotAreaRecord(); } } diff --git a/src/java/org/apache/poi/hssf/record/chart/PlotGrowthRecord.java b/src/java/org/apache/poi/hssf/record/chart/PlotGrowthRecord.java index d538a9b44f..3af8916d1d 100644 --- a/src/java/org/apache/poi/hssf/record/chart/PlotGrowthRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/PlotGrowthRecord.java @@ -21,26 +21,27 @@ import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * The plot growth record specifies the scaling factors used when a font is scaled. */ public final class PlotGrowthRecord extends StandardRecord { - public final static short sid = 0x1064; - private int field_1_horizontalScale; - private int field_2_verticalScale; + public static final short sid = 0x1064; + private int field_1_horizontalScale; + private int field_2_verticalScale; - public PlotGrowthRecord() - { + public PlotGrowthRecord() {} + public PlotGrowthRecord(PlotGrowthRecord other) { + field_1_horizontalScale = other.field_1_horizontalScale; + field_2_verticalScale = other.field_2_verticalScale; } - public PlotGrowthRecord(RecordInputStream in) - { - field_1_horizontalScale = in.readInt(); - field_2_verticalScale = in.readInt(); - + public PlotGrowthRecord(RecordInputStream in) { + field_1_horizontalScale = in.readInt(); + field_2_verticalScale = in.readInt(); } public String toString() @@ -51,11 +52,11 @@ public final class PlotGrowthRecord extends StandardRecord { buffer.append(" .horizontalScale = ") .append("0x").append(HexDump.toHex( getHorizontalScale ())) .append(" (").append( getHorizontalScale() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .verticalScale = ") .append("0x").append(HexDump.toHex( getVerticalScale ())) .append(" (").append( getVerticalScale() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append("[/PLOTGROWTH]\n"); return buffer.toString(); @@ -75,16 +76,17 @@ public final class PlotGrowthRecord extends StandardRecord { return sid; } - public Object clone() { - PlotGrowthRecord rec = new PlotGrowthRecord(); - - rec.field_1_horizontalScale = field_1_horizontalScale; - rec.field_2_verticalScale = field_2_verticalScale; - return rec; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public PlotGrowthRecord clone() { + return copy(); } - - + public PlotGrowthRecord copy() { + return new PlotGrowthRecord(this); + } /** * Get the horizontalScale field for the PlotGrowth record. diff --git a/src/java/org/apache/poi/hssf/record/chart/SeriesChartGroupIndexRecord.java b/src/java/org/apache/poi/hssf/record/chart/SeriesChartGroupIndexRecord.java index 6d095149c5..e56ff395be 100644 --- a/src/java/org/apache/poi/hssf/record/chart/SeriesChartGroupIndexRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/SeriesChartGroupIndexRecord.java @@ -21,23 +21,25 @@ import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * The series chart group index record stores the index to the CHARTFORMAT record (0 based). */ public final class SeriesChartGroupIndexRecord extends StandardRecord { - public final static short sid = 0x1045; - private short field_1_chartGroupIndex; + public static final short sid = 0x1045; + private short field_1_chartGroupIndex; - public SeriesChartGroupIndexRecord() - { + public SeriesChartGroupIndexRecord() {} + public SeriesChartGroupIndexRecord(SeriesChartGroupIndexRecord other) { + super(other); + field_1_chartGroupIndex = other.field_1_chartGroupIndex; } - public SeriesChartGroupIndexRecord(RecordInputStream in) - { - field_1_chartGroupIndex = in.readShort(); + public SeriesChartGroupIndexRecord(RecordInputStream in) { + field_1_chartGroupIndex = in.readShort(); } public String toString() @@ -48,7 +50,7 @@ public final class SeriesChartGroupIndexRecord extends StandardRecord { buffer.append(" .chartGroupIndex = ") .append("0x").append(HexDump.toHex( getChartGroupIndex ())) .append(" (").append( getChartGroupIndex() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append("[/SERTOCRT]\n"); return buffer.toString(); @@ -67,15 +69,18 @@ public final class SeriesChartGroupIndexRecord extends StandardRecord { return sid; } - public Object clone() { - SeriesChartGroupIndexRecord rec = new SeriesChartGroupIndexRecord(); - - rec.field_1_chartGroupIndex = field_1_chartGroupIndex; - return rec; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public SeriesChartGroupIndexRecord clone() { + return copy(); } - - + @Override + public SeriesChartGroupIndexRecord copy() { + return new SeriesChartGroupIndexRecord(this); + } /** * Get the chart group index field for the SeriesChartGroupIndex record. diff --git a/src/java/org/apache/poi/hssf/record/chart/SeriesIndexRecord.java b/src/java/org/apache/poi/hssf/record/chart/SeriesIndexRecord.java index 09d8c65b4f..877bcc9480 100644 --- a/src/java/org/apache/poi/hssf/record/chart/SeriesIndexRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/SeriesIndexRecord.java @@ -21,23 +21,24 @@ import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * links a series to its position in the series list. */ public final class SeriesIndexRecord extends StandardRecord { - public final static short sid = 0x1065; - private short field_1_index; + public static final short sid = 0x1065; + private short field_1_index; + public SeriesIndexRecord() {} - public SeriesIndexRecord() - { - + public SeriesIndexRecord(SeriesIndexRecord other) { + super(other); + field_1_index = other.field_1_index; } - public SeriesIndexRecord(RecordInputStream in) - { - field_1_index = in.readShort(); + public SeriesIndexRecord(RecordInputStream in) { + field_1_index = in.readShort(); } public String toString() @@ -48,7 +49,7 @@ public final class SeriesIndexRecord extends StandardRecord { buffer.append(" .index = ") .append("0x").append(HexDump.toHex( getIndex ())) .append(" (").append( getIndex() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append("[/SINDEX]\n"); return buffer.toString(); @@ -67,15 +68,18 @@ public final class SeriesIndexRecord extends StandardRecord { return sid; } - public Object clone() { - SeriesIndexRecord rec = new SeriesIndexRecord(); - - rec.field_1_index = field_1_index; - return rec; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public SeriesIndexRecord clone() { + return copy(); } - - + @Override + public SeriesIndexRecord copy() { + return new SeriesIndexRecord(this); + } /** * Get the index field for the SeriesIndex record. diff --git a/src/java/org/apache/poi/hssf/record/chart/SeriesLabelsRecord.java b/src/java/org/apache/poi/hssf/record/chart/SeriesLabelsRecord.java index 66a49188a7..f882371ff6 100644 --- a/src/java/org/apache/poi/hssf/record/chart/SeriesLabelsRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/SeriesLabelsRecord.java @@ -23,14 +23,13 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * The series label record defines the type of label associated with the data format record.<p> - * - * @author Glen Stampoultzis (glens at apache.org) + * The series label record defines the type of label associated with the data format record. */ public final class SeriesLabelsRecord extends StandardRecord { - public final static short sid = 0x100c; + public static final short sid = 0x100c; private static final BitField showActual = BitFieldFactory.getInstance(0x01); private static final BitField showPercent = BitFieldFactory.getInstance(0x02); @@ -39,16 +38,17 @@ public final class SeriesLabelsRecord extends StandardRecord { private static final BitField showLabel = BitFieldFactory.getInstance(0x10); private static final BitField showBubbleSizes = BitFieldFactory.getInstance(0x20); - private short field_1_formatFlags; + private short field_1_formatFlags; - public SeriesLabelsRecord() - { + public SeriesLabelsRecord() {} + public SeriesLabelsRecord(SeriesLabelsRecord other) { + super(other); + field_1_formatFlags = other.field_1_formatFlags; } - public SeriesLabelsRecord(RecordInputStream in) - { - field_1_formatFlags = in.readShort(); + public SeriesLabelsRecord(RecordInputStream in) { + field_1_formatFlags = in.readShort(); } public String toString() @@ -59,13 +59,13 @@ public final class SeriesLabelsRecord extends StandardRecord { buffer.append(" .formatFlags = ") .append("0x").append(HexDump.toHex( getFormatFlags ())) .append(" (").append( getFormatFlags() ).append(" )"); - buffer.append(System.getProperty("line.separator")); - buffer.append(" .showActual = ").append(isShowActual()).append('\n'); - buffer.append(" .showPercent = ").append(isShowPercent()).append('\n'); - buffer.append(" .labelAsPercentage = ").append(isLabelAsPercentage()).append('\n'); - buffer.append(" .smoothedLine = ").append(isSmoothedLine()).append('\n'); - buffer.append(" .showLabel = ").append(isShowLabel()).append('\n'); - buffer.append(" .showBubbleSizes = ").append(isShowBubbleSizes()).append('\n'); + buffer.append(System.getProperty("line.separator")); + buffer.append(" .showActual = ").append(isShowActual()).append('\n'); + buffer.append(" .showPercent = ").append(isShowPercent()).append('\n'); + buffer.append(" .labelAsPercentage = ").append(isLabelAsPercentage()).append('\n'); + buffer.append(" .smoothedLine = ").append(isSmoothedLine()).append('\n'); + buffer.append(" .showLabel = ").append(isShowLabel()).append('\n'); + buffer.append(" .showBubbleSizes = ").append(isShowBubbleSizes()).append('\n'); buffer.append("[/ATTACHEDLABEL]\n"); return buffer.toString(); @@ -84,15 +84,18 @@ public final class SeriesLabelsRecord extends StandardRecord { return sid; } - public Object clone() { - SeriesLabelsRecord rec = new SeriesLabelsRecord(); - - rec.field_1_formatFlags = field_1_formatFlags; - return rec; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public SeriesLabelsRecord clone() { + return copy(); } - - + @Override + public SeriesLabelsRecord copy() { + return new SeriesLabelsRecord(this); + } /** * Get the format flags field for the SeriesLabels record. diff --git a/src/java/org/apache/poi/hssf/record/chart/SeriesListRecord.java b/src/java/org/apache/poi/hssf/record/chart/SeriesListRecord.java index 5457702ee6..70b83bed6d 100644 --- a/src/java/org/apache/poi/hssf/record/chart/SeriesListRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/SeriesListRecord.java @@ -22,18 +22,24 @@ import java.util.Arrays; import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * SERIESLIST (0x1016)<p> - * + * * The series list record defines the series displayed as an overlay to the main chart record.<p> - * + * * (As with all chart related records, documentation is lacking. * See {@link ChartRecord} for more details) */ public final class SeriesListRecord extends StandardRecord { - public final static short sid = 0x1016; - private short[] field_1_seriesNumbers; + public static final short sid = 0x1016; + private short[] field_1_seriesNumbers; + + public SeriesListRecord(SeriesListRecord other) { + super(other); + field_1_seriesNumbers = (other.field_1_seriesNumbers == null) ? null : other.field_1_seriesNumbers.clone(); + } public SeriesListRecord(short[] seriesNumbers) { field_1_seriesNumbers = (seriesNumbers == null) ? null : seriesNumbers.clone(); @@ -44,17 +50,17 @@ public final class SeriesListRecord extends StandardRecord { short[] ss = new short[nItems]; for (int i = 0; i < nItems; i++) { ss[i] = in.readShort(); - + } field_1_seriesNumbers = ss; } public String toString() { StringBuilder buffer = new StringBuilder(); - + buffer.append("[SERIESLIST]\n"); buffer.append(" .seriesNumbers= ").append(" (").append( Arrays.toString(getSeriesNumbers()) ).append(" )"); - buffer.append("\n"); + buffer.append("\n"); buffer.append("[/SERIESLIST]\n"); return buffer.toString(); @@ -77,8 +83,17 @@ public final class SeriesListRecord extends StandardRecord { return sid; } - public Object clone() { - return new SeriesListRecord(field_1_seriesNumbers); + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public SeriesListRecord clone() { + return copy(); + } + + @Override + public SeriesListRecord copy() { + return new SeriesListRecord(this); } /** diff --git a/src/java/org/apache/poi/hssf/record/chart/SeriesRecord.java b/src/java/org/apache/poi/hssf/record/chart/SeriesRecord.java index 6ebef9abd4..22405ecde2 100644 --- a/src/java/org/apache/poi/hssf/record/chart/SeriesRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/SeriesRecord.java @@ -21,46 +21,56 @@ import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * The series record describes the overall data for a series. */ public final class SeriesRecord extends StandardRecord { - public final static short sid = 0x1003; - private short field_1_categoryDataType; - public final static short CATEGORY_DATA_TYPE_DATES = 0; - public final static short CATEGORY_DATA_TYPE_NUMERIC = 1; - public final static short CATEGORY_DATA_TYPE_SEQUENCE = 2; - public final static short CATEGORY_DATA_TYPE_TEXT = 3; - private short field_2_valuesDataType; - public final static short VALUES_DATA_TYPE_DATES = 0; - public final static short VALUES_DATA_TYPE_NUMERIC = 1; - public final static short VALUES_DATA_TYPE_SEQUENCE = 2; - public final static short VALUES_DATA_TYPE_TEXT = 3; - private short field_3_numCategories; - private short field_4_numValues; - private short field_5_bubbleSeriesType; - public final static short BUBBLE_SERIES_TYPE_DATES = 0; - public final static short BUBBLE_SERIES_TYPE_NUMERIC = 1; - public final static short BUBBLE_SERIES_TYPE_SEQUENCE = 2; - public final static short BUBBLE_SERIES_TYPE_TEXT = 3; - private short field_6_numBubbleValues; - - - public SeriesRecord() - { - + public static final short sid = 0x1003; + + public static final short CATEGORY_DATA_TYPE_DATES = 0; + public static final short CATEGORY_DATA_TYPE_NUMERIC = 1; + public static final short CATEGORY_DATA_TYPE_SEQUENCE = 2; + public static final short CATEGORY_DATA_TYPE_TEXT = 3; + + public static final short VALUES_DATA_TYPE_DATES = 0; + public static final short VALUES_DATA_TYPE_NUMERIC = 1; + public static final short VALUES_DATA_TYPE_SEQUENCE = 2; + public static final short VALUES_DATA_TYPE_TEXT = 3; + + public static final short BUBBLE_SERIES_TYPE_DATES = 0; + public static final short BUBBLE_SERIES_TYPE_NUMERIC = 1; + public static final short BUBBLE_SERIES_TYPE_SEQUENCE = 2; + public static final short BUBBLE_SERIES_TYPE_TEXT = 3; + + private short field_1_categoryDataType; + private short field_2_valuesDataType; + private short field_3_numCategories; + private short field_4_numValues; + private short field_5_bubbleSeriesType; + private short field_6_numBubbleValues; + + + public SeriesRecord() {} + + public SeriesRecord(SeriesRecord other) { + super(other); + field_1_categoryDataType = other.field_1_categoryDataType; + field_2_valuesDataType = other.field_2_valuesDataType; + field_3_numCategories = other.field_3_numCategories; + field_4_numValues = other.field_4_numValues; + field_5_bubbleSeriesType = other.field_5_bubbleSeriesType; + field_6_numBubbleValues = other.field_6_numBubbleValues; } - public SeriesRecord(RecordInputStream in) - { - field_1_categoryDataType = in.readShort(); - field_2_valuesDataType = in.readShort(); - field_3_numCategories = in.readShort(); - field_4_numValues = in.readShort(); - field_5_bubbleSeriesType = in.readShort(); - field_6_numBubbleValues = in.readShort(); - + public SeriesRecord(RecordInputStream in) { + field_1_categoryDataType = in.readShort(); + field_2_valuesDataType = in.readShort(); + field_3_numCategories = in.readShort(); + field_4_numValues = in.readShort(); + field_5_bubbleSeriesType = in.readShort(); + field_6_numBubbleValues = in.readShort(); } public String toString() @@ -71,27 +81,27 @@ public final class SeriesRecord extends StandardRecord { buffer.append(" .categoryDataType = ") .append("0x").append(HexDump.toHex( getCategoryDataType ())) .append(" (").append( getCategoryDataType() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .valuesDataType = ") .append("0x").append(HexDump.toHex( getValuesDataType ())) .append(" (").append( getValuesDataType() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .numCategories = ") .append("0x").append(HexDump.toHex( getNumCategories ())) .append(" (").append( getNumCategories() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .numValues = ") .append("0x").append(HexDump.toHex( getNumValues ())) .append(" (").append( getNumValues() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .bubbleSeriesType = ") .append("0x").append(HexDump.toHex( getBubbleSeriesType ())) .append(" (").append( getBubbleSeriesType() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .numBubbleValues = ") .append("0x").append(HexDump.toHex( getNumBubbleValues ())) .append(" (").append( getNumBubbleValues() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append("[/SERIES]\n"); return buffer.toString(); @@ -115,25 +125,23 @@ public final class SeriesRecord extends StandardRecord { return sid; } - public Object clone() { - SeriesRecord rec = new SeriesRecord(); - - rec.field_1_categoryDataType = field_1_categoryDataType; - rec.field_2_valuesDataType = field_2_valuesDataType; - rec.field_3_numCategories = field_3_numCategories; - rec.field_4_numValues = field_4_numValues; - rec.field_5_bubbleSeriesType = field_5_bubbleSeriesType; - rec.field_6_numBubbleValues = field_6_numBubbleValues; - return rec; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public SeriesRecord clone() { + return copy(); } - - + @Override + public SeriesRecord copy() { + return new SeriesRecord(this); + } /** * Get the category data type field for the Series record. * - * @return One of + * @return One of * CATEGORY_DATA_TYPE_DATES * CATEGORY_DATA_TYPE_NUMERIC * CATEGORY_DATA_TYPE_SEQUENCE @@ -148,7 +156,7 @@ public final class SeriesRecord extends StandardRecord { * Set the category data type field for the Series record. * * @param field_1_categoryDataType - * One of + * One of * CATEGORY_DATA_TYPE_DATES * CATEGORY_DATA_TYPE_NUMERIC * CATEGORY_DATA_TYPE_SEQUENCE @@ -162,7 +170,7 @@ public final class SeriesRecord extends StandardRecord { /** * Get the values data type field for the Series record. * - * @return One of + * @return One of * VALUES_DATA_TYPE_DATES * VALUES_DATA_TYPE_NUMERIC * VALUES_DATA_TYPE_SEQUENCE @@ -177,7 +185,7 @@ public final class SeriesRecord extends StandardRecord { * Set the values data type field for the Series record. * * @param field_2_valuesDataType - * One of + * One of * VALUES_DATA_TYPE_DATES * VALUES_DATA_TYPE_NUMERIC * VALUES_DATA_TYPE_SEQUENCE @@ -223,7 +231,7 @@ public final class SeriesRecord extends StandardRecord { /** * Get the bubble series type field for the Series record. * - * @return One of + * @return One of * BUBBLE_SERIES_TYPE_DATES * BUBBLE_SERIES_TYPE_NUMERIC * BUBBLE_SERIES_TYPE_SEQUENCE @@ -238,7 +246,7 @@ public final class SeriesRecord extends StandardRecord { * Set the bubble series type field for the Series record. * * @param field_5_bubbleSeriesType - * One of + * One of * BUBBLE_SERIES_TYPE_DATES * BUBBLE_SERIES_TYPE_NUMERIC * BUBBLE_SERIES_TYPE_SEQUENCE diff --git a/src/java/org/apache/poi/hssf/record/chart/SeriesTextRecord.java b/src/java/org/apache/poi/hssf/record/chart/SeriesTextRecord.java index f6b0de4f29..bf7f92af08 100644 --- a/src/java/org/apache/poi/hssf/record/chart/SeriesTextRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/SeriesTextRecord.java @@ -21,17 +21,21 @@ import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; import org.apache.poi.util.StringUtil; /** - * SERIESTEXT (0x100D)<p> + * SERIESTEXT (0x100D)<p> * Defines a series name */ public final class SeriesTextRecord extends StandardRecord { - public final static short sid = 0x100D; + public static final short sid = 0x100D; - /** the actual text cannot be longer than 255 characters */ + /** + * the actual text cannot be longer than 255 characters + */ private static final int MAX_LEN = 0xFF; + private int field_1_id; private boolean is16bit; private String field_4_text; @@ -41,6 +45,13 @@ public final class SeriesTextRecord extends StandardRecord { is16bit = false; } + public SeriesTextRecord(SeriesTextRecord other) { + super(other); + field_1_id = other.field_1_id; + is16bit = other.is16bit; + field_4_text = other.field_4_text; + } + public SeriesTextRecord(RecordInputStream in) { field_1_id = in.readUShort(); int field_2_textLength = in.readUByte(); @@ -87,13 +98,17 @@ public final class SeriesTextRecord extends StandardRecord { return sid; } - public Object clone() { - SeriesTextRecord rec = new SeriesTextRecord(); + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public SeriesTextRecord clone() { + return copy(); + } - rec.field_1_id = field_1_id; - rec.is16bit = is16bit; - rec.field_4_text = field_4_text; - return rec; + @Override + public SeriesTextRecord copy() { + return new SeriesTextRecord(this); } /** diff --git a/src/java/org/apache/poi/hssf/record/chart/SeriesToChartGroupRecord.java b/src/java/org/apache/poi/hssf/record/chart/SeriesToChartGroupRecord.java index 17e6134bcf..62f8fca5ae 100644 --- a/src/java/org/apache/poi/hssf/record/chart/SeriesToChartGroupRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/SeriesToChartGroupRecord.java @@ -21,25 +21,26 @@ import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** - * Indicates the chart-group index for a series. The order probably defines the mapping. - * So the 0th record probably means the 0th series. The only field in this of course defines which chart + * Indicates the chart-group index for a series. The order probably defines the mapping. + * So the 0th record probably means the 0th series. The only field in this of course defines which chart * group the 0th series (for instance) would map to. Confusing? Well thats because it is. (p 522 BCG) */ public final class SeriesToChartGroupRecord extends StandardRecord { - public final static short sid = 0x1045; - private short field_1_chartGroupIndex; + public static final short sid = 0x1045; + private short field_1_chartGroupIndex; + public SeriesToChartGroupRecord() {} - public SeriesToChartGroupRecord() - { - + public SeriesToChartGroupRecord(SeriesToChartGroupRecord other) { + super(other); + field_1_chartGroupIndex = other.field_1_chartGroupIndex; } - public SeriesToChartGroupRecord(RecordInputStream in) - { - field_1_chartGroupIndex = in.readShort(); + public SeriesToChartGroupRecord(RecordInputStream in) { + field_1_chartGroupIndex = in.readShort(); } public String toString() @@ -50,7 +51,7 @@ public final class SeriesToChartGroupRecord extends StandardRecord { buffer.append(" .chartGroupIndex = ") .append("0x").append(HexDump.toHex( getChartGroupIndex ())) .append(" (").append( getChartGroupIndex() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append("[/SeriesToChartGroup]\n"); return buffer.toString(); @@ -69,15 +70,18 @@ public final class SeriesToChartGroupRecord extends StandardRecord { return sid; } - public Object clone() { - SeriesToChartGroupRecord rec = new SeriesToChartGroupRecord(); - - rec.field_1_chartGroupIndex = field_1_chartGroupIndex; - return rec; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public SeriesToChartGroupRecord clone() { + return copy(); } - - + @Override + public SeriesToChartGroupRecord copy() { + return new SeriesToChartGroupRecord(this); + } /** * Get the chart group index field for the SeriesToChartGroup record. diff --git a/src/java/org/apache/poi/hssf/record/chart/SheetPropertiesRecord.java b/src/java/org/apache/poi/hssf/record/chart/SheetPropertiesRecord.java index cc79df93d7..ab29b181a5 100644 --- a/src/java/org/apache/poi/hssf/record/chart/SheetPropertiesRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/SheetPropertiesRecord.java @@ -23,31 +23,36 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * Describes a chart sheet properties record. SHTPROPS (0x1044)<p> - * + * * (As with all chart related records, documentation is lacking. * See {@link ChartRecord} for more details) */ public final class SheetPropertiesRecord extends StandardRecord { - public final static short sid = 0x1044; - + public static final short sid = 0x1044; + + public static final byte EMPTY_NOT_PLOTTED = 0; + public static final byte EMPTY_ZERO = 1; + public static final byte EMPTY_INTERPOLATED = 2; + private static final BitField chartTypeManuallyFormatted = BitFieldFactory.getInstance(0x01); private static final BitField plotVisibleOnly = BitFieldFactory.getInstance(0x02); private static final BitField doNotSizeWithWindow = BitFieldFactory.getInstance(0x04); private static final BitField defaultPlotDimensions = BitFieldFactory.getInstance(0x08); private static final BitField autoPlotArea = BitFieldFactory.getInstance(0x10); - + private int field_1_flags; private int field_2_empty; - public final static byte EMPTY_NOT_PLOTTED = 0; - public final static byte EMPTY_ZERO = 1; - public final static byte EMPTY_INTERPOLATED = 2; + public SheetPropertiesRecord() {} - public SheetPropertiesRecord() { - // fields uninitialised + public SheetPropertiesRecord(SheetPropertiesRecord other) { + super(other); + field_1_flags = other.field_1_flags; + field_2_empty = other.field_2_empty; } public SheetPropertiesRecord(RecordInputStream in) { @@ -60,12 +65,12 @@ public final class SheetPropertiesRecord extends StandardRecord { buffer.append("[SHTPROPS]\n"); buffer.append(" .flags = ").append(HexDump.shortToHex(field_1_flags)).append('\n'); - buffer.append(" .chartTypeManuallyFormatted= ").append(isChartTypeManuallyFormatted()).append('\n'); - buffer.append(" .plotVisibleOnly = ").append(isPlotVisibleOnly()).append('\n'); - buffer.append(" .doNotSizeWithWindow = ").append(isDoNotSizeWithWindow()).append('\n'); - buffer.append(" .defaultPlotDimensions = ").append(isDefaultPlotDimensions()).append('\n'); - buffer.append(" .autoPlotArea = ").append(isAutoPlotArea()).append('\n'); - buffer.append(" .empty = ").append(HexDump.shortToHex(field_2_empty)).append('\n'); + buffer.append(" .chartTypeManuallyFormatted= ").append(isChartTypeManuallyFormatted()).append('\n'); + buffer.append(" .plotVisibleOnly = ").append(isPlotVisibleOnly()).append('\n'); + buffer.append(" .doNotSizeWithWindow = ").append(isDoNotSizeWithWindow()).append('\n'); + buffer.append(" .defaultPlotDimensions = ").append(isDefaultPlotDimensions()).append('\n'); + buffer.append(" .autoPlotArea = ").append(isAutoPlotArea()).append('\n'); + buffer.append(" .empty = ").append(HexDump.shortToHex(field_2_empty)).append('\n'); buffer.append("[/SHTPROPS]\n"); return buffer.toString(); @@ -84,12 +89,17 @@ public final class SheetPropertiesRecord extends StandardRecord { return sid; } - public Object clone() { - SheetPropertiesRecord rec = new SheetPropertiesRecord(); - - rec.field_1_flags = field_1_flags; - rec.field_2_empty = field_2_empty; - return rec; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public SheetPropertiesRecord clone() { + return copy(); + } + + @Override + public SheetPropertiesRecord copy() { + return new SheetPropertiesRecord(this); } /** @@ -102,7 +112,7 @@ public final class SheetPropertiesRecord extends StandardRecord { /** * Get the empty field for the SheetProperties record. * - * @return One of + * @return One of * EMPTY_NOT_PLOTTED * EMPTY_ZERO * EMPTY_INTERPOLATED @@ -115,7 +125,7 @@ public final class SheetPropertiesRecord extends StandardRecord { * Set the empty field for the SheetProperties record. * * @param empty - * One of + * One of * EMPTY_NOT_PLOTTED * EMPTY_ZERO * EMPTY_INTERPOLATED diff --git a/src/java/org/apache/poi/hssf/record/chart/TextRecord.java b/src/java/org/apache/poi/hssf/record/chart/TextRecord.java index ce447694cb..f41673310f 100644 --- a/src/java/org/apache/poi/hssf/record/chart/TextRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/TextRecord.java @@ -23,13 +23,14 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * The text record is used to define text stored on a chart. */ public final class TextRecord extends StandardRecord { - public final static short sid = 0x1025; - + public static final short sid = 0x1025; + private static final BitField dataLabelPlacement = BitFieldFactory.getInstance(0x000F); private static final BitField autoColor = BitFieldFactory.getInstance(0x0001); private static final BitField showKey = BitFieldFactory.getInstance(0x0002); @@ -45,66 +46,82 @@ public final class TextRecord extends StandardRecord { private static final BitField showValueAsPercentage = BitFieldFactory.getInstance(0x1000); private static final BitField showBubbleSizes = BitFieldFactory.getInstance(0x2000); private static final BitField showLabel = BitFieldFactory.getInstance(0x4000); - - - private byte field_1_horizontalAlignment; - public final static byte HORIZONTAL_ALIGNMENT_LEFT = 1; - public final static byte HORIZONTAL_ALIGNMENT_CENTER = 2; - public final static byte HORIZONTAL_ALIGNMENT_BOTTOM = 3; - public final static byte HORIZONTAL_ALIGNMENT_JUSTIFY = 4; - private byte field_2_verticalAlignment; - public final static byte VERTICAL_ALIGNMENT_TOP = 1; - public final static byte VERTICAL_ALIGNMENT_CENTER = 2; - public final static byte VERTICAL_ALIGNMENT_BOTTOM = 3; - public final static byte VERTICAL_ALIGNMENT_JUSTIFY = 4; - private short field_3_displayMode; - public final static short DISPLAY_MODE_TRANSPARENT = 1; - public final static short DISPLAY_MODE_OPAQUE = 2; - private int field_4_rgbColor; - private int field_5_x; - private int field_6_y; - private int field_7_width; - private int field_8_height; - private short field_9_options1; - public final static short ROTATION_NONE = 0; - public final static short ROTATION_TOP_TO_BOTTOM = 1; - public final static short ROTATION_ROTATED_90_DEGREES = 2; - public final static short ROTATION_ROTATED_90_DEGREES_CLOCKWISE = 3; - private short field_10_indexOfColorValue; - private short field_11_options2; - public final static short DATA_LABEL_PLACEMENT_CHART_DEPENDENT = 0; - public final static short DATA_LABEL_PLACEMENT_OUTSIDE = 1; - public final static short DATA_LABEL_PLACEMENT_INSIDE = 2; - public final static short DATA_LABEL_PLACEMENT_CENTER = 3; - public final static short DATA_LABEL_PLACEMENT_AXIS = 4; - public final static short DATA_LABEL_PLACEMENT_ABOVE = 5; - public final static short DATA_LABEL_PLACEMENT_BELOW = 6; - public final static short DATA_LABEL_PLACEMENT_LEFT = 7; - public final static short DATA_LABEL_PLACEMENT_RIGHT = 8; - public final static short DATA_LABEL_PLACEMENT_AUTO = 9; - public final static short DATA_LABEL_PLACEMENT_USER_MOVED = 10; - private short field_12_textRotation; - - - public TextRecord() - { - - } - - public TextRecord(RecordInputStream in) - { - field_1_horizontalAlignment = in.readByte(); - field_2_verticalAlignment = in.readByte(); - field_3_displayMode = in.readShort(); - field_4_rgbColor = in.readInt(); - field_5_x = in.readInt(); - field_6_y = in.readInt(); - field_7_width = in.readInt(); - field_8_height = in.readInt(); - field_9_options1 = in.readShort(); - field_10_indexOfColorValue = in.readShort(); - field_11_options2 = in.readShort(); - field_12_textRotation = in.readShort(); + + + public static final byte HORIZONTAL_ALIGNMENT_LEFT = 1; + public static final byte HORIZONTAL_ALIGNMENT_CENTER = 2; + public static final byte HORIZONTAL_ALIGNMENT_BOTTOM = 3; + public static final byte HORIZONTAL_ALIGNMENT_JUSTIFY = 4; + + public static final byte VERTICAL_ALIGNMENT_TOP = 1; + public static final byte VERTICAL_ALIGNMENT_CENTER = 2; + public static final byte VERTICAL_ALIGNMENT_BOTTOM = 3; + public static final byte VERTICAL_ALIGNMENT_JUSTIFY = 4; + + public static final short DISPLAY_MODE_TRANSPARENT = 1; + public static final short DISPLAY_MODE_OPAQUE = 2; + + public static final short ROTATION_NONE = 0; + public static final short ROTATION_TOP_TO_BOTTOM = 1; + public static final short ROTATION_ROTATED_90_DEGREES = 2; + public static final short ROTATION_ROTATED_90_DEGREES_CLOCKWISE = 3; + + public static final short DATA_LABEL_PLACEMENT_CHART_DEPENDENT = 0; + public static final short DATA_LABEL_PLACEMENT_OUTSIDE = 1; + public static final short DATA_LABEL_PLACEMENT_INSIDE = 2; + public static final short DATA_LABEL_PLACEMENT_CENTER = 3; + public static final short DATA_LABEL_PLACEMENT_AXIS = 4; + public static final short DATA_LABEL_PLACEMENT_ABOVE = 5; + public static final short DATA_LABEL_PLACEMENT_BELOW = 6; + public static final short DATA_LABEL_PLACEMENT_LEFT = 7; + public static final short DATA_LABEL_PLACEMENT_RIGHT = 8; + public static final short DATA_LABEL_PLACEMENT_AUTO = 9; + public static final short DATA_LABEL_PLACEMENT_USER_MOVED = 10; + + private byte field_1_horizontalAlignment; + private byte field_2_verticalAlignment; + private short field_3_displayMode; + private int field_4_rgbColor; + private int field_5_x; + private int field_6_y; + private int field_7_width; + private int field_8_height; + private short field_9_options1; + private short field_10_indexOfColorValue; + private short field_11_options2; + private short field_12_textRotation; + + public TextRecord() {} + + public TextRecord(TextRecord other) { + super(other); + field_1_horizontalAlignment = other.field_1_horizontalAlignment; + field_2_verticalAlignment = other.field_2_verticalAlignment; + field_3_displayMode = other.field_3_displayMode; + field_4_rgbColor = other.field_4_rgbColor; + field_5_x = other.field_5_x; + field_6_y = other.field_6_y; + field_7_width = other.field_7_width; + field_8_height = other.field_8_height; + field_9_options1 = other.field_9_options1; + field_10_indexOfColorValue = other.field_10_indexOfColorValue; + field_11_options2 = other.field_11_options2; + field_12_textRotation = other.field_12_textRotation; + } + + public TextRecord(RecordInputStream in) { + field_1_horizontalAlignment = in.readByte(); + field_2_verticalAlignment = in.readByte(); + field_3_displayMode = in.readShort(); + field_4_rgbColor = in.readInt(); + field_5_x = in.readInt(); + field_6_y = in.readInt(); + field_7_width = in.readInt(); + field_8_height = in.readInt(); + field_9_options1 = in.readShort(); + field_10_indexOfColorValue = in.readShort(); + field_11_options2 = in.readShort(); + field_12_textRotation = in.readShort(); } public String toString() @@ -115,65 +132,65 @@ public final class TextRecord extends StandardRecord { buffer.append(" .horizontalAlignment = ") .append("0x").append(HexDump.toHex( getHorizontalAlignment ())) .append(" (").append( getHorizontalAlignment() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .verticalAlignment = ") .append("0x").append(HexDump.toHex( getVerticalAlignment ())) .append(" (").append( getVerticalAlignment() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .displayMode = ") .append("0x").append(HexDump.toHex( getDisplayMode ())) .append(" (").append( getDisplayMode() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .rgbColor = ") .append("0x").append(HexDump.toHex( getRgbColor ())) .append(" (").append( getRgbColor() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .x = ") .append("0x").append(HexDump.toHex( getX ())) .append(" (").append( getX() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .y = ") .append("0x").append(HexDump.toHex( getY ())) .append(" (").append( getY() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .width = ") .append("0x").append(HexDump.toHex( getWidth ())) .append(" (").append( getWidth() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .height = ") .append("0x").append(HexDump.toHex( getHeight ())) .append(" (").append( getHeight() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .options1 = ") .append("0x").append(HexDump.toHex( getOptions1 ())) .append(" (").append( getOptions1() ).append(" )"); - buffer.append(System.getProperty("line.separator")); - buffer.append(" .autoColor = ").append(isAutoColor()).append('\n'); - buffer.append(" .showKey = ").append(isShowKey()).append('\n'); - buffer.append(" .showValue = ").append(isShowValue()).append('\n'); - buffer.append(" .vertical = ").append(isVertical()).append('\n'); - buffer.append(" .autoGeneratedText = ").append(isAutoGeneratedText()).append('\n'); - buffer.append(" .generated = ").append(isGenerated()).append('\n'); - buffer.append(" .autoLabelDeleted = ").append(isAutoLabelDeleted()).append('\n'); - buffer.append(" .autoBackground = ").append(isAutoBackground()).append('\n'); - buffer.append(" .rotation = ").append(getRotation()).append('\n'); - buffer.append(" .showCategoryLabelAsPercentage = ").append(isShowCategoryLabelAsPercentage()).append('\n'); - buffer.append(" .showValueAsPercentage = ").append(isShowValueAsPercentage()).append('\n'); - buffer.append(" .showBubbleSizes = ").append(isShowBubbleSizes()).append('\n'); - buffer.append(" .showLabel = ").append(isShowLabel()).append('\n'); + buffer.append(System.getProperty("line.separator")); + buffer.append(" .autoColor = ").append(isAutoColor()).append('\n'); + buffer.append(" .showKey = ").append(isShowKey()).append('\n'); + buffer.append(" .showValue = ").append(isShowValue()).append('\n'); + buffer.append(" .vertical = ").append(isVertical()).append('\n'); + buffer.append(" .autoGeneratedText = ").append(isAutoGeneratedText()).append('\n'); + buffer.append(" .generated = ").append(isGenerated()).append('\n'); + buffer.append(" .autoLabelDeleted = ").append(isAutoLabelDeleted()).append('\n'); + buffer.append(" .autoBackground = ").append(isAutoBackground()).append('\n'); + buffer.append(" .rotation = ").append(getRotation()).append('\n'); + buffer.append(" .showCategoryLabelAsPercentage = ").append(isShowCategoryLabelAsPercentage()).append('\n'); + buffer.append(" .showValueAsPercentage = ").append(isShowValueAsPercentage()).append('\n'); + buffer.append(" .showBubbleSizes = ").append(isShowBubbleSizes()).append('\n'); + buffer.append(" .showLabel = ").append(isShowLabel()).append('\n'); buffer.append(" .indexOfColorValue = ") .append("0x").append(HexDump.toHex( getIndexOfColorValue ())) .append(" (").append( getIndexOfColorValue() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .options2 = ") .append("0x").append(HexDump.toHex( getOptions2 ())) .append(" (").append( getOptions2() ).append(" )"); - buffer.append(System.getProperty("line.separator")); - buffer.append(" .dataLabelPlacement = ").append(getDataLabelPlacement()).append('\n'); + buffer.append(System.getProperty("line.separator")); + buffer.append(" .dataLabelPlacement = ").append(getDataLabelPlacement()).append('\n'); buffer.append(" .textRotation = ") .append("0x").append(HexDump.toHex( getTextRotation ())) .append(" (").append( getTextRotation() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append("[/TEXT]\n"); return buffer.toString(); @@ -203,31 +220,23 @@ public final class TextRecord extends StandardRecord { return sid; } - public Object clone() { - TextRecord rec = new TextRecord(); - - rec.field_1_horizontalAlignment = field_1_horizontalAlignment; - rec.field_2_verticalAlignment = field_2_verticalAlignment; - rec.field_3_displayMode = field_3_displayMode; - rec.field_4_rgbColor = field_4_rgbColor; - rec.field_5_x = field_5_x; - rec.field_6_y = field_6_y; - rec.field_7_width = field_7_width; - rec.field_8_height = field_8_height; - rec.field_9_options1 = field_9_options1; - rec.field_10_indexOfColorValue = field_10_indexOfColorValue; - rec.field_11_options2 = field_11_options2; - rec.field_12_textRotation = field_12_textRotation; - return rec; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public TextRecord clone() { + return copy(); } - - + @Override + public TextRecord copy() { + return new TextRecord(this); + } /** * Get the horizontal alignment field for the Text record. * - * @return One of + * @return One of * HORIZONTAL_ALIGNMENT_LEFT * HORIZONTAL_ALIGNMENT_CENTER * HORIZONTAL_ALIGNMENT_BOTTOM @@ -242,7 +251,7 @@ public final class TextRecord extends StandardRecord { * Set the horizontal alignment field for the Text record. * * @param field_1_horizontalAlignment - * One of + * One of * HORIZONTAL_ALIGNMENT_LEFT * HORIZONTAL_ALIGNMENT_CENTER * HORIZONTAL_ALIGNMENT_BOTTOM @@ -256,7 +265,7 @@ public final class TextRecord extends StandardRecord { /** * Get the vertical alignment field for the Text record. * - * @return One of + * @return One of * VERTICAL_ALIGNMENT_TOP * VERTICAL_ALIGNMENT_CENTER * VERTICAL_ALIGNMENT_BOTTOM @@ -271,7 +280,7 @@ public final class TextRecord extends StandardRecord { * Set the vertical alignment field for the Text record. * * @param field_2_verticalAlignment - * One of + * One of * VERTICAL_ALIGNMENT_TOP * VERTICAL_ALIGNMENT_CENTER * VERTICAL_ALIGNMENT_BOTTOM @@ -285,7 +294,7 @@ public final class TextRecord extends StandardRecord { /** * Get the display mode field for the Text record. * - * @return One of + * @return One of * DISPLAY_MODE_TRANSPARENT * DISPLAY_MODE_OPAQUE */ @@ -298,7 +307,7 @@ public final class TextRecord extends StandardRecord { * Set the display mode field for the Text record. * * @param field_3_displayMode - * One of + * One of * DISPLAY_MODE_TRANSPARENT * DISPLAY_MODE_OPAQUE */ @@ -525,7 +534,7 @@ public final class TextRecord extends StandardRecord { /** * Sets the auto generated text field value. - * + * */ public void setAutoGeneratedText(boolean value) { @@ -533,7 +542,7 @@ public final class TextRecord extends StandardRecord { } /** - * + * * @return the auto generated text field value. */ public boolean isAutoGeneratedText() @@ -543,7 +552,7 @@ public final class TextRecord extends StandardRecord { /** * Sets the generated field value. - * + * */ public void setGenerated(boolean value) { @@ -551,7 +560,7 @@ public final class TextRecord extends StandardRecord { } /** - * + * * @return the generated field value. */ public boolean isGenerated() @@ -561,7 +570,7 @@ public final class TextRecord extends StandardRecord { /** * Sets the auto label deleted field value. - * + * */ public void setAutoLabelDeleted(boolean value) { @@ -569,7 +578,7 @@ public final class TextRecord extends StandardRecord { } /** - * + * * @return the auto label deleted field value. */ public boolean isAutoLabelDeleted() @@ -579,7 +588,7 @@ public final class TextRecord extends StandardRecord { /** * Sets the auto background field value. - * + * */ public void setAutoBackground(boolean value) { @@ -587,7 +596,7 @@ public final class TextRecord extends StandardRecord { } /** - * + * * @return the auto background field value. */ public boolean isAutoBackground() @@ -597,7 +606,7 @@ public final class TextRecord extends StandardRecord { /** * Sets the rotation field value. - * + * */ public void setRotation(short value) { @@ -605,7 +614,7 @@ public final class TextRecord extends StandardRecord { } /** - * + * * @return the rotation field value. */ public short getRotation() @@ -615,7 +624,7 @@ public final class TextRecord extends StandardRecord { /** * Sets the show category label as percentage field value. - * + * */ public void setShowCategoryLabelAsPercentage(boolean value) { @@ -623,7 +632,7 @@ public final class TextRecord extends StandardRecord { } /** - * + * * @return the show category label as percentage field value. */ public boolean isShowCategoryLabelAsPercentage() @@ -633,7 +642,7 @@ public final class TextRecord extends StandardRecord { /** * Sets the show value as percentage field value. - * + * */ public void setShowValueAsPercentage(boolean value) { @@ -641,7 +650,7 @@ public final class TextRecord extends StandardRecord { } /** - * + * * @return the show value as percentage field value. */ public boolean isShowValueAsPercentage() @@ -651,7 +660,7 @@ public final class TextRecord extends StandardRecord { /** * Sets the show bubble sizes field value. - * + * */ public void setShowBubbleSizes(boolean value) { @@ -659,7 +668,7 @@ public final class TextRecord extends StandardRecord { } /** - * + * * @return the show bubble sizes field value. */ public boolean isShowBubbleSizes() @@ -669,7 +678,7 @@ public final class TextRecord extends StandardRecord { /** * Sets the show label field value. - * + * */ public void setShowLabel(boolean value) { @@ -677,7 +686,7 @@ public final class TextRecord extends StandardRecord { } /** - * + * * @return the show label field value. */ public boolean isShowLabel() @@ -687,7 +696,7 @@ public final class TextRecord extends StandardRecord { /** * Sets the data label placement field value. - * + * */ public void setDataLabelPlacement(short value) { @@ -695,7 +704,7 @@ public final class TextRecord extends StandardRecord { } /** - * + * * @return the data label placement field value. */ public short getDataLabelPlacement() diff --git a/src/java/org/apache/poi/hssf/record/chart/TickRecord.java b/src/java/org/apache/poi/hssf/record/chart/TickRecord.java index 9080a22e24..7b5b7763a8 100644 --- a/src/java/org/apache/poi/hssf/record/chart/TickRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/TickRecord.java @@ -23,55 +23,65 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * The Tick record defines how tick marks and label positioning/formatting<p> - * - * @author Andrew C. Oliver(acoliver at apache.org) */ public final class TickRecord extends StandardRecord { - public final static short sid = 0x101E; - + public static final short sid = 0x101E; + private static final BitField autoTextColor = BitFieldFactory.getInstance(0x1); private static final BitField autoTextBackground = BitFieldFactory.getInstance(0x2); private static final BitField rotation = BitFieldFactory.getInstance(0x1c); private static final BitField autorotate = BitFieldFactory.getInstance(0x20); - - private byte field_1_majorTickType; - private byte field_2_minorTickType; - private byte field_3_labelPosition; - private byte field_4_background; - private int field_5_labelColorRgb; - private int field_6_zero1; - private int field_7_zero2; - private int field_8_zero3; - private int field_9_zero4; - private short field_10_options; - private short field_11_tickColor; - private short field_12_zero5; - - - public TickRecord() - { - } - - public TickRecord(RecordInputStream in) - { - - field_1_majorTickType = in.readByte(); - field_2_minorTickType = in.readByte(); - field_3_labelPosition = in.readByte(); - field_4_background = in.readByte(); - field_5_labelColorRgb = in.readInt(); - field_6_zero1 = in.readInt(); - field_7_zero2 = in.readInt(); - field_8_zero3 = in.readInt(); - field_9_zero4 = in.readInt(); - - field_10_options = in.readShort(); - field_11_tickColor = in.readShort(); - field_12_zero5 = in.readShort(); + private byte field_1_majorTickType; + private byte field_2_minorTickType; + private byte field_3_labelPosition; + private byte field_4_background; + private int field_5_labelColorRgb; + private int field_6_zero1; + private int field_7_zero2; + private int field_8_zero3; + private int field_9_zero4; + private short field_10_options; + private short field_11_tickColor; + private short field_12_zero5; + + + public TickRecord() {} + + public TickRecord(TickRecord other) { + super(other); + field_1_majorTickType = other.field_1_majorTickType; + field_2_minorTickType = other.field_2_minorTickType; + field_3_labelPosition = other.field_3_labelPosition; + field_4_background = other.field_4_background; + field_5_labelColorRgb = other.field_5_labelColorRgb; + field_6_zero1 = other.field_6_zero1; + field_7_zero2 = other.field_7_zero2; + field_8_zero3 = other.field_8_zero3; + field_9_zero4 = other.field_9_zero4; + field_10_options = other.field_10_options; + field_11_tickColor = other.field_11_tickColor; + field_12_zero5 = other.field_12_zero5; + } + + public TickRecord(RecordInputStream in) { + field_1_majorTickType = in.readByte(); + field_2_minorTickType = in.readByte(); + field_3_labelPosition = in.readByte(); + field_4_background = in.readByte(); + field_5_labelColorRgb = in.readInt(); + field_6_zero1 = in.readInt(); + field_7_zero2 = in.readInt(); + field_8_zero3 = in.readInt(); + field_9_zero4 = in.readInt(); + + field_10_options = in.readShort(); + field_11_tickColor = in.readShort(); + field_12_zero5 = in.readShort(); } public String toString() @@ -82,47 +92,47 @@ public final class TickRecord extends StandardRecord { buffer.append(" .majorTickType = ") .append("0x").append(HexDump.toHex( getMajorTickType ())) .append(" (").append( getMajorTickType() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .minorTickType = ") .append("0x").append(HexDump.toHex( getMinorTickType ())) .append(" (").append( getMinorTickType() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .labelPosition = ") .append("0x").append(HexDump.toHex( getLabelPosition ())) .append(" (").append( getLabelPosition() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .background = ") .append("0x").append(HexDump.toHex( getBackground ())) .append(" (").append( getBackground() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .labelColorRgb = ") .append("0x").append(HexDump.toHex( getLabelColorRgb ())) .append(" (").append( getLabelColorRgb() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .zero1 = ") .append("0x").append(HexDump.toHex( getZero1 ())) .append(" (").append( getZero1() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .zero2 = ") .append("0x").append(HexDump.toHex( getZero2 ())) .append(" (").append( getZero2() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .options = ") .append("0x").append(HexDump.toHex( getOptions ())) .append(" (").append( getOptions() ).append(" )"); - buffer.append(System.getProperty("line.separator")); - buffer.append(" .autoTextColor = ").append(isAutoTextColor()).append('\n'); - buffer.append(" .autoTextBackground = ").append(isAutoTextBackground()).append('\n'); - buffer.append(" .rotation = ").append(getRotation()).append('\n'); - buffer.append(" .autorotate = ").append(isAutorotate()).append('\n'); + buffer.append(System.getProperty("line.separator")); + buffer.append(" .autoTextColor = ").append(isAutoTextColor()).append('\n'); + buffer.append(" .autoTextBackground = ").append(isAutoTextBackground()).append('\n'); + buffer.append(" .rotation = ").append(getRotation()).append('\n'); + buffer.append(" .autorotate = ").append(isAutorotate()).append('\n'); buffer.append(" .tickColor = ") .append("0x").append(HexDump.toHex( getTickColor ())) .append(" (").append( getTickColor() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .zero3 = ") .append("0x").append(HexDump.toHex( getZero3 ())) .append(" (").append( getZero3() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append("[/TICK]\n"); return buffer.toString(); @@ -152,26 +162,18 @@ public final class TickRecord extends StandardRecord { return sid; } - public Object clone() { - TickRecord rec = new TickRecord(); - - rec.field_1_majorTickType = field_1_majorTickType; - rec.field_2_minorTickType = field_2_minorTickType; - rec.field_3_labelPosition = field_3_labelPosition; - rec.field_4_background = field_4_background; - rec.field_5_labelColorRgb = field_5_labelColorRgb; - rec.field_6_zero1 = field_6_zero1; - rec.field_7_zero2 = field_7_zero2; - rec.field_8_zero3 = field_8_zero3; - rec.field_9_zero4 = field_9_zero4; - rec.field_10_options = field_10_options; - rec.field_11_tickColor = field_11_tickColor; - rec.field_12_zero5 = field_12_zero5; - return rec; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public TickRecord clone() { + return copy(); } - - + @Override + public TickRecord copy() { + return new TickRecord(this); + } /** * Get the major tick type field for the Tick record. diff --git a/src/java/org/apache/poi/hssf/record/chart/UnitsRecord.java b/src/java/org/apache/poi/hssf/record/chart/UnitsRecord.java index c1823554f0..a9dd25519a 100644 --- a/src/java/org/apache/poi/hssf/record/chart/UnitsRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/UnitsRecord.java @@ -21,24 +21,25 @@ import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * The units record describes units. */ public final class UnitsRecord extends StandardRecord { - public final static short sid = 0x1001; - private short field_1_units; + public static final short sid = 0x1001; + private short field_1_units; - public UnitsRecord() - { + public UnitsRecord() {} + public UnitsRecord(UnitsRecord other) { + super(other); + field_1_units = other.field_1_units; } - public UnitsRecord(RecordInputStream in) - { - field_1_units = in.readShort(); - + public UnitsRecord(RecordInputStream in) { + field_1_units = in.readShort(); } public String toString() @@ -49,7 +50,7 @@ public final class UnitsRecord extends StandardRecord { buffer.append(" .units = ") .append("0x").append(HexDump.toHex( getUnits ())) .append(" (").append( getUnits() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append("[/UNITS]\n"); return buffer.toString(); @@ -68,15 +69,18 @@ public final class UnitsRecord extends StandardRecord { return sid; } - public Object clone() { - UnitsRecord rec = new UnitsRecord(); - - rec.field_1_units = field_1_units; - return rec; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public UnitsRecord clone() { + return copy(); } - - + @Override + public UnitsRecord copy() { + return new UnitsRecord(this); + } /** * Get the units field for the Units record. diff --git a/src/java/org/apache/poi/hssf/record/chart/ValueRangeRecord.java b/src/java/org/apache/poi/hssf/record/chart/ValueRangeRecord.java index 73d810ea54..a710786960 100644 --- a/src/java/org/apache/poi/hssf/record/chart/ValueRangeRecord.java +++ b/src/java/org/apache/poi/hssf/record/chart/ValueRangeRecord.java @@ -23,13 +23,14 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * The value range record defines the range of the value axis. */ public final class ValueRangeRecord extends StandardRecord { - public final static short sid = 0x101f; - + public static final short sid = 0x101f; + private static final BitField automaticMinimum = BitFieldFactory.getInstance(0x0001); private static final BitField automaticMaximum = BitFieldFactory.getInstance(0x0002); private static final BitField automaticMajor = BitFieldFactory.getInstance(0x0004); @@ -39,29 +40,33 @@ public final class ValueRangeRecord extends StandardRecord { private static final BitField valuesInReverse = BitFieldFactory.getInstance(0x0040); private static final BitField crossCategoryAxisAtMaximum = BitFieldFactory.getInstance(0x0080); private static final BitField reserved = BitFieldFactory.getInstance(0x0100); - - private double field_1_minimumAxisValue; - private double field_2_maximumAxisValue; - private double field_3_majorIncrement; - private double field_4_minorIncrement; - private double field_5_categoryAxisCross; - private short field_6_options; + private double field_1_minimumAxisValue; + private double field_2_maximumAxisValue; + private double field_3_majorIncrement; + private double field_4_minorIncrement; + private double field_5_categoryAxisCross; + private short field_6_options; - public ValueRangeRecord() - { + public ValueRangeRecord() {} + public ValueRangeRecord(ValueRangeRecord other) { + super(other); + field_1_minimumAxisValue = other.field_1_minimumAxisValue; + field_2_maximumAxisValue = other.field_2_maximumAxisValue; + field_3_majorIncrement = other.field_3_majorIncrement; + field_4_minorIncrement = other.field_4_minorIncrement; + field_5_categoryAxisCross = other.field_5_categoryAxisCross; + field_6_options = other.field_6_options; } - public ValueRangeRecord(RecordInputStream in) - { - field_1_minimumAxisValue = in.readDouble(); - field_2_maximumAxisValue = in.readDouble(); - field_3_majorIncrement = in.readDouble(); - field_4_minorIncrement = in.readDouble(); - field_5_categoryAxisCross = in.readDouble(); - field_6_options = in.readShort(); - + public ValueRangeRecord(RecordInputStream in) { + field_1_minimumAxisValue = in.readDouble(); + field_2_maximumAxisValue = in.readDouble(); + field_3_majorIncrement = in.readDouble(); + field_4_minorIncrement = in.readDouble(); + field_5_categoryAxisCross = in.readDouble(); + field_6_options = in.readShort(); } public String toString() @@ -71,32 +76,32 @@ public final class ValueRangeRecord extends StandardRecord { buffer.append("[VALUERANGE]\n"); buffer.append(" .minimumAxisValue = ") .append(" (").append( getMinimumAxisValue() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .maximumAxisValue = ") .append(" (").append( getMaximumAxisValue() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .majorIncrement = ") .append(" (").append( getMajorIncrement() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .minorIncrement = ") .append(" (").append( getMinorIncrement() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .categoryAxisCross = ") .append(" (").append( getCategoryAxisCross() ).append(" )"); - buffer.append(System.getProperty("line.separator")); + buffer.append(System.getProperty("line.separator")); buffer.append(" .options = ") .append("0x").append(HexDump.toHex( getOptions ())) .append(" (").append( getOptions() ).append(" )"); - buffer.append(System.getProperty("line.separator")); - buffer.append(" .automaticMinimum = ").append(isAutomaticMinimum()).append('\n'); - buffer.append(" .automaticMaximum = ").append(isAutomaticMaximum()).append('\n'); - buffer.append(" .automaticMajor = ").append(isAutomaticMajor()).append('\n'); - buffer.append(" .automaticMinor = ").append(isAutomaticMinor()).append('\n'); - buffer.append(" .automaticCategoryCrossing = ").append(isAutomaticCategoryCrossing()).append('\n'); - buffer.append(" .logarithmicScale = ").append(isLogarithmicScale()).append('\n'); - buffer.append(" .valuesInReverse = ").append(isValuesInReverse()).append('\n'); - buffer.append(" .crossCategoryAxisAtMaximum = ").append(isCrossCategoryAxisAtMaximum()).append('\n'); - buffer.append(" .reserved = ").append(isReserved()).append('\n'); + buffer.append(System.getProperty("line.separator")); + buffer.append(" .automaticMinimum = ").append(isAutomaticMinimum()).append('\n'); + buffer.append(" .automaticMaximum = ").append(isAutomaticMaximum()).append('\n'); + buffer.append(" .automaticMajor = ").append(isAutomaticMajor()).append('\n'); + buffer.append(" .automaticMinor = ").append(isAutomaticMinor()).append('\n'); + buffer.append(" .automaticCategoryCrossing = ").append(isAutomaticCategoryCrossing()).append('\n'); + buffer.append(" .logarithmicScale = ").append(isLogarithmicScale()).append('\n'); + buffer.append(" .valuesInReverse = ").append(isValuesInReverse()).append('\n'); + buffer.append(" .crossCategoryAxisAtMaximum = ").append(isCrossCategoryAxisAtMaximum()).append('\n'); + buffer.append(" .reserved = ").append(isReserved()).append('\n'); buffer.append("[/VALUERANGE]\n"); return buffer.toString(); @@ -120,20 +125,18 @@ public final class ValueRangeRecord extends StandardRecord { return sid; } - public Object clone() { - ValueRangeRecord rec = new ValueRangeRecord(); - - rec.field_1_minimumAxisValue = field_1_minimumAxisValue; - rec.field_2_maximumAxisValue = field_2_maximumAxisValue; - rec.field_3_majorIncrement = field_3_majorIncrement; - rec.field_4_minorIncrement = field_4_minorIncrement; - rec.field_5_categoryAxisCross = field_5_categoryAxisCross; - rec.field_6_options = field_6_options; - return rec; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public ValueRangeRecord clone() { + return copy(); } - - + @Override + public ValueRangeRecord copy() { + return new ValueRangeRecord(this); + } /** * Get the minimum axis value field for the ValueRange record. diff --git a/src/java/org/apache/poi/hssf/record/common/ExtRst.java b/src/java/org/apache/poi/hssf/record/common/ExtRst.java new file mode 100644 index 0000000000..efdb5b1eac --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/common/ExtRst.java @@ -0,0 +1,261 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hssf.record.common; + +import java.util.Arrays; +import java.util.stream.Stream; + +import org.apache.poi.hssf.record.cont.ContinuableRecordOutput; +import org.apache.poi.util.IOUtils; +import org.apache.poi.util.Internal; +import org.apache.poi.util.LittleEndianInput; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.StringUtil; + +@Internal +public class ExtRst implements Comparable<ExtRst> { + private static final POILogger _logger = POILogFactory.getLogger(ExtRst.class); + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 100_000; + + private short reserved; + + // This is a Phs (see page 881) + private short formattingFontIndex; + private short formattingOptions; + + // This is a RPHSSub (see page 894) + private int numberOfRuns; + private String phoneticText; + + // This is an array of PhRuns (see page 881) + private PhRun[] phRuns; + // Sometimes there's some cruft at the end + private byte[] extraData; + + protected ExtRst() { + populateEmpty(); + } + + protected ExtRst(ExtRst other) { + reserved = other.reserved; + formattingFontIndex = other.formattingFontIndex; + formattingOptions = other.formattingOptions; + numberOfRuns = other.numberOfRuns; + phoneticText = other.phoneticText; + phRuns = (other.phRuns == null) ? null : Stream.of(other.phRuns).map(PhRun::new).toArray(PhRun[]::new); + } + + protected ExtRst(LittleEndianInput in, int expectedLength) { + reserved = in.readShort(); + + // Old style detection (Reserved = 0xFF) + if(reserved == -1) { + populateEmpty(); + return; + } + + // Spot corrupt records + if(reserved != 1) { + _logger.log(POILogger.WARN, "Warning - ExtRst has wrong magic marker, expecting 1 but found " + reserved + " - ignoring"); + // Grab all the remaining data, and ignore it + for(int i=0; i<expectedLength-2; i++) { + in.readByte(); + } + // And make us be empty + populateEmpty(); + return; + } + + // Carry on reading in as normal + short stringDataSize = in.readShort(); + + formattingFontIndex = in.readShort(); + formattingOptions = in.readShort(); + + // RPHSSub + numberOfRuns = in.readUShort(); + short length1 = in.readShort(); + // No really. Someone clearly forgot to read + // the docs on their datastructure... + short length2 = in.readShort(); + // And sometimes they write out garbage :( + if(length1 == 0 && length2 > 0) { + length2 = 0; + } + if(length1 != length2) { + throw new IllegalStateException( + "The two length fields of the Phonetic Text don't agree! " + + length1 + " vs " + length2 + ); + } + phoneticText = StringUtil.readUnicodeLE(in, length1); + + int runData = stringDataSize - 4 - 6 - (2*phoneticText.length()); + int numRuns = (runData / 6); + phRuns = new PhRun[numRuns]; + for(int i=0; i<phRuns.length; i++) { + phRuns[i] = new PhRun(in); + } + + int extraDataLength = runData - (numRuns*6); + if(extraDataLength < 0) { + _logger.log( POILogger.WARN, "Warning - ExtRst overran by " + (0-extraDataLength) + " bytes"); + extraDataLength = 0; + } + extraData = IOUtils.safelyAllocate(extraDataLength, MAX_RECORD_LENGTH); + for(int i=0; i<extraData.length; i++) { + extraData[i] = in.readByte(); + } + } + + private void populateEmpty() { + reserved = 1; + phoneticText = ""; + phRuns = new PhRun[0]; + extraData = new byte[0]; + } + + /** + * Returns our size, excluding our + * 4 byte header + */ + protected int getDataSize() { + return 4 + 6 + (2*phoneticText.length()) + + (6*phRuns.length) + extraData.length; + } + protected void serialize(ContinuableRecordOutput out) { + int dataSize = getDataSize(); + + out.writeContinueIfRequired(8); + out.writeShort(reserved); + out.writeShort(dataSize); + out.writeShort(formattingFontIndex); + out.writeShort(formattingOptions); + + out.writeContinueIfRequired(6); + out.writeShort(numberOfRuns); + out.writeShort(phoneticText.length()); + out.writeShort(phoneticText.length()); + + out.writeContinueIfRequired(phoneticText.length()*2); + StringUtil.putUnicodeLE(phoneticText, out); + + for(int i=0; i<phRuns.length; i++) { + phRuns[i].serialize(out); + } + + out.write(extraData); + } + + public boolean equals(Object obj) { + if(! (obj instanceof ExtRst)) { + return false; + } + ExtRst other = (ExtRst)obj; + return (compareTo(other) == 0); + } + public int compareTo(ExtRst o) { + int result; + + result = reserved - o.reserved; + if (result != 0) { + return result; + } + result = formattingFontIndex - o.formattingFontIndex; + if (result != 0) { + return result; + } + result = formattingOptions - o.formattingOptions; + if (result != 0) { + return result; + } + result = numberOfRuns - o.numberOfRuns; + if (result != 0) { + return result; + } + + result = phoneticText.compareTo(o.phoneticText); + if (result != 0) { + return result; + } + + result = phRuns.length - o.phRuns.length; + if (result != 0) { + return result; + } + for(int i=0; i<phRuns.length; i++) { + result = phRuns[i].phoneticTextFirstCharacterOffset - o.phRuns[i].phoneticTextFirstCharacterOffset; + if (result != 0) { + return result; + } + result = phRuns[i].realTextFirstCharacterOffset - o.phRuns[i].realTextFirstCharacterOffset; + if (result != 0) { + return result; + } + result = phRuns[i].realTextLength - o.phRuns[i].realTextLength; + if (result != 0) { + return result; + } + } + + result = Arrays.hashCode(extraData)-Arrays.hashCode(o.extraData); + + return result; + } + + @Override + public int hashCode() { + int hash = reserved; + hash = 31*hash+formattingFontIndex; + hash = 31*hash+formattingOptions; + hash = 31*hash+numberOfRuns; + hash = 31*hash+phoneticText.hashCode(); + + if (phRuns != null) { + for (PhRun ph : phRuns) { + hash = 31*hash+ph.phoneticTextFirstCharacterOffset; + hash = 31*hash+ph.realTextFirstCharacterOffset; + hash = 31*hash+ph.realTextLength; + } + } + return hash; + } + + public ExtRst copy() { + return new ExtRst(this); + } + + public short getFormattingFontIndex() { + return formattingFontIndex; + } + public short getFormattingOptions() { + return formattingOptions; + } + public int getNumberOfRuns() { + return numberOfRuns; + } + public String getPhoneticText() { + return phoneticText; + } + public PhRun[] getPhRuns() { + return phRuns; + } + +} 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 2d8ba002d0..145b2e2085 100644 --- a/src/java/org/apache/poi/hssf/record/common/ExtendedColor.java +++ b/src/java/org/apache/poi/hssf/record/common/ExtendedColor.java @@ -17,9 +17,11 @@ package org.apache.poi.hssf.record.common; +import org.apache.poi.common.Duplicatable; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** @@ -27,16 +29,16 @@ import org.apache.poi.util.LittleEndianOutput; * <P> * The HSSF file format normally stores Color information in the * Palette (see PaletteRecord), but for a few cases (eg Conditional - * Formatting, Sheet Extensions), this XSSF-style color record + * Formatting, Sheet Extensions), this XSSF-style color record * can be used. */ -public final class ExtendedColor implements Cloneable { +public final class ExtendedColor implements Duplicatable { public static final int TYPE_AUTO = 0; public static final int TYPE_INDEXED = 1; public static final int TYPE_RGB = 2; public static final int TYPE_THEMED = 3; public static final int TYPE_UNSET = 4; - + public static final int THEME_DARK_1 = 0; public static final int THEME_LIGHT_1 = 1; public static final int THEME_DARK_2 = 2; @@ -50,23 +52,33 @@ public final class ExtendedColor implements Cloneable { public static final int THEME_HYPERLINK = 10; // This one is SheetEx only, not allowed in CFs public static final int THEME_FOLLOWED_HYPERLINK = 11; - + private int type; - + // Type = Indexed private int colorIndex; // Type = RGB private byte[] rgba; // Type = Theme private int themeIndex; - + private double tint; - + public ExtendedColor() { - this.type = TYPE_INDEXED; - this.colorIndex = 0; - this.tint = 0d; + type = TYPE_INDEXED; + colorIndex = 0; + tint = 0d; } + + public ExtendedColor(ExtendedColor other) { + type = other.type; + tint = other.tint; + colorIndex = other.colorIndex; + rgba = (other.rgba == null) ? null : other.rgba.clone(); + themeIndex = other.themeIndex; + } + + public ExtendedColor(LittleEndianInput in) { type = in.readInt(); if (type == TYPE_INDEXED) { @@ -99,7 +111,7 @@ public final class ExtendedColor implements Cloneable { public void setColorIndex(int colorIndex) { this.colorIndex = colorIndex; } - + /** * @return Red Green Blue Alpha, if type is {@link #TYPE_RGB} */ @@ -109,7 +121,7 @@ public final class ExtendedColor implements Cloneable { public void setRGBA(byte[] rgba) { this.rgba = (rgba == null) ? null : rgba.clone(); } - + /** * @return Theme color type index, eg {@link #THEME_DARK_1}, if type is {@link #TYPE_THEMED} */ @@ -134,7 +146,7 @@ public final class ExtendedColor implements Cloneable { } this.tint = tint; } - + public String toString() { StringBuilder buffer = new StringBuilder(); buffer.append(" [Extended Color]\n"); @@ -146,23 +158,20 @@ public final class ExtendedColor implements Cloneable { buffer.append(" [/Extended Color]\n"); return buffer.toString(); } - + @Override - public ExtendedColor clone() { - ExtendedColor exc = new ExtendedColor(); - exc.type = type; - exc.tint = tint; - if (type == TYPE_INDEXED) { - exc.colorIndex = colorIndex; - } else if (type == TYPE_RGB) { - exc.rgba = new byte[4]; - System.arraycopy(rgba, 0, exc.rgba, 0, 4); - } else if (type == TYPE_THEMED) { - exc.themeIndex = themeIndex; - } - return exc; + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public ExtendedColor clone() { + return copy(); } - + + @Override + public ExtendedColor copy() { + return new ExtendedColor(this); + } + public int getDataLength() { return 4+4+8; } diff --git a/src/java/org/apache/poi/hssf/record/common/FeatFormulaErr2.java b/src/java/org/apache/poi/hssf/record/common/FeatFormulaErr2.java index e798337f82..dde71cc515 100644 --- a/src/java/org/apache/poi/hssf/record/common/FeatFormulaErr2.java +++ b/src/java/org/apache/poi/hssf/record/common/FeatFormulaErr2.java @@ -18,8 +18,6 @@ package org.apache.poi.hssf.record.common; import org.apache.poi.hssf.record.FeatRecord; -//import org.apache.poi.hssf.record.Feat11Record; -//import org.apache.poi.hssf.record.Feat12Record; import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; @@ -28,8 +26,8 @@ import org.apache.poi.util.LittleEndianOutput; /** * Title: FeatFormulaErr2 (Formula Evaluation Shared Feature) common record part * <P> - * This record part specifies Formula Evaluation & Error Ignoring data - * for a sheet, stored as part of a Shared Feature. It can be found in + * This record part specifies Formula Evaluation & Error Ignoring data + * for a sheet, stored as part of a Shared Feature. It can be found in * records such as {@link FeatRecord}. * For the full meanings of the flags, see pages 669 and 670 * of the Excel binary file format documentation and/or @@ -44,15 +42,19 @@ public final class FeatFormulaErr2 implements SharedFeature { private static final BitField CHECK_DATETIME_FORMATS = BitFieldFactory.getInstance(0x20); private static final BitField CHECK_UNPROTECTED_FORMULAS = BitFieldFactory.getInstance(0x40); private static final BitField PERFORM_DATA_VALIDATION = BitFieldFactory.getInstance(0x80); - + /** * What errors we should ignore */ private int errorCheck; - - + + public FeatFormulaErr2() {} + public FeatFormulaErr2(FeatFormulaErr2 other) { + errorCheck = other.errorCheck; + } + public FeatFormulaErr2(RecordInputStream in) { errorCheck = in.readInt(); } @@ -60,14 +62,14 @@ public final class FeatFormulaErr2 implements SharedFeature { public String toString() { StringBuilder buffer = new StringBuilder(); buffer.append(" [FEATURE FORMULA ERRORS]\n"); - buffer.append(" checkCalculationErrors = "); - buffer.append(" checkEmptyCellRef = "); - buffer.append(" checkNumbersAsText = "); - buffer.append(" checkInconsistentRanges = "); - buffer.append(" checkInconsistentFormulas = "); - buffer.append(" checkDateTimeFormats = "); - buffer.append(" checkUnprotectedFormulas = "); - buffer.append(" performDataValidation = "); + buffer.append(" checkCalculationErrors = "); + buffer.append(" checkEmptyCellRef = "); + buffer.append(" checkNumbersAsText = "); + buffer.append(" checkInconsistentRanges = "); + buffer.append(" checkInconsistentFormulas = "); + buffer.append(" checkDateTimeFormats = "); + buffer.append(" checkUnprotectedFormulas = "); + buffer.append(" performDataValidation = "); buffer.append(" [/FEATURE FORMULA ERRORS]\n"); return buffer.toString(); } @@ -79,7 +81,7 @@ public final class FeatFormulaErr2 implements SharedFeature { public int getDataSize() { return 4; } - + public int _getRawErrorCheckValue() { return errorCheck; } @@ -139,4 +141,9 @@ public final class FeatFormulaErr2 implements SharedFeature { public void setPerformDataValidation(boolean performDataValidation) { errorCheck = PERFORM_DATA_VALIDATION.setBoolean(errorCheck, performDataValidation); } + + @Override + public FeatFormulaErr2 copy() { + return new FeatFormulaErr2(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/common/FeatProtection.java b/src/java/org/apache/poi/hssf/record/common/FeatProtection.java index 2e6e94008a..9e9a45fb55 100644 --- a/src/java/org/apache/poi/hssf/record/common/FeatProtection.java +++ b/src/java/org/apache/poi/hssf/record/common/FeatProtection.java @@ -20,8 +20,6 @@ package org.apache.poi.hssf.record.common; import org.apache.poi.hssf.record.FeatRecord; import org.apache.poi.hssf.record.PasswordRecord; import org.apache.poi.hssf.record.PasswordRev4Record; -//import org.apache.poi.hssf.record.Feat11Record; -//import org.apache.poi.hssf.record.Feat12Record; import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.StringUtil; @@ -39,35 +37,42 @@ public final class FeatProtection implements SharedFeature { public static final long HAS_SELF_RELATIVE_SECURITY_FEATURE = 1; private int fSD; - + /** * 0 means no password. Otherwise indicates the - * password verifier algorithm (same kind as + * password verifier algorithm (same kind as * {@link PasswordRecord} and * {@link PasswordRev4Record}) */ private int passwordVerifier; - + private String title; private byte[] securityDescriptor; - + public FeatProtection() { securityDescriptor = new byte[0]; } + public FeatProtection(FeatProtection other) { + fSD = other.fSD; + passwordVerifier = other.passwordVerifier; + title = other.title; + securityDescriptor = (other.securityDescriptor == null) ? null : other.securityDescriptor.clone(); + } + public FeatProtection(RecordInputStream in) { fSD = in.readInt(); passwordVerifier = in.readInt(); - + title = StringUtil.readUnicodeString(in); - + securityDescriptor = in.readRemainder(); } public String toString() { StringBuilder buffer = new StringBuilder(); buffer.append(" [FEATURE PROTECTION]\n"); - buffer.append(" Self Relative = " + fSD); + buffer.append(" Self Relative = " + fSD); buffer.append(" Password Verifier = " + passwordVerifier); buffer.append(" Title = " + title); buffer.append(" Security Descriptor Size = " + securityDescriptor.length); @@ -103,4 +108,9 @@ public final class FeatProtection implements SharedFeature { public int getFSD() { return fSD; } + + @Override + public FeatProtection copy() { + return new FeatProtection(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/common/FeatSmartTag.java b/src/java/org/apache/poi/hssf/record/common/FeatSmartTag.java index c8e2b29542..2e8e08e16f 100644 --- a/src/java/org/apache/poi/hssf/record/common/FeatSmartTag.java +++ b/src/java/org/apache/poi/hssf/record/common/FeatSmartTag.java @@ -18,11 +18,12 @@ package org.apache.poi.hssf.record.common; import org.apache.poi.hssf.record.FeatRecord; -//import org.apache.poi.hssf.record.Feat11Record; -//import org.apache.poi.hssf.record.Feat12Record; import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.util.LittleEndianOutput; +//import org.apache.poi.hssf.record.Feat11Record; +//import org.apache.poi.hssf.record.Feat12Record; + /** * Title: FeatSmartTag (Smart Tag Shared Feature) common record part * <P> @@ -36,11 +37,15 @@ import org.apache.poi.util.LittleEndianOutput; public final class FeatSmartTag implements SharedFeature { // TODO - process private byte[] data; - + public FeatSmartTag() { data = new byte[0]; } + public FeatSmartTag(FeatSmartTag other) { + data = (other.data == null) ? null : other.data.clone(); + } + public FeatSmartTag(RecordInputStream in) { data = in.readRemainder(); } @@ -59,4 +64,9 @@ public final class FeatSmartTag implements SharedFeature { public void serialize(LittleEndianOutput out) { out.write(data); } + + @Override + public FeatSmartTag copy() { + return new FeatSmartTag(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/common/FormatRun.java b/src/java/org/apache/poi/hssf/record/common/FormatRun.java new file mode 100644 index 0000000000..4e927f15c5 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/common/FormatRun.java @@ -0,0 +1,84 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hssf.record.common; + +import org.apache.poi.util.Internal; +import org.apache.poi.util.LittleEndianInput; +import org.apache.poi.util.LittleEndianOutput; + +@Internal +public class FormatRun implements Comparable<FormatRun> { + final short _character; + short _fontIndex; + + public FormatRun(short character, short fontIndex) { + this._character = character; + this._fontIndex = fontIndex; + } + + public FormatRun(FormatRun other) { + _character = other._character; + _fontIndex = other._fontIndex; + } + + public FormatRun(LittleEndianInput in) { + this(in.readShort(), in.readShort()); + } + + public short getCharacterPos() { + return _character; + } + + public short getFontIndex() { + return _fontIndex; + } + + public boolean equals(Object o) { + if (!(o instanceof FormatRun)) { + return false; + } + FormatRun other = (FormatRun) o; + + return _character == other._character && _fontIndex == other._fontIndex; + } + + public int compareTo(FormatRun r) { + if (_character == r._character && _fontIndex == r._fontIndex) { + return 0; + } + if (_character == r._character) { + return _fontIndex - r._fontIndex; + } + return _character - r._character; + } + + @Override + public int hashCode() { + assert false : "hashCode not designed"; + return 42; // any arbitrary constant will do + } + + public String toString() { + return "character=" + _character + ",fontIndex=" + _fontIndex; + } + + public void serialize(LittleEndianOutput out) { + out.writeShort(_character); + out.writeShort(_fontIndex); + } +} diff --git a/src/java/org/apache/poi/hssf/record/common/FtrHeader.java b/src/java/org/apache/poi/hssf/record/common/FtrHeader.java index 5d08211c0a..851e1e6c94 100644 --- a/src/java/org/apache/poi/hssf/record/common/FtrHeader.java +++ b/src/java/org/apache/poi/hssf/record/common/FtrHeader.java @@ -17,18 +17,20 @@ package org.apache.poi.hssf.record.common; +import org.apache.poi.common.Duplicatable; import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.Removal; /** * Title: FtrHeader (Future Record Header) common record part * <P> * This record part specifies a header for a Ftr (Future) * style record, which includes extra attributes above and - * beyond those of a traditional record. + * beyond those of a traditional record. */ -public final class FtrHeader implements Cloneable { +public final class FtrHeader implements Duplicatable { /** This MUST match the type on the containing record */ private short recordType; /** This is a FrtFlags */ @@ -40,6 +42,12 @@ public final class FtrHeader implements Cloneable { associatedRange = new CellRangeAddress(0, 0, 0, 0); } + public FtrHeader(FtrHeader other) { + recordType = other.recordType; + grbitFrt = other.grbitFrt; + associatedRange = other.associatedRange.copy(); + } + public FtrHeader(RecordInputStream in) { recordType = in.readShort(); grbitFrt = in.readShort(); @@ -87,11 +95,15 @@ public final class FtrHeader implements Cloneable { this.associatedRange = associatedRange; } - public Object clone() { - FtrHeader result = new FtrHeader(); - result.recordType = recordType; - result.grbitFrt = grbitFrt; - result.associatedRange = associatedRange.copy(); - return result; + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public FtrHeader clone() { + return copy(); + } + + public FtrHeader copy() { + return new FtrHeader(this); } }
\ No newline at end of file diff --git a/src/java/org/apache/poi/hssf/record/common/PhRun.java b/src/java/org/apache/poi/hssf/record/common/PhRun.java new file mode 100644 index 0000000000..0f33254b46 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/common/PhRun.java @@ -0,0 +1,55 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hssf.record.common; + +import org.apache.poi.hssf.record.cont.ContinuableRecordOutput; +import org.apache.poi.util.Internal; +import org.apache.poi.util.LittleEndianInput; + +@Internal +public class PhRun { + final int phoneticTextFirstCharacterOffset; + final int realTextFirstCharacterOffset; + final int realTextLength; + + public PhRun(PhRun other) { + phoneticTextFirstCharacterOffset = other.phoneticTextFirstCharacterOffset; + realTextFirstCharacterOffset = other.realTextFirstCharacterOffset; + realTextLength = other.realTextLength; + } + + public PhRun(int phoneticTextFirstCharacterOffset, + int realTextFirstCharacterOffset, int realTextLength) { + this.phoneticTextFirstCharacterOffset = phoneticTextFirstCharacterOffset; + this.realTextFirstCharacterOffset = realTextFirstCharacterOffset; + this.realTextLength = realTextLength; + } + + PhRun(LittleEndianInput in) { + phoneticTextFirstCharacterOffset = in.readUShort(); + realTextFirstCharacterOffset = in.readUShort(); + realTextLength = in.readUShort(); + } + + void serialize(ContinuableRecordOutput out) { + out.writeContinueIfRequired(6); + out.writeShort(phoneticTextFirstCharacterOffset); + out.writeShort(realTextFirstCharacterOffset); + out.writeShort(realTextLength); + } +} diff --git a/src/java/org/apache/poi/hssf/record/common/SharedFeature.java b/src/java/org/apache/poi/hssf/record/common/SharedFeature.java index 1ce8bce1f2..63d3172ef6 100644 --- a/src/java/org/apache/poi/hssf/record/common/SharedFeature.java +++ b/src/java/org/apache/poi/hssf/record/common/SharedFeature.java @@ -23,7 +23,8 @@ import org.apache.poi.util.LittleEndianOutput; * Common Interface for all Shared Features */ public interface SharedFeature { - public String toString(); - public void serialize(LittleEndianOutput out); - public int getDataSize(); + String toString(); + void serialize(LittleEndianOutput out); + int getDataSize(); + SharedFeature copy(); } diff --git a/src/java/org/apache/poi/hssf/record/common/UnicodeString.java b/src/java/org/apache/poi/hssf/record/common/UnicodeString.java index 80689564b9..fedaf31b22 100644 --- a/src/java/org/apache/poi/hssf/record/common/UnicodeString.java +++ b/src/java/org/apache/poi/hssf/record/common/UnicodeString.java @@ -18,368 +18,91 @@ package org.apache.poi.hssf.record.common; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.stream.Collectors; +import org.apache.poi.common.Duplicatable; import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.cont.ContinuableRecordInput; import org.apache.poi.hssf.record.cont.ContinuableRecordOutput; import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; -import org.apache.poi.util.IOUtils; -import org.apache.poi.util.LittleEndianInput; -import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; -import org.apache.poi.util.StringUtil; +import org.apache.poi.util.Removal; /** - * Title: Unicode String<p> - * Description: Unicode String - just standard fields that are in several records. - * It is considered more desirable then repeating it in all of them.<p> - * This is often called a XLUnicodeRichExtendedString in MS documentation.<p> - * REFERENCE: PG 264 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<p> - * REFERENCE: PG 951 Excel Binary File Format (.xls) Structure Specification v20091214 + * Unicode String - just standard fields that are in several records. + * It is considered more desirable then repeating it in all of them.<p> + * This is often called a XLUnicodeRichExtendedString in MS documentation.<p> */ -public class UnicodeString implements Comparable<UnicodeString> { +public class UnicodeString implements Comparable<UnicodeString>, Duplicatable { private static final POILogger _logger = POILogFactory.getLogger(UnicodeString.class); - //arbitrarily selected; may need to increase - private static final int MAX_RECORD_LENGTH = 100_000; - + private static final BitField highByte = BitFieldFactory.getInstance(0x1); + // 0x2 is reserved + private static final BitField extBit = BitFieldFactory.getInstance(0x4); + private static final BitField richText = BitFieldFactory.getInstance(0x8); private short field_1_charCount; private byte field_2_optionflags; private String field_3_string; private List<FormatRun> field_4_format_runs; private ExtRst field_5_ext_rst; - private static final BitField highByte = BitFieldFactory.getInstance(0x1); - // 0x2 is reserved - private static final BitField extBit = BitFieldFactory.getInstance(0x4); - private static final BitField richText = BitFieldFactory.getInstance(0x8); - public static class FormatRun implements Comparable<FormatRun> { - final short _character; - short _fontIndex; - - public FormatRun(short character, short fontIndex) { - this._character = character; - this._fontIndex = fontIndex; - } - - public FormatRun(LittleEndianInput in) { - this(in.readShort(), in.readShort()); - } - - public short getCharacterPos() { - return _character; - } - - public short getFontIndex() { - return _fontIndex; - } - - public boolean equals(Object o) { - if (!(o instanceof FormatRun)) { - return false; - } - FormatRun other = ( FormatRun ) o; - - return _character == other._character && _fontIndex == other._fontIndex; - } + private UnicodeString(UnicodeString other) { + field_1_charCount = other.field_1_charCount; + field_2_optionflags = other.field_2_optionflags; + field_3_string = other.field_3_string; + field_4_format_runs = (other.field_4_format_runs == null) ? null : + other.field_4_format_runs.stream().map(FormatRun::new).collect(Collectors.toList()); + field_5_ext_rst = (other.field_5_ext_rst == null) ? null : other.field_5_ext_rst.copy(); + } - public int compareTo(FormatRun r) { - if (_character == r._character && _fontIndex == r._fontIndex) { - return 0; - } - if (_character == r._character) { - return _fontIndex - r._fontIndex; - } - return _character - r._character; - } + public UnicodeString(String str) { + setString(str); + } - @Override - public int hashCode() { - assert false : "hashCode not designed"; - return 42; // any arbitrary constant will do - } + /** + * construct a unicode string record and fill its fields, ID is ignored + * @param in the RecordInputstream to read the record from + */ + public UnicodeString(RecordInputStream in) { + field_1_charCount = in.readShort(); + field_2_optionflags = in.readByte(); - public String toString() { - return "character="+_character+",fontIndex="+_fontIndex; + int runCount = 0; + int extensionLength = 0; + //Read the number of rich runs if rich text. + if (isRichText()) { + runCount = in.readShort(); } - - public void serialize(LittleEndianOutput out) { - out.writeShort(_character); - out.writeShort(_fontIndex); + //Read the size of extended data if present. + if (isExtendedText()) { + extensionLength = in.readInt(); } - } - - // See page 681 - public static class ExtRst implements Comparable<ExtRst> { - private short reserved; - - // This is a Phs (see page 881) - private short formattingFontIndex; - private short formattingOptions; - - // This is a RPHSSub (see page 894) - private int numberOfRuns; - private String phoneticText; - - // This is an array of PhRuns (see page 881) - private PhRun[] phRuns; - // Sometimes there's some cruft at the end - private byte[] extraData; - - private void populateEmpty() { - reserved = 1; - phoneticText = ""; - phRuns = new PhRun[0]; - extraData = new byte[0]; - } - - protected ExtRst() { - populateEmpty(); - } - protected ExtRst(LittleEndianInput in, int expectedLength) { - reserved = in.readShort(); - - // Old style detection (Reserved = 0xFF) - if(reserved == -1) { - populateEmpty(); - return; - } - - // Spot corrupt records - if(reserved != 1) { - _logger.log(POILogger.WARN, "Warning - ExtRst has wrong magic marker, expecting 1 but found " + reserved + " - ignoring"); - // Grab all the remaining data, and ignore it - for(int i=0; i<expectedLength-2; i++) { - in.readByte(); - } - // And make us be empty - populateEmpty(); - return; - } - // Carry on reading in as normal - short stringDataSize = in.readShort(); - - formattingFontIndex = in.readShort(); - formattingOptions = in.readShort(); - - // RPHSSub - numberOfRuns = in.readUShort(); - short length1 = in.readShort(); - // No really. Someone clearly forgot to read - // the docs on their datastructure... - short length2 = in.readShort(); - // And sometimes they write out garbage :( - if(length1 == 0 && length2 > 0) { - length2 = 0; - } - if(length1 != length2) { - throw new IllegalStateException( - "The two length fields of the Phonetic Text don't agree! " + - length1 + " vs " + length2 - ); - } - phoneticText = StringUtil.readUnicodeLE(in, length1); - - int runData = stringDataSize - 4 - 6 - (2*phoneticText.length()); - int numRuns = (runData / 6); - phRuns = new PhRun[numRuns]; - for(int i=0; i<phRuns.length; i++) { - phRuns[i] = new PhRun(in); - } + boolean isCompressed = ((field_2_optionflags & 1) == 0); + int cc = getCharCount(); + field_3_string = (isCompressed) ? in.readCompressedUnicode(cc) : in.readUnicodeLEString(cc); - int extraDataLength = runData - (numRuns*6); - if(extraDataLength < 0) { - _logger.log( POILogger.WARN, "Warning - ExtRst overran by " + (0-extraDataLength) + " bytes"); - extraDataLength = 0; - } - extraData = IOUtils.safelyAllocate(extraDataLength, MAX_RECORD_LENGTH); - for(int i=0; i<extraData.length; i++) { - extraData[i] = in.readByte(); - } - } - /** - * Returns our size, excluding our - * 4 byte header - */ - protected int getDataSize() { - return 4 + 6 + (2*phoneticText.length()) + - (6*phRuns.length) + extraData.length; - } - protected void serialize(ContinuableRecordOutput out) { - int dataSize = getDataSize(); - - out.writeContinueIfRequired(8); - out.writeShort(reserved); - out.writeShort(dataSize); - out.writeShort(formattingFontIndex); - out.writeShort(formattingOptions); - - out.writeContinueIfRequired(6); - out.writeShort(numberOfRuns); - out.writeShort(phoneticText.length()); - out.writeShort(phoneticText.length()); - - out.writeContinueIfRequired(phoneticText.length()*2); - StringUtil.putUnicodeLE(phoneticText, out); - - for(int i=0; i<phRuns.length; i++) { - phRuns[i].serialize(out); + if (isRichText() && (runCount > 0)) { + field_4_format_runs = new ArrayList<>(runCount); + for (int i=0;i<runCount;i++) { + field_4_format_runs.add(new FormatRun(in)); } - - out.write(extraData); - } + } - public boolean equals(Object obj) { - if(! (obj instanceof ExtRst)) { - return false; - } - ExtRst other = (ExtRst)obj; - return (compareTo(other) == 0); - } - public int compareTo(ExtRst o) { - int result; - - result = reserved - o.reserved; - if (result != 0) { - return result; - } - result = formattingFontIndex - o.formattingFontIndex; - if (result != 0) { - return result; - } - result = formattingOptions - o.formattingOptions; - if (result != 0) { - return result; - } - result = numberOfRuns - o.numberOfRuns; - if (result != 0) { - return result; - } - - result = phoneticText.compareTo(o.phoneticText); - if (result != 0) { - return result; - } - - result = phRuns.length - o.phRuns.length; - if (result != 0) { - return result; - } - for(int i=0; i<phRuns.length; i++) { - result = phRuns[i].phoneticTextFirstCharacterOffset - o.phRuns[i].phoneticTextFirstCharacterOffset; - if (result != 0) { - return result; - } - result = phRuns[i].realTextFirstCharacterOffset - o.phRuns[i].realTextFirstCharacterOffset; - if (result != 0) { - return result; - } - result = phRuns[i].realTextLength - o.phRuns[i].realTextLength; - if (result != 0) { - return result; - } - } - - result = Arrays.hashCode(extraData)-Arrays.hashCode(o.extraData); - - return result; - } - - @Override - public int hashCode() { - int hash = reserved; - hash = 31*hash+formattingFontIndex; - hash = 31*hash+formattingOptions; - hash = 31*hash+numberOfRuns; - hash = 31*hash+phoneticText.hashCode(); - - if (phRuns != null) { - for (PhRun ph : phRuns) { - hash = 31*hash+ph.phoneticTextFirstCharacterOffset; - hash = 31*hash+ph.realTextFirstCharacterOffset; - hash = 31*hash+ph.realTextLength; - } - } - return hash; - } - - protected ExtRst clone() { - ExtRst ext = new ExtRst(); - ext.reserved = reserved; - ext.formattingFontIndex = formattingFontIndex; - ext.formattingOptions = formattingOptions; - ext.numberOfRuns = numberOfRuns; - ext.phoneticText = phoneticText; - ext.phRuns = new PhRun[phRuns.length]; - for(int i=0; i<ext.phRuns.length; i++) { - ext.phRuns[i] = new PhRun( - phRuns[i].phoneticTextFirstCharacterOffset, - phRuns[i].realTextFirstCharacterOffset, - phRuns[i].realTextLength - ); + if (isExtendedText() && (extensionLength > 0)) { + field_5_ext_rst = new ExtRst(new ContinuableRecordInput(in), extensionLength); + if(field_5_ext_rst.getDataSize()+4 != extensionLength) { + _logger.log(POILogger.WARN, "ExtRst was supposed to be " + extensionLength + " bytes long, but seems to actually be " + (field_5_ext_rst.getDataSize() + 4)); } - return ext; - } - - public short getFormattingFontIndex() { - return formattingFontIndex; - } - public short getFormattingOptions() { - return formattingOptions; - } - public int getNumberOfRuns() { - return numberOfRuns; - } - public String getPhoneticText() { - return phoneticText; - } - public PhRun[] getPhRuns() { - return phRuns; - } - } - public static class PhRun { - private int phoneticTextFirstCharacterOffset; - private int realTextFirstCharacterOffset; - private int realTextLength; - - public PhRun(int phoneticTextFirstCharacterOffset, - int realTextFirstCharacterOffset, int realTextLength) { - this.phoneticTextFirstCharacterOffset = phoneticTextFirstCharacterOffset; - this.realTextFirstCharacterOffset = realTextFirstCharacterOffset; - this.realTextLength = realTextLength; - } - private PhRun(LittleEndianInput in) { - phoneticTextFirstCharacterOffset = in.readUShort(); - realTextFirstCharacterOffset = in.readUShort(); - realTextLength = in.readUShort(); - } - private void serialize(ContinuableRecordOutput out) { - out.writeContinueIfRequired(6); - out.writeShort(phoneticTextFirstCharacterOffset); - out.writeShort(realTextFirstCharacterOffset); - out.writeShort(realTextLength); - } - } - - private UnicodeString() { - //Used for clone method. - } - - public UnicodeString(String str) - { - setString(str); + } } - - public int hashCode() { int stringHash = 0; @@ -405,8 +128,8 @@ public class UnicodeString implements Comparable<UnicodeString> { //OK lets do this in stages to return a quickly, first check the actual string if (field_1_charCount != other.field_1_charCount - || field_2_optionflags != other.field_2_optionflags - || !field_3_string.equals(other.field_3_string)) { + || field_2_optionflags != other.field_2_optionflags + || !field_3_string.equals(other.field_3_string)) { return false; } @@ -422,16 +145,16 @@ public class UnicodeString implements Comparable<UnicodeString> { //Strings are equal, so now compare formatting runs. int size = field_4_format_runs.size(); if (size != other.field_4_format_runs.size()) { - return false; + return false; } for (int i=0;i<size;i++) { - FormatRun run1 = field_4_format_runs.get(i); - FormatRun run2 = other.field_4_format_runs.get(i); + FormatRun run1 = field_4_format_runs.get(i); + FormatRun run2 = other.field_4_format_runs.get(i); - if (!run1.equals(run2)) { - return false; - } + if (!run1.equals(run2)) { + return false; + } } // Well the format runs are equal as well!, better check the ExtRst data @@ -440,46 +163,8 @@ public class UnicodeString implements Comparable<UnicodeString> { } else if (other.field_5_ext_rst == null) { return false; } - - return field_5_ext_rst.equals(other.field_5_ext_rst); - } - /** - * construct a unicode string record and fill its fields, ID is ignored - * @param in the RecordInputstream to read the record from - */ - public UnicodeString(RecordInputStream in) { - field_1_charCount = in.readShort(); - field_2_optionflags = in.readByte(); - - int runCount = 0; - int extensionLength = 0; - //Read the number of rich runs if rich text. - if (isRichText()) { - runCount = in.readShort(); - } - //Read the size of extended data if present. - if (isExtendedText()) { - extensionLength = in.readInt(); - } - - boolean isCompressed = ((field_2_optionflags & 1) == 0); - int cc = getCharCount(); - field_3_string = (isCompressed) ? in.readCompressedUnicode(cc) : in.readUnicodeLEString(cc); - - if (isRichText() && (runCount > 0)) { - field_4_format_runs = new ArrayList<>(runCount); - for (int i=0;i<runCount;i++) { - field_4_format_runs.add(new FormatRun(in)); - } - } - - if (isExtendedText() && (extensionLength > 0)) { - field_5_ext_rst = new ExtRst(new ContinuableRecordInput(in), extensionLength); - if(field_5_ext_rst.getDataSize()+4 != extensionLength) { - _logger.log(POILogger.WARN, "ExtRst was supposed to be " + extensionLength + " bytes long, but seems to actually be " + (field_5_ext_rst.getDataSize() + 4)); - } - } + return field_5_ext_rst.equals(other.field_5_ext_rst); } @@ -737,7 +422,7 @@ public class UnicodeString implements Comparable<UnicodeString> { if (isExtendedText() && field_5_ext_rst != null) { extendedDataSize = 4 + field_5_ext_rst.getDataSize(); } - + // Serialise the bulk of the String // The writeString handles tricky continue stuff for us out.writeString(field_3_string, numberOfRichTextRuns, extendedDataSize); @@ -812,21 +497,16 @@ public class UnicodeString implements Comparable<UnicodeString> { return extBit.isSet(getOptionFlags()); } - public Object clone() { - UnicodeString str = new UnicodeString(); - str.field_1_charCount = field_1_charCount; - str.field_2_optionflags = field_2_optionflags; - str.field_3_string = field_3_string; - if (field_4_format_runs != null) { - str.field_4_format_runs = new ArrayList<>(); - for (FormatRun r : field_4_format_runs) { - str.field_4_format_runs.add(new FormatRun(r._character, r._fontIndex)); - } - } - if (field_5_ext_rst != null) { - str.field_5_ext_rst = field_5_ext_rst.clone(); - } + @Override + @SuppressWarnings("squid:S2975") + @Deprecated + @Removal(version = "5.0.0") + public UnicodeString clone() { + return copy(); + } - return str; + @Override + public UnicodeString copy() { + return new UnicodeString(this); } } diff --git a/src/java/org/apache/poi/hssf/record/cont/ContinuableRecord.java b/src/java/org/apache/poi/hssf/record/cont/ContinuableRecord.java index 8c170aa3af..dceb7b86b1 100644 --- a/src/java/org/apache/poi/hssf/record/cont/ContinuableRecord.java +++ b/src/java/org/apache/poi/hssf/record/cont/ContinuableRecord.java @@ -29,9 +29,12 @@ import org.apache.poi.util.LittleEndianOutput; */ public abstract class ContinuableRecord extends Record { - protected ContinuableRecord() { - // no fields to initialise + protected ContinuableRecord() {} + + protected ContinuableRecord(ContinuableRecord other) { + super(other); } + /** * Serializes this record's content to the supplied data output.<p> * The standard BIFF header (ushort sid, ushort size) has been handled by the superclass, so diff --git a/src/java/org/apache/poi/hssf/record/pivottable/DataItemRecord.java b/src/java/org/apache/poi/hssf/record/pivottable/DataItemRecord.java index d104540082..a55fa6fd7b 100644 --- a/src/java/org/apache/poi/hssf/record/pivottable/DataItemRecord.java +++ b/src/java/org/apache/poi/hssf/record/pivottable/DataItemRecord.java @@ -24,9 +24,7 @@ import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.StringUtil; /** - * SXDI - Data Item (0x00C5)<br> - * - * @author Patrick Cheng + * SXDI - Data Item (0x00C5) */ public final class DataItemRecord extends StandardRecord { public static final short sid = 0x00C5; @@ -38,7 +36,18 @@ public final class DataItemRecord extends StandardRecord { private int isxvi; private int ifmt; private String name; - + + public DataItemRecord(DataItemRecord other) { + super(other); + isxvdData = other.isxvdData; + iiftab = other.iiftab; + df = other.df; + isxvd = other.isxvd; + isxvi = other.isxvi; + ifmt = other.ifmt; + name = other.name; + } + public DataItemRecord(RecordInputStream in) { isxvdData = in.readUShort(); iiftab = in.readUShort(); @@ -46,20 +55,20 @@ public final class DataItemRecord extends StandardRecord { isxvd = in.readUShort(); isxvi = in.readUShort(); ifmt = in.readUShort(); - + name = in.readString(); } - + @Override protected void serialize(LittleEndianOutput out) { - + out.writeShort(isxvdData); out.writeShort(iiftab); out.writeShort(df); out.writeShort(isxvd); out.writeShort(isxvi); out.writeShort(ifmt); - + StringUtil.writeUnicodeString(out, name); } @@ -76,7 +85,7 @@ public final class DataItemRecord extends StandardRecord { @Override public String toString() { StringBuilder buffer = new StringBuilder(); - + buffer.append("[SXDI]\n"); buffer.append(" .isxvdData = ").append(HexDump.shortToHex(isxvdData)).append("\n"); buffer.append(" .iiftab = ").append(HexDump.shortToHex(iiftab)).append("\n"); @@ -87,4 +96,9 @@ public final class DataItemRecord extends StandardRecord { buffer.append("[/SXDI]\n"); return buffer.toString(); } + + @Override + public DataItemRecord copy() { + return new DataItemRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/pivottable/ExtendedPivotTableViewFieldsRecord.java b/src/java/org/apache/poi/hssf/record/pivottable/ExtendedPivotTableViewFieldsRecord.java index 0a1bb11cd3..119c23b2da 100644 --- a/src/java/org/apache/poi/hssf/record/pivottable/ExtendedPivotTableViewFieldsRecord.java +++ b/src/java/org/apache/poi/hssf/record/pivottable/ExtendedPivotTableViewFieldsRecord.java @@ -25,9 +25,7 @@ import org.apache.poi.util.RecordFormatException; import org.apache.poi.util.StringUtil; /** - * SXVDEX - Extended PivotTable View Fields (0x0100)<br> - * - * @author Patrick Cheng + * SXVDEX - Extended PivotTable View Fields (0x0100) */ public final class ExtendedPivotTableViewFieldsRecord extends StandardRecord { public static final short sid = 0x0100; @@ -45,8 +43,19 @@ public final class ExtendedPivotTableViewFieldsRecord extends StandardRecord { /** custom sub-total name */ private String _subtotalName; - public ExtendedPivotTableViewFieldsRecord(RecordInputStream in) { + public ExtendedPivotTableViewFieldsRecord(ExtendedPivotTableViewFieldsRecord other) { + super(other); + _grbit1 = other._grbit1; + _grbit2 = other._grbit2; + _citmShow = other._citmShow; + _isxdiSort = other._isxdiSort; + _isxdiShow = other._isxdiShow; + _reserved1 = other._reserved1; + _reserved2 = other._reserved2; + _subtotalName = other._subtotalName; + } + public ExtendedPivotTableViewFieldsRecord(RecordInputStream in) { _grbit1 = in.readInt(); _grbit2 = in.readUByte(); _citmShow = in.readUByte(); @@ -99,7 +108,7 @@ public final class ExtendedPivotTableViewFieldsRecord extends StandardRecord { @Override protected int getDataSize() { - + return 4 + 1 + 1 + 2 + 2 + 2 + 4 + 4 + (_subtotalName == null ? 0 : (2*_subtotalName.length())); // in unicode } @@ -124,4 +133,9 @@ public final class ExtendedPivotTableViewFieldsRecord extends StandardRecord { buffer.append("[/SXVDEX]\n"); return buffer.toString(); } + + @Override + public ExtendedPivotTableViewFieldsRecord copy() { + return new ExtendedPivotTableViewFieldsRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/pivottable/PageItemRecord.java b/src/java/org/apache/poi/hssf/record/pivottable/PageItemRecord.java index 8d8a059cd4..ac615ed822 100644 --- a/src/java/org/apache/poi/hssf/record/pivottable/PageItemRecord.java +++ b/src/java/org/apache/poi/hssf/record/pivottable/PageItemRecord.java @@ -17,6 +17,8 @@ package org.apache.poi.hssf.record.pivottable; +import java.util.stream.Stream; + import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.util.HexDump; @@ -24,9 +26,7 @@ import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.RecordFormatException; /** - * SXPI - Page Item (0x00B6)<br> - * - * @author Patrick Cheng + * SXPI - Page Item (0x00B6) */ public final class PageItemRecord extends StandardRecord { public static final short sid = 0x00B6; @@ -40,6 +40,12 @@ public final class PageItemRecord extends StandardRecord { /** Object ID for the drop-down arrow */ private int _idObj; + public FieldInfo(FieldInfo other) { + _isxvi = other._isxvi; + _isxvd = other._isxvd; + _idObj = other._idObj; + } + public FieldInfo(RecordInputStream in) { _isxvi = in.readShort(); _isxvd = in.readShort(); @@ -63,6 +69,11 @@ public final class PageItemRecord extends StandardRecord { private final FieldInfo[] _fieldInfos; + public PageItemRecord(PageItemRecord other) { + super(other); + _fieldInfos = Stream.of(other._fieldInfos).map(FieldInfo::new).toArray(FieldInfo[]::new); + } + public PageItemRecord(RecordInputStream in) { int dataSize = in.remaining(); if (dataSize % FieldInfo.ENCODED_SIZE != 0) { @@ -80,8 +91,8 @@ public final class PageItemRecord extends StandardRecord { @Override protected void serialize(LittleEndianOutput out) { - for (int i = 0; i < _fieldInfos.length; i++) { - _fieldInfos[i].serialize(out); + for (FieldInfo fieldInfo : _fieldInfos) { + fieldInfo.serialize(out); } } @@ -108,4 +119,9 @@ public final class PageItemRecord extends StandardRecord { sb.append("[/SXPI]\n"); return sb.toString(); } + + @Override + public PageItemRecord copy() { + return new PageItemRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/pivottable/StreamIDRecord.java b/src/java/org/apache/poi/hssf/record/pivottable/StreamIDRecord.java index 70c82f0a33..49202d4e8e 100644 --- a/src/java/org/apache/poi/hssf/record/pivottable/StreamIDRecord.java +++ b/src/java/org/apache/poi/hssf/record/pivottable/StreamIDRecord.java @@ -23,19 +23,22 @@ import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; /** - * SXIDSTM - Stream ID (0x00D5)<br> - * - * @author Patrick Cheng + * SXIDSTM - Stream ID (0x00D5) */ public final class StreamIDRecord extends StandardRecord { public static final short sid = 0x00D5; private int idstm; - + + public StreamIDRecord(StreamIDRecord other) { + super(other); + idstm = other.idstm; + } + public StreamIDRecord(RecordInputStream in) { idstm = in.readShort(); } - + @Override protected void serialize(LittleEndianOutput out) { out.writeShort(idstm); @@ -61,4 +64,9 @@ public final class StreamIDRecord extends StandardRecord { buffer.append("[/SXIDSTM]\n"); return buffer.toString(); } + + @Override + public StreamIDRecord copy() { + return new StreamIDRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/pivottable/ViewDefinitionRecord.java b/src/java/org/apache/poi/hssf/record/pivottable/ViewDefinitionRecord.java index afda2ac001..0b1eb257d3 100644 --- a/src/java/org/apache/poi/hssf/record/pivottable/ViewDefinitionRecord.java +++ b/src/java/org/apache/poi/hssf/record/pivottable/ViewDefinitionRecord.java @@ -38,26 +38,52 @@ public final class ViewDefinitionRecord extends StandardRecord { private int colFirstData; private int iCache; private int reserved; - + private int sxaxis4Data; private int ipos4Data; private int cDim; - + private int cDimRw; - + private int cDimCol; private int cDimPg; - + private int cDimData; private int cRw; private int cCol; private int grbit; private int itblAutoFmt; - + private String dataField; private String name; - + + public ViewDefinitionRecord(ViewDefinitionRecord other) { + super(other); + rwFirst = other.rwFirst; + rwLast = other.rwLast; + colFirst = other.colFirst; + colLast = other.colLast; + rwFirstHead = other.rwFirstHead; + rwFirstData = other.rwFirstData; + colFirstData = other.colFirstData; + iCache = other.iCache; + reserved = other.reserved; + sxaxis4Data = other.sxaxis4Data; + ipos4Data = other.ipos4Data; + cDim = other.cDim; + cDimRw = other.cDimRw; + cDimCol = other.cDimCol; + cDimPg = other.cDimPg; + cDimData = other.cDimData; + cRw = other.cRw; + cCol = other.cCol; + grbit = other.grbit; + itblAutoFmt = other.itblAutoFmt; + name = other.name; + dataField = other.dataField; + } + public ViewDefinitionRecord(RecordInputStream in) { rwFirst = in.readUShort(); rwLast = in.readUShort(); @@ -85,7 +111,7 @@ public final class ViewDefinitionRecord extends StandardRecord { name = StringUtil.readUnicodeString(in, cchName); dataField = StringUtil.readUnicodeString(in, cchData); } - + @Override protected void serialize(LittleEndianOutput out) { out.writeShort(rwFirst); @@ -112,7 +138,7 @@ public final class ViewDefinitionRecord extends StandardRecord { out.writeShort(dataField.length()); StringUtil.writeUnicodeStringFlagAndData(out, name); - StringUtil.writeUnicodeStringFlagAndData(out, dataField); + StringUtil.writeUnicodeStringFlagAndData(out, dataField); } @Override @@ -157,4 +183,9 @@ public final class ViewDefinitionRecord extends StandardRecord { buffer.append("[/SXVIEW]\n"); return buffer.toString(); } + + @Override + public ViewDefinitionRecord copy() { + return new ViewDefinitionRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/pivottable/ViewFieldsRecord.java b/src/java/org/apache/poi/hssf/record/pivottable/ViewFieldsRecord.java index 8c761ea8ff..7812902ba0 100644 --- a/src/java/org/apache/poi/hssf/record/pivottable/ViewFieldsRecord.java +++ b/src/java/org/apache/poi/hssf/record/pivottable/ViewFieldsRecord.java @@ -24,9 +24,7 @@ import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.StringUtil; /** - * SXVD - View Fields (0x00B1)<br> - * - * @author Patrick Cheng + * SXVD - View Fields (0x00B1) */ public final class ViewFieldsRecord extends StandardRecord { public static final short sid = 0x00B1; @@ -40,18 +38,31 @@ public final class ViewFieldsRecord extends StandardRecord { private int _cSub; private int _grbitSub; private int _cItm; - + private String _name; - + /** * values for the {@link ViewFieldsRecord#_sxaxis} field */ - private static final class Axis { - public static final int NO_AXIS = 0; - public static final int ROW = 1; - public static final int COLUMN = 2; - public static final int PAGE = 4; - public static final int DATA = 8; + private enum Axis { + NO_AXIS(0), + ROW(1), + COLUMN(2), + PAGE(4), + DATA(8); + int id; + Axis(int id) { + this.id = id; + } + } + + public ViewFieldsRecord(ViewFieldsRecord other) { + super(other); + _sxaxis = other._sxaxis; + _cSub = other._cSub; + _grbitSub = other._grbitSub; + _cItm = other._cItm; + _name = other._name; } public ViewFieldsRecord(RecordInputStream in) { @@ -59,7 +70,7 @@ public final class ViewFieldsRecord extends StandardRecord { _cSub = in.readShort(); _grbitSub = in.readShort(); _cItm = in.readShort(); - + int cchName = in.readUShort(); if (cchName != STRING_NOT_PRESENT_LEN) { int flag = in.readByte(); @@ -70,15 +81,15 @@ public final class ViewFieldsRecord extends StandardRecord { } } } - + @Override protected void serialize(LittleEndianOutput out) { - + out.writeShort(_sxaxis); out.writeShort(_cSub); out.writeShort(_grbitSub); out.writeShort(_cItm); - + if (_name != null) { StringUtil.writeUnicodeString(out, _name); } else { @@ -91,8 +102,8 @@ public final class ViewFieldsRecord extends StandardRecord { if (_name == null) { return BASE_SIZE; } - return BASE_SIZE - + 1 // unicode flag + return BASE_SIZE + + 1 // unicode flag + _name.length() * (StringUtil.hasMultibyte(_name) ? 2 : 1); } @@ -110,8 +121,13 @@ public final class ViewFieldsRecord extends StandardRecord { buffer.append(" .grbitSub = ").append(HexDump.shortToHex(_grbitSub)).append('\n'); buffer.append(" .cItm = ").append(HexDump.shortToHex(_cItm)).append('\n'); buffer.append(" .name = ").append(_name).append('\n'); - + buffer.append("[/SXVD]\n"); return buffer.toString(); } + + @Override + public ViewFieldsRecord copy() { + return new ViewFieldsRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/record/pivottable/ViewSourceRecord.java b/src/java/org/apache/poi/hssf/record/pivottable/ViewSourceRecord.java index b4fb2815b9..88d11df8ba 100644 --- a/src/java/org/apache/poi/hssf/record/pivottable/ViewSourceRecord.java +++ b/src/java/org/apache/poi/hssf/record/pivottable/ViewSourceRecord.java @@ -24,18 +24,21 @@ import org.apache.poi.util.LittleEndianOutput; /** * SXVS - View Source (0x00E3)<br> - * - * @author Patrick Cheng */ public final class ViewSourceRecord extends StandardRecord { public static final short sid = 0x00E3; private int vs; - + + public ViewSourceRecord(ViewSourceRecord other) { + super(other); + vs = other.vs; + } + public ViewSourceRecord(RecordInputStream in) { vs = in.readShort(); } - + @Override protected void serialize(LittleEndianOutput out) { out.writeShort(vs); @@ -61,4 +64,9 @@ public final class ViewSourceRecord extends StandardRecord { buffer.append("[/SXVS]\n"); return buffer.toString(); } + + @Override + public ViewSourceRecord copy() { + return new ViewSourceRecord(this); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java index 68cbc96c9e..14a97a2772 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java @@ -19,7 +19,9 @@ package org.apache.poi.hssf.usermodel; import java.util.List; +import java.util.Objects; +import org.apache.poi.common.Duplicatable; import org.apache.poi.hssf.model.InternalWorkbook; import org.apache.poi.hssf.record.ExtendedFormatRecord; import org.apache.poi.hssf.record.FontRecord; @@ -41,7 +43,7 @@ import org.apache.poi.ss.usermodel.VerticalAlignment; * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#getCellStyleAt(int) * @see org.apache.poi.hssf.usermodel.HSSFCell#setCellStyle(HSSFCellStyle) */ -public final class HSSFCellStyle implements CellStyle { +public final class HSSFCellStyle implements CellStyle, Duplicatable { private final ExtendedFormatRecord _format; private final short _index; private final InternalWorkbook _workbook; @@ -59,6 +61,13 @@ public final class HSSFCellStyle implements CellStyle { _format = rec; } + protected HSSFCellStyle(HSSFCellStyle other) { + _workbook = other._workbook; + _index = other._index; + _format = other._format; + } + + /** * get the index within the HSSFWorkbook (sequence within the collection of ExtnededFormat objects) * @return unique index number of the underlying record this style represents (probably you don't care @@ -863,11 +872,7 @@ public final class HSSFCellStyle implements CellStyle { @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((_format == null) ? 0 : _format.hashCode()); - result = prime * result + _index; - return result; + return Objects.hash(_format, _index); } @Override @@ -895,4 +900,8 @@ public final class HSSFCellStyle implements CellStyle { return false; } + @Override + public HSSFCellStyle copy() { + return new HSSFCellStyle(this); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFChart.java b/src/java/org/apache/poi/hssf/usermodel/HSSFChart.java index 0895fe94f1..6aabcceeac 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFChart.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFChart.java @@ -34,38 +34,7 @@ import org.apache.poi.hssf.record.RecordBase; import org.apache.poi.hssf.record.SCLRecord; import org.apache.poi.hssf.record.UnknownRecord; import org.apache.poi.hssf.record.VCenterRecord; -import org.apache.poi.hssf.record.chart.AreaFormatRecord; -import org.apache.poi.hssf.record.chart.AxisLineFormatRecord; -import org.apache.poi.hssf.record.chart.AxisOptionsRecord; -import org.apache.poi.hssf.record.chart.AxisParentRecord; -import org.apache.poi.hssf.record.chart.AxisRecord; -import org.apache.poi.hssf.record.chart.AxisUsedRecord; -import org.apache.poi.hssf.record.chart.BarRecord; -import org.apache.poi.hssf.record.chart.BeginRecord; -import org.apache.poi.hssf.record.chart.CategorySeriesAxisRecord; -import org.apache.poi.hssf.record.chart.ChartFormatRecord; -import org.apache.poi.hssf.record.chart.ChartRecord; -import org.apache.poi.hssf.record.chart.ChartTitleFormatRecord; -import org.apache.poi.hssf.record.chart.DataFormatRecord; -import org.apache.poi.hssf.record.chart.DefaultDataLabelTextPropertiesRecord; -import org.apache.poi.hssf.record.chart.EndRecord; -import org.apache.poi.hssf.record.chart.FontBasisRecord; -import org.apache.poi.hssf.record.chart.FontIndexRecord; -import org.apache.poi.hssf.record.chart.FrameRecord; -import org.apache.poi.hssf.record.chart.LegendRecord; -import org.apache.poi.hssf.record.chart.LineFormatRecord; -import org.apache.poi.hssf.record.chart.LinkedDataRecord; -import org.apache.poi.hssf.record.chart.PlotAreaRecord; -import org.apache.poi.hssf.record.chart.PlotGrowthRecord; -import org.apache.poi.hssf.record.chart.SeriesIndexRecord; -import org.apache.poi.hssf.record.chart.SeriesRecord; -import org.apache.poi.hssf.record.chart.SeriesTextRecord; -import org.apache.poi.hssf.record.chart.SeriesToChartGroupRecord; -import org.apache.poi.hssf.record.chart.SheetPropertiesRecord; -import org.apache.poi.hssf.record.chart.TextRecord; -import org.apache.poi.hssf.record.chart.TickRecord; -import org.apache.poi.hssf.record.chart.UnitsRecord; -import org.apache.poi.hssf.record.chart.ValueRangeRecord; +import org.apache.poi.hssf.record.chart.*; import org.apache.poi.ss.formula.ptg.Area3DPtg; import org.apache.poi.ss.formula.ptg.AreaPtgBase; import org.apache.poi.ss.formula.ptg.Ptg; @@ -74,8 +43,6 @@ import org.apache.poi.ss.util.CellRangeAddressBase; /** * Has methods for construction of a chart object. - * - * @author Glen Stampoultzis (glens at apache.org) */ public final class HSSFChart { private HSSFSheet sheet; @@ -235,11 +202,11 @@ public final class HSSFChart { lastSeries.insertData(linkedDataRecord); } } - + if (lastChart == null) { continue; } - + if (r instanceof LegendRecord) { lastChart.legendRecord = (LegendRecord)r; } else if(r instanceof SeriesRecord) { @@ -1254,30 +1221,30 @@ public final class HSSFChart { } else if (record instanceof EndRecord) { newRecord = new EndRecord(); } else if (record instanceof SeriesRecord) { - SeriesRecord seriesRecord = (SeriesRecord) ((SeriesRecord)record).clone(); + SeriesRecord seriesRecord = (SeriesRecord) ((SeriesRecord)record).copy(); newSeries = new HSSFSeries(seriesRecord); newRecord = seriesRecord; } else if (record instanceof LinkedDataRecord) { - LinkedDataRecord linkedDataRecord = ((LinkedDataRecord)record).clone(); + LinkedDataRecord linkedDataRecord = ((LinkedDataRecord)record).copy(); if (newSeries != null) { newSeries.insertData(linkedDataRecord); } newRecord = linkedDataRecord; } else if (record instanceof DataFormatRecord) { - DataFormatRecord dataFormatRecord = ((DataFormatRecord)record).clone(); + DataFormatRecord dataFormatRecord = ((DataFormatRecord)record).copy(); dataFormatRecord.setSeriesIndex((short)seriesIdx) ; dataFormatRecord.setSeriesNumber((short)seriesIdx) ; newRecord = dataFormatRecord; } else if (record instanceof SeriesTextRecord) { - SeriesTextRecord seriesTextRecord = (SeriesTextRecord) ((SeriesTextRecord)record).clone(); + SeriesTextRecord seriesTextRecord = (SeriesTextRecord) ((SeriesTextRecord)record).copy(); if (newSeries != null) { newSeries.setSeriesTitleText(seriesTextRecord); } newRecord = seriesTextRecord; } else if (record instanceof Record) { - newRecord = (Record) ((Record)record).clone(); + newRecord = (Record) ((Record)record).copy(); } if (newRecord != null) diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFHyperlink.java b/src/java/org/apache/poi/hssf/usermodel/HSSFHyperlink.java index 88b55d5357..7d3defe16d 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFHyperlink.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFHyperlink.java @@ -39,7 +39,7 @@ public class HSSFHyperlink implements Hyperlink { /** * Construct a new hyperlink - * + * * This method is internal to be used only by * {@link HSSFCreationHelper#createHyperlink(HyperlinkType)}. * @@ -76,7 +76,7 @@ public class HSSFHyperlink implements Hyperlink { this.record = record; link_type = getType(record); } - + private static HyperlinkType getType(HyperlinkRecord record) { HyperlinkType link_type; // Figure out the type @@ -94,11 +94,11 @@ public class HSSFHyperlink implements Hyperlink { } return link_type; } - + protected HSSFHyperlink(Hyperlink other) { if (other instanceof HSSFHyperlink) { HSSFHyperlink hlink = (HSSFHyperlink) other; - record = hlink.record.clone(); + record = hlink.record.copy(); link_type = getType(record); } else { @@ -264,7 +264,7 @@ public class HSSFHyperlink implements Hyperlink { public HyperlinkType getType() { return link_type; } - + /** * Return the type of this hyperlink * @@ -277,7 +277,7 @@ public class HSSFHyperlink implements Hyperlink { public HyperlinkType getTypeEnum() { return getType(); } - + /** * @return whether the objects have the same HyperlinkRecord */ @@ -288,7 +288,7 @@ public class HSSFHyperlink implements Hyperlink { HSSFHyperlink otherLink = (HSSFHyperlink) other; return record == otherLink.record; } - + @Override public int hashCode() { return record.hashCode(); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFRichTextString.java b/src/java/org/apache/poi/hssf/usermodel/HSSFRichTextString.java index 3b8f83d8ef..dd146e03f3 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFRichTextString.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFRichTextString.java @@ -21,8 +21,8 @@ import java.util.Iterator; import org.apache.poi.hssf.model.InternalWorkbook; import org.apache.poi.hssf.record.LabelSSTRecord; +import org.apache.poi.hssf.record.common.FormatRun; import org.apache.poi.hssf.record.common.UnicodeString; -import org.apache.poi.hssf.record.common.UnicodeString.FormatRun; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.RichTextString; /** @@ -105,9 +105,7 @@ public final class HSSFRichTextString implements Comparable<HSSFRichTextString>, * be affected by changes that we make to this string. */ private UnicodeString cloneStringIfRequired() { - if (_book == null) - return _string; - return (UnicodeString)_string.clone(); + return (_book == null) ? _string : _string.copy(); } private void addToSSTIfRequired() { @@ -148,16 +146,16 @@ public final class HSSFRichTextString implements Comparable<HSSFRichTextString>, Iterator<FormatRun> formatting = _string.formatIterator(); if (formatting != null) { while (formatting.hasNext()) { - UnicodeString.FormatRun r = formatting.next(); + FormatRun r = formatting.next(); if ((r.getCharacterPos() >= startIndex) && (r.getCharacterPos() < endIndex)) formatting.remove(); } } - _string.addFormatRun(new UnicodeString.FormatRun((short)startIndex, fontIndex)); + _string.addFormatRun(new FormatRun((short)startIndex, fontIndex)); if (endIndex != length()) - _string.addFormatRun(new UnicodeString.FormatRun((short)endIndex, currentFont)); + _string.addFormatRun(new FormatRun((short)endIndex, currentFont)); addToSSTIfRequired(); } @@ -240,9 +238,9 @@ public final class HSSFRichTextString implements Comparable<HSSFRichTextString>, */ public short getFontAtIndex( int index ) { int size = _string.getFormatRunCount(); - UnicodeString.FormatRun currentRun = null; + FormatRun currentRun = null; for (int i=0;i<size;i++) { - UnicodeString.FormatRun r = _string.getFormatRun(i); + FormatRun r = _string.getFormatRun(i); if (r.getCharacterPos() > index) { break; } @@ -270,7 +268,7 @@ public final class HSSFRichTextString implements Comparable<HSSFRichTextString>, * @return the index within the string. */ public int getIndexOfFormattingRun(int index) { - UnicodeString.FormatRun r = _string.getFormatRun(index); + FormatRun r = _string.getFormatRun(index); return r.getCharacterPos(); } @@ -281,7 +279,7 @@ public final class HSSFRichTextString implements Comparable<HSSFRichTextString>, * @return the font number used. */ public short getFontOfFormattingRun(int index) { - UnicodeString.FormatRun r = _string.getFormatRun(index); + FormatRun r = _string.getFormatRun(index); return r.getFontIndex(); } @@ -307,7 +305,7 @@ public final class HSSFRichTextString implements Comparable<HSSFRichTextString>, return 42; // any arbitrary constant will do } - + /** * @return the plain text representation of this string. */ diff --git a/src/java/org/apache/poi/hssf/util/CellRangeAddress8Bit.java b/src/java/org/apache/poi/hssf/util/CellRangeAddress8Bit.java index 50a2ac2c13..c70e525667 100644 --- a/src/java/org/apache/poi/hssf/util/CellRangeAddress8Bit.java +++ b/src/java/org/apache/poi/hssf/util/CellRangeAddress8Bit.java @@ -53,6 +53,7 @@ public final class CellRangeAddress8Bit extends CellRangeAddressBase { out.writeByte(getLastColumn()); } + @Override public CellRangeAddress8Bit copy() { return new CellRangeAddress8Bit(getFirstRow(), getLastRow(), getFirstColumn(), getLastColumn()); } diff --git a/src/java/org/apache/poi/hssf/util/LazilyConcatenatedByteArray.java b/src/java/org/apache/poi/hssf/util/LazilyConcatenatedByteArray.java index d7bb427cba..5b084916a2 100644 --- a/src/java/org/apache/poi/hssf/util/LazilyConcatenatedByteArray.java +++ b/src/java/org/apache/poi/hssf/util/LazilyConcatenatedByteArray.java @@ -49,6 +49,10 @@ public class LazilyConcatenatedByteArray { arrays.add(array); } + public void concatenate(LazilyConcatenatedByteArray other) { + arrays.addAll(other.arrays); + } + /** * Gets the concatenated contents as a single byte array. * diff --git a/src/java/org/apache/poi/poifs/crypt/Decryptor.java b/src/java/org/apache/poi/poifs/crypt/Decryptor.java index ad75f5b134..d3743c47d4 100644 --- a/src/java/org/apache/poi/poifs/crypt/Decryptor.java +++ b/src/java/org/apache/poi/poifs/crypt/Decryptor.java @@ -24,7 +24,6 @@ import java.util.function.Supplier; import javax.crypto.Cipher; import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; import org.apache.poi.EncryptedDocumentException; import org.apache.poi.common.usermodel.GenericRecord; @@ -32,18 +31,26 @@ import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.util.GenericRecordUtil; -public abstract class Decryptor implements Cloneable, GenericRecord { +public abstract class Decryptor implements GenericRecord { @SuppressWarnings({"squid:S2068"}) public static final String DEFAULT_PASSWORD="VelvetSweatshop"; public static final String DEFAULT_POIFS_ENTRY="EncryptedPackage"; - + protected EncryptionInfo encryptionInfo; private SecretKey secretKey; private byte[] verifier, integrityHmacKey, integrityHmacValue; - protected Decryptor() { + protected Decryptor() {} + + protected Decryptor(Decryptor other) { + encryptionInfo = other.encryptionInfo; + // secretKey is immutable + secretKey = other.secretKey; + verifier = (other.verifier == null) ? null : other.verifier.clone(); + integrityHmacKey = (other.integrityHmacKey == null) ? null : other.integrityHmacKey.clone(); + integrityHmacValue = (other.integrityHmacValue == null) ? null : other.integrityHmacValue.clone(); } - + /** * Return a stream with decrypted data. * <p> @@ -60,7 +67,7 @@ public abstract class Decryptor implements Cloneable, GenericRecord { /** * Wraps a stream for decryption<p> - * + * * As we are handling streams and don't know the total length beforehand, * it's the callers duty to care for the length of the entries. * @@ -96,7 +103,7 @@ public abstract class Decryptor implements Cloneable, GenericRecord { throws GeneralSecurityException { throw new EncryptedDocumentException("this decryptor doesn't support initCipherForBlock"); } - + public abstract boolean verifyPassword(String password) throws GeneralSecurityException; @@ -137,7 +144,7 @@ public abstract class Decryptor implements Cloneable, GenericRecord { public SecretKey getSecretKey() { return secretKey; } - + public byte[] getIntegrityHmacKey() { return integrityHmacKey; } @@ -167,11 +174,11 @@ public abstract class Decryptor implements Cloneable, GenericRecord { protected int getBlockSizeInBytes() { return encryptionInfo.getHeader().getBlockSize(); } - + protected int getKeySizeInBytes() { return encryptionInfo.getHeader().getKeySize()/8; } - + public EncryptionInfo getEncryptionInfo() { return encryptionInfo; } @@ -180,16 +187,7 @@ public abstract class Decryptor implements Cloneable, GenericRecord { this.encryptionInfo = encryptionInfo; } - @Override - public Decryptor clone() throws CloneNotSupportedException { - Decryptor other = (Decryptor)super.clone(); - other.integrityHmacKey = integrityHmacKey.clone(); - other.integrityHmacValue = integrityHmacValue.clone(); - other.verifier = verifier.clone(); - other.secretKey = new SecretKeySpec(secretKey.getEncoded(), secretKey.getAlgorithm()); - // encryptionInfo is set from outside - return other; - } + public abstract Decryptor copy(); @Override public Map<String, Supplier<?>> getGenericProperties() { diff --git a/src/java/org/apache/poi/poifs/crypt/EncryptionHeader.java b/src/java/org/apache/poi/poifs/crypt/EncryptionHeader.java index 6518281d6f..38f666e15e 100644 --- a/src/java/org/apache/poi/poifs/crypt/EncryptionHeader.java +++ b/src/java/org/apache/poi/poifs/crypt/EncryptionHeader.java @@ -22,18 +22,19 @@ import java.util.Map; import java.util.function.Supplier; import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.common.Duplicatable; import org.apache.poi.common.usermodel.GenericRecord; /** * Reads and processes OOXML Encryption Headers * The constants are largely based on ZIP constants. */ -public abstract class EncryptionHeader implements Cloneable, GenericRecord { +public abstract class EncryptionHeader implements GenericRecord, Duplicatable { public static final int ALGORITHM_RC4 = CipherAlgorithm.rc4.ecmaId; public static final int ALGORITHM_AES_128 = CipherAlgorithm.aes128.ecmaId; public static final int ALGORITHM_AES_192 = CipherAlgorithm.aes192.ecmaId; public static final int ALGORITHM_AES_256 = CipherAlgorithm.aes256.ecmaId; - + public static final int HASH_NONE = HashAlgorithm.none.ecmaId; public static final int HASH_SHA1 = HashAlgorithm.sha1.ecmaId; public static final int HASH_SHA256 = HashAlgorithm.sha256.ecmaId; @@ -46,7 +47,7 @@ public abstract class EncryptionHeader implements Cloneable, GenericRecord { public static final int MODE_ECB = ChainingMode.ecb.ecmaId; public static final int MODE_CBC = ChainingMode.cbc.ecmaId; public static final int MODE_CFB = ChainingMode.cfb.ecmaId; - + private int flags; private int sizeExtra; private CipherAlgorithm cipherAlgorithm; @@ -57,13 +58,26 @@ public abstract class EncryptionHeader implements Cloneable, GenericRecord { private ChainingMode chainingMode; private byte[] keySalt; private String cspName; - + protected EncryptionHeader() {} + protected EncryptionHeader(EncryptionHeader other) { + flags = other.flags; + sizeExtra = other.sizeExtra; + cipherAlgorithm = other.cipherAlgorithm; + hashAlgorithm = other.hashAlgorithm; + keyBits = other.keyBits; + blockSize = other.blockSize; + providerType = other.providerType; + chainingMode = other.chainingMode; + keySalt = (other.keySalt == null) ? null : other.keySalt.clone(); + cspName = other.cspName; + } + public ChainingMode getChainingMode() { return chainingMode; } - + protected void setChainingMode(ChainingMode chainingMode) { this.chainingMode = chainingMode; } @@ -71,7 +85,7 @@ public abstract class EncryptionHeader implements Cloneable, GenericRecord { public int getFlags() { return flags; } - + protected void setFlags(int flags) { this.flags = flags; } @@ -79,7 +93,7 @@ public abstract class EncryptionHeader implements Cloneable, GenericRecord { public int getSizeExtra() { return sizeExtra; } - + protected void setSizeExtra(int sizeExtra) { this.sizeExtra = sizeExtra; } @@ -87,7 +101,7 @@ public abstract class EncryptionHeader implements Cloneable, GenericRecord { public CipherAlgorithm getCipherAlgorithm() { return cipherAlgorithm; } - + protected void setCipherAlgorithm(CipherAlgorithm cipherAlgorithm) { this.cipherAlgorithm = cipherAlgorithm; if (cipherAlgorithm.allowedKeySize.length == 1) { @@ -106,7 +120,7 @@ public abstract class EncryptionHeader implements Cloneable, GenericRecord { public int getKeySize() { return keyBits; } - + /** * Sets the keySize (in bits). Before calling this method, make sure * to set the cipherAlgorithm, as the amount of keyBits gets validated against @@ -127,41 +141,36 @@ public abstract class EncryptionHeader implements Cloneable, GenericRecord { public int getBlockSize() { return blockSize; } - + protected void setBlockSize(int blockSize) { this.blockSize = blockSize; } - + public byte[] getKeySalt() { return keySalt; } - + protected void setKeySalt(byte[] salt) { this.keySalt = (salt == null) ? null : salt.clone(); } public CipherProvider getCipherProvider() { return providerType; - } + } protected void setCipherProvider(CipherProvider providerType) { this.providerType = providerType; } - + public String getCspName() { return cspName; } - + protected void setCspName(String cspName) { this.cspName = cspName; } - @Override - public EncryptionHeader clone() throws CloneNotSupportedException { - EncryptionHeader other = (EncryptionHeader)super.clone(); - other.keySalt = (keySalt == null) ? null : keySalt.clone(); - return other; - } + public abstract EncryptionHeader copy(); @Override public Map<String, Supplier<?>> getGenericProperties() { diff --git a/src/java/org/apache/poi/poifs/crypt/EncryptionInfo.java b/src/java/org/apache/poi/poifs/crypt/EncryptionInfo.java index 826b57e419..81aca4e417 100644 --- a/src/java/org/apache/poi/poifs/crypt/EncryptionInfo.java +++ b/src/java/org/apache/poi/poifs/crypt/EncryptionInfo.java @@ -42,17 +42,7 @@ import org.apache.poi.util.LittleEndianInput; * some {@link EncryptionMode}s. * @see #getBuilder(EncryptionMode) */ -public class EncryptionInfo implements Cloneable, GenericRecord { - private final EncryptionMode encryptionMode; - private final int versionMajor; - private final int versionMinor; - private final int encryptionFlags; - - private EncryptionHeader header; - private EncryptionVerifier verifier; - private Decryptor decryptor; - private Encryptor encryptor; - +public class EncryptionInfo implements GenericRecord { /** * A flag that specifies whether CryptoAPI RC4 or ECMA-376 encryption * ECMA-376 is used. It MUST be 1 unless flagExternal is 1. If flagExternal is 1, it MUST be 0. @@ -65,14 +55,14 @@ public class EncryptionInfo implements Cloneable, GenericRecord { */ @SuppressWarnings("WeakerAccess") public static final BitField flagDocProps = BitFieldFactory.getInstance(0x08); - + /** * A value that MUST be 1 if extensible encryption is used. If this value is 1, * the value of every other field in this structure MUST be 0. */ @SuppressWarnings("WeakerAccess") public static final BitField flagExternal = BitFieldFactory.getInstance(0x10); - + /** * A value that MUST be 1 if the protected content is an ECMA-376 document * ECMA-376. If the fAES bit is 1, the fCryptoAPI bit MUST also be 1. @@ -87,13 +77,23 @@ public class EncryptionInfo implements Cloneable, GenericRecord { "CRYPTO_API", "DOC_PROPS", "EXTERNAL", "AES" }; + private final EncryptionMode encryptionMode; + private final int versionMajor; + private final int versionMinor; + private final int encryptionFlags; + + private EncryptionHeader header; + private EncryptionVerifier verifier; + private Decryptor decryptor; + private Encryptor encryptor; + /** * Opens for decryption */ public EncryptionInfo(POIFSFileSystem fs) throws IOException { this(fs.getRoot()); } - + /** * Opens for decryption */ @@ -141,7 +141,7 @@ public class EncryptionInfo implements Cloneable, GenericRecord { " / fDocProps: "+flagDocProps.isSet(encryptionFlags)+ " / fAES: "+flagAES.isSet(encryptionFlags)); } - + EncryptionInfoBuilder eib; try { eib = getBuilder(encryptionMode); @@ -151,7 +151,7 @@ public class EncryptionInfo implements Cloneable, GenericRecord { eib.initialize(this, dis); } - + /** * Prepares for encryption, using the given Encryption Mode, and * all other parameters as default. @@ -160,7 +160,7 @@ public class EncryptionInfo implements Cloneable, GenericRecord { public EncryptionInfo(EncryptionMode encryptionMode) { this(encryptionMode, null, null, -1, -1, null); } - + /** * Constructs an EncryptionInfo from scratch * @@ -171,7 +171,7 @@ public class EncryptionInfo implements Cloneable, GenericRecord { * @param keyBits the bit count of the key * @param blockSize the size of a cipher block * @param chainingMode the chaining mode - * + * * @throws EncryptedDocumentException if the given parameters mismatch, e.g. only certain combinations * of keyBits, blockSize are allowed for a given {@link CipherAlgorithm} */ @@ -183,7 +183,7 @@ public class EncryptionInfo implements Cloneable, GenericRecord { , int blockSize , ChainingMode chainingMode ) { - this.encryptionMode = encryptionMode; + this.encryptionMode = encryptionMode; versionMajor = encryptionMode.versionMajor; versionMinor = encryptionMode.versionMinor; encryptionFlags = encryptionMode.encryptionFlags; @@ -194,10 +194,28 @@ public class EncryptionInfo implements Cloneable, GenericRecord { } catch (Exception e) { throw new EncryptedDocumentException(e); } - + eib.initialize(this, cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode); } + public EncryptionInfo(EncryptionInfo other) { + encryptionMode = other.encryptionMode; + versionMajor = other.versionMajor; + versionMinor = other.versionMinor; + encryptionFlags = other.encryptionFlags; + + header = (other.header == null) ? null : other.header.copy(); + verifier = (other.verifier == null) ? null : other.verifier.copy(); + if (other.decryptor != null) { + decryptor = other.decryptor.copy(); + decryptor.setEncryptionInfo(this); + } + if (other.encryptor != null) { + encryptor = other.encryptor.copy(); + encryptor.setEncryptionInfo(this); + } + } + /** * This method loads the builder class with reflection, which may generate * a {@code ClassNotFoundException} if the class is not on the classpath. @@ -222,7 +240,7 @@ public class EncryptionInfo implements Cloneable, GenericRecord { eib = (EncryptionInfoBuilder)cl.loadClass(encryptionMode.builder).newInstance(); return eib; } - + public int getVersionMajor() { return versionMajor; } @@ -242,7 +260,7 @@ public class EncryptionInfo implements Cloneable, GenericRecord { public EncryptionVerifier getVerifier() { return verifier; } - + public Decryptor getDecryptor() { return decryptor; } @@ -270,7 +288,7 @@ public class EncryptionInfo implements Cloneable, GenericRecord { public EncryptionMode getEncryptionMode() { return encryptionMode; } - + /** * @return true, if Document Summary / Summary are encrypted and stored in the {@code EncryptedStream} stream, * otherwise the Summaries aren't encrypted and located in their usual streams @@ -278,17 +296,9 @@ public class EncryptionInfo implements Cloneable, GenericRecord { public boolean isDocPropsEncrypted() { return !flagDocProps.isSet(getEncryptionFlags()); } - - @Override - public EncryptionInfo clone() throws CloneNotSupportedException { - EncryptionInfo other = (EncryptionInfo)super.clone(); - other.header = header.clone(); - other.verifier = verifier.clone(); - other.decryptor = decryptor.clone(); - other.decryptor.setEncryptionInfo(other); - other.encryptor = encryptor.clone(); - other.encryptor.setEncryptionInfo(other); - return other; + + public EncryptionInfo copy() { + return new EncryptionInfo(this); } @Override diff --git a/src/java/org/apache/poi/poifs/crypt/EncryptionVerifier.java b/src/java/org/apache/poi/poifs/crypt/EncryptionVerifier.java index 0f3e44b10b..d45fb28c27 100644 --- a/src/java/org/apache/poi/poifs/crypt/EncryptionVerifier.java +++ b/src/java/org/apache/poi/poifs/crypt/EncryptionVerifier.java @@ -21,12 +21,13 @@ 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; /** - * Used when checking if a key is valid for a document + * Used when checking if a key is valid for a document */ -public abstract class EncryptionVerifier implements Cloneable, GenericRecord { +public abstract class EncryptionVerifier implements GenericRecord, Duplicatable { private byte[] salt; private byte[] encryptedVerifier; private byte[] encryptedVerifierHash; @@ -36,21 +37,32 @@ public abstract class EncryptionVerifier implements Cloneable, GenericRecord { private CipherAlgorithm cipherAlgorithm; private ChainingMode chainingMode; private HashAlgorithm hashAlgorithm; - + protected EncryptionVerifier() {} + protected EncryptionVerifier(EncryptionVerifier other) { + salt = (other.salt == null) ? null : other.salt.clone(); + encryptedVerifier = (other.encryptedVerifier == null) ? null : other.encryptedVerifier.clone(); + encryptedVerifierHash = (other.encryptedVerifierHash == null) ? null : other.encryptedVerifierHash.clone(); + encryptedKey = (other.encryptedKey == null) ? null : other.encryptedKey.clone(); + spinCount = other.spinCount; + cipherAlgorithm = other.cipherAlgorithm; + chainingMode = other.chainingMode; + hashAlgorithm = other.hashAlgorithm; + } + public byte[] getSalt() { return salt; } public byte[] getEncryptedVerifier() { return encryptedVerifier; - } - + } + public byte[] getEncryptedVerifierHash() { return encryptedVerifierHash; - } - + } + public int getSpinCount() { return spinCount; } @@ -58,15 +70,15 @@ public abstract class EncryptionVerifier implements Cloneable, GenericRecord { public byte[] getEncryptedKey() { return encryptedKey; } - + public CipherAlgorithm getCipherAlgorithm() { return cipherAlgorithm; } - + public HashAlgorithm getHashAlgorithm() { return hashAlgorithm; } - + public ChainingMode getChainingMode() { return chainingMode; } @@ -102,16 +114,8 @@ public abstract class EncryptionVerifier implements Cloneable, GenericRecord { protected void setHashAlgorithm(HashAlgorithm hashAlgorithm) { this.hashAlgorithm = hashAlgorithm; } - - @Override - public EncryptionVerifier clone() throws CloneNotSupportedException { - EncryptionVerifier other = (EncryptionVerifier)super.clone(); - other.salt = (salt == null) ? null : salt.clone(); - other.encryptedVerifier = (encryptedVerifier == null) ? null : encryptedVerifier.clone(); - other.encryptedVerifierHash = (encryptedVerifierHash == null) ? null : encryptedVerifierHash.clone(); - other.encryptedKey = (encryptedKey == null) ? null : encryptedKey.clone(); - return other; - } + + public abstract EncryptionVerifier copy(); @Override public Map<String, Supplier<?>> getGenericProperties() { diff --git a/src/java/org/apache/poi/poifs/crypt/Encryptor.java b/src/java/org/apache/poi/poifs/crypt/Encryptor.java index 8c241be780..93db9a2792 100644 --- a/src/java/org/apache/poi/poifs/crypt/Encryptor.java +++ b/src/java/org/apache/poi/poifs/crypt/Encryptor.java @@ -23,7 +23,6 @@ import java.util.Map; import java.util.function.Supplier; import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; import org.apache.poi.EncryptedDocumentException; import org.apache.poi.common.usermodel.GenericRecord; @@ -31,11 +30,19 @@ import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.util.GenericRecordUtil; -public abstract class Encryptor implements Cloneable, GenericRecord { +public abstract class Encryptor implements GenericRecord { protected static final String DEFAULT_POIFS_ENTRY = Decryptor.DEFAULT_POIFS_ENTRY; private EncryptionInfo encryptionInfo; private SecretKey secretKey; - + + protected Encryptor() {} + + protected Encryptor(Encryptor other) { + encryptionInfo = other.encryptionInfo; + // secretKey is immutable + secretKey = other.secretKey; + } + /** * Return a output stream for encrypted data. * @@ -47,9 +54,9 @@ public abstract class Encryptor implements Cloneable, GenericRecord { // for tests public abstract void confirmPassword(String password, byte[] keySpec, byte[] keySalt, byte[] verifier, byte[] verifierSalt, byte[] integritySalt); - + public abstract void confirmPassword(String password); - + public static Encryptor getInstance(EncryptionInfo info) { return info.getEncryptor(); } @@ -62,7 +69,7 @@ public abstract class Encryptor implements Cloneable, GenericRecord { throws IOException, GeneralSecurityException { throw new EncryptedDocumentException("this decryptor doesn't support writing directly to a stream"); } - + public SecretKey getSecretKey() { return secretKey; } @@ -89,14 +96,8 @@ public abstract class Encryptor implements Cloneable, GenericRecord { public void setChunkSize(int chunkSize) { throw new EncryptedDocumentException("this decryptor doesn't support changing the chunk size"); } - - @Override - public Encryptor clone() throws CloneNotSupportedException { - Encryptor other = (Encryptor)super.clone(); - other.secretKey = new SecretKeySpec(secretKey.getEncoded(), secretKey.getAlgorithm()); - // encryptionInfo is set from outside - return other; - } + + public abstract Encryptor copy(); @Override public Map<String, Supplier<?>> getGenericProperties() { diff --git a/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java b/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java index 176e779b31..368d2dbb31 100644 --- a/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java +++ b/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java @@ -28,16 +28,22 @@ import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import org.apache.poi.EncryptedDocumentException; -import org.apache.poi.poifs.crypt.*; +import org.apache.poi.poifs.crypt.ChunkedCipherInputStream; +import org.apache.poi.poifs.crypt.CryptoFunctions; +import org.apache.poi.poifs.crypt.Decryptor; +import org.apache.poi.poifs.crypt.EncryptionHeader; +import org.apache.poi.poifs.crypt.EncryptionInfo; +import org.apache.poi.poifs.crypt.EncryptionVerifier; +import org.apache.poi.poifs.crypt.HashAlgorithm; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.DocumentInputStream; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.StringUtil; -public class BinaryRC4Decryptor extends Decryptor implements Cloneable { +public class BinaryRC4Decryptor extends Decryptor { private long length = -1L; private int chunkSize = 512; - + private class BinaryRC4CipherInputStream extends ChunkedCipherInputStream { @Override @@ -54,12 +60,18 @@ public class BinaryRC4Decryptor extends Decryptor implements Cloneable { public BinaryRC4CipherInputStream(InputStream stream, int size, int initialPos) throws GeneralSecurityException { super(stream, size, chunkSize, initialPos); - } + } } protected BinaryRC4Decryptor() { } + protected BinaryRC4Decryptor(BinaryRC4Decryptor other) { + super(other); + length = other.length; + chunkSize = other.chunkSize; + } + @Override public boolean verifyPassword(String password) { EncryptionVerifier ver = getEncryptionInfo().getVerifier(); @@ -89,8 +101,8 @@ public class BinaryRC4Decryptor extends Decryptor implements Cloneable { public Cipher initCipherForBlock(Cipher cipher, int block) throws GeneralSecurityException { return initCipherForBlock(cipher, block, getEncryptionInfo(), getSecretKey(), Cipher.DECRYPT_MODE); - } - + } + protected static Cipher initCipherForBlock(Cipher cipher, int block, EncryptionInfo encryptionInfo, SecretKey skey, int encryptMode) throws GeneralSecurityException { @@ -136,20 +148,20 @@ public class BinaryRC4Decryptor extends Decryptor implements Cloneable { length = dis.readLong(); return new BinaryRC4CipherInputStream(dis, length); } - + @Override public InputStream getDataStream(InputStream stream, int size, int initialPos) throws IOException, GeneralSecurityException { return new BinaryRC4CipherInputStream(stream, size, initialPos); } - + @Override public long getLength() { if (length == -1L) { throw new IllegalStateException("Decryptor.getDataStream() was not called"); } - + return length; } @@ -157,9 +169,9 @@ public class BinaryRC4Decryptor extends Decryptor implements Cloneable { public void setChunkSize(int chunkSize) { this.chunkSize = chunkSize; } - + @Override - public BinaryRC4Decryptor clone() throws CloneNotSupportedException { - return (BinaryRC4Decryptor)super.clone(); + public BinaryRC4Decryptor copy() { + return new BinaryRC4Decryptor(this); } } diff --git a/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionHeader.java b/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionHeader.java index 549d0f85f9..f9051b652c 100644 --- a/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionHeader.java +++ b/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionHeader.java @@ -24,7 +24,7 @@ import org.apache.poi.poifs.crypt.HashAlgorithm; import org.apache.poi.poifs.crypt.standard.EncryptionRecord; import org.apache.poi.util.LittleEndianByteArrayOutputStream; -public class BinaryRC4EncryptionHeader extends EncryptionHeader implements EncryptionRecord, Cloneable { +public class BinaryRC4EncryptionHeader extends EncryptionHeader implements EncryptionRecord { protected BinaryRC4EncryptionHeader() { setCipherAlgorithm(CipherAlgorithm.rc4); @@ -38,14 +38,16 @@ public class BinaryRC4EncryptionHeader extends EncryptionHeader implements Encry setChainingMode(null); } + protected BinaryRC4EncryptionHeader(BinaryRC4EncryptionHeader other) { + super(other); + } + @Override public void write(LittleEndianByteArrayOutputStream littleendianbytearrayoutputstream) { } @Override - public BinaryRC4EncryptionHeader clone() throws CloneNotSupportedException { - return (BinaryRC4EncryptionHeader)super.clone(); + public BinaryRC4EncryptionHeader copy() { + return new BinaryRC4EncryptionHeader(this); } - - } diff --git a/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionVerifier.java b/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionVerifier.java index 098a69452a..689c06932d 100644 --- a/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionVerifier.java +++ b/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionVerifier.java @@ -18,12 +18,14 @@ package org.apache.poi.poifs.crypt.binaryrc4; import org.apache.poi.EncryptedDocumentException; -import org.apache.poi.poifs.crypt.*; +import org.apache.poi.poifs.crypt.CipherAlgorithm; +import org.apache.poi.poifs.crypt.EncryptionVerifier; +import org.apache.poi.poifs.crypt.HashAlgorithm; import org.apache.poi.poifs.crypt.standard.EncryptionRecord; import org.apache.poi.util.LittleEndianByteArrayOutputStream; import org.apache.poi.util.LittleEndianInput; -public class BinaryRC4EncryptionVerifier extends EncryptionVerifier implements EncryptionRecord, Cloneable { +public class BinaryRC4EncryptionVerifier extends EncryptionVerifier implements EncryptionRecord { protected BinaryRC4EncryptionVerifier() { setSpinCount(-1); @@ -50,12 +52,16 @@ public class BinaryRC4EncryptionVerifier extends EncryptionVerifier implements E setHashAlgorithm(HashAlgorithm.md5); } + protected BinaryRC4EncryptionVerifier(BinaryRC4EncryptionVerifier other) { + super(other); + } + @Override protected void setSalt(byte[] salt) { if (salt == null || salt.length != 16) { throw new EncryptedDocumentException("invalid verifier salt"); } - + super.setSalt(salt); } @@ -83,7 +89,7 @@ public class BinaryRC4EncryptionVerifier extends EncryptionVerifier implements E } @Override - public BinaryRC4EncryptionVerifier clone() throws CloneNotSupportedException { - return (BinaryRC4EncryptionVerifier)super.clone(); + public BinaryRC4EncryptionVerifier copy() { + return new BinaryRC4EncryptionVerifier(this); } } diff --git a/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Encryptor.java b/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Encryptor.java index 6c67f32015..c048271421 100644 --- a/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Encryptor.java +++ b/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Encryptor.java @@ -39,11 +39,15 @@ import org.apache.poi.poifs.crypt.standard.EncryptionRecord; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.util.LittleEndianByteArrayOutputStream; -public class BinaryRC4Encryptor extends Encryptor implements Cloneable { +public class BinaryRC4Encryptor extends Encryptor { private int chunkSize = 512; - - protected BinaryRC4Encryptor() { + + protected BinaryRC4Encryptor() {} + + protected BinaryRC4Encryptor(BinaryRC4Encryptor other) { + super(other); + chunkSize = other.chunkSize; } @Override @@ -90,7 +94,7 @@ public class BinaryRC4Encryptor extends Encryptor implements Cloneable { throws IOException, GeneralSecurityException { return new BinaryRC4CipherOutputStream(stream); } - + protected int getKeySizeInBytes() { return getEncryptionInfo().getHeader().getKeySize() / 8; } @@ -116,10 +120,10 @@ public class BinaryRC4Encryptor extends Encryptor implements Cloneable { public void setChunkSize(int chunkSize) { this.chunkSize = chunkSize; } - + @Override - public BinaryRC4Encryptor clone() throws CloneNotSupportedException { - return (BinaryRC4Encryptor)super.clone(); + public BinaryRC4Encryptor copy() { + return new BinaryRC4Encryptor(this); } protected class BinaryRC4CipherOutputStream extends ChunkedCipherOutputStream { @@ -139,7 +143,7 @@ public class BinaryRC4Encryptor extends Encryptor implements Cloneable { throws GeneralSecurityException { return BinaryRC4Decryptor.initCipherForBlock(cipher, block, getEncryptionInfo(), getSecretKey(), Cipher.ENCRYPT_MODE); } - + @Override protected void calculateChecksum(File file, int i) { } diff --git a/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java b/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java index 550dcde2ee..affadffdc2 100644 --- a/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java +++ b/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java @@ -49,13 +49,13 @@ import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndianInputStream; import org.apache.poi.util.StringUtil; -public class CryptoAPIDecryptor extends Decryptor implements Cloneable { +public class CryptoAPIDecryptor extends Decryptor { private long length = -1L; private int chunkSize = -1; static class StreamDescriptorEntry { - static BitField flagStream = BitFieldFactory.getInstance(1); + static final BitField flagStream = BitFieldFactory.getInstance(1); int streamOffset; int streamSize; @@ -65,7 +65,12 @@ public class CryptoAPIDecryptor extends Decryptor implements Cloneable { String streamName; } - protected CryptoAPIDecryptor() { + protected CryptoAPIDecryptor() {} + + protected CryptoAPIDecryptor(CryptoAPIDecryptor other) { + super(other); + length = other.length; + chunkSize = other.chunkSize; } @Override @@ -153,13 +158,13 @@ public class CryptoAPIDecryptor extends Decryptor implements Cloneable { * Decrypt the Document-/SummaryInformation and other optionally streams. * Opposed to other crypto modes, cryptoapi is record based and can't be used * to stream-decrypt a whole file.<p> - * + * * Summary entries are only encrypted within cryptoapi encrypted files. * Binary RC4 encrypted files use non-encrypted/default property sets - * + * * @param root root directory node of the OLE file containing the encrypted properties * @param encryptedStream name of the encrypted stream - - * "encryption" for HSSF/HWPF, "encryptedStream" (or encryptedSummary?) for HSLF + * "encryption" for HSSF/HWPF, "encryptedStream" (or encryptedSummary?) for HSLF * * @see <a href="http://msdn.microsoft.com/en-us/library/dd943321(v=office.12).aspx">2.3.5.4 RC4 CryptoAPI Encrypted Summary Stream</a> */ @@ -239,8 +244,8 @@ public class CryptoAPIDecryptor extends Decryptor implements Cloneable { } @Override - public CryptoAPIDecryptor clone() throws CloneNotSupportedException { - return (CryptoAPIDecryptor)super.clone(); + public CryptoAPIDecryptor copy() { + return new CryptoAPIDecryptor(this); } private class CryptoAPICipherInputStream extends ChunkedCipherInputStream { diff --git a/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionHeader.java b/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionHeader.java index 2e838f7ddf..9c0af9b177 100644 --- a/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionHeader.java +++ b/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionHeader.java @@ -27,12 +27,16 @@ import org.apache.poi.poifs.crypt.HashAlgorithm; import org.apache.poi.poifs.crypt.standard.StandardEncryptionHeader; import org.apache.poi.util.LittleEndianInput; -public class CryptoAPIEncryptionHeader extends StandardEncryptionHeader implements Cloneable { +public class CryptoAPIEncryptionHeader extends StandardEncryptionHeader { public CryptoAPIEncryptionHeader(LittleEndianInput is) throws IOException { super(is); } + protected CryptoAPIEncryptionHeader(CryptoAPIEncryptionHeader other) { + super(other); + } + protected CryptoAPIEncryptionHeader(CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) { @@ -62,7 +66,7 @@ public class CryptoAPIEncryptionHeader extends StandardEncryptionHeader implemen } @Override - public CryptoAPIEncryptionHeader clone() throws CloneNotSupportedException { - return (CryptoAPIEncryptionHeader)super.clone(); + public CryptoAPIEncryptionHeader copy() { + return new CryptoAPIEncryptionHeader(this); } } diff --git a/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionVerifier.java b/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionVerifier.java index 9c43626f2d..c54b9851d0 100644 --- a/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionVerifier.java +++ b/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionVerifier.java @@ -23,7 +23,7 @@ import org.apache.poi.poifs.crypt.HashAlgorithm; import org.apache.poi.poifs.crypt.standard.StandardEncryptionVerifier; import org.apache.poi.util.LittleEndianInput; -public class CryptoAPIEncryptionVerifier extends StandardEncryptionVerifier implements Cloneable { +public class CryptoAPIEncryptionVerifier extends StandardEncryptionVerifier { protected CryptoAPIEncryptionVerifier(LittleEndianInput is, CryptoAPIEncryptionHeader header) { @@ -36,6 +36,10 @@ public class CryptoAPIEncryptionVerifier extends StandardEncryptionVerifier impl super(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode); } + protected CryptoAPIEncryptionVerifier(CryptoAPIEncryptionVerifier other) { + super(other); + } + @Override protected void setSalt(byte[] salt) { super.setSalt(salt); @@ -52,7 +56,7 @@ public class CryptoAPIEncryptionVerifier extends StandardEncryptionVerifier impl } @Override - public CryptoAPIEncryptionVerifier clone() throws CloneNotSupportedException { - return (CryptoAPIEncryptionVerifier)super.clone(); + public CryptoAPIEncryptionVerifier copy() { + return new CryptoAPIEncryptionVerifier(this); } } diff --git a/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptor.java b/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptor.java index 60b1be2841..652e7f51d7 100644 --- a/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptor.java +++ b/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptor.java @@ -46,11 +46,15 @@ import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.StringUtil; -public class CryptoAPIEncryptor extends Encryptor implements Cloneable { - +public class CryptoAPIEncryptor extends Encryptor { + private int chunkSize = 512; - - CryptoAPIEncryptor() { + + CryptoAPIEncryptor() {} + + CryptoAPIEncryptor(CryptoAPIEncryptor other) { + super(other); + chunkSize = other.chunkSize; } @Override @@ -98,31 +102,31 @@ public class CryptoAPIEncryptor extends Encryptor implements Cloneable { public Cipher initCipherForBlock(Cipher cipher, int block) throws GeneralSecurityException { return CryptoAPIDecryptor.initCipherForBlock(cipher, block, getEncryptionInfo(), getSecretKey(), Cipher.ENCRYPT_MODE); - } + } @Override public ChunkedCipherOutputStream getDataStream(DirectoryNode dir) throws IOException { throw new IOException("not supported"); } - + @Override public CryptoAPICipherOutputStream getDataStream(OutputStream stream, int initialOffset) throws IOException, GeneralSecurityException { return new CryptoAPICipherOutputStream(stream); } - + /** * Encrypt the Document-/SummaryInformation and other optionally streams. * Opposed to other crypto modes, cryptoapi is record based and can't be used * to stream-encrypt a whole file - * + * * @see <a href="http://msdn.microsoft.com/en-us/library/dd943321(v=office.12).aspx">2.3.5.4 RC4 CryptoAPI Encrypted Summary Stream</a> */ public void setSummaryEntries(DirectoryNode dir, String encryptedStream, POIFSFileSystem entries) throws IOException, GeneralSecurityException { CryptoAPIDocumentOutputStream bos = new CryptoAPIDocumentOutputStream(this); // NOSONAR byte[] buf = new byte[8]; - + bos.write(buf, 0, 8); // skip header List<StreamDescriptorEntry> descList = new ArrayList<>(); @@ -137,24 +141,24 @@ public class CryptoAPIEncryptor extends Encryptor implements Cloneable { descEntry.streamName = entry.getName(); descEntry.flags = StreamDescriptorEntry.flagStream.setValue(0, 1); descEntry.reserved2 = 0; - + bos.setBlock(block); DocumentInputStream dis = dir.createDocumentInputStream(entry); IOUtils.copy(dis, bos); dis.close(); - + descEntry.streamSize = bos.size() - descEntry.streamOffset; descList.add(descEntry); - + block++; } - + int streamDescriptorArrayOffset = bos.size(); - + bos.setBlock(0); LittleEndian.putUInt(buf, 0, descList.size()); bos.write(buf, 0, 4); - + for (StreamDescriptorEntry sde : descList) { LittleEndian.putUInt(buf, 0, sde.streamOffset); bos.write(buf, 0, 4); @@ -173,7 +177,7 @@ public class CryptoAPIEncryptor extends Encryptor implements Cloneable { LittleEndian.putShort(buf, 0, (short)0); // null-termination bos.write(buf, 0, 2); } - + int savedSize = bos.size(); int streamDescriptorArraySize = savedSize - streamDescriptorArrayOffset; LittleEndian.putUInt(buf, 0, streamDescriptorArrayOffset); @@ -183,7 +187,7 @@ public class CryptoAPIEncryptor extends Encryptor implements Cloneable { bos.setBlock(0); bos.write(buf, 0, 8); bos.setSize(savedSize); - + dir.createDocument(encryptedStream, new ByteArrayInputStream(bos.getBuf(), 0, savedSize)); } @@ -195,10 +199,10 @@ public class CryptoAPIEncryptor extends Encryptor implements Cloneable { public void setChunkSize(int chunkSize) { this.chunkSize = chunkSize; } - + @Override - public CryptoAPIEncryptor clone() throws CloneNotSupportedException { - return (CryptoAPIEncryptor)super.clone(); + public CryptoAPIEncryptor copy() { + return new CryptoAPIEncryptor(this); } protected class CryptoAPICipherOutputStream extends ChunkedCipherOutputStream { diff --git a/src/java/org/apache/poi/poifs/crypt/standard/StandardDecryptor.java b/src/java/org/apache/poi/poifs/crypt/standard/StandardDecryptor.java index 9c7926033d..9fedce6122 100644 --- a/src/java/org/apache/poi/poifs/crypt/standard/StandardDecryptor.java +++ b/src/java/org/apache/poi/poifs/crypt/standard/StandardDecryptor.java @@ -43,10 +43,14 @@ import org.apache.poi.util.LittleEndian; /** */ -public class StandardDecryptor extends Decryptor implements Cloneable { +public class StandardDecryptor extends Decryptor { private long _length = -1; - protected StandardDecryptor() { + protected StandardDecryptor() {} + + protected StandardDecryptor(StandardDecryptor other) { + super(other); + _length = other._length; } @Override @@ -68,7 +72,7 @@ public class StandardDecryptor extends Decryptor implements Cloneable { // ... The number of bytes used by the encrypted Verifier hash MUST be 32 ... // TODO: check and trim/pad the hashes to 32 byte[] verifierHash = Arrays.copyOf(decryptedVerifierHash, calcVerifierHash.length); - + if (Arrays.equals(calcVerifierHash, verifierHash)) { setSecretKey(skey); return true; @@ -79,7 +83,7 @@ public class StandardDecryptor extends Decryptor implements Cloneable { throw new EncryptedDocumentException(e); } } - + protected static SecretKey generateSecretKey(String password, EncryptionVerifier ver, int keySize) { HashAlgorithm hashAlgo = ver.getHashAlgorithm(); @@ -95,7 +99,7 @@ public class StandardDecryptor extends Decryptor implements Cloneable { byte[] x3 = new byte[x1.length + x2.length]; System.arraycopy(x1, 0, x3, 0, x1.length); System.arraycopy(x2, 0, x3, x1.length, x2.length); - + byte[] key = Arrays.copyOf(x3, keySize); return new SecretKeySpec(key, ver.getCipherAlgorithm().jceId); @@ -131,12 +135,12 @@ public class StandardDecryptor extends Decryptor implements Cloneable { verifyPassword(null); } // limit wrong calculated ole entries - (bug #57080) - // standard encryption always uses aes encoding, so blockSize is always 16 + // standard encryption always uses aes encoding, so blockSize is always 16 // http://stackoverflow.com/questions/3283787/size-of-data-after-aes-encryption int blockSize = getEncryptionInfo().getHeader().getCipherAlgorithm().blockSize; long cipherLen = (_length/blockSize + 1) * blockSize; Cipher cipher = getCipher(getSecretKey()); - + InputStream boundedDis = new BoundedInputStream(dis, cipherLen); return new BoundedInputStream(new CipherInputStream(boundedDis, cipher), _length); } @@ -153,7 +157,7 @@ public class StandardDecryptor extends Decryptor implements Cloneable { } @Override - public StandardDecryptor clone() throws CloneNotSupportedException { - return (StandardDecryptor)super.clone(); + public StandardDecryptor copy() { + return new StandardDecryptor(this); } } diff --git a/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionHeader.java b/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionHeader.java index 2c42c60f8e..139bb2ac70 100644 --- a/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionHeader.java +++ b/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionHeader.java @@ -34,7 +34,11 @@ import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.StringUtil; -public class StandardEncryptionHeader extends EncryptionHeader implements EncryptionRecord, Cloneable { +public class StandardEncryptionHeader extends EncryptionHeader implements EncryptionRecord { + + protected StandardEncryptionHeader(StandardEncryptionHeader other) { + super(other); + } protected StandardEncryptionHeader(LittleEndianInput is) throws IOException { setFlags(is.readInt()); @@ -67,7 +71,7 @@ public class StandardEncryptionHeader extends EncryptionHeader implements Encryp } else { ((InputStream)is).reset(); } - + if (checkForSalt == 16) { setCspName(""); } else { @@ -81,7 +85,7 @@ public class StandardEncryptionHeader extends EncryptionHeader implements Encryp } setCspName(builder.toString()); } - + setChainingMode(ChainingMode.ecb); setKeySalt(null); } @@ -97,9 +101,9 @@ public class StandardEncryptionHeader extends EncryptionHeader implements Encryp // see http://msdn.microsoft.com/en-us/library/windows/desktop/bb931357(v=vs.85).aspx for a full list // setCspName("Microsoft Enhanced RSA and AES Cryptographic Provider"); } - + /** - * serializes the header + * serializes the header */ @Override public void write(LittleEndianByteArrayOutputStream bos) { @@ -120,11 +124,11 @@ public class StandardEncryptionHeader extends EncryptionHeader implements Encryp bos.write(StringUtil.getToUnicodeLE(cspName)); bos.writeShort(0); int headerSize = bos.getWriteIndex()-startIdx-LittleEndianConsts.INT_SIZE; - sizeOutput.writeInt(headerSize); + sizeOutput.writeInt(headerSize); } @Override - public StandardEncryptionHeader clone() throws CloneNotSupportedException { - return (StandardEncryptionHeader)super.clone(); + public StandardEncryptionHeader copy() { + return new StandardEncryptionHeader(this); } } diff --git a/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionVerifier.java b/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionVerifier.java index a60feae30a..4c5f2e0d3d 100644 --- a/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionVerifier.java +++ b/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionVerifier.java @@ -25,12 +25,12 @@ import org.apache.poi.util.LittleEndianByteArrayOutputStream; import org.apache.poi.util.LittleEndianInput; /** - * Used when checking if a key is valid for a document + * Used when checking if a key is valid for a document */ -public class StandardEncryptionVerifier extends EncryptionVerifier implements EncryptionRecord, Cloneable { +public class StandardEncryptionVerifier extends EncryptionVerifier implements EncryptionRecord { private static final int SPIN_COUNT = 50000; private final int verifierHashSize; - + protected StandardEncryptionVerifier(LittleEndianInput is, StandardEncryptionHeader header) { int saltSize = is.readInt(); @@ -56,9 +56,9 @@ public class StandardEncryptionVerifier extends EncryptionVerifier implements En setCipherAlgorithm(header.getCipherAlgorithm()); setChainingMode(header.getChainingMode()); setEncryptedKey(null); - setHashAlgorithm(header.getHashAlgorithm()); + setHashAlgorithm(header.getHashAlgorithm()); } - + protected StandardEncryptionVerifier(CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) { setCipherAlgorithm(cipherAlgorithm); setHashAlgorithm(hashAlgorithm); @@ -67,6 +67,11 @@ public class StandardEncryptionVerifier extends EncryptionVerifier implements En verifierHashSize = hashAlgorithm.hashSize; } + protected StandardEncryptionVerifier(StandardEncryptionVerifier other) { + super(other); + verifierHashSize = other.verifierHashSize; + } + // make method visible for this package @Override protected void setSalt(byte[] salt) { @@ -75,7 +80,7 @@ public class StandardEncryptionVerifier extends EncryptionVerifier implements En } super.setSalt(salt); } - + // make method visible for this package @Override protected void setEncryptedVerifier(byte[] encryptedVerifier) { @@ -87,7 +92,7 @@ public class StandardEncryptionVerifier extends EncryptionVerifier implements En protected void setEncryptedVerifierHash(byte[] encryptedVerifierHash) { super.setEncryptedVerifierHash(encryptedVerifierHash); } - + @Override public void write(LittleEndianByteArrayOutputStream bos) { // see [MS-OFFCRYPTO] - 2.3.4.9 @@ -95,7 +100,7 @@ public class StandardEncryptionVerifier extends EncryptionVerifier implements En assert(salt.length == 16); bos.writeInt(salt.length); // salt size bos.write(salt); - + // The resulting Verifier value MUST be an array of 16 bytes. byte[] encryptedVerifier = getEncryptedVerifier(); assert(encryptedVerifier.length == 16); @@ -121,7 +126,7 @@ public class StandardEncryptionVerifier extends EncryptionVerifier implements En } @Override - public StandardEncryptionVerifier clone() throws CloneNotSupportedException { - return (StandardEncryptionVerifier)super.clone(); + public StandardEncryptionVerifier copy() { + return new StandardEncryptionVerifier(this); } } diff --git a/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java b/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java index 4c4ca2a3fb..2dfbc1f547 100644 --- a/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java +++ b/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java @@ -53,11 +53,14 @@ import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.apache.poi.util.TempFile; -public class StandardEncryptor extends Encryptor implements Cloneable { +public class StandardEncryptor extends Encryptor { private static final POILogger logger = POILogFactory.getLogger(StandardEncryptor.class); - protected StandardEncryptor() { - } + protected StandardEncryptor() {} + + protected StandardEncryptor(StandardEncryptor other) { + super(other); + } @Override public void confirmPassword(String password) { @@ -66,15 +69,15 @@ public class StandardEncryptor extends Encryptor implements Cloneable { byte[] salt = new byte[16], verifier = new byte[16]; r.nextBytes(salt); r.nextBytes(verifier); - + confirmPassword(password, null, null, salt, verifier, null); } - - + + /** * Fills the fields of verifier and header with the calculated hashes based * on the password and a random salt - * + * * see [MS-OFFCRYPTO] - 2.3.4.7 ECMA-376 Document Encryption Key Generation */ @Override @@ -85,35 +88,35 @@ public class StandardEncryptor extends Encryptor implements Cloneable { SecretKey secretKey = generateSecretKey(password, ver, getKeySizeInBytes()); setSecretKey(secretKey); Cipher cipher = getCipher(secretKey, null); - + try { byte[] encryptedVerifier = cipher.doFinal(verifier); MessageDigest hashAlgo = CryptoFunctions.getMessageDigest(ver.getHashAlgorithm()); byte[] calcVerifierHash = hashAlgo.digest(verifier); - + // 2.3.3 EncryptionVerifier ... - // An array of bytes that contains the encrypted form of the - // hash of the randomly generated Verifier value. The length of the array MUST be the size of - // the encryption block size multiplied by the number of blocks needed to encrypt the hash of the - // Verifier. If the encryption algorithm is RC4, the length MUST be 20 bytes. If the encryption + // An array of bytes that contains the encrypted form of the + // hash of the randomly generated Verifier value. The length of the array MUST be the size of + // the encryption block size multiplied by the number of blocks needed to encrypt the hash of the + // Verifier. If the encryption algorithm is RC4, the length MUST be 20 bytes. If the encryption // algorithm is AES, the length MUST be 32 bytes. After decrypting the EncryptedVerifierHash // field, only the first VerifierHashSize bytes MUST be used. int encVerHashSize = ver.getCipherAlgorithm().encryptedVerifierHashLength; byte[] encryptedVerifierHash = cipher.doFinal(Arrays.copyOf(calcVerifierHash, encVerHashSize)); - + ver.setEncryptedVerifier(encryptedVerifier); ver.setEncryptedVerifierHash(encryptedVerifierHash); } catch (GeneralSecurityException e) { throw new EncryptedDocumentException("Password confirmation failed", e); } - + } private Cipher getCipher(SecretKey key, String padding) { EncryptionVerifier ver = getEncryptionInfo().getVerifier(); return CryptoFunctions.getCipher(key, ver.getCipherAlgorithm(), ver.getChainingMode(), null, Cipher.ENCRYPT_MODE, padding); } - + @Override public OutputStream getDataStream(final DirectoryNode dir) throws IOException, GeneralSecurityException { @@ -121,7 +124,7 @@ public class StandardEncryptor extends Encryptor implements Cloneable { DataSpaceMapUtils.addDefaultDataSpace(dir); return new StandardCipherOutputStream(dir); } - + protected class StandardCipherOutputStream extends FilterOutputStream implements POIFSWriterListener { protected long countBytes; protected final File fileOut; @@ -137,19 +140,19 @@ public class StandardEncryptor extends Encryptor implements Cloneable { // see also [MS-OFFCRYPT] - 2.3.4.15 // The final data block MUST be padded to the next integral multiple of the // KeyData.blockSize value. Any padding bytes can be used. Note that the StreamSize - // field of the EncryptedPackage field specifies the number of bytes of + // field of the EncryptedPackage field specifies the number of bytes of // unencrypted data as specified in section 2.3.4.4. super( - new CipherOutputStream(new FileOutputStream(fileOut), getCipher(getSecretKey(), "PKCS5Padding")) + new CipherOutputStream(new FileOutputStream(fileOut), getCipher(getSecretKey(), "PKCS5Padding")) ); this.fileOut = fileOut; this.dir = dir; } - + protected StandardCipherOutputStream(DirectoryNode dir) throws IOException { this(dir, TempFile.createTempFile("encrypted_package", "crypt")); } - + @Override public void write(byte[] b, int off, int len) throws IOException { out.write(b, off, len); @@ -161,28 +164,28 @@ public class StandardEncryptor extends Encryptor implements Cloneable { out.write(b); countBytes++; } - + @Override public void close() throws IOException { // the CipherOutputStream adds the padding bytes on close() - super.close(); + super.close(); writeToPOIFS(); } - + void writeToPOIFS() throws IOException { int oleStreamSize = (int)(fileOut.length()+LittleEndianConsts.LONG_SIZE); dir.createDocument(DEFAULT_POIFS_ENTRY, oleStreamSize, this); // TODO: any properties??? } - + @Override public void processPOIFSWriterEvent(POIFSWriterEvent event) { try { LittleEndianOutputStream leos = new LittleEndianOutputStream(event.getStream()); - // StreamSize (8 bytes): An unsigned integer that specifies the number of bytes used by data - // encrypted within the EncryptedData field, not including the size of the StreamSize field. - // Note that the actual size of the \EncryptedPackage stream (1) can be larger than this + // StreamSize (8 bytes): An unsigned integer that specifies the number of bytes used by data + // encrypted within the EncryptedData field, not including the size of the StreamSize field. + // Note that the actual size of the \EncryptedPackage stream (1) can be larger than this // value, depending on the block size of the chosen encryption algorithm leos.writeLong(countBytes); @@ -199,16 +202,16 @@ public class StandardEncryptor extends Encryptor implements Cloneable { } } } - + protected int getKeySizeInBytes() { return getEncryptionInfo().getHeader().getKeySize()/8; } - + protected void createEncryptionInfoEntry(DirectoryNode dir) throws IOException { final EncryptionInfo info = getEncryptionInfo(); final StandardEncryptionHeader header = (StandardEncryptionHeader)info.getHeader(); final StandardEncryptionVerifier verifier = (StandardEncryptionVerifier)info.getVerifier(); - + EncryptionRecord er = new EncryptionRecord(){ @Override public void write(LittleEndianByteArrayOutputStream bos) { @@ -219,14 +222,14 @@ public class StandardEncryptor extends Encryptor implements Cloneable { verifier.write(bos); } }; - + createEncryptionEntry(dir, "EncryptionInfo", er); - + // TODO: any properties??? } @Override - public StandardEncryptor clone() throws CloneNotSupportedException { - return (StandardEncryptor)super.clone(); + public StandardEncryptor copy() { + return new StandardEncryptor(this); } } diff --git a/src/java/org/apache/poi/poifs/crypt/xor/XORDecryptor.java b/src/java/org/apache/poi/poifs/crypt/xor/XORDecryptor.java index 66664b9d4a..d2cebca389 100644 --- a/src/java/org/apache/poi/poifs/crypt/xor/XORDecryptor.java +++ b/src/java/org/apache/poi/poifs/crypt/xor/XORDecryptor.java @@ -33,11 +33,16 @@ import org.apache.poi.poifs.crypt.EncryptionInfo; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.util.LittleEndian; -public class XORDecryptor extends Decryptor implements Cloneable { +public class XORDecryptor extends Decryptor { private long length = -1L; private int chunkSize = 512; - protected XORDecryptor() { + protected XORDecryptor() {} + + protected XORDecryptor(XORDecryptor other) { + super(other); + length = other.length; + chunkSize = other.chunkSize; } @Override @@ -93,23 +98,23 @@ public class XORDecryptor extends Decryptor implements Cloneable { public void setChunkSize(int chunkSize) { this.chunkSize = chunkSize; } - + @Override - public XORDecryptor clone() throws CloneNotSupportedException { - return (XORDecryptor)super.clone(); + public XORDecryptor copy() { + return new XORDecryptor(this); } private class XORCipherInputStream extends ChunkedCipherInputStream { private final int initialOffset; private int recordStart; private int recordEnd; - + public XORCipherInputStream(InputStream stream, int initialPos) throws GeneralSecurityException { super(stream, Integer.MAX_VALUE, chunkSize); this.initialOffset = initialPos; } - + @Override protected Cipher initCipherForBlock(Cipher existing, int block) throws GeneralSecurityException { @@ -123,19 +128,19 @@ public class XORDecryptor extends Decryptor implements Cloneable { final byte[] chunk = getChunk(); final byte[] plain = getPlain(); final int posInChunk = pos & getChunkMask(); - + /* * From: http://social.msdn.microsoft.com/Forums/en-US/3dadbed3-0e68-4f11-8b43-3a2328d9ebd5 - * + * * The initial value for XorArrayIndex is as follows: * XorArrayIndex = (FileOffset + Data.Length) % 16 - * + * * The FileOffset variable in this context is the stream offset into the Workbook stream at * the time we are about to write each of the bytes of the record data. - * This (the value) is then incremented after each byte is written. + * This (the value) is then incremented after each byte is written. */ final int xorArrayIndex = initialOffset+recordEnd+(pos-recordStart); - + for (int i=0; pos+i < recordEnd && i < totalBytes; i++) { // The following is taken from the Libre Office implementation // It seems that the encrypt and decrypt method is mixed up @@ -149,16 +154,16 @@ public class XORDecryptor extends Decryptor implements Cloneable { // the other bytes will be encoded, when setNextRecordSize is called the next time return totalBytes; } - + private byte rotateLeft(byte bits, int shift) { return (byte)(((bits & 0xff) << shift) | ((bits & 0xff) >>> (8 - shift))); } - - + + /** * Decrypts a xor obfuscated byte array. * The data is decrypted in-place - * + * * @see <a href="http://msdn.microsoft.com/en-us/library/dd908506.aspx">2.3.7.3 Binary Document XOR Data Transformation Method 1</a> */ @Override diff --git a/src/java/org/apache/poi/poifs/crypt/xor/XOREncryptionHeader.java b/src/java/org/apache/poi/poifs/crypt/xor/XOREncryptionHeader.java index 873c1abde6..4af028656a 100644 --- a/src/java/org/apache/poi/poifs/crypt/xor/XOREncryptionHeader.java +++ b/src/java/org/apache/poi/poifs/crypt/xor/XOREncryptionHeader.java @@ -21,17 +21,21 @@ import org.apache.poi.poifs.crypt.EncryptionHeader; import org.apache.poi.poifs.crypt.standard.EncryptionRecord; import org.apache.poi.util.LittleEndianByteArrayOutputStream; -public class XOREncryptionHeader extends EncryptionHeader implements EncryptionRecord, Cloneable { +public class XOREncryptionHeader extends EncryptionHeader implements EncryptionRecord { protected XOREncryptionHeader() { } + protected XOREncryptionHeader(XOREncryptionHeader other) { + super(other); + } + @Override public void write(LittleEndianByteArrayOutputStream leos) { } @Override - public XOREncryptionHeader clone() throws CloneNotSupportedException { - return (XOREncryptionHeader)super.clone(); + public XOREncryptionHeader copy() { + return new XOREncryptionHeader(this); } } diff --git a/src/java/org/apache/poi/poifs/crypt/xor/XOREncryptionVerifier.java b/src/java/org/apache/poi/poifs/crypt/xor/XOREncryptionVerifier.java index d3a18e1398..8d6482b31c 100644 --- a/src/java/org/apache/poi/poifs/crypt/xor/XOREncryptionVerifier.java +++ b/src/java/org/apache/poi/poifs/crypt/xor/XOREncryptionVerifier.java @@ -22,7 +22,7 @@ import org.apache.poi.poifs.crypt.standard.EncryptionRecord; import org.apache.poi.util.LittleEndianByteArrayOutputStream; import org.apache.poi.util.LittleEndianInput; -public class XOREncryptionVerifier extends EncryptionVerifier implements EncryptionRecord, Cloneable { +public class XOREncryptionVerifier extends EncryptionVerifier implements EncryptionRecord { protected XOREncryptionVerifier() { setEncryptedKey(new byte[2]); @@ -31,14 +31,14 @@ public class XOREncryptionVerifier extends EncryptionVerifier implements Encrypt protected XOREncryptionVerifier(LittleEndianInput is) { /** - * key (2 bytes): An unsigned integer that specifies the obfuscation key. + * key (2 bytes): An unsigned integer that specifies the obfuscation key. * See [MS-OFFCRYPTO], 2.3.6.2 section, the first step of initializing XOR * array where it describes the generation of 16-bit XorKey value. */ byte[] key = new byte[2]; is.readFully(key); setEncryptedKey(key); - + /** * verificationBytes (2 bytes): An unsigned integer that specifies * the password verification identifier. @@ -47,7 +47,11 @@ public class XOREncryptionVerifier extends EncryptionVerifier implements Encrypt is.readFully(verifier); setEncryptedVerifier(verifier); } - + + protected XOREncryptionVerifier(XOREncryptionVerifier other) { + super(other); + } + @Override public void write(LittleEndianByteArrayOutputStream bos) { bos.write(getEncryptedKey()); @@ -55,8 +59,8 @@ public class XOREncryptionVerifier extends EncryptionVerifier implements Encrypt } @Override - public XOREncryptionVerifier clone() throws CloneNotSupportedException { - return (XOREncryptionVerifier)super.clone(); + public XOREncryptionVerifier copy() { + return new XOREncryptionVerifier(this); } @Override diff --git a/src/java/org/apache/poi/poifs/crypt/xor/XOREncryptor.java b/src/java/org/apache/poi/poifs/crypt/xor/XOREncryptor.java index 04cd5a8543..3b180b20d4 100644 --- a/src/java/org/apache/poi/poifs/crypt/xor/XOREncryptor.java +++ b/src/java/org/apache/poi/poifs/crypt/xor/XOREncryptor.java @@ -33,8 +33,11 @@ import org.apache.poi.poifs.crypt.Encryptor; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.util.LittleEndian; -public class XOREncryptor extends Encryptor implements Cloneable { - protected XOREncryptor() { +public class XOREncryptor extends Encryptor { + protected XOREncryptor() {} + + protected XOREncryptor(XOREncryptor other) { + super(other); } @Override @@ -81,8 +84,8 @@ public class XOREncryptor extends Encryptor implements Cloneable { } @Override - public XOREncryptor clone() throws CloneNotSupportedException { - return (XOREncryptor)super.clone(); + public XOREncryptor copy() { + return new XOREncryptor(this); } private class XORCipherOutputStream extends ChunkedCipherOutputStream { diff --git a/src/java/org/apache/poi/ss/formula/Formula.java b/src/java/org/apache/poi/ss/formula/Formula.java index 50ae3d2aea..ae406f1488 100644 --- a/src/java/org/apache/poi/ss/formula/Formula.java +++ b/src/java/org/apache/poi/ss/formula/Formula.java @@ -31,8 +31,6 @@ import org.apache.poi.util.LittleEndianOutput; /** * Encapsulates an encoded formula token array. - * - * @author Josh Micich */ public class Formula { @@ -45,6 +43,11 @@ public class Formula { private final byte[] _byteEncoding; private final int _encodedTokenLen; + public Formula(Formula other) { + _byteEncoding = (other._byteEncoding == null) ? null : other._byteEncoding.clone(); + _encodedTokenLen = other._encodedTokenLen; + } + private Formula(byte[] byteEncoding, int encodedTokenLen) { _byteEncoding = byteEncoding.clone(); _encodedTokenLen = encodedTokenLen; diff --git a/src/java/org/apache/poi/ss/formula/ptg/AbstractFunctionPtg.java b/src/java/org/apache/poi/ss/formula/ptg/AbstractFunctionPtg.java index bfb7aeba6a..d05637c3ac 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/AbstractFunctionPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/AbstractFunctionPtg.java @@ -26,8 +26,6 @@ import org.apache.poi.ss.formula.function.FunctionMetadataRegistry; * This class provides the base functionality for Excel sheet functions * There are two kinds of function Ptgs - tFunc and tFuncVar * Therefore, this class will have ONLY two subclasses - * @author Avik Sengupta - * @author Andrew C. Oliver (acoliver at apache dot org) */ public abstract class AbstractFunctionPtg extends OperationPtg { diff --git a/src/java/org/apache/poi/ss/formula/ptg/AddPtg.java b/src/java/org/apache/poi/ss/formula/ptg/AddPtg.java index b18bf3a335..aedc6dd86f 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/AddPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/AddPtg.java @@ -18,22 +18,19 @@ package org.apache.poi.ss.formula.ptg; /** - * Addition operator PTG the "+" binomial operator. If you need more - * explanation than that then well...We really can't help you here. - * @author Andrew C. Oliver (acoliver@apache.org) - * @author Jason Height (jheight at chariot dot net dot au) + * Addition operator PTG the "+" binomial operator. */ public final class AddPtg extends ValueOperatorPtg { public final static byte sid = 0x03; - + private final static String ADD = "+"; - public static final ValueOperatorPtg instance = new AddPtg(); + public static final AddPtg instance = new AddPtg(); private AddPtg() { // enforce singleton } - + protected byte getSid() { return sid; } @@ -41,8 +38,8 @@ public final class AddPtg extends ValueOperatorPtg { public int getNumberOfOperands() { return 2; } - - /** implementation of method from OperationsPtg*/ + + /** implementation of method from OperationsPtg*/ public String toFormulaString(String[] operands) { StringBuilder buffer = new StringBuilder(); @@ -51,4 +48,9 @@ public final class AddPtg extends ValueOperatorPtg { buffer.append(operands[ 1 ]); return buffer.toString(); } + + @Override + public AddPtg copy() { + return instance; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/Area2DPtgBase.java b/src/java/org/apache/poi/ss/formula/ptg/Area2DPtgBase.java index b356591b73..66ffdcc516 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/Area2DPtgBase.java +++ b/src/java/org/apache/poi/ss/formula/ptg/Area2DPtgBase.java @@ -30,6 +30,11 @@ public abstract class Area2DPtgBase extends AreaPtgBase { protected Area2DPtgBase(int firstRow, int lastRow, int firstColumn, int lastColumn, boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative) { super(firstRow, lastRow, firstColumn, lastColumn, firstRowRelative, lastRowRelative, firstColRelative, lastColRelative); } + + protected Area2DPtgBase(Area2DPtgBase other) { + super(other); + } + protected Area2DPtgBase(AreaReference ar) { super(ar); } diff --git a/src/java/org/apache/poi/ss/formula/ptg/Area3DPtg.java b/src/java/org/apache/poi/ss/formula/ptg/Area3DPtg.java index 823a1462fe..0b43cef9df 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/Area3DPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/Area3DPtg.java @@ -26,13 +26,11 @@ import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; /** - * <p>Title: Area 3D Ptg - 3D reference (Sheet + Area)</p> - * <p>Description: Defined an area in Extern Sheet. </p> - * <p>REFERENCE: </p> - * - * <p>This is HSSF only, as it matches the HSSF file format way of - * referring to the sheet by an extern index. The XSSF equivalent - * is {@link Area3DPxg} + * Area 3D Ptg - 3D reference (Sheet + Area)<p> + * Defined an area in Extern Sheet.<p> + * + * This is HSSF only, as it matches the HSSF file format way of referring to the sheet by an extern index. + * The XSSF equivalent is {@link Area3DPxg} */ public final class Area3DPtg extends AreaPtgBase implements WorkbookDependentFormula, ExternSheetReferenceToken { public final static byte sid = 0x3b; @@ -46,6 +44,11 @@ public final class Area3DPtg extends AreaPtgBase implements WorkbookDependentFor setExternSheetIndex(externIdx); } + public Area3DPtg(Area3DPtg other) { + super(other); + field_1_index_extern_sheet = other.field_1_index_extern_sheet; + } + public Area3DPtg(LittleEndianInput in) { field_1_index_extern_sheet = in.readShort(); readCoordinates(in); @@ -104,8 +107,14 @@ public final class Area3DPtg extends AreaPtgBase implements WorkbookDependentFor public String toFormulaString(FormulaRenderingWorkbook book) { return ExternSheetNameResolver.prependSheetName(book, field_1_index_extern_sheet, formatReferenceAsString()); } + @Override public String toFormulaString() { throw new RuntimeException("3D references need a workbook to determine formula text"); } + + @Override + public Area3DPtg copy() { + return new Area3DPtg(this); + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/Area3DPxg.java b/src/java/org/apache/poi/ss/formula/ptg/Area3DPxg.java index 9c7a5da0d5..d746ee0bc9 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/Area3DPxg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/Area3DPxg.java @@ -19,28 +19,34 @@ package org.apache.poi.ss.formula.ptg; import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.formula.SheetIdentifier; -import org.apache.poi.ss.formula.SheetNameFormatter; import org.apache.poi.ss.formula.SheetRangeAndWorkbookIndexFormatter; import org.apache.poi.ss.formula.SheetRangeIdentifier; import org.apache.poi.ss.util.AreaReference; import org.apache.poi.util.LittleEndianOutput; /** - * <p>Title: XSSF Area 3D Reference (Sheet + Area)<P> - * <p>Description: Defined an area in an external or different sheet. <P> - * <p>REFERENCE: </p> - * - * <p>This is XSSF only, as it stores the sheet / book references - * in String form. The HSSF equivalent using indexes is {@link Area3DPtg}</p> + * XSSF Area 3D Reference (Sheet + Area)<p> + * Defined an area in an external or different sheet.<p> + * + * This is XSSF only, as it stores the sheet / book references + * in String form. The HSSF equivalent using indexes is {@link Area3DPtg} */ public final class Area3DPxg extends AreaPtgBase implements Pxg3D { private int externalWorkbookNumber = -1; private String firstSheetName; private String lastSheetName; + public Area3DPxg(Area3DPxg other) { + super(other); + externalWorkbookNumber = other.externalWorkbookNumber; + firstSheetName = other.firstSheetName; + lastSheetName = other.lastSheetName; + } + public Area3DPxg(int externalWorkbookNumber, SheetIdentifier sheetName, String arearef) { this(externalWorkbookNumber, sheetName, new AreaReference(arearef, SpreadsheetVersion.EXCEL2007)); } + public Area3DPxg(int externalWorkbookNumber, SheetIdentifier sheetName, AreaReference arearef) { super(arearef); this.externalWorkbookNumber = externalWorkbookNumber; @@ -79,7 +85,7 @@ public final class Area3DPxg extends AreaPtgBase implements Pxg3D { sb.append("]"); return sb.toString(); } - + public int getExternalWorkbookNumber() { return externalWorkbookNumber; } @@ -89,7 +95,7 @@ public final class Area3DPxg extends AreaPtgBase implements Pxg3D { public String getLastSheetName() { return lastSheetName; } - + public void setSheetName(String sheetName) { this.firstSheetName = sheetName; } @@ -100,7 +106,7 @@ public final class Area3DPxg extends AreaPtgBase implements Pxg3D { public String format2DRefAsString() { return formatReferenceAsString(); } - + public String toFormulaString() { StringBuilder sb = new StringBuilder(64); @@ -117,4 +123,8 @@ public final class Area3DPxg extends AreaPtgBase implements Pxg3D { throw new IllegalStateException("XSSF-only Ptg, should not be serialised"); } + @Override + public Area3DPxg copy() { + return new Area3DPxg(this); + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/AreaErrPtg.java b/src/java/org/apache/poi/ss/formula/ptg/AreaErrPtg.java index 0685e8ec9d..e2bb2fe66d 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/AreaErrPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/AreaErrPtg.java @@ -23,8 +23,6 @@ import org.apache.poi.util.LittleEndianOutput; /** * AreaErr - handles deleted cell area references. - * - * @author Daniel Noll (daniel at nuix dot com dot au) */ public final class AreaErrPtg extends OperandPtg { public final static byte sid = 0x2B; @@ -59,5 +57,10 @@ public final class AreaErrPtg extends OperandPtg { public int getSize() { return 9; } -} + @Override + public AreaErrPtg copy() { + // immutable + return this; + } +}
\ No newline at end of file diff --git a/src/java/org/apache/poi/ss/formula/ptg/AreaNPtg.java b/src/java/org/apache/poi/ss/formula/ptg/AreaNPtg.java index bc8f76e3db..0c0faca505 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/AreaNPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/AreaNPtg.java @@ -26,6 +26,10 @@ import org.apache.poi.util.LittleEndianInput; public final class AreaNPtg extends Area2DPtgBase { public final static short sid = 0x2D; + public AreaNPtg(AreaNPtg other) { + super(other); + } + public AreaNPtg(LittleEndianInput in) { super(in); } @@ -33,4 +37,9 @@ public final class AreaNPtg extends Area2DPtgBase { protected byte getSid() { return sid; } + + @Override + public AreaNPtg copy() { + return new AreaNPtg(this); + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/AreaPtg.java b/src/java/org/apache/poi/ss/formula/ptg/AreaPtg.java index 93f9a06332..ca711e6f06 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/AreaPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/AreaPtg.java @@ -22,7 +22,6 @@ import org.apache.poi.util.LittleEndianInput; /** * Specifies a rectangular area of cells A1:A4 for instance. - * @author Jason Height (jheight at chariot dot net dot au) */ public final class AreaPtg extends Area2DPtgBase { public final static short sid = 0x25; @@ -30,17 +29,26 @@ public final class AreaPtg extends Area2DPtgBase { public AreaPtg(int firstRow, int lastRow, int firstColumn, int lastColumn, boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative) { super(firstRow, lastRow, firstColumn, lastColumn, firstRowRelative, lastRowRelative, firstColRelative, lastColRelative); } - + + public AreaPtg(AreaPtg other) { + super(other); + } + public AreaPtg(LittleEndianInput in) { super(in); } - + public AreaPtg(AreaReference arearef) { super(arearef); } - + @Override protected byte getSid() { return sid; } + + @Override + public AreaPtg copy() { + return new AreaPtg(this); + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/AreaPtgBase.java b/src/java/org/apache/poi/ss/formula/ptg/AreaPtgBase.java index 21c19ccd14..bed2914a2a 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/AreaPtgBase.java +++ b/src/java/org/apache/poi/ss/formula/ptg/AreaPtgBase.java @@ -27,17 +27,12 @@ import org.apache.poi.util.LittleEndianOutput; /** * Specifies a rectangular area of cells A1:A4 for instance. - * @author andy - * @author Jason Height (jheight at chariot dot net dot au) */ public abstract class AreaPtgBase extends OperandPtg implements AreaI { - /** - * TODO - (May-2008) fix subclasses of AreaPtg 'AreaN~' which are used in shared formulas. - * see similar comment in ReferencePtg - */ - protected final RuntimeException notImplemented() { - return new RuntimeException("Coding Error: This method should never be called. This ptg should be converted"); - } + + private final static BitField rowRelative = BitFieldFactory.getInstance(0x8000); + private final static BitField colRelative = BitFieldFactory.getInstance(0x4000); + private final static BitField columnMask = BitFieldFactory.getInstance(0x3FFF); /** zero based, unsigned 16 bit */ private int field_1_first_row; @@ -48,12 +43,14 @@ public abstract class AreaPtgBase extends OperandPtg implements AreaI { /** zero based, unsigned 8 bit */ private int field_4_last_column; //BitFields: (last row relative, last col relative, last column number) - private final static BitField rowRelative = BitFieldFactory.getInstance(0x8000); - private final static BitField colRelative = BitFieldFactory.getInstance(0x4000); - private final static BitField columnMask = BitFieldFactory.getInstance(0x3FFF); + protected AreaPtgBase() {} - protected AreaPtgBase() { - // do nothing + protected AreaPtgBase(AreaPtgBase other) { + super(other); + field_1_first_row = other.field_1_first_row; + field_2_last_row = other.field_2_last_row; + field_3_first_column = other.field_3_first_column; + field_4_last_column = other.field_4_last_column; } protected AreaPtgBase(AreaReference ar) { @@ -96,11 +93,11 @@ public abstract class AreaPtgBase extends OperandPtg implements AreaI { setLastColRelative(firstColRelative); } } - + /** * Sort the first and last row and columns in-place to the preferred (top left:bottom right) order * Note: Sort only occurs when an instance is constructed or when this method is called. - * + * * <p>For example, <code>$E5:B$10</code> becomes <code>B5:$E$10</code></p> */ public void sortTopLeftToBottomRight() { diff --git a/src/java/org/apache/poi/ss/formula/ptg/ArrayPtg.java b/src/java/org/apache/poi/ss/formula/ptg/ArrayPtg.java index 66072bdd3d..7426c41f7a 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/ArrayPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/ArrayPtg.java @@ -31,18 +31,16 @@ import org.apache.poi.util.LittleEndianOutput; * It is only after the "size" of all the Ptgs is met, that the ArrayPtg data is actually * held after this. So Ptg.createParsedExpression keeps track of the number of * ArrayPtg elements and need to parse the data upto the FORMULA record size. - * - * @author Jason Height (jheight at chariot dot net dot au) */ public final class ArrayPtg extends Ptg { - public static final byte sid = 0x20; + public static final byte sid = 0x20; private static final int RESERVED_FIELD_LEN = 7; /** * The size of the plain tArray token written within the standard formula tokens * (not including the data which comes after all formula tokens) */ - public static final int PLAIN_TOKEN_SIZE = 1+RESERVED_FIELD_LEN; + public static final int PLAIN_TOKEN_SIZE = 1 + RESERVED_FIELD_LEN; // 7 bytes of data (stored as an int, short and byte here) private final int _reserved0Int; @@ -50,7 +48,7 @@ public final class ArrayPtg extends Ptg { private final int _reserved2Byte; // data from these fields comes after the Ptg data of all tokens in current formula - private final int _nColumns; + private final int _nColumns; private final int _nRows; private final Object[] _arrayValues; @@ -62,6 +60,16 @@ public final class ArrayPtg extends Ptg { _nRows = nRows; _arrayValues = arrayValues.clone(); } + + public ArrayPtg(ArrayPtg other) { + _reserved0Int = other._reserved0Int; + _reserved1Short = other._reserved1Short; + _reserved2Byte = other._reserved2Byte; + _nColumns = other._nColumns; + _nRows = other._nRows; + _arrayValues = (other._arrayValues == null) ? null : other._arrayValues.clone(); + } + /** * @param values2d array values arranged in rows */ @@ -264,5 +272,16 @@ public final class ArrayPtg extends Ptg { result.setClass(getPtgClass()); return result; } + + @Override + public Initial copy() { + // immutable + return this; + } + } + + @Override + public ArrayPtg copy() { + return new ArrayPtg(this); } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/AttrPtg.java b/src/java/org/apache/poi/ss/formula/ptg/AttrPtg.java index 0af61b897f..d046b684b6 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/AttrPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/AttrPtg.java @@ -24,22 +24,13 @@ import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; /** - * "Special Attributes" + * "Special Attributes"<p> * This seems to be a Misc Stuff and Junk record. One function it serves is * in SUM functions (i.e. SUM(A1:A3) causes an area PTG then an ATTR with the SUM option set) - * @author andy - * @author Jason Height (jheight at chariot dot net dot au) */ public final class AttrPtg extends ControlPtg { public final static byte sid = 0x19; private final static int SIZE = 4; - private final byte _options; - private final short _data; - - /** only used for tAttrChoose: table of offsets to starts of args */ - private final int[] _jumpTable; - /** only used for tAttrChoose: offset to the tFuncVar for CHOOSE() */ - private final int _chooseFuncOffset; // flags 'volatile' and 'space', can be combined. // OOO spec says other combinations are theoretically possible but not likely to occur. @@ -74,6 +65,14 @@ public final class AttrPtg extends ControlPtg { public static final int SPACE_AFTER_EQUALITY = 0x06; } + private final byte _options; + private final short _data; + + /** only used for tAttrChoose: table of offsets to starts of args */ + private final int[] _jumpTable; + /** only used for tAttrChoose: offset to the tFuncVar for CHOOSE() */ + private final int _chooseFuncOffset; + public AttrPtg(LittleEndianInput in) { _options = in.readByte(); _data = in.readShort(); @@ -259,4 +258,10 @@ public final class AttrPtg extends ControlPtg { } return "UNKNOWN ATTRIBUTE"; } + + @Override + public AttrPtg copy() { + // immutable + return this; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/BoolPtg.java b/src/java/org/apache/poi/ss/formula/ptg/BoolPtg.java index 28b5619052..a64b532246 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/BoolPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/BoolPtg.java @@ -22,10 +22,6 @@ import org.apache.poi.util.LittleEndianOutput; /** * Boolean (boolean) Stores a (java) boolean value in a formula. - * - * @author Paul Krause (pkrause at soundbite dot com) - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Jason Height (jheight at chariot dot net dot au) */ public final class BoolPtg extends ScalarConstantPtg { public static final int SIZE = 2; @@ -63,4 +59,9 @@ public final class BoolPtg extends ScalarConstantPtg { public String toFormulaString() { return _value ? "TRUE" : "FALSE"; } + + @Override + public BoolPtg copy() { + return this; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/ConcatPtg.java b/src/java/org/apache/poi/ss/formula/ptg/ConcatPtg.java index a4c0ec9187..91d0840d3c 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/ConcatPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/ConcatPtg.java @@ -17,22 +17,17 @@ package org.apache.poi.ss.formula.ptg; -/** - * - * @author andy - * @author Jason Height (jheight at chariot dot net dot au) - */ public final class ConcatPtg extends ValueOperatorPtg { public final static byte sid = 0x08; - + private final static String CONCAT = "&"; - - public static final ValueOperatorPtg instance = new ConcatPtg(); + + public static final ConcatPtg instance = new ConcatPtg(); private ConcatPtg() { // enforce singleton } - + protected byte getSid() { return sid; } @@ -40,7 +35,7 @@ public final class ConcatPtg extends ValueOperatorPtg { public int getNumberOfOperands() { return 2; } - + public String toFormulaString(String[] operands) { StringBuilder buffer = new StringBuilder(); @@ -49,4 +44,9 @@ public final class ConcatPtg extends ValueOperatorPtg { buffer.append(operands[ 1 ]); return buffer.toString(); } + + @Override + public ConcatPtg copy() { + return instance; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/ControlPtg.java b/src/java/org/apache/poi/ss/formula/ptg/ControlPtg.java index 6e819daab7..a206b5dbe9 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/ControlPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/ControlPtg.java @@ -17,18 +17,10 @@ package org.apache.poi.ss.formula.ptg; -/** - * Common superclass for - * tExp - * tTbl - * tParen - * tNlr - * tAttr - * tSheet - * tEndSheet - */ public abstract class ControlPtg extends Ptg { + protected ControlPtg() {} + public boolean isBaseToken() { return true; } diff --git a/src/java/org/apache/poi/ss/formula/ptg/Deleted3DPxg.java b/src/java/org/apache/poi/ss/formula/ptg/Deleted3DPxg.java index 01cbe455a0..576a80d67a 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/Deleted3DPxg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/Deleted3DPxg.java @@ -33,6 +33,13 @@ public final class Deleted3DPxg extends OperandPtg implements Pxg { this.externalWorkbookNumber = externalWorkbookNumber; this.sheetName = sheetName; } + + public Deleted3DPxg(Deleted3DPxg other) { + super(other); + externalWorkbookNumber = other.externalWorkbookNumber; + sheetName = other.sheetName; + } + public Deleted3DPxg(String sheetName) { this(-1, sheetName); } @@ -59,7 +66,7 @@ public final class Deleted3DPxg extends OperandPtg implements Pxg { public String getSheetName() { return sheetName; } - + public void setSheetName(String sheetName) { this.sheetName = sheetName; } @@ -78,7 +85,7 @@ public final class Deleted3DPxg extends OperandPtg implements Pxg { sb.append(FormulaError.REF.getString()); return sb.toString(); } - + public byte getDefaultOperandClass() { return Ptg.CLASS_VALUE; } @@ -89,4 +96,9 @@ public final class Deleted3DPxg extends OperandPtg implements Pxg { public void write(LittleEndianOutput out) { throw new IllegalStateException("XSSF-only Ptg, should not be serialised"); } + + @Override + public Deleted3DPxg copy() { + return new Deleted3DPxg(this); + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/DeletedArea3DPtg.java b/src/java/org/apache/poi/ss/formula/ptg/DeletedArea3DPtg.java index 70dd6cb4f9..2be7058127 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/DeletedArea3DPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/DeletedArea3DPtg.java @@ -24,10 +24,9 @@ import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; /** - * Title: Deleted Area 3D Ptg - 3D referecnce (Sheet + Area)<P> - * Description: Defined a area in Extern Sheet. <P> - * REFERENCE: <P> - * @author Patrick Luby + * Deleted Area 3D Ptg - 3D referecnce (Sheet + Area)<p> + * Defined a area in Extern Sheet. + * * @version 1.0-pre */ public final class DeletedArea3DPtg extends OperandPtg implements WorkbookDependentFormula { @@ -41,7 +40,7 @@ public final class DeletedArea3DPtg extends OperandPtg implements WorkbookDepend unused1 = 0; unused2 = 0; } - + public DeletedArea3DPtg(LittleEndianInput in) { field_1_index_extern_sheet = in.readUShort(); unused1 = in.readInt(); @@ -65,4 +64,10 @@ public final class DeletedArea3DPtg extends OperandPtg implements WorkbookDepend out.writeInt(unused1); out.writeInt(unused2); } + + @Override + public DeletedArea3DPtg copy() { + // immutable + return this; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/DeletedRef3DPtg.java b/src/java/org/apache/poi/ss/formula/ptg/DeletedRef3DPtg.java index 6974defe40..763cdc2377 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/DeletedRef3DPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/DeletedRef3DPtg.java @@ -25,8 +25,9 @@ import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; /** - * Title: Deleted Reference 3D Ptg <P> - * Description: Defined a cell in extern sheet. <P> + * Deleted Reference 3D Ptg<p> + * Defined a cell in extern sheet. + * * @since 1.0-pre */ public final class DeletedRef3DPtg extends OperandPtg implements WorkbookDependentFormula { @@ -62,4 +63,10 @@ public final class DeletedRef3DPtg extends OperandPtg implements WorkbookDepende out.writeShort(field_1_index_extern_sheet); out.writeInt(unused1); } + + @Override + public DeletedRef3DPtg copy() { + // immutable + return this; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/DividePtg.java b/src/java/org/apache/poi/ss/formula/ptg/DividePtg.java index f1dfbdd27e..d2b11921a6 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/DividePtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/DividePtg.java @@ -19,18 +19,16 @@ package org.apache.poi.ss.formula.ptg; /** * This PTG implements the standard binomial divide "/" - * @author Andrew C. Oliver acoliver at apache dot org - * @author Jason Height (jheight at chariot dot net dot au) */ public final class DividePtg extends ValueOperatorPtg { public final static byte sid = 0x06; - public static final ValueOperatorPtg instance = new DividePtg(); + public static final DividePtg instance = new DividePtg(); private DividePtg() { // enforce singleton } - + protected byte getSid() { return sid; } @@ -46,5 +44,10 @@ public final class DividePtg extends ValueOperatorPtg { buffer.append("/"); buffer.append(operands[ 1 ]); return buffer.toString(); - } + } + + @Override + public DividePtg copy() { + return instance; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/EqualPtg.java b/src/java/org/apache/poi/ss/formula/ptg/EqualPtg.java index 54db3f3f35..99961e3eda 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/EqualPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/EqualPtg.java @@ -24,12 +24,12 @@ package org.apache.poi.ss.formula.ptg; public final class EqualPtg extends ValueOperatorPtg { public final static byte sid = 0x0b; - public static final ValueOperatorPtg instance = new EqualPtg(); + public static final EqualPtg instance = new EqualPtg(); private EqualPtg() { // enforce singleton } - + protected byte getSid() { return sid; } @@ -37,14 +37,19 @@ public final class EqualPtg extends ValueOperatorPtg { public int getNumberOfOperands() { return 2; } - + public String toFormulaString(String[] operands) { StringBuilder buffer = new StringBuilder(); - + buffer.append(operands[ 0 ]); buffer.append("="); buffer.append(operands[ 1 ]); return buffer.toString(); - } + } + + @Override + public EqualPtg copy() { + return instance; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/ErrPtg.java b/src/java/org/apache/poi/ss/formula/ptg/ErrPtg.java index 36c276f377..7be341dab5 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/ErrPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/ErrPtg.java @@ -86,4 +86,9 @@ public final class ErrPtg extends ScalarConstantPtg { throw new RuntimeException("Unexpected error code (" + code + ")"); } } + + @Override + public ErrPtg copy() { + return this; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/ExpPtg.java b/src/java/org/apache/poi/ss/formula/ptg/ExpPtg.java index 83ebc2044d..66da8a23fe 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/ExpPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/ExpPtg.java @@ -20,15 +20,10 @@ package org.apache.poi.ss.formula.ptg; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; -/** - * - * @author andy - * @author Jason Height (jheight at chariot dot net dot au) - * @author dmui (save existing implementation) - */ public final class ExpPtg extends ControlPtg { private final static int SIZE = 5; public final static short sid = 0x1; + private final int field_1_first_row; private final int field_2_first_col; @@ -71,4 +66,9 @@ public final class ExpPtg extends ControlPtg { public String toString() { return "[Array Formula or Shared Formula]\n" + "row = " + getRow() + "\n" + "col = " + getColumn() + "\n"; } + + @Override + public ExpPtg copy() { + return this; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/FuncPtg.java b/src/java/org/apache/poi/ss/formula/ptg/FuncPtg.java index ecfccb67b2..6fc76a5815 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/FuncPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/FuncPtg.java @@ -22,11 +22,6 @@ import org.apache.poi.ss.formula.function.FunctionMetadataRegistry; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; -/** - * @author aviks - * @author Jason Height (jheight at chariot dot net dot au) - * @author Danny Mui (dmui at apache dot org) (Leftover handling) - */ public final class FuncPtg extends AbstractFunctionPtg { public final static byte sid = 0x21; @@ -57,4 +52,10 @@ public final class FuncPtg extends AbstractFunctionPtg { public int getSize() { return SIZE; } + + @Override + public FuncPtg copy() { + // immutable + return this; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/FuncVarPtg.java b/src/java/org/apache/poi/ss/formula/ptg/FuncVarPtg.java index a1cacd8ba5..05c18a05e0 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/FuncVarPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/FuncVarPtg.java @@ -23,10 +23,7 @@ import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; -/** - * @author Jason Height (jheight at chariot dot net dot au) - */ -public final class FuncVarPtg extends AbstractFunctionPtg{ +public final class FuncVarPtg extends AbstractFunctionPtg { public final static byte sid = 0x22; private final static int SIZE = 4; @@ -90,4 +87,10 @@ public final class FuncVarPtg extends AbstractFunctionPtg{ public int getSize() { return SIZE; } + + @Override + public FuncVarPtg copy() { + // immutable + return this; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/GreaterEqualPtg.java b/src/java/org/apache/poi/ss/formula/ptg/GreaterEqualPtg.java index 54ae3f7dcc..c89d1c8876 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/GreaterEqualPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/GreaterEqualPtg.java @@ -20,19 +20,17 @@ package org.apache.poi.ss.formula.ptg; /** * PTG class to implement greater or equal to - * - * @author fred at stsci dot edu */ public final class GreaterEqualPtg extends ValueOperatorPtg { public final static int SIZE = 1; public final static byte sid = 0x0c; - public static final ValueOperatorPtg instance = new GreaterEqualPtg(); + public static final GreaterEqualPtg instance = new GreaterEqualPtg(); private GreaterEqualPtg() { // enforce singleton } - + protected byte getSid() { return sid; } @@ -51,4 +49,9 @@ public final class GreaterEqualPtg extends ValueOperatorPtg { return buffer.toString(); } + + @Override + public GreaterEqualPtg copy() { + return instance; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/GreaterThanPtg.java b/src/java/org/apache/poi/ss/formula/ptg/GreaterThanPtg.java index 8f8152b07a..307fb6eee7 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/GreaterThanPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/GreaterThanPtg.java @@ -20,18 +20,17 @@ package org.apache.poi.ss.formula.ptg; /** * Greater than operator PTG ">" - * @author Cameron Riley (criley at ekmail.com) */ public final class GreaterThanPtg extends ValueOperatorPtg { - public final static byte sid = 0x0D; + public final static byte sid = 0x0D; private final static String GREATERTHAN = ">"; - public static final ValueOperatorPtg instance = new GreaterThanPtg(); + public static final GreaterThanPtg instance = new GreaterThanPtg(); private GreaterThanPtg() { // enforce singleton } - + protected byte getSid() { return sid; } @@ -43,13 +42,13 @@ public final class GreaterThanPtg extends ValueOperatorPtg { public int getNumberOfOperands() { return 2; } - - /** + + /** * Implementation of method from OperationsPtg * @param operands a String array of operands * @return String the Formula as a String - */ - public String toFormulaString(String[] operands) + */ + public String toFormulaString(String[] operands) { StringBuilder buffer = new StringBuilder(); @@ -58,4 +57,9 @@ public final class GreaterThanPtg extends ValueOperatorPtg { buffer.append(operands[ 1 ]); return buffer.toString(); } + + @Override + public GreaterThanPtg copy() { + return instance; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/IntPtg.java b/src/java/org/apache/poi/ss/formula/ptg/IntPtg.java index b91784edb2..f2c56f76a8 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/IntPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/IntPtg.java @@ -21,11 +21,7 @@ import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; /** - * Integer (unsigned short integer) Stores an unsigned short value (java int) in - * a formula - * - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Jason Height (jheight at chariot dot net dot au) + * Integer (unsigned short integer) Stores an unsigned short value (java int) in a formula */ public final class IntPtg extends ScalarConstantPtg { // 16 bit unsigned integer @@ -34,8 +30,8 @@ public final class IntPtg extends ScalarConstantPtg { /** * Excel represents integers 0..65535 with the tInt token. - * - * @return <code>true</code> if the specified value is within the range of values + * + * @return <code>true</code> if the specified value is within the range of values * <tt>IntPtg</tt> can represent. */ public static boolean isInRange(int i) { @@ -73,4 +69,9 @@ public final class IntPtg extends ScalarConstantPtg { public String toFormulaString() { return String.valueOf(getValue()); } + + @Override + public IntPtg copy() { + return this; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/IntersectionPtg.java b/src/java/org/apache/poi/ss/formula/ptg/IntersectionPtg.java index 1927cb9754..9a641654fa 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/IntersectionPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/IntersectionPtg.java @@ -19,13 +19,10 @@ package org.apache.poi.ss.formula.ptg; import org.apache.poi.util.LittleEndianOutput; -/** - * @author Daniel Noll (daniel at nuix dot com dot au) - */ public final class IntersectionPtg extends OperationPtg { public final static byte sid = 0x0f; - public static final OperationPtg instance = new IntersectionPtg(); + public static final IntersectionPtg instance = new IntersectionPtg(); private IntersectionPtg() { // enforce singleton @@ -59,4 +56,9 @@ public final class IntersectionPtg extends OperationPtg { public int getNumberOfOperands() { return 2; } + + @Override + public IntersectionPtg copy() { + return instance; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/LessEqualPtg.java b/src/java/org/apache/poi/ss/formula/ptg/LessEqualPtg.java index 305c4ef2e8..d7aa350c63 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/LessEqualPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/LessEqualPtg.java @@ -1,4 +1,4 @@ - + /* ==================================================================== Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with @@ -23,18 +23,16 @@ package org.apache.poi.ss.formula.ptg; /** * Ptg class to implement less than or equal - * - * @author fred at stsci dot edu */ public final class LessEqualPtg extends ValueOperatorPtg { public final static byte sid = 0x0a; - public static final ValueOperatorPtg instance = new LessEqualPtg(); + public static final LessEqualPtg instance = new LessEqualPtg(); private LessEqualPtg() { // enforce singleton } - + protected byte getSid() { return sid; } @@ -50,4 +48,9 @@ public final class LessEqualPtg extends ValueOperatorPtg { buffer.append( operands[1] ); return buffer.toString(); } + + @Override + public LessEqualPtg copy() { + return instance; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/LessThanPtg.java b/src/java/org/apache/poi/ss/formula/ptg/LessThanPtg.java index b86854f9cf..f98b215cd8 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/LessThanPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/LessThanPtg.java @@ -18,24 +18,23 @@ package org.apache.poi.ss.formula.ptg; /** - * Less than operator PTG "<". The SID is taken from the + * Less than operator PTG "<". The SID is taken from the * Openoffice.orgs Documentation of the Excel File Format, * Table 3.5.7 - * @author Cameron Riley (criley at ekmail.com) */ public final class LessThanPtg extends ValueOperatorPtg { /** the sid for the less than operator as hex */ - public final static byte sid = 0x09; + public final static byte sid = 0x09; /** identifier for LESS THAN char */ private final static String LESSTHAN = "<"; - public static final ValueOperatorPtg instance = new LessThanPtg(); + public static final LessThanPtg instance = new LessThanPtg(); private LessThanPtg() { // enforce singleton } - + protected byte getSid() { return sid; } @@ -47,13 +46,13 @@ public final class LessThanPtg extends ValueOperatorPtg { public int getNumberOfOperands() { return 2; } - - /** + + /** * Implementation of method from OperationsPtg * @param operands a String array of operands * @return String the Formula as a String - */ - public String toFormulaString(String[] operands) + */ + public String toFormulaString(String[] operands) { StringBuilder buffer = new StringBuilder(); buffer.append(operands[ 0 ]); @@ -61,4 +60,9 @@ public final class LessThanPtg extends ValueOperatorPtg { buffer.append(operands[ 1 ]); return buffer.toString(); } + + @Override + public LessThanPtg copy() { + return instance; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/MemAreaPtg.java b/src/java/org/apache/poi/ss/formula/ptg/MemAreaPtg.java index 9ebca5061b..9dfd5cf079 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/MemAreaPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/MemAreaPtg.java @@ -20,9 +20,6 @@ package org.apache.poi.ss.formula.ptg; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; -/** - * @author Daniel Noll (daniel at nuix dot com dot au) - */ public final class MemAreaPtg extends OperandPtg { public final static short sid = 0x26; private final static int SIZE = 7; @@ -71,4 +68,10 @@ public final class MemAreaPtg extends OperandPtg { sb.append("]"); return sb.toString(); } + + @Override + public MemAreaPtg copy() { + // immutable + return this; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/MemErrPtg.java b/src/java/org/apache/poi/ss/formula/ptg/MemErrPtg.java index 44f541da99..d8efb220d1 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/MemErrPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/MemErrPtg.java @@ -20,18 +20,18 @@ package org.apache.poi.ss.formula.ptg; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; -/** - * - * @author andy - * @author Jason Height (jheight at chariot dot net dot au) - * @author Daniel Noll (daniel at nuix dot com dot au) - */ public final class MemErrPtg extends OperandPtg { public final static short sid = 0x27; private final static int SIZE = 7; private int field_1_reserved; private short field_2_subex_len; + public MemErrPtg(MemErrPtg other) { + super(other); + field_1_reserved = other.field_1_reserved; + field_2_subex_len = other.field_2_subex_len; + } + public MemErrPtg(LittleEndianInput in) { field_1_reserved = in.readInt(); field_2_subex_len = in.readShort(); @@ -54,4 +54,9 @@ public final class MemErrPtg extends OperandPtg { public byte getDefaultOperandClass() { return Ptg.CLASS_VALUE; } + + @Override + public MemErrPtg copy() { + return new MemErrPtg(this); + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/MemFuncPtg.java b/src/java/org/apache/poi/ss/formula/ptg/MemFuncPtg.java index 077cfe485b..ed20c36e7c 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/MemFuncPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/MemFuncPtg.java @@ -20,9 +20,6 @@ package org.apache.poi.ss.formula.ptg; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; -/** - * @author Glen Stampoultzis (glens at apache.org) - */ public final class MemFuncPtg extends OperandPtg { public final static byte sid = 0x29; @@ -72,4 +69,10 @@ public final class MemFuncPtg extends OperandPtg { sb.append("]"); return sb.toString(); } + + @Override + public MemFuncPtg copy() { + // immutable + return this; + } }
\ No newline at end of file diff --git a/src/java/org/apache/poi/ss/formula/ptg/MissingArgPtg.java b/src/java/org/apache/poi/ss/formula/ptg/MissingArgPtg.java index 84e4412873..75cbd35143 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/MissingArgPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/MissingArgPtg.java @@ -21,10 +21,6 @@ import org.apache.poi.util.LittleEndianOutput; /** * Missing Function Arguments - * - * Avik Sengupta <avik at apache.org> - * - * @author Jason Height (jheight at chariot dot net dot au) */ public final class MissingArgPtg extends ScalarConstantPtg { @@ -48,4 +44,9 @@ public final class MissingArgPtg extends ScalarConstantPtg { public String toFormulaString() { return " "; } + + @Override + public MissingArgPtg copy() { + return this; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/MultiplyPtg.java b/src/java/org/apache/poi/ss/formula/ptg/MultiplyPtg.java index fb4f468e3c..c99e90318a 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/MultiplyPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/MultiplyPtg.java @@ -18,19 +18,17 @@ package org.apache.poi.ss.formula.ptg; /** - * Implements the standard mathmatical multiplication - * - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Jason Height (jheight at chariot dot net dot au) + * Implements the standard mathematical multiplication "*" */ public final class MultiplyPtg extends ValueOperatorPtg { public final static byte sid = 0x05; - public static final ValueOperatorPtg instance = new MultiplyPtg(); + public static final MultiplyPtg instance = new MultiplyPtg(); private MultiplyPtg() { // enforce singleton } - + protected byte getSid() { return sid; } @@ -38,7 +36,7 @@ public final class MultiplyPtg extends ValueOperatorPtg { public int getNumberOfOperands() { return 2; } - + public String toFormulaString(String[] operands) { StringBuilder buffer = new StringBuilder(); @@ -46,5 +44,10 @@ public final class MultiplyPtg extends ValueOperatorPtg { buffer.append("*"); buffer.append(operands[ 1 ]); return buffer.toString(); - } + } + + @Override + public MultiplyPtg copy() { + return instance; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/NamePtg.java b/src/java/org/apache/poi/ss/formula/ptg/NamePtg.java index a8632b534b..e3c833f024 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/NamePtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/NamePtg.java @@ -24,13 +24,11 @@ import org.apache.poi.util.LittleEndianOutput; /** * See the spec at 2.5.198.76 PtgName - * - * @author andy - * @author Jason Height (jheight at chariot dot net dot au) */ public final class NamePtg extends OperandPtg implements WorkbookDependentFormula { public final static short sid = 0x23; private final static int SIZE = 5; + /** one-based index to defined name record */ private int field_1_label_index; private short field_2_zero; // reserved must be 0 @@ -42,6 +40,12 @@ public final class NamePtg extends OperandPtg implements WorkbookDependentFormul field_1_label_index = 1 + nameIndex; // convert to 1-based } + public NamePtg(NamePtg other) { + super(other); + field_1_label_index = other.field_1_label_index; + field_2_zero = other.field_2_zero; + } + /** Creates new NamePtg */ public NamePtg(LittleEndianInput in) { field_1_label_index = in.readUShort(); @@ -81,4 +85,9 @@ public final class NamePtg extends OperandPtg implements WorkbookDependentFormul public byte getDefaultOperandClass() { return Ptg.CLASS_REF; } + + @Override + public NamePtg copy() { + return new NamePtg(this); + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/NameXPtg.java b/src/java/org/apache/poi/ss/formula/ptg/NameXPtg.java index 4684ef40b7..c1b50e20ac 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/NameXPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/NameXPtg.java @@ -25,7 +25,7 @@ import org.apache.poi.util.LittleEndianOutput; /** * A Name, be that a Named Range or a Function / User Defined * Function, addressed in the HSSF External Sheet style. - * + * * <p>This is HSSF only, as it matches the HSSF file format way of * referring to the sheet by an extern index. The XSSF equivalent * is {@link NameXPxg} @@ -77,12 +77,12 @@ public final class NameXPtg extends OperandPtg implements WorkbookDependentFormu public String toFormulaString() { throw new RuntimeException("3D references need a workbook to determine formula text"); } - + public String toString(){ return "NameXPtg:[sheetRefIndex:" + _sheetRefIndex + " , nameNumber:" + _nameNumber + "]"; } - + public byte getDefaultOperandClass() { return Ptg.CLASS_VALUE; } @@ -93,4 +93,10 @@ public final class NameXPtg extends OperandPtg implements WorkbookDependentFormu public int getNameIndex() { return _nameNumber - 1; } + + @Override + public NameXPtg copy() { + // immutable + return this; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/NameXPxg.java b/src/java/org/apache/poi/ss/formula/ptg/NameXPxg.java index 0b098ba768..94cb7f4cea 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/NameXPxg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/NameXPxg.java @@ -23,7 +23,7 @@ import org.apache.poi.util.LittleEndianOutput; /** * A Name, be that a Named Range or a Function / User Defined * Function, addressed in the HSSF External Sheet style. - * + * * <p>This is XSSF only, as it stores the sheet / book references * in String form. The HSSF equivalent using indexes is {@link NameXPtg}</p> */ @@ -37,6 +37,14 @@ public final class NameXPxg extends OperandPtg implements Pxg { this.sheetName = sheetName; this.nameName = nameName; } + + public NameXPxg(NameXPxg other) { + super(other); + externalWorkbookNumber = other.externalWorkbookNumber; + sheetName = other.sheetName; + nameName = other.nameName; + } + public NameXPxg(String sheetName, String nameName) { this(-1, sheetName, nameName); } @@ -70,7 +78,7 @@ public final class NameXPxg extends OperandPtg implements Pxg { public String getNameName() { return nameName; } - + public void setSheetName(String sheetName) { this.sheetName = sheetName; } @@ -94,7 +102,7 @@ public final class NameXPxg extends OperandPtg implements Pxg { sb.append(nameName); return sb.toString(); } - + public byte getDefaultOperandClass() { return Ptg.CLASS_VALUE; } @@ -105,4 +113,9 @@ public final class NameXPxg extends OperandPtg implements Pxg { public void write(LittleEndianOutput out) { throw new IllegalStateException("XSSF-only Ptg, should not be serialised"); } + + @Override + public NameXPxg copy() { + return new NameXPxg(this); + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/NotEqualPtg.java b/src/java/org/apache/poi/ss/formula/ptg/NotEqualPtg.java index c6c557a349..07725ebfda 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/NotEqualPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/NotEqualPtg.java @@ -19,18 +19,16 @@ package org.apache.poi.ss.formula.ptg; /** * Ptg class to implement not equal - * - * @author fred at stsci dot edu */ public final class NotEqualPtg extends ValueOperatorPtg { public final static byte sid = 0x0e; - public static final ValueOperatorPtg instance = new NotEqualPtg(); + public static final NotEqualPtg instance = new NotEqualPtg(); private NotEqualPtg() { // enforce singleton } - + protected byte getSid() { return sid; } @@ -49,4 +47,9 @@ public final class NotEqualPtg extends ValueOperatorPtg { return buffer.toString(); } + + @Override + public NotEqualPtg copy() { + return instance; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/NumberPtg.java b/src/java/org/apache/poi/ss/formula/ptg/NumberPtg.java index 6cec23604b..c226c8bee0 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/NumberPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/NumberPtg.java @@ -24,9 +24,6 @@ import org.apache.poi.util.LittleEndianOutput; /** * Number Stores a floating point value in a formula value stored in a 8 byte * field using IEEE notation - * - * @author Avik Sengupta - * @author Jason Height (jheight at chariot dot net dot au) */ public final class NumberPtg extends ScalarConstantPtg { public final static int SIZE = 9; @@ -41,7 +38,7 @@ public final class NumberPtg extends ScalarConstantPtg { * Create a NumberPtg from a string representation of the number Number * format is not checked, it is expected to be validated in the parser that * calls this method. - * + * * @param value String representation of a floating point number */ public NumberPtg(String value) { @@ -68,4 +65,9 @@ public final class NumberPtg extends ScalarConstantPtg { public String toFormulaString() { return NumberToTextConverter.toText(field_1_value); } + + @Override + public NumberPtg copy() { + return this; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/OperandPtg.java b/src/java/org/apache/poi/ss/formula/ptg/OperandPtg.java index 0c36a84437..1f1ab3c761 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/OperandPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/OperandPtg.java @@ -17,10 +17,13 @@ package org.apache.poi.ss.formula.ptg; -/** - * @author Josh Micich - */ -public abstract class OperandPtg extends Ptg implements Cloneable { +public abstract class OperandPtg extends Ptg { + + protected OperandPtg() {} + + protected OperandPtg(OperandPtg other) { + super(other); + } /** * All Operand {@link Ptg}s are classified ('relative', 'value', 'array') @@ -28,11 +31,7 @@ public abstract class OperandPtg extends Ptg implements Cloneable { public final boolean isBaseToken() { return false; } - public final OperandPtg copy() { - try { - return (OperandPtg) clone(); - } catch (CloneNotSupportedException e) { - throw new RuntimeException(e); - } - } + + @Override + public abstract OperandPtg copy(); } diff --git a/src/java/org/apache/poi/ss/formula/ptg/OperationPtg.java b/src/java/org/apache/poi/ss/formula/ptg/OperationPtg.java index 089d3c7368..7d09d16169 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/OperationPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/OperationPtg.java @@ -26,19 +26,21 @@ public abstract class OperationPtg extends Ptg { public final static int TYPE_BINARY = 1; public final static int TYPE_FUNCTION = 2; + protected OperationPtg() {} + /** * returns a string representation of the operations - * the length of the input array should equal the number returned by + * the length of the input array should equal the number returned by * @see #getNumberOfOperands - * + * */ public abstract String toFormulaString(String[] operands); - + /** * The number of operands expected by the operations */ public abstract int getNumberOfOperands(); - + public byte getDefaultOperandClass() { return Ptg.CLASS_VALUE; } diff --git a/src/java/org/apache/poi/ss/formula/ptg/ParenthesisPtg.java b/src/java/org/apache/poi/ss/formula/ptg/ParenthesisPtg.java index 1ea30abe20..bc63048cd5 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/ParenthesisPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/ParenthesisPtg.java @@ -23,18 +23,13 @@ import org.apache.poi.util.LittleEndianOutput; * While formula tokens are stored in RPN order and thus do not need parenthesis * for precedence reasons, Parenthesis tokens ARE written to ensure that user * entered parenthesis are displayed as-is on reading back - * - * Avik Sengupta <lists@aviksengupta.com> Andrew C. Oliver (acoliver at - * apache dot org) - * - * @author Jason Height (jheight at chariot dot net dot au) */ public final class ParenthesisPtg extends ControlPtg { private final static int SIZE = 1; public final static byte sid = 0x15; - public static final ControlPtg instance = new ParenthesisPtg(); + public static final ParenthesisPtg instance = new ParenthesisPtg(); private ParenthesisPtg() { // enforce singleton @@ -55,4 +50,9 @@ public final class ParenthesisPtg extends ControlPtg { public String toFormulaString(String[] operands) { return "(" + operands[0] + ")"; } + + @Override + public ParenthesisPtg copy() { + return instance; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/PercentPtg.java b/src/java/org/apache/poi/ss/formula/ptg/PercentPtg.java index f27fb33574..b5e6664d16 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/PercentPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/PercentPtg.java @@ -19,21 +19,19 @@ package org.apache.poi.ss.formula.ptg; /** * Percent PTG. - * - * @author Daniel Noll (daniel at nuix.com.au) */ public final class PercentPtg extends ValueOperatorPtg { public final static int SIZE = 1; public final static byte sid = 0x14; - + private final static String PERCENT = "%"; - public static final ValueOperatorPtg instance = new PercentPtg(); + public static final PercentPtg instance = new PercentPtg(); private PercentPtg() { // enforce singleton } - + protected byte getSid() { return sid; } @@ -41,7 +39,7 @@ public final class PercentPtg extends ValueOperatorPtg { public int getNumberOfOperands() { return 1; } - + public String toFormulaString(String[] operands) { StringBuilder buffer = new StringBuilder(); @@ -49,4 +47,9 @@ public final class PercentPtg extends ValueOperatorPtg { buffer.append(PERCENT); return buffer.toString(); } + + @Override + public PercentPtg copy() { + return instance; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/PowerPtg.java b/src/java/org/apache/poi/ss/formula/ptg/PowerPtg.java index 6f5e8158e3..d7bd306b49 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/PowerPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/PowerPtg.java @@ -17,20 +17,15 @@ package org.apache.poi.ss.formula.ptg; -/** - * - * @author andy - * @author Jason Height (jheight at chariot dot net dot au) - */ public final class PowerPtg extends ValueOperatorPtg { public final static byte sid = 0x07; - public static final ValueOperatorPtg instance = new PowerPtg(); + public static final PowerPtg instance = new PowerPtg(); private PowerPtg() { // enforce singleton } - + protected byte getSid() { return sid; } @@ -38,14 +33,19 @@ public final class PowerPtg extends ValueOperatorPtg { public int getNumberOfOperands() { return 2; // TODO - 2 seems wrong (Jun 2008). Maybe this method is not relevant } - + public String toFormulaString(String[] operands) { StringBuilder buffer = new StringBuilder(); - + buffer.append(operands[ 0 ]); buffer.append("^"); buffer.append(operands[ 1 ]); return buffer.toString(); - } + } + + @Override + public PowerPtg copy() { + return instance; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/Ptg.java b/src/java/org/apache/poi/ss/formula/ptg/Ptg.java index a7649482e7..b85df16887 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/Ptg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/Ptg.java @@ -20,6 +20,7 @@ package org.apache.poi.ss.formula.ptg; import java.util.ArrayList; import java.util.List; +import org.apache.poi.common.Duplicatable; import org.apache.poi.util.LittleEndianByteArrayOutputStream; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; @@ -36,9 +37,21 @@ import org.apache.poi.util.LittleEndianOutput; * <em>Reverse-Polish Notation</em> order. The RPN ordering also simplifies formula * evaluation logic, so POI mostly accesses <tt>Ptg</tt>s in the same way. */ -public abstract class Ptg { +public abstract class Ptg implements Duplicatable { public static final Ptg[] EMPTY_PTG_ARRAY = { }; + public static final byte CLASS_REF = 0x00; + public static final byte CLASS_VALUE = 0x20; + public static final byte CLASS_ARRAY = 0x40; + + private byte ptgClass = CLASS_REF; //base ptg + + protected Ptg() {} + + protected Ptg(Ptg other) { + ptgClass = other.ptgClass; + } + /** * Reads <tt>size</tt> bytes of the input stream, to create an array of <tt>Ptg</tt>s. * Extra data (beyond <tt>size</tt>) may be read if and <tt>ArrayPtg</tt>s are present. @@ -199,7 +212,7 @@ public abstract class Ptg { */ public static int serializePtgs(Ptg[] ptgs, byte[] array, int offset) { LittleEndianByteArrayOutputStream out = new LittleEndianByteArrayOutputStream(array, offset); // NOSONAR - + List<Ptg> arrayPtgs = null; for (Ptg ptg : ptgs) { @@ -241,12 +254,6 @@ public abstract class Ptg { return this.getClass().toString(); } - public static final byte CLASS_REF = 0x00; - public static final byte CLASS_VALUE = 0x20; - public static final byte CLASS_ARRAY = 0x40; - - private byte ptgClass = CLASS_REF; //base ptg - public final void setClass(byte thePtgClass) { if (isBaseToken()) { throw new RuntimeException("setClass should not be called on a base token"); @@ -311,4 +318,7 @@ public abstract class Ptg { } return false; } + + @Override + public abstract Ptg copy(); } diff --git a/src/java/org/apache/poi/ss/formula/ptg/RangePtg.java b/src/java/org/apache/poi/ss/formula/ptg/RangePtg.java index 6918f78ab9..35b43414c7 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/RangePtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/RangePtg.java @@ -20,14 +20,11 @@ package org.apache.poi.ss.formula.ptg; import org.apache.poi.util.LittleEndianOutput; -/** - * @author Daniel Noll (daniel at nuix dot com dot au) - */ public final class RangePtg extends OperationPtg { public final static int SIZE = 1; public final static byte sid = 0x11; - public static final OperationPtg instance = new RangePtg(); + public static final RangePtg instance = new RangePtg(); private RangePtg() { // enforce singleton @@ -68,4 +65,8 @@ public final class RangePtg extends OperationPtg { return 2; } + @Override + public RangePtg copy() { + return instance; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/Ref2DPtgBase.java b/src/java/org/apache/poi/ss/formula/ptg/Ref2DPtgBase.java index 81a4b381f3..c0d0566b54 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/Ref2DPtgBase.java +++ b/src/java/org/apache/poi/ss/formula/ptg/Ref2DPtgBase.java @@ -21,13 +21,9 @@ import org.apache.poi.ss.util.CellReference; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; -/** - * @author Josh Micich - */ abstract class Ref2DPtgBase extends RefPtgBase { private final static int SIZE = 5; - protected Ref2DPtgBase(int row, int column, boolean isRowRelative, boolean isColumnRelative) { setRow(row); setColumn(column); @@ -35,6 +31,11 @@ abstract class Ref2DPtgBase extends RefPtgBase { setColRelative(isColumnRelative); } + protected Ref2DPtgBase(Ref2DPtgBase other) { + super(other); + } + + protected Ref2DPtgBase(LittleEndianInput in) { readCoordinates(in); } diff --git a/src/java/org/apache/poi/ss/formula/ptg/Ref3DPtg.java b/src/java/org/apache/poi/ss/formula/ptg/Ref3DPtg.java index e5506f3668..34105ee673 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/Ref3DPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/Ref3DPtg.java @@ -25,20 +25,23 @@ import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; /** - * <p>Title: Reference 3D Ptg</p> - * <p>Description: Defined a cell in extern sheet.</p> - * <p>REFERENCE: </p> - * - * <p>This is HSSF only, as it matches the HSSF file format way of - * referring to the sheet by an extern index. The XSSF equivalent - * is {@link Ref3DPxg} + * Reference 3D Ptg<p> + * Defined a cell in extern sheet.<p> + * + * This is HSSF only, as it matches the HSSF file format way of + * referring to the sheet by an extern index. The XSSF equivalent + * is {@link Ref3DPxg} */ public final class Ref3DPtg extends RefPtgBase implements WorkbookDependentFormula, ExternSheetReferenceToken { public final static byte sid = 0x3a; private final static int SIZE = 7; // 6 + 1 for Ptg - private int field_1_index_extern_sheet; + private int field_1_index_extern_sheet; + public Ref3DPtg(Ref3DPtg other) { + super(other); + field_1_index_extern_sheet = other.field_1_index_extern_sheet; + } public Ref3DPtg(LittleEndianInput in) { field_1_index_extern_sheet = in.readShort(); @@ -95,4 +98,9 @@ public final class Ref3DPtg extends RefPtgBase implements WorkbookDependentFormu public String toFormulaString() { throw new RuntimeException("3D references need a workbook to determine formula text"); } + + @Override + public Ref3DPtg copy() { + return new Ref3DPtg(this); + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/Ref3DPxg.java b/src/java/org/apache/poi/ss/formula/ptg/Ref3DPxg.java index 8ff8c7effc..5327650dc0 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/Ref3DPxg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/Ref3DPxg.java @@ -24,25 +24,31 @@ import org.apache.poi.ss.util.CellReference; import org.apache.poi.util.LittleEndianOutput; /** - * <p>Title: XSSF 3D Reference</p> - * <p>Description: Defines a cell in an external or different sheet.</p> - * <p>REFERENCE: </p> - * - * <p>This is XSSF only, as it stores the sheet / book references - * in String form. The HSSF equivalent using indexes is {@link Ref3DPtg}</p> + * XSSF 3D Reference<p> + * Defines a cell in an external or different sheet.<p> + * + * This is XSSF only, as it stores the sheet / book references + * in String form. The HSSF equivalent using indexes is {@link Ref3DPtg} */ public final class Ref3DPxg extends RefPtgBase implements Pxg3D { private int externalWorkbookNumber = -1; private String firstSheetName; private String lastSheetName; + public Ref3DPxg(Ref3DPxg other) { + super(other); + externalWorkbookNumber = other.externalWorkbookNumber; + firstSheetName = other.firstSheetName; + lastSheetName = other.lastSheetName; + } + public Ref3DPxg(int externalWorkbookNumber, SheetIdentifier sheetName, String cellref) { this(externalWorkbookNumber, sheetName, new CellReference(cellref)); } public Ref3DPxg(int externalWorkbookNumber, SheetIdentifier sheetName, CellReference c) { super(c); this.externalWorkbookNumber = externalWorkbookNumber; - + this.firstSheetName = sheetName.getSheetIdentifier().getName(); if (sheetName instanceof SheetRangeIdentifier) { this.lastSheetName = ((SheetRangeIdentifier)sheetName).getLastSheetIdentifier().getName(); @@ -50,7 +56,7 @@ public final class Ref3DPxg extends RefPtgBase implements Pxg3D { this.lastSheetName = null; } } - + public Ref3DPxg(SheetIdentifier sheetName, String cellref) { this(sheetName, new CellReference(cellref)); } @@ -77,7 +83,7 @@ public final class Ref3DPxg extends RefPtgBase implements Pxg3D { sb.append("]"); return sb.toString(); } - + public int getExternalWorkbookNumber() { return externalWorkbookNumber; } @@ -87,14 +93,14 @@ public final class Ref3DPxg extends RefPtgBase implements Pxg3D { public String getLastSheetName() { return lastSheetName; } - + public void setSheetName(String sheetName) { this.firstSheetName = sheetName; } public void setLastSheetName(String sheetName) { this.lastSheetName = sheetName; } - + public String format2DRefAsString() { return formatReferenceAsString(); } @@ -107,11 +113,16 @@ public final class Ref3DPxg extends RefPtgBase implements Pxg3D { sb.append(formatReferenceAsString()); return sb.toString(); } - + public int getSize() { return 1; } public void write(LittleEndianOutput out) { throw new IllegalStateException("XSSF-only Ptg, should not be serialised"); } + + @Override + public Ref3DPxg copy() { + return new Ref3DPxg(this); + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/RefErrorPtg.java b/src/java/org/apache/poi/ss/formula/ptg/RefErrorPtg.java index e450644b8f..7027d5ccf4 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/RefErrorPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/RefErrorPtg.java @@ -23,7 +23,6 @@ import org.apache.poi.util.LittleEndianOutput; /** * RefError - handles deleted cell reference - * @author Jason Height (jheight at chariot dot net dot au) */ public final class RefErrorPtg extends OperandPtg { @@ -34,6 +33,12 @@ public final class RefErrorPtg extends OperandPtg { public RefErrorPtg() { field_1_reserved = 0; } + + public RefErrorPtg(RefErrorPtg other) { + super(other); + field_1_reserved = other.field_1_reserved; + } + public RefErrorPtg(LittleEndianInput in) { field_1_reserved = in.readInt(); } @@ -55,8 +60,13 @@ public final class RefErrorPtg extends OperandPtg { public String toFormulaString() { return FormulaError.REF.getString(); } - + public byte getDefaultOperandClass() { return Ptg.CLASS_REF; } + + @Override + public RefErrorPtg copy() { + return new RefErrorPtg(this); + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/RefNPtg.java b/src/java/org/apache/poi/ss/formula/ptg/RefNPtg.java index 90d43ca945..faf6e9ab8d 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/RefNPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/RefNPtg.java @@ -20,10 +20,6 @@ package org.apache.poi.ss.formula.ptg; import org.apache.poi.ss.util.CellReference; import org.apache.poi.util.LittleEndianInput; -/** - * RefNPtg - * @author Jason Height (jheight at apache dot com) - */ public final class RefNPtg extends Ref2DPtgBase { public final static byte sid = 0x2C; @@ -31,6 +27,10 @@ public final class RefNPtg extends Ref2DPtgBase { super(in); } + public RefNPtg(RefNPtg other) { + super(other); + } + protected byte getSid() { return sid; } @@ -44,13 +44,18 @@ public final class RefNPtg extends Ref2DPtgBase { } else { builder.append(getRow()+1); } - + if(isColRelative()) { builder.append(" ColOffset: ").append(getColumn()); } else { builder.append(CellReference.convertNumToColString(getColumn())); } - + return builder.toString(); } + + @Override + public RefNPtg copy() { + return new RefNPtg(this); + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/RefPtg.java b/src/java/org/apache/poi/ss/formula/ptg/RefPtg.java index 297c0e7d89..0f9811a4bb 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/RefPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/RefPtg.java @@ -22,8 +22,6 @@ import org.apache.poi.util.LittleEndianInput; /** * ReferencePtg - handles references (such as A1, A2, IA4) - * @author Andrew C. Oliver (acoliver@apache.org) - * @author Jason Height (jheight at chariot dot net dot au) */ public final class RefPtg extends Ref2DPtgBase { public final static byte sid = 0x24; @@ -36,6 +34,10 @@ public final class RefPtg extends Ref2DPtgBase { super(new CellReference(cellref)); } + public RefPtg(RefPtg other) { + super(other); + } + public RefPtg(int row, int column, boolean isRowRelative, boolean isColumnRelative) { super(row, column, isRowRelative, isColumnRelative); } @@ -51,4 +53,9 @@ public final class RefPtg extends Ref2DPtgBase { protected byte getSid() { return sid; } + + @Override + public RefPtg copy() { + return new RefPtg(this); + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/RefPtgBase.java b/src/java/org/apache/poi/ss/formula/ptg/RefPtgBase.java index 31a3a56be7..34f9747ce5 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/RefPtgBase.java +++ b/src/java/org/apache/poi/ss/formula/ptg/RefPtgBase.java @@ -25,12 +25,21 @@ import org.apache.poi.util.LittleEndianOutput; /** * ReferencePtgBase - handles references (such as A1, A2, IA4) - * - * @author Andrew C. Oliver (acoliver@apache.org) - * @author Jason Height (jheight at chariot dot net dot au) */ public abstract class RefPtgBase extends OperandPtg { + /** + * YK: subclasses of RefPtgBase are used by the FormulaParser and FormulaEvaluator accross HSSF and XSSF. + * The bit mask should accommodate the maximum number of avaiable columns, i.e. 0x3FFF. + * + * @see org.apache.poi.ss.SpreadsheetVersion + */ + private static final BitField column = BitFieldFactory.getInstance(0x3FFF); + + private static final BitField rowRelative = BitFieldFactory.getInstance(0x8000); + private static final BitField colRelative = BitFieldFactory.getInstance(0x4000); + + /** The row index - zero based unsigned 16 bit value */ private int field_1_row; /** @@ -38,19 +47,13 @@ public abstract class RefPtgBase extends OperandPtg { * 16 - isRowRelative - bit 15 - isColumnRelative */ private int field_2_col; - private static final BitField rowRelative = BitFieldFactory.getInstance(0x8000); - private static final BitField colRelative = BitFieldFactory.getInstance(0x4000); - /** - * YK: subclasses of RefPtgBase are used by the FormulaParser and FormulaEvaluator accross HSSF and XSSF. - * The bit mask should accommodate the maximum number of avaiable columns, i.e. 0x3FFF. - * - * @see org.apache.poi.ss.SpreadsheetVersion - */ - private static final BitField column = BitFieldFactory.getInstance(0x3FFF); + protected RefPtgBase() {} - protected RefPtgBase() { - // Required for clone methods + protected RefPtgBase(RefPtgBase other) { + super(other); + field_1_row = other.field_1_row; + field_2_col = other.field_2_col; } protected RefPtgBase(CellReference c) { diff --git a/src/java/org/apache/poi/ss/formula/ptg/ScalarConstantPtg.java b/src/java/org/apache/poi/ss/formula/ptg/ScalarConstantPtg.java index 210d887df4..d4e4827f55 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/ScalarConstantPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/ScalarConstantPtg.java @@ -19,9 +19,7 @@ package org.apache.poi.ss.formula.ptg; /** - * Common superclass of all {@link Ptg}s that represent simple constant values. - * - * @author Josh Micich + * Common superclass of all {@link Ptg Ptgs} that represent simple constant values. */ public abstract class ScalarConstantPtg extends Ptg { public final boolean isBaseToken() { @@ -39,4 +37,6 @@ public abstract class ScalarConstantPtg extends Ptg { sb.append("]"); return sb.toString(); } + + } diff --git a/src/java/org/apache/poi/ss/formula/ptg/StringPtg.java b/src/java/org/apache/poi/ss/formula/ptg/StringPtg.java index c9b8e53546..d9fbd27417 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/StringPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/StringPtg.java @@ -24,10 +24,6 @@ import org.apache.poi.util.StringUtil; /** * String Stores a String value in a formula value stored in the format * <length 2 bytes>char[] - * - * @author Werner Froidevaux - * @author Jason Height (jheight at chariot dot net dot au) - * @author Bernard Chesnoy */ public final class StringPtg extends ScalarConstantPtg { public final static byte sid = 0x17; @@ -56,7 +52,7 @@ public final class StringPtg extends ScalarConstantPtg { * Create a StringPtg from a string representation of the number Number * format is not checked, it is expected to be validated in the parser that * calls this method. - * + * * @param value : * String representation of a floating point number */ @@ -105,4 +101,9 @@ public final class StringPtg extends ScalarConstantPtg { sb.append(FORMULA_DELIMITER); return sb.toString(); } + + @Override + public StringPtg copy() { + return this; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/SubtractPtg.java b/src/java/org/apache/poi/ss/formula/ptg/SubtractPtg.java index 5ae6ec7a9f..54e7817f5b 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/SubtractPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/SubtractPtg.java @@ -17,20 +17,15 @@ package org.apache.poi.ss.formula.ptg; -/** - * - * @author andy - * @author Jason Height (jheight at chariot dot net dot au) - */ public final class SubtractPtg extends ValueOperatorPtg { public final static byte sid = 0x04; - public static final ValueOperatorPtg instance = new SubtractPtg(); + public static final SubtractPtg instance = new SubtractPtg(); private SubtractPtg() { // enforce singleton } - + protected byte getSid() { return sid; } @@ -38,7 +33,7 @@ public final class SubtractPtg extends ValueOperatorPtg { public int getNumberOfOperands() { return 2; } - + public String toFormulaString(String[] operands) { StringBuilder buffer = new StringBuilder(); @@ -47,4 +42,9 @@ public final class SubtractPtg extends ValueOperatorPtg { buffer.append(operands[ 1 ]); return buffer.toString(); } + + @Override + public SubtractPtg copy() { + return instance; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/TblPtg.java b/src/java/org/apache/poi/ss/formula/ptg/TblPtg.java index b8a2109b56..1d37e6672c 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/TblPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/TblPtg.java @@ -37,6 +37,7 @@ import org.apache.poi.util.LittleEndianOutput; public final class TblPtg extends ControlPtg { private final static int SIZE = 5; public final static short sid = 0x02; + /** The row number of the upper left corner */ private final int field_1_first_row; /** The column number of the upper left corner */ @@ -77,4 +78,10 @@ public final class TblPtg extends ControlPtg { buffer.append("top left col = ").append(getColumn()).append("\n"); return buffer.toString(); } + + @Override + public TblPtg copy() { + // immutable + return this; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/UnaryMinusPtg.java b/src/java/org/apache/poi/ss/formula/ptg/UnaryMinusPtg.java index 54b423e82f..a257977826 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/UnaryMinusPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/UnaryMinusPtg.java @@ -18,21 +18,19 @@ package org.apache.poi.ss.formula.ptg; /** - * Unary Plus operator - * does not have any effect on the operand - * @author Avik Sengupta + * Unary Plus operator - does not have any effect on the operand */ public final class UnaryMinusPtg extends ValueOperatorPtg { public final static byte sid = 0x13; - + private final static String MINUS = "-"; - public static final ValueOperatorPtg instance = new UnaryMinusPtg(); + public static final UnaryMinusPtg instance = new UnaryMinusPtg(); private UnaryMinusPtg() { // enforce singleton } - + protected byte getSid() { return sid; } @@ -40,12 +38,17 @@ public final class UnaryMinusPtg extends ValueOperatorPtg { public int getNumberOfOperands() { return 1; } - - /** implementation of method from OperationsPtg*/ + + /** implementation of method from OperationsPtg*/ public String toFormulaString(String[] operands) { StringBuilder buffer = new StringBuilder(); buffer.append(MINUS); buffer.append(operands[ 0]); return buffer.toString(); } + + @Override + public UnaryMinusPtg copy() { + return instance; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/UnaryPlusPtg.java b/src/java/org/apache/poi/ss/formula/ptg/UnaryPlusPtg.java index be6ba540d6..68a0d0e1ae 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/UnaryPlusPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/UnaryPlusPtg.java @@ -18,21 +18,19 @@ package org.apache.poi.ss.formula.ptg; /** - * Unary Plus operator - * does not have any effect on the operand - * @author Avik Sengupta + * Unary Plus operator - does not have any effect on the operand */ public final class UnaryPlusPtg extends ValueOperatorPtg { public final static byte sid = 0x12; - + private final static String ADD = "+"; - public static final ValueOperatorPtg instance = new UnaryPlusPtg(); + public static final UnaryPlusPtg instance = new UnaryPlusPtg(); private UnaryPlusPtg() { // enforce singleton } - + protected byte getSid() { return sid; } @@ -40,12 +38,17 @@ public final class UnaryPlusPtg extends ValueOperatorPtg { public int getNumberOfOperands() { return 1; } - - /** implementation of method from OperationsPtg*/ + + /** implementation of method from OperationsPtg*/ public String toFormulaString(String[] operands) { StringBuilder buffer = new StringBuilder(); buffer.append(ADD); buffer.append(operands[ 0]); return buffer.toString(); } + + @Override + public UnaryPlusPtg copy() { + return instance; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/UnionPtg.java b/src/java/org/apache/poi/ss/formula/ptg/UnionPtg.java index 45042df0f9..681f9efc54 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/UnionPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/UnionPtg.java @@ -26,7 +26,7 @@ import org.apache.poi.util.LittleEndianOutput; public final class UnionPtg extends OperationPtg { public final static byte sid = 0x10; - public static final OperationPtg instance = new UnionPtg(); + public static final UnionPtg instance = new UnionPtg(); private UnionPtg() { // enforce singleton @@ -67,4 +67,8 @@ public final class UnionPtg extends OperationPtg { return 2; } + @Override + public UnionPtg copy() { + return instance; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/UnknownPtg.java b/src/java/org/apache/poi/ss/formula/ptg/UnknownPtg.java index 8eac21208e..9992cadf9a 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/UnknownPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/UnknownPtg.java @@ -18,10 +18,6 @@ package org.apache.poi.ss.formula.ptg; import org.apache.poi.util.LittleEndianOutput; -/** - * @author andy - * @author Jason Height (jheight at chariot dot net dot au) - */ public class UnknownPtg extends Ptg { private short size = 1; private final int _sid; @@ -47,4 +43,9 @@ public class UnknownPtg extends Ptg { public byte getDefaultOperandClass() { return Ptg.CLASS_VALUE; } + + @Override + public UnknownPtg copy() { + return this; + } } diff --git a/src/java/org/apache/poi/ss/formula/ptg/ValueOperatorPtg.java b/src/java/org/apache/poi/ss/formula/ptg/ValueOperatorPtg.java index 1194adfd2a..a3e595df04 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/ValueOperatorPtg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/ValueOperatorPtg.java @@ -23,11 +23,11 @@ import org.apache.poi.util.LittleEndianOutput; * Common superclass of all value operators. Subclasses include all unary and * binary operators except for the reference operators (IntersectionPtg, * RangePtg, UnionPtg) - * - * @author Josh Micich */ public abstract class ValueOperatorPtg extends OperationPtg { + protected ValueOperatorPtg() {} + /** * All Operator <tt>Ptg</tt>s are base tokens (i.e. are not RVA classified) */ diff --git a/src/java/org/apache/poi/ss/util/CellRangeAddress.java b/src/java/org/apache/poi/ss/util/CellRangeAddress.java index 2b65ae660e..c466f275cc 100644 --- a/src/java/org/apache/poi/ss/util/CellRangeAddress.java +++ b/src/java/org/apache/poi/ss/util/CellRangeAddress.java @@ -24,8 +24,8 @@ import org.apache.poi.util.LittleEndianOutput; /** * See OOO documentation: excelfileformat.pdf sec 2.5.14 - 'Cell Range Address'<p> - * - * <p>In the Microsoft documentation, this is also known as a + * + * <p>In the Microsoft documentation, this is also known as a * Ref8U - see page 831 of version 1.0 of the documentation. * * Note - {@link SelectionRecord} uses the BIFF5 version of this structure @@ -36,7 +36,7 @@ public class CellRangeAddress extends CellRangeAddressBase { /** * Creates new cell range. Indexes are zero-based. - * + * * @param firstRow Index of first row * @param lastRow Index of last row (inclusive), must be equal to or larger than {@code firstRow} * @param firstCol Index of first column @@ -44,7 +44,7 @@ public class CellRangeAddress extends CellRangeAddressBase { */ public CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol) { super(firstRow, lastRow, firstCol, lastCol); - + if (lastRow < firstRow || lastCol < firstCol) { throw new IllegalArgumentException("Invalid cell range, having lastRow < firstRow || lastCol < firstCol, " + "had rows " + lastRow + " >= " + firstRow + " or cells " + lastCol + " >= " + firstCol); @@ -70,6 +70,7 @@ public class CellRangeAddress extends CellRangeAddressBase { return in.readUShort(); } + @Override public CellRangeAddress copy() { return new CellRangeAddress(getFirstRow(), getLastRow(), getFirstColumn(), getLastColumn()); } @@ -103,7 +104,7 @@ public class CellRangeAddress extends CellRangeAddressBase { //for a single-cell reference return A1 instead of A1:A1 //for full-column ranges or full-row ranges return A:A instead of A, - //and 1:1 instead of 1 + //and 1:1 instead of 1 if(!cellRefFrom.equals(cellRefTo) || isFullColumnRange() || isFullRowRange()){ sb.append(':'); @@ -114,10 +115,10 @@ public class CellRangeAddress extends CellRangeAddressBase { /** * Creates a CellRangeAddress from a cell range reference string. - * - * @param ref usually a standard area ref (e.g. "B1:D8"). May be a single - * cell ref (e.g. "B5") in which case the result is a 1 x 1 cell - * range. May also be a whole row range (e.g. "3:5"), or a whole + * + * @param ref usually a standard area ref (e.g. "B1:D8"). May be a single + * cell ref (e.g. "B5") in which case the result is a 1 x 1 cell + * range. May also be a whole row range (e.g. "3:5"), or a whole * column range (e.g. "C:F") */ public static CellRangeAddress valueOf(String ref) { diff --git a/src/java/org/apache/poi/ss/util/CellRangeAddressBase.java b/src/java/org/apache/poi/ss/util/CellRangeAddressBase.java index 1224e479d6..bef4596743 100644 --- a/src/java/org/apache/poi/ss/util/CellRangeAddressBase.java +++ b/src/java/org/apache/poi/ss/util/CellRangeAddressBase.java @@ -17,14 +17,12 @@ package org.apache.poi.ss.util; -import java.util.ArrayList; -import java.util.Collections; import java.util.EnumSet; import java.util.Iterator; -import java.util.List; import java.util.NoSuchElementException; import java.util.Set; +import org.apache.poi.common.Duplicatable; import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.usermodel.Cell; @@ -34,13 +32,13 @@ import org.apache.poi.ss.usermodel.Cell; * * Common superclass of 8-bit and 16-bit versions */ -public abstract class CellRangeAddressBase implements Iterable<CellAddress> { +public abstract class CellRangeAddressBase implements Iterable<CellAddress>, Duplicatable { /** * Indicates a cell or range is in the given relative position in a range. * More than one of these may apply at once. */ - public static enum CellPosition { + public enum CellPosition { /** range starting rows are equal */ TOP, /** range ending rows are equal */ @@ -138,7 +136,7 @@ public abstract class CellRangeAddressBase implements Iterable<CellAddress> { } /** - * Determines if the given coordinates lie within the bounds + * Determines if the given coordinates lie within the bounds * of this range. * * @param rowInd The row, 0-based. @@ -150,11 +148,11 @@ public abstract class CellRangeAddressBase implements Iterable<CellAddress> { return _firstRow <= rowInd && rowInd <= _lastRow && //containsRow _firstCol <= colInd && colInd <= _lastCol; //containsColumn } - + /** - * Determines if the given {@link CellReference} lies within the bounds - * of this range. - * <p>NOTE: It is up to the caller to ensure the reference is + * Determines if the given {@link CellReference} lies within the bounds + * of this range. + * <p>NOTE: It is up to the caller to ensure the reference is * for the correct sheet, since this instance doesn't have a sheet reference. * * @param ref the CellReference to check @@ -164,11 +162,11 @@ public abstract class CellRangeAddressBase implements Iterable<CellAddress> { public boolean isInRange(CellReference ref) { return isInRange(ref.getRow(), ref.getCol()); } - + /** - * Determines if the given {@link CellAddress} lies within the bounds - * of this range. - * <p>NOTE: It is up to the caller to ensure the reference is + * Determines if the given {@link CellAddress} lies within the bounds + * of this range. + * <p>NOTE: It is up to the caller to ensure the reference is * for the correct sheet, since this instance doesn't have a sheet reference. * * @param ref the CellAddress to check @@ -178,11 +176,11 @@ public abstract class CellRangeAddressBase implements Iterable<CellAddress> { public boolean isInRange(CellAddress ref) { return isInRange(ref.getRow(), ref.getColumn()); } - + /** - * Determines if the given {@link Cell} lies within the bounds - * of this range. - * <p>NOTE: It is up to the caller to ensure the reference is + * Determines if the given {@link Cell} lies within the bounds + * of this range. + * <p>NOTE: It is up to the caller to ensure the reference is * for the correct sheet, since this instance doesn't have a sheet reference. * * @param cell the Cell to check @@ -192,7 +190,7 @@ public abstract class CellRangeAddressBase implements Iterable<CellAddress> { public boolean isInRange(Cell cell) { return isInRange(cell.getRowIndex(), cell.getColumnIndex()); } - + /** * Check if the row is in the specified cell range * @@ -202,7 +200,7 @@ public abstract class CellRangeAddressBase implements Iterable<CellAddress> { public boolean containsRow(int rowInd) { return _firstRow <= rowInd && rowInd <= _lastRow; } - + /** * Check if the column is in the specified cell range * @@ -212,7 +210,7 @@ public abstract class CellRangeAddressBase implements Iterable<CellAddress> { public boolean containsColumn(int colInd) { return _firstCol <= colInd && colInd <= _lastCol; } - + /** * Determines whether or not this CellRangeAddress and the specified CellRangeAddress intersect. * @@ -226,7 +224,7 @@ public abstract class CellRangeAddressBase implements Iterable<CellAddress> { other._firstRow <= this._lastRow && other._firstCol <= this._lastCol; } - + /** * Useful for logic like table/range styling, where some elements apply based on relative position in a range. * @param rowInd @@ -245,10 +243,10 @@ public abstract class CellRangeAddressBase implements Iterable<CellAddress> { if (rowInd == getLastRow()) positions.add(CellPosition.BOTTOM); if (colInd == getFirstColumn()) positions.add(CellPosition.LEFT); if (colInd == getLastColumn()) positions.add(CellPosition.RIGHT); - + return positions; } - + /** * @param firstCol column number for the upper left hand corner */ @@ -291,37 +289,37 @@ public abstract class CellRangeAddressBase implements Iterable<CellAddress> { public Iterator<CellAddress> iterator() { return new RowMajorCellAddressIterator(this); } - + /** * Iterates over the cell addresses in a cell range in row major order - * + * * The iterator is unaffected by changes to the CellRangeAddressBase instance * after the iterator is created. */ private static class RowMajorCellAddressIterator implements Iterator<CellAddress> { private final int firstRow, firstCol, lastRow, lastCol; private int r, c; - + public RowMajorCellAddressIterator(CellRangeAddressBase ref) { r = firstRow = ref.getFirstRow(); c = firstCol = ref.getFirstColumn(); lastRow = ref.getLastRow(); lastCol = ref.getLastColumn(); - + // whole row and whole column ranges currently not supported if (firstRow < 0) throw new IllegalStateException("First row cannot be negative."); if (firstCol < 0) throw new IllegalStateException("First column cannot be negative."); - + // avoid infinite iteration if (firstRow > lastRow) throw new IllegalStateException("First row cannot be greater than last row."); if (firstCol > lastCol) throw new IllegalStateException("First column cannot be greater than last column."); } - + @Override public boolean hasNext() { return r <= lastRow && c <= lastCol; } - + @Override public CellAddress next() { if (hasNext()) { @@ -346,7 +344,7 @@ public abstract class CellRangeAddressBase implements Iterable<CellAddress> { CellAddress crB = new CellAddress(_lastRow, _lastCol); return getClass().getName() + " [" + crA.formatAsString() + ":" + crB.formatAsString() +"]"; } - + // In case _firstRow > _lastRow or _firstCol > _lastCol protected int getMinRow() { return Math.min(_firstRow, _lastRow); @@ -360,7 +358,7 @@ public abstract class CellRangeAddressBase implements Iterable<CellAddress> { protected int getMaxColumn() { return Math.max(_firstCol, _lastCol); } - + @Override public boolean equals(Object other) { if (other instanceof CellRangeAddressBase) { @@ -372,7 +370,7 @@ public abstract class CellRangeAddressBase implements Iterable<CellAddress> { } return false; } - + @Override public int hashCode() { return (getMinColumn() + diff --git a/src/java/org/apache/poi/ss/util/SSCellRange.java b/src/java/org/apache/poi/ss/util/SSCellRange.java index e948465567..766e2e3564 100644 --- a/src/java/org/apache/poi/ss/util/SSCellRange.java +++ b/src/java/org/apache/poi/ss/util/SSCellRange.java @@ -20,7 +20,7 @@ package org.apache.poi.ss.util; import java.lang.reflect.Array; import java.util.Iterator; import java.util.List; -import java.util.NoSuchElementException; +import java.util.stream.Stream; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellRange; @@ -28,8 +28,6 @@ import org.apache.poi.util.Internal; /** * For POI internal use only - * - * @author Josh Micich */ @Internal public final class SSCellRange<K extends Cell> implements CellRange<K> { @@ -108,30 +106,8 @@ public final class SSCellRange<K extends Cell> implements CellRange<K> { } return result; } - public Iterator<K> iterator() { - return new ArrayIterator<>(_flattenedArray); - } - private static final class ArrayIterator<D> implements Iterator<D> { - - private final D[] _array; - private int _index; - public ArrayIterator(D[] array) { - _array = array.clone(); - _index = 0; - } - public boolean hasNext() { - return _index < _array.length; - } - public D next() { - if (_index >= _array.length) { - throw new NoSuchElementException(String.valueOf(_index)); - } - return _array[_index++]; - } - - public void remove() { - throw new UnsupportedOperationException("Cannot remove cells from this CellRange."); - } + public Iterator<K> iterator() { + return Stream.of(_flattenedArray).iterator(); } } diff --git a/src/java/org/apache/poi/util/IntMapper.java b/src/java/org/apache/poi/util/IntMapper.java index 921b820b84..db68883edf 100644 --- a/src/java/org/apache/poi/util/IntMapper.java +++ b/src/java/org/apache/poi/util/IntMapper.java @@ -19,76 +19,79 @@ package org.apache.poi.util; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.poi.common.Duplicatable; /** * A List of objects that are indexed AND keyed by an int; also allows for getting * the index of a value in the list - * - * <p>I am happy is someone wants to re-implement this without using the + * <p> + * I am happy is someone wants to re-implement this without using the * internal list and hashmap. If so could you please make sure that * you can add elements half way into the list and have the value-key mappings - * update</p> - * - * - * @author Jason Height + * update */ -public class IntMapper<T> -{ - private List<T> elements; - private Map<T,Integer> valueKeyMap; +public class IntMapper<T> implements Duplicatable { + private final List<T> elements; + private final Map<T, Integer> valueKeyMap; - private static final int _default_size = 10; + private static final int _default_size = 10; /** * create an IntMapper of default size */ - - public IntMapper() - { + public IntMapper() { this(_default_size); } - public IntMapper(final int initialCapacity) - { + public IntMapper(final int initialCapacity) { elements = new ArrayList<>(initialCapacity); valueKeyMap = new HashMap<>(initialCapacity); } + public IntMapper(IntMapper<T> other) { + elements = new ArrayList<>(other.elements); + valueKeyMap = new HashMap<>(other.valueKeyMap); + } + /** * Appends the specified element to the end of this list * * @param value element to be appended to this list. - * * @return true (as per the general contract of the Collection.add - * method). + * method). */ - public boolean add(final T value) - { - int index = elements.size(); - elements.add(value); - valueKeyMap.put(value, index); - return true; + public boolean add(final T value) { + int index = elements.size(); + elements.add(value); + valueKeyMap.put(value, index); + return true; } public int size() { - return elements.size(); + return elements.size(); } public T get(int index) { - return elements.get(index); + return elements.get(index); } public int getIndex(T o) { - Integer i = valueKeyMap.get(o); - if (i == null) - return -1; - return i.intValue(); + return valueKeyMap.getOrDefault(o, -1); } public Iterator<T> iterator() { - return elements.iterator(); + return elements.iterator(); } -} // end public class IntMapper + @Override + public IntMapper<T> copy() { + return new IntMapper<>(this); + } +}
\ No newline at end of file |